Skip to content

Commit

Permalink
Issue #424 Add DataCube.apply_polygon
Browse files Browse the repository at this point in the history
  • Loading branch information
soxofaan committed Nov 14, 2023
1 parent 40be725 commit f741056
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 104 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#310](https://github.com/Open-EO/openeo-python-client/issues/310))
- Add `collection_property()` helper to easily build collection metadata property filters for `Connection.load_collection()`
([#331](https://github.com/Open-EO/openeo-python-client/pull/331))
- Add `DataCube.apply_polygon()` (standardized version of experimental `chunk_polygon`) ([#424](https://github.com/Open-EO/openeo-python-client/issues/424))

### Changed

Expand Down
43 changes: 41 additions & 2 deletions openeo/rest/datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -1193,11 +1193,11 @@ def reduce_spatial(
metadata=self.metadata.reduce_spatial(),
)

# @openeo_process
@deprecated("Use :py:meth:`apply_polygon`.", version="0.26.0")
def chunk_polygon(
self,
chunks: Union[shapely.geometry.base.BaseGeometry, dict, str, pathlib.Path, Parameter, VectorCube],
process: Union[str, PGNode, typing.Callable],
process: Union[str, PGNode, typing.Callable, UDF],
mask_value: float = None,
context: Optional[dict] = None,
) -> DataCube:
Expand Down Expand Up @@ -1237,6 +1237,45 @@ def chunk_polygon(
),
)

@openeo_process
def apply_polygon(
self,
polygons: Union[shapely.geometry.base.BaseGeometry, dict, str, pathlib.Path, Parameter, VectorCube],
process: Union[str, PGNode, typing.Callable, UDF],
mask_value: Optional[float] = None,
context: Optional[dict] = None,
) -> DataCube:
"""
Apply a process to segments of the data cube that are defined by the given polygons.
For each polygon provided, all pixels for which the point at the pixel center intersects
with the polygon (as defined in the Simple Features standard by the OGC) are collected into sub data cubes.
If a pixel is part of multiple of the provided polygons (e.g., when the polygons overlap),
the GeometriesOverlap exception is thrown.
Each sub data cube is passed individually to the given process.
.. warning:: experimental process: not generally supported, API subject to change.
:param polygons: Polygons, provided as a shapely geometry, a GeoJSON-style dictionary,
a public GeoJSON URL, or a path (that is valid for the back-end) to a GeoJSON file.
:param process: "child callback" function, see :ref:`callbackfunctions`
:param mask_value: The value used for pixels outside the polygon.
:param context: Additional data to be passed to the process.
"""
process = build_child_callback(process, parent_parameters=["data"], connection=self.connection)
valid_geojson_types = ["Polygon", "MultiPolygon", "Feature", "FeatureCollection"]
polygons = self._get_geometry_argument(polygons, valid_geojson_types=valid_geojson_types)
mask_value = float(mask_value) if mask_value is not None else None
return self.process(
process_id="apply_polygon",
data=THIS,
polygons=polygons,
process=process,
arguments=dict_no_none(
mask_value=mask_value,
context=context,
),
)

def reduce_bands(self, reducer: Union[str, PGNode, typing.Callable, UDF]) -> DataCube:
"""
Shortcut for :py:meth:`reduce_dimension` along the band dimension
Expand Down
8 changes: 6 additions & 2 deletions tests/rest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
from openeo.rest.datacube import DataCube


def get_download_graph(cube: DataCube, drop_save_result: bool = False) -> dict:
def get_download_graph(cube: DataCube, *, drop_save_result: bool = False, drop_load_collection: bool = False) -> dict:
"""
Do fake download of a cube and intercept the process graph
:param cube: cube to download
:param connection: connection object
:param drop_save_result: whether to drop the save_result node
:param drop_load_collection: whether to drop the load_collection node
:return:
"""
# TODO: move this to a testing utility module
with mock.patch.object(cube.connection, 'download') as download:
cube.download("out.geotiff", format="GTIFF")
download.assert_called_once()
Expand All @@ -21,6 +23,8 @@ def get_download_graph(cube: DataCube, drop_save_result: bool = False) -> dict:
save_results_nodes = [k for k, v in actual_graph.items() if v["process_id"] == "save_result"]
assert len(save_results_nodes) == 1
del actual_graph[save_results_nodes[0]]
if drop_load_collection:
actual_graph = {k: v for (k, v) in actual_graph.items() if v["process_id"] != "load_collection"}
return actual_graph


Expand Down
1 change: 1 addition & 0 deletions tests/rest/datacube/test_datacube.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def test_min_time(s2cube, api_version):

def _get_leaf_node(cube, force_flat=True) -> dict:
"""Get leaf node (node with result=True), supporting old and new style of graph building."""
# TODO: replace this with get_download_graph
if isinstance(cube, DataCube):
if force_flat:
flat_graph = cube.flat_graph()
Expand Down
Loading

0 comments on commit f741056

Please sign in to comment.