Skip to content

Commit

Permalink
EP-3981 Add #71 #114 references to vector cube todo's
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Apr 20, 2022
1 parent aa5ec2c commit 7d540bb
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 28 deletions.
25 changes: 13 additions & 12 deletions openeo_driver/ProcessGraphDeserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ def vector_buffer(args: Dict, env: EvalEnv) -> dict:
input_crs = 'epsg:4326'
buffer_resolution = 3

# TODO EP-3981 convert `geometry` to vector cube and move buffer logic to there
# TODO #114 EP-3981 convert `geometry` to vector cube and move buffer logic to there
if isinstance(geometry, str):
# TODO: assumption here that `geometry` is a path/url
geoms = list(DelayedVector(geometry).geometries)
Expand Down Expand Up @@ -664,7 +664,7 @@ def chunk_polygon(args: dict, env: EvalEnv) -> DriverDataCube:
data_cube = extract_arg(args, 'data')

# Chunks parameter check.
# TODO EP-3981 normalize first to vector cube and simplify logic
# TODO #114 EP-3981 normalize first to vector cube and simplify logic
if isinstance(chunks, DelayedVector):
polygons = list(chunks.geometries)
for p in polygons:
Expand Down Expand Up @@ -705,7 +705,7 @@ def fit_class_random_forest(args: dict, env: EvalEnv) -> DriverMlModel:

predictors = extract_arg(args, 'predictors')
if not isinstance(predictors, AggregatePolygonSpatialResult):
# TODO EP-3981 add support for real vector cubes.
# TODO #114 EP-3981 add support for real vector cubes.
raise ProcessParameterInvalidException(
parameter="predictors", process="fit_class_random_forest",
reason=f"should be non-temporal vector-cube (got `{type(predictors)}`)."
Expand All @@ -716,7 +716,7 @@ def fit_class_random_forest(args: dict, env: EvalEnv) -> DriverMlModel:
and target.get("type") == "FeatureCollection"
and isinstance(target.get("features"), list)
):
# TODO EP-3981 vector cube support
# TODO #114 EP-3981 vector cube support
raise ProcessParameterInvalidException(
parameter="target", process="fit_class_random_forest",
reason='only GeoJSON FeatureCollection is currently supported.',
Expand Down Expand Up @@ -949,7 +949,7 @@ def aggregate_spatial(args: dict, env: EvalEnv) -> DriverDataCube:
target_dimension = args.get('target_dimension', None)

geoms = extract_arg(args, 'geometries')
# TODO: convert all cases to DriverVectorCube first and just work with that
# TODO #114: convert all cases to DriverVectorCube first and just work with that
if isinstance(geoms, DriverVectorCube):
geoms = geoms
elif isinstance(geoms, dict):
Expand Down Expand Up @@ -993,11 +993,11 @@ def mask_polygon(args: dict, env: EvalEnv) -> DriverDataCube:
replacement = args.get('replacement', None)
inside = args.get('inside', False)

# TODO: instead of if-elif-else chain: generically "cast" to VectorCube first (e.g. for wide input
# TODO #114: instead of if-elif-else chain: generically "cast" to VectorCube first (e.g. for wide input
# support: GeoJSON, WKT, ...) and then convert to MultiPolygon?
if isinstance(mask, DelayedVector):
# TODO: avoid reading DelayedVector twice due to dry-run?
# TODO EP-3981 embed DelayedVector in VectorCube implementation
# TODO #114 EP-3981 embed DelayedVector in VectorCube implementation
polygon = shapely.ops.unary_union(list(mask.geometries))
elif isinstance(mask, DriverVectorCube):
polygon = mask.to_multipolygon()
Expand Down Expand Up @@ -1073,7 +1073,7 @@ def filter_spatial(args: Dict, env: EvalEnv) -> DriverDataCube:
geometries = extract_arg(args, 'geometries')

if not isinstance(geometries, dict):
# TODO: support DelayedVector
# TODO #114: support DriverDataCube
raise NotImplementedError("filter_spatial only supports dict but got {g!r}".format(g=geometries))

geometries = geojson_to_geometry(geometries)
Expand Down Expand Up @@ -1173,6 +1173,7 @@ def run_udf(args: dict, env: EvalEnv):
if dry_run_tracer and isinstance(data, AggregatePolygonResult):
return JSONResult({})

# TODO #114 add support for DriverVectorCube
if isinstance(data, AggregatePolygonResult):
pass
if isinstance(data, (DelayedVector, dict)):
Expand Down Expand Up @@ -1346,15 +1347,15 @@ def apply_process(process_id: str, args: dict, namespace: Union[str, None], env:
.returns("TODO", schema={"type": "object", "subtype": "vector-cube"})
)
def read_vector(args: Dict, env: EvalEnv) -> DelayedVector:
# TODO EP-3981: deprecated in favor of load_uploaded_files/load_external? https://github.com/Open-EO/openeo-processes/issues/322
# TODO #114 EP-3981: deprecated in favor of load_uploaded_files/load_external? https://github.com/Open-EO/openeo-processes/issues/322
path = extract_arg(args, 'filename')
return DelayedVector(path)


@process_registry_100.add_function(spec=read_spec("openeo-processes/1.x/proposals/load_uploaded_files.json"))
def load_uploaded_files(args: dict, env: EvalEnv) -> DriverVectorCube:
# TODO EP-3981 process name is still under discussion https://github.com/Open-EO/openeo-processes/issues/322
# TODO EP-3981 also other return types: raster data cube, array, ...
# TODO #114 EP-3981 process name is still under discussion https://github.com/Open-EO/openeo-processes/issues/322
# TODO also other return types: raster data cube, array, ...
paths = extract_arg(args, 'paths', process_id="load_uploaded_files")
format = extract_arg(args, 'format', process_id="load_uploaded_files")
options = args.get("options", {})
Expand All @@ -1376,7 +1377,7 @@ def load_uploaded_files(args: dict, env: EvalEnv) -> DriverVectorCube:
.returns("TODO", schema={"type": "object", "subtype": "vector-cube"})
)
def get_geometries(args: Dict, env: EvalEnv) -> Union[DelayedVector, dict]:
# TODO: standardize or deprecate this? EP-3981 https://github.com/Open-EO/openeo-processes/issues/322
# TODO: standardize or deprecate this? #114 EP-3981 https://github.com/Open-EO/openeo-processes/issues/322
feature_collection = args.get('feature_collection', None)
path = args.get('filename', None)
if path is not None:
Expand Down
6 changes: 3 additions & 3 deletions openeo_driver/datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ class DriverVectorCube:
DIM_GEOMETRIES = "geometries"

