From c95d1f16dad2b5440c4a7b5c3a99ed289428b317 Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Fri, 7 Jun 2024 20:40:01 +0200 Subject: [PATCH] Issue #287 Support DriverVectorCube in apply_polygon other refs: #288, d180c2410 --- CHANGELOG.md | 4 +++ openeo_driver/ProcessGraphDeserializer.py | 10 +++--- openeo_driver/_version.py | 2 +- tests/data/pg/1.0/apply_polygon.json | 1 - tests/test_views_execute.py | 43 +++++++++++++++++++++++ 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b13474bd..55eabd0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ and start a new "In Progress" section above it. ## In progress +## 0.102.2 + +- Support `DriverVectorCube` in `apply_polygon` ([#287](https://github.com/Open-EO/openeo-python-driver/issues/287)) + ## 0.102.0 - Emit "in" operator ([Open-EO/openeo-opensearch-client#32](https://github.com/Open-EO/openeo-opensearch-client/issues/32), diff --git a/openeo_driver/ProcessGraphDeserializer.py b/openeo_driver/ProcessGraphDeserializer.py index 20507cea..7aaf8193 100644 --- a/openeo_driver/ProcessGraphDeserializer.py +++ b/openeo_driver/ProcessGraphDeserializer.py @@ -866,19 +866,19 @@ def apply_polygon(args: ProcessArgs, env: EvalEnv) -> DriverDataCube: reason = "{m!s} is not a polygon.".format(m=p) raise ProcessParameterInvalidException(parameter="polygons", process="apply_polygon", reason=reason) polygon = MultiPolygon(polygons) + elif isinstance(polygons, DriverVectorCube): + # TODO #288: I know it's wrong to coerce to MultiPolygon here, but we stick to this ill-defined API for now. + polygon = polygons.to_multipolygon() elif isinstance(polygons, shapely.geometry.base.BaseGeometry): polygon = MultiPolygon(polygons) elif isinstance(polygons, dict): polygon = geojson_to_multipolygon(polygons) if isinstance(polygon, shapely.geometry.Polygon): polygon = MultiPolygon([polygon]) - elif isinstance(polygons, str): - # Delayed vector is not supported yet. - reason = "Polygon of type string is not yet supported." - raise ProcessParameterInvalidException(parameter="polygons", process="apply_polygon", reason=reason) else: - reason = "Polygon type is not supported." + reason = f"unsupported type: {type(polygons).__name__}" raise ProcessParameterInvalidException(parameter="polygons", process="apply_polygon", reason=reason) + if polygon.area == 0: reason = "Polygon {m!s} has an area of {a!r}".format(m=polygon, a=polygon.area) raise ProcessParameterInvalidException(parameter="polygons", process="apply_polygon", reason=reason) diff --git a/openeo_driver/_version.py b/openeo_driver/_version.py index e67d92ac..d95af414 100644 --- a/openeo_driver/_version.py +++ b/openeo_driver/_version.py @@ -1 +1 @@ -__version__ = "0.102.1a1" +__version__ = "0.102.2a1" diff --git a/tests/data/pg/1.0/apply_polygon.json b/tests/data/pg/1.0/apply_polygon.json index c98324cd..67d69ffe 100644 --- a/tests/data/pg/1.0/apply_polygon.json +++ b/tests/data/pg/1.0/apply_polygon.json @@ -30,7 +30,6 @@ } ] }, - "mask_value": -5, "process": { "process_graph": { "runudf1": { diff --git a/tests/test_views_execute.py b/tests/test_views_execute.py index 42b2e7de..ff3c41c9 100644 --- a/tests/test_views_execute.py +++ b/tests/test_views_execute.py @@ -1,3 +1,5 @@ +import shutil + import dataclasses import json import math @@ -3691,6 +3693,47 @@ def test_apply_polygon(api): assert params["spatial_extent"] == {"west": 1.0, "south": 5.0, "east": 12.0, "north": 16.0, "crs": "EPSG:4326"} +def test_apply_polygon_with_vector_cube(api, tmp_path): + shutil.copy(get_path("geojson/FeatureCollection01.json"), tmp_path / "geometry.json") + with ephemeral_fileserver(tmp_path) as fileserver_root: + url = f"{fileserver_root}/geometry.json" + + pg = { + "load_raster": { + "process_id": "load_collection", + "arguments": {"id": "S2_FOOBAR"}, + }, + "load_vector": { + "process_id": "load_url", + "arguments": {"url": str(url), "format": "GeoJSON"}, + }, + "apply_polygon": { + "process_id": "apply_polygon", + "arguments": { + "data": {"from_node": "load_raster"}, + "polygons": {"from_node": "load_vector"}, + "process": { + "process_graph": { + "constant": { + "process_id": "constant", + "arguments": {"x": {"from_parameter": "x"}}, + "result": True, + } + } + }, + }, + "result": True, + }, + } + _ = api.check_result(pg) + dummy = dummy_backend.get_collection("S2_FOOBAR") + assert dummy.apply_polygon.call_count == 1 + polygons = dummy.apply_polygon.call_args.kwargs["polygons"] + # TODO #288 instead of MultPolygon, this should actually be a vector cube, feature collection or something equivalent + assert isinstance(polygons, shapely.geometry.MultiPolygon) + assert polygons.bounds == (4.45, 51.1, 4.52, 51.2) + + def test_fit_class_random_forest(api): res = api.check_result("fit_class_random_forest.json")