Skip to content

Commit

Permalink
apply_polygon: rename polygons parameter to geometries
Browse files Browse the repository at this point in the history
But still support legacy `polygons` for now

refs: Open-EO/openeo-processes#511, #288
  • Loading branch information
soxofaan committed Jul 17, 2024
1 parent 992f7e4 commit 15b72a7
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ and start a new "In Progress" section above it.

## In progress


## 0.107.2

- Fix default level of `inspect` process (defaults to `info`) ([#424](https://github.com/Open-EO/openeo-geopyspark-driver/issues/424))
- `apply_polygon`: add support for `geometries` argument (in addition to legacy, but still supported `polygons`) ([Open-EO/openeo-processes#511](https://github.com/Open-EO/openeo-processes/issues/511))

## 0.107.1

Expand Down
29 changes: 17 additions & 12 deletions openeo_driver/ProcessGraphDeserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,32 +850,37 @@ def chunk_polygon(args: ProcessArgs, env: EvalEnv) -> DriverDataCube:
def apply_polygon(args: ProcessArgs, env: EvalEnv) -> DriverDataCube:
data_cube = args.get_required("data", expected_type=DriverDataCube)
process = args.get_deep("process", "process_graph", expected_type=dict)
polygons = args.get_required("polygons")
if "polygons" in args and "geometries" not in args:
# TODO remove this deprecated "polygons" parameter handling when not used anymore
_log.warning("In process 'apply_polygon': parameter 'polygons' is deprecated, use 'geometries' instead.")
geometries = args.get_required("polygons")
else:
geometries = args.get_required("geometries")
mask_value = args.get_optional("mask_value", expected_type=(int, float), default=None)
context = args.get_optional("context", default=None)

# TODO #114 EP-3981 normalize first to vector cube and simplify logic
# TODO #288: this logic (copied from original chunk_polygon implementation) coerces the input polygons
# to a single MultiPolygon of pure (non-multi) polygons, which is conceptually wrong.
# Instead it should normalize to a feature collection or vector cube.
if isinstance(polygons, DelayedVector):
polygons = list(polygons.geometries)
for p in polygons:
if isinstance(geometries, DelayedVector):
geometries = list(geometries.geometries)
for p in geometries:
if not isinstance(p, shapely.geometry.Polygon):
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):
polygon = MultiPolygon(geometries)
elif isinstance(geometries, 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)
polygon = geometries.to_multipolygon()
elif isinstance(geometries, shapely.geometry.base.BaseGeometry):
polygon = MultiPolygon(geometries)
elif isinstance(geometries, dict):
polygon = geojson_to_multipolygon(geometries)
if isinstance(polygon, shapely.geometry.Polygon):
polygon = MultiPolygon([polygon])
else:
reason = f"unsupported type: {type(polygons).__name__}"
reason = f"unsupported type: {type(geometries).__name__}"
raise ProcessParameterInvalidException(parameter="polygons", process="apply_polygon", reason=reason)

if polygon.area == 0:
Expand Down
2 changes: 1 addition & 1 deletion openeo_driver/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.107.1a1"
__version__ = "0.107.2a1"
1 change: 1 addition & 0 deletions openeo_driver/dry_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def _normalize_geometry(self, geometries) -> Tuple[Union[DriverVectorCube, Delay
elif isinstance(geometries, shapely.geometry.base.BaseGeometry):
_log.warning(
"_normalize_geometry: TODO are we still reaching this code?",
# TODO yes we are, apparently due to #288
stack_info=True,
)
# TODO: buffer distance of 10m assumes certain resolution (e.g. sentinel2 pixels)
Expand Down
2 changes: 1 addition & 1 deletion tests/data/pg/1.0/apply_polygon.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"process_id": "apply_polygon",
"arguments": {
"data": {"from_node": "collection"},
"polygons": {
"geometries": {
"type": "FeatureCollection",
"features": [
{
Expand Down
26 changes: 22 additions & 4 deletions tests/test_views_execute.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
import shutil

import dataclasses
import json
import math
Expand Down Expand Up @@ -3737,13 +3737,31 @@ def test_chunk_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(api):
def test_apply_polygon_legacy(api, caplog):
caplog.set_level(logging.WARNING)
api.check_result("apply_polygon.json", preprocess=lambda s: s.replace("geometries", "polygons"))
params = dummy_backend.last_load_collection_call("S2_FOOBAR")
assert params["spatial_extent"] == {"west": 1.0, "south": 5.0, "east": 12.0, "north": 16.0, "crs": "EPSG:4326"}
assert "In process 'apply_polygon': parameter 'polygons' is deprecated, use 'geometries' instead." in caplog.text


def test_apply_polygon(api, caplog):
caplog.set_level(logging.WARNING)
api.check_result("apply_polygon.json")
params = dummy_backend.last_load_collection_call("S2_FOOBAR")
assert params["spatial_extent"] == {"west": 1.0, "south": 5.0, "east": 12.0, "north": 16.0, "crs": "EPSG:4326"}
# TODO due to #288 we can not simply assert absence of any warnings/errors
# assert caplog.text == ""
assert "deprecated" not in caplog.text


def test_apply_polygon_no_geometries(api):
res = api.result("apply_polygon.json", preprocess=lambda s: s.replace("geometries", "heometriez"))
res.assert_error(400, "ProcessParameterRequired", "Process 'apply_polygon' parameter 'geometries' is required")


def test_apply_polygon_with_vector_cube(api, tmp_path):
@pytest.mark.parametrize("geometries_argument", ["polygons", "geometries"])
def test_apply_polygon_with_vector_cube(api, tmp_path, geometries_argument):
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"
Expand All @@ -3761,7 +3779,7 @@ def test_apply_polygon_with_vector_cube(api, tmp_path):
"process_id": "apply_polygon",
"arguments": {
"data": {"from_node": "load_raster"},
"polygons": {"from_node": "load_vector"},
geometries_argument: {"from_node": "load_vector"},
"process": {
"process_graph": {
"constant": {
Expand Down

0 comments on commit 15b72a7

Please sign in to comment.