def __init__(self, geometries: gpd.GeoDataFrame, cube: Optional[xarray.DataArray] = None):
# TODO EP-3981: consider other data containers (xarray) and lazy loading?
# TODO #114 EP-3981: lazy loading (like DelayedVector)?
if cube is not None:
if cube.dims[0] != self.DIM_GEOMETRIES:
log.error(f"First cube dim should be {self.DIM_GEOMETRIES!r} but got dims {cube.dims!r}")
Expand All @@ -176,9 +176,9 @@ def with_cube(self, cube: xarray.DataArray) -> "DriverVectorCube":
def from_fiona(cls, paths: List[str], driver: str, options: dict):
"""Factory to load vector cube data using fiona/GeoPandas."""
if len(paths) != 1:
# TODO EP-3981: support multiple paths
# TODO #114 EP-3981: support multiple paths
raise FeatureUnsupportedException(message="Loading a vector cube from multiple files is not supported")
# TODO EP-3981: lazy loading like/with DelayedVector
# TODO #114 EP-3981: lazy loading like/with DelayedVector
return cls(geometries=gpd.read_file(paths[0], driver=driver))

def _as_geopandas_df(self) -> gpd.GeoDataFrame:
Expand Down
1 change: 1 addition & 0 deletions openeo_driver/delayed_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def _read_shapefile_crs(shp_path: str) -> pyproj.CRS:

@staticmethod
def _as_geometry_collection(feature_collection: Dict) -> Dict:
# TODO #71 #114 Deprecate/avoid usage of GeometryCollection
geometries = (feature['geometry'] for feature in feature_collection['features'])

