Skip to content

Commit f741056

Browse files
committed
Issue #424 Add DataCube.apply_polygon
1 parent 40be725 commit f741056

File tree

5 files changed

+326
-104
lines changed

5 files changed

+326
-104
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
([#310](https://github.com/Open-EO/openeo-python-client/issues/310))
1515
- Add `collection_property()` helper to easily build collection metadata property filters for `Connection.load_collection()`
1616
([#331](https://github.com/Open-EO/openeo-python-client/pull/331))
17+
- Add `DataCube.apply_polygon()` (standardized version of experimental `chunk_polygon`) ([#424](https://github.com/Open-EO/openeo-python-client/issues/424))
1718

1819
### Changed
1920

openeo/rest/datacube.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,11 +1193,11 @@ def reduce_spatial(
11931193
metadata=self.metadata.reduce_spatial(),
11941194
)
11951195

1196-
# @openeo_process
1196+
@deprecated("Use :py:meth:`apply_polygon`.", version="0.26.0")
11971197
def chunk_polygon(
11981198
self,
11991199
chunks: Union[shapely.geometry.base.BaseGeometry, dict, str, pathlib.Path, Parameter, VectorCube],
1200-
process: Union[str, PGNode, typing.Callable],
1200+
process: Union[str, PGNode, typing.Callable, UDF],
12011201
mask_value: float = None,
12021202
context: Optional[dict] = None,
12031203
) -> DataCube:
@@ -1237,6 +1237,45 @@ def chunk_polygon(
12371237
),
12381238
)
12391239

1240+
@openeo_process
1241+
def apply_polygon(
1242+
self,
1243+
polygons: Union[shapely.geometry.base.BaseGeometry, dict, str, pathlib.Path, Parameter, VectorCube],
1244+
process: Union[str, PGNode, typing.Callable, UDF],
1245+
mask_value: Optional[float] = None,
1246+
context: Optional[dict] = None,
1247+
) -> DataCube:
1248+
"""
1249+
Apply a process to segments of the data cube that are defined by the given polygons.
1250+
For each polygon provided, all pixels for which the point at the pixel center intersects
1251+
with the polygon (as defined in the Simple Features standard by the OGC) are collected into sub data cubes.
1252+
If a pixel is part of multiple of the provided polygons (e.g., when the polygons overlap),
1253+
the GeometriesOverlap exception is thrown.
1254+
Each sub data cube is passed individually to the given process.
1255+
1256+
.. warning:: experimental process: not generally supported, API subject to change.
1257+
1258+
:param polygons: Polygons, provided as a shapely geometry, a GeoJSON-style dictionary,
1259+
a public GeoJSON URL, or a path (that is valid for the back-end) to a GeoJSON file.
1260+
:param process: "child callback" function, see :ref:`callbackfunctions`
1261+
:param mask_value: The value used for pixels outside the polygon.
1262+
:param context: Additional data to be passed to the process.
1263+
"""
1264+
process = build_child_callback(process, parent_parameters=["data"], connection=self.connection)
1265+
valid_geojson_types = ["Polygon", "MultiPolygon", "Feature", "FeatureCollection"]
1266+
polygons = self._get_geometry_argument(polygons, valid_geojson_types=valid_geojson_types)
1267+
mask_value = float(mask_value) if mask_value is not None else None
1268+
return self.process(
1269+
process_id="apply_polygon",
1270+
data=THIS,
1271+
polygons=polygons,
1272+
process=process,
1273+
arguments=dict_no_none(
1274+
mask_value=mask_value,
1275+
context=context,
1276+
),
1277+
)
1278+
12401279
def reduce_bands(self, reducer: Union[str, PGNode, typing.Callable, UDF]) -> DataCube:
12411280
"""
12421281
Shortcut for :py:meth:`reduce_dimension` along the band dimension

tests/rest/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
from openeo.rest.datacube import DataCube
66

77

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

2630

tests/rest/datacube/test_datacube.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def test_min_time(s2cube, api_version):
6565

6666
def _get_leaf_node(cube, force_flat=True) -> dict:
6767
"""Get leaf node (node with result=True), supporting old and new style of graph building."""
68+
# TODO: replace this with get_download_graph
6869
if isinstance(cube, DataCube):
6970
if force_flat:
7071
flat_graph = cube.flat_graph()

0 commit comments

Comments
 (0)