return {
Expand Down
7 changes: 4 additions & 3 deletions openeo_driver/dry_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def aggregate_spatial(
reducer: dict,
target_dimension: str = "result",
) -> Union[AggregatePolygonResult, AggregatePolygonSpatialResult]:
# TODO EP-3981 normalize to vector cube instead of GeometryCollection
# TODO #71 #114 EP-3981 normalize to vector cube instead of GeometryCollection
geometries, bbox = self._normalize_geometry(geometries)
cube = self.filter_bbox(**bbox, operation="_weak_spatial_extent")
cube._process(operation="aggregate_spatial", arguments={"geometries": geometries})
Expand All @@ -456,7 +456,7 @@ def _normalize_geometry(self, geometries) -> Tuple[Union[DriverVectorCube, Delay
Helper to preprocess geometries (as used in aggregate_spatial and mask_polygon)
and extract bbox (e.g. for filter_bbox)
"""
# TODO EP-3981 normalize to vector cube instead of GeometryCollection
# TODO #71 #114 EP-3981 normalize to vector cube instead of GeometryCollection
if isinstance(geometries, DriverVectorCube):
bbox = geometries.get_bounding_box()
elif isinstance(geometries, dict):
Expand All @@ -478,7 +478,7 @@ def _normalize_geometry(self, geometries) -> Tuple[Union[DriverVectorCube, Delay
bbox = dict(west=bbox[0], south=bbox[1], east=bbox[2], north=bbox[3], crs="EPSG:4326")
return geometries, bbox

# TODO: this is a workaround until vectorcube is fully upgraded
# TODO: #114 this is a workaround until vectorcube is fully upgraded
def raster_to_vector(self):
return AggregatePolygonResult(timeseries={}, regions=None)

Expand All @@ -504,6 +504,7 @@ def reduce_dimension(self, reducer, dimension: str, context: Any, env: EvalEnv)

def chunk_polygon(self, reducer, chunks: MultiPolygon, mask_value: float, env: EvalEnv, context={}) -> 'DryRunDataCube':
polygons: List[Polygon] = chunks.geoms
# TODO #71 #114 Deprecate/avoid usage of GeometryCollection
geometries, bbox = self._normalize_geometry(GeometryCollection(polygons))
cube = self.filter_bbox(**bbox, operation="_weak_spatial_extent")
return cube._process("chunk_polygon", arguments={"geometries": geometries})
Expand Down
6 changes: 3 additions & 3 deletions openeo_driver/dummy/dummy_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def assert_polygon_sequence(geometries: Union[Sequence, BaseMultipartGeometry]):
for g in geometries:
assert isinstance(g, Polygon) or isinstance(g, MultiPolygon)

# TODO EP-3981 normalize to vector cube and preserve original properties
# TODO #114 EP-3981 normalize to vector cube and preserve original properties
if isinstance(geometries, DriverVectorCube):
# Build dummy aggregation data cube
dims = (DriverVectorCube.DIM_GEOMETRIES,)
Expand All @@ -239,7 +239,7 @@ def assert_polygon_sequence(geometries: Union[Sequence, BaseMultipartGeometry]):
geometries = [geometry for geometry in DelayedVector(geometries).geometries]
assert_polygon_sequence(geometries)
elif isinstance(geometries, GeometryCollection):
# TODO EP-3981: GeometryCollection is deprecated
# TODO #71 #114 EP-3981: GeometryCollection is deprecated
assert_polygon_sequence(geometries)
elif isinstance(geometries, BaseGeometry):
assert_polygon_sequence([geometries])
Expand All @@ -256,7 +256,7 @@ def assert_polygon_sequence(geometries: Union[Sequence, BaseMultipartGeometry]):


class DummyAggregatePolygonSpatialResult(AggregatePolygonSpatialResult):
# TODO EP-3981 replace with proper VectorCube implementation
# TODO #114 EP-3981 replace with proper VectorCube implementation

def __init__(self, cube: DummyDataCube, geometries: Iterable[BaseGeometry]):
super().__init__(csv_dir="/dev/null", regions=geometries)
Expand Down
11 changes: 5 additions & 6 deletions openeo_driver/save_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class AggregatePolygonResult(JSONResult): # TODO: if it supports NetCDF and CSV
"""

# TODO EP-3981 port this to proper vector cube support
# TODO #71 #114 EP-3981 port this to proper vector cube support

def __init__(self, timeseries: dict, regions: GeometryCollection, metadata:CollectionMetadata=None):
super().__init__(data=timeseries)
Expand Down Expand Up @@ -429,11 +429,10 @@ def to_covjson(self) -> dict:
}



class AggregatePolygonResultCSV(AggregatePolygonResult):
# TODO #71 #114 EP-3981 port this to proper vector cube support


def __init__(self, csv_dir, regions: GeometryCollection, metadata:CollectionMetadata=None):
def __init__(self, csv_dir, regions: GeometryCollection, metadata: CollectionMetadata = None):

def _flatten_df(df):
df.index = df.feature_index
Expand Down Expand Up @@ -464,7 +463,7 @@ class AggregatePolygonSpatialResult(SaveResult):
"""
Container for result of `aggregate_polygon` process (aka "zonal stats") for a spatial layer.
"""
# TODO EP-3981 replace with proper VectorCube implementation
# TODO #71 #114 EP-3981 replace with proper VectorCube implementation

DEFAULT_FORMAT = "JSON"

Expand Down Expand Up @@ -597,7 +596,7 @@ def to_save_result(data: Any, format: Optional[str] = None, options: Optional[di
elif isinstance(data, DriverVectorCube):
return VectorCubeResult(cube=data, format=format, options=options)
elif isinstance(data, DelayedVector):
# TODO EP-3981 add vector cube support: keep features from feature collection
# TODO #114 EP-3981 add vector cube support: keep features from feature collection
geojsons = [mapping(geometry) for geometry in data.geometries]
return JSONResult(geojsons, format=format, options=options)
elif isinstance(data, np.ndarray):
Expand Down
3 changes: 2 additions & 1 deletion openeo_driver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def smart_bool(value):

def geojson_to_geometry(geojson: dict) -> shapely.geometry.base.BaseGeometry:
"""Convert GeoJSON object to shapely geometry object"""
# TODO EP-3981 standardize on using (FeatureCollection like) vector cubes instead of GeometryCollection?
# TODO #71 #114 EP-3981 standardize on using (FeatureCollection like) vector cubes instead of GeometryCollection?
if geojson["type"] == "FeatureCollection":
geojson = {
'type': 'GeometryCollection',
Expand All @@ -147,6 +147,7 @@ def geojson_to_multipolygon(
means dissolving overlapping polygons into one).
"""
# TODO: option to also force conversion of Polygon to MultiPolygon?
# TODO: #71 #114 migrate/centralize all this kind of logic to vector cubes
if geojson["type"] == "Feature":
geojson = geojson["geometry"]

Expand Down

0 comments on commit 7d540bb

Please sign in to comment.