Skip to content

Commit f095480

Browse files
committed
Issue #197/#211/#213 use load_geojson in TestVectorCubeRunUDF
1 parent 1726a78 commit f095480

File tree

3 files changed

+104
-118
lines changed

3 files changed

+104
-118
lines changed

openeo_driver/ProcessGraphDeserializer.py

+1
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,7 @@ def load_geojson(args: ProcessArgs, env: EvalEnv) -> DriverVectorCube:
15981598
allowed_types=["Point", "MultiPoint", "Polygon", "MultiPolygon", "Feature", "FeatureCollection"]
15991599
),
16001600
)
1601+
# TODO: better default value for `properties`? https://github.com/Open-EO/openeo-processes/issues/448
16011602
properties = args.get_optional("properties", default=[], expected_type=(list, tuple))
16021603
vector_cube = env.backend_implementation.vector_cube_cls.from_geojson(data, columns_for_cube=properties)
16031604
return vector_cube

openeo_driver/datacube.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from pyproj import CRS
2222

2323
from openeo_driver.datastructs import ResolutionMergeArgs, SarBackscatterArgs, StacAsset
24-
from openeo_driver.errors import FeatureUnsupportedException, InternalException
24+
from openeo_driver.errors import FeatureUnsupportedException, InternalException, ProcessGraphInvalidException
2525
from openeo_driver.util.geometry import GeometryBufferer, validate_geojson_coordinates
2626
from openeo_driver.util.ioformats import IOFORMATS
2727
from openeo_driver.util.pgparsing import SingleRunUDFProcessGraph
@@ -638,6 +638,10 @@ def apply_dimension(
638638

639639
if single_run_udf:
640640
# Process with single "run_udf" node
641+
if single_run_udf.data != {"from_parameter": "data"}:
642+
raise ProcessGraphInvalidException(
643+
message="Vector cube `apply_dimension` process does not reference `data` parameter."
644+
)
641645
if (
642646
dimension == self.DIM_GEOMETRIES
643647
or (dimension in {self.DIM_BANDS, self.DIM_PROPERTIES}.intersection(self.get_dimension_names()))
@@ -651,7 +655,7 @@ def apply_dimension(
651655
feature_collection = openeo.udf.FeatureCollection(id="_", data=gdf)
652656
# TODO: dedicated UDF signature to indicate to work on vector cube through a feature collection based API
653657
udf_data = openeo.udf.UdfData(
654-
proj={"EPSG": self._geometries.crs.to_epsg()},
658+
proj={"EPSG": self._geometries.crs.to_epsg()} if self._geometries.crs else None,
655659
feature_collection_list=[feature_collection],
656660
user_context=context,
657661
)

tests/test_views_execute.py

+97-116
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,22 @@ class TestVectorCubeRunUDF:
36283628
- https://github.com/Open-EO/openeo-geopyspark-driver/issues/437
36293629
"""
36303630

3631+
def _build_run_udf_callback(self, udf_code: str) -> dict:
3632+
udf_code = textwrap.dedent(udf_code)
3633+
return {
3634+
"process_graph": {
3635+
"runudf1": {
3636+
"process_id": "run_udf",
3637+
"arguments": {
3638+
"data": {"from_parameter": "data"},
3639+
"udf": udf_code,
3640+
"runtime": "Python",
3641+
},
3642+
"result": True,
3643+
}
3644+
},
3645+
}
3646+
36313647
@pytest.mark.parametrize(
36323648
"dimension",
36333649
[
@@ -3636,40 +3652,32 @@ class TestVectorCubeRunUDF:
36363652
],
36373653
)
36383654
def test_apply_dimension_run_udf_change_geometry(self, api100, dimension):
3639-
udf_code = """
3640-
from openeo.udf import UdfData, FeatureCollection
3641-
def process_geometries(udf_data: UdfData) -> UdfData:
3642-
[feature_collection] = udf_data.get_feature_collection_list()
3643-
gdf = feature_collection.data
3644-
gdf["geometry"] = gdf["geometry"].buffer(distance=1, resolution=2)
3645-
udf_data.set_feature_collection_list([
3646-
FeatureCollection(id="_", data=gdf),
3647-
])
3648-
"""
3649-
udf_code = textwrap.dedent(udf_code)
3655+
"""VectorCube + apply_dimension + UDF (changing geometry)"""
36503656
process_graph = {
3651-
"get_vector_data": {
3652-
"process_id": "load_uploaded_files",
3653-
"arguments": {"paths": [str(get_path("geojson/FeatureCollection02.json"))], "format": "GeoJSON"},
3657+
"load": {
3658+
"process_id": "load_geojson",
3659+
"arguments": {
3660+
"data": load_json("geojson/FeatureCollection02.json"),
3661+
"properties": ["pop"],
3662+
},
36543663
},
36553664
"apply_dimension": {
36563665
"process_id": "apply_dimension",
36573666
"arguments": {
3658-
"data": {"from_node": "get_vector_data"},
3667+
"data": {"from_node": "load"},
36593668
"dimension": dimension,
3660-
"process": {
3661-
"process_graph": {
3662-
"runudf1": {
3663-
"process_id": "run_udf",
3664-
"arguments": {
3665-
"data": {"from_node": "get_vector_data"},
3666-
"udf": udf_code,
3667-
"runtime": "Python",
3668-
},
3669-
"result": True,
3670-
}
3671-
},
3672-
},
3669+
"process": self._build_run_udf_callback(
3670+
"""
3671+
from openeo.udf import UdfData, FeatureCollection
3672+
def process_geometries(udf_data: UdfData) -> UdfData:
3673+
[feature_collection] = udf_data.get_feature_collection_list()
3674+
gdf = feature_collection.data
3675+
gdf["geometry"] = gdf["geometry"].buffer(distance=1, resolution=2)
3676+
udf_data.set_feature_collection_list([
3677+
FeatureCollection(id="_", data=gdf),
3678+
])
3679+
"""
3680+
),
36733681
},
36743682
"result": True,
36753683
},
@@ -3708,42 +3716,33 @@ def test_apply_dimension_run_udf_filter_on_geometries(self, api100, dimension):
37083716
Test to use `apply_dimension(dimension="...", process=UDF)` to filter out certain
37093717
entries from geometries dimension based on geometry (e.g. intersection with another geometry)
37103718
"""
3711-
udf_code = """
3712-
from openeo.udf import UdfData, FeatureCollection
3713-
import shapely.geometry
3714-
def process_geometries(udf_data: UdfData) -> UdfData:
3715-
[feature_collection] = udf_data.get_feature_collection_list()
3716-
gdf = feature_collection.data
3717-
to_intersect = shapely.geometry.box(4, 3, 8, 4)
3718-
gdf = gdf[gdf["geometry"].intersects(to_intersect)]
3719-
udf_data.set_feature_collection_list([
3720-
FeatureCollection(id="_", data=gdf),
3721-
])
3722-
"""
3723-
udf_code = textwrap.dedent(udf_code)
37243719
process_graph = {
3725-
"get_vector_data": {
3726-
"process_id": "load_uploaded_files",
3727-
"arguments": {"paths": [str(get_path("geojson/FeatureCollection10.json"))], "format": "GeoJSON"},
3720+
"load": {
3721+
"process_id": "load_geojson",
3722+
"arguments": {
3723+
"data": load_json("geojson/FeatureCollection10.json"),
3724+
"properties": ["pop"],
3725+
},
37283726
},
37293727
"apply_dimension": {
37303728
"process_id": "apply_dimension",
37313729
"arguments": {
3732-
"data": {"from_node": "get_vector_data"},
3730+
"data": {"from_node": "load"},
37333731
"dimension": dimension,
3734-
"process": {
3735-
"process_graph": {
3736-
"runudf1": {
3737-
"process_id": "run_udf",
3738-
"arguments": {
3739-
"data": {"from_node": "get_vector_data"},
3740-
"udf": udf_code,
3741-
"runtime": "Python",
3742-
},
3743-
"result": True,
3744-
}
3745-
},
3746-
},
3732+
"process": self._build_run_udf_callback(
3733+
"""
3734+
from openeo.udf import UdfData, FeatureCollection
3735+
import shapely.geometry
3736+
def process_geometries(udf_data: UdfData) -> UdfData:
3737+
[feature_collection] = udf_data.get_feature_collection_list()
3738+
gdf = feature_collection.data
3739+
to_intersect = shapely.geometry.box(4, 3, 8, 4)
3740+
gdf = gdf[gdf["geometry"].intersects(to_intersect)]
3741+
udf_data.set_feature_collection_list([
3742+
FeatureCollection(id="_", data=gdf),
3743+
])
3744+
"""
3745+
),
37473746
},
37483747
"result": True,
37493748
},
@@ -3787,41 +3786,32 @@ def test_apply_dimension_run_udf_filter_on_properties(self, api100, dimension):
37873786
as apply_dimension only allows changing the cardinality of the provided dimension ("properties" in this case),
37883787
not any other dimension (like "geometries" in this case).
37893788
"""
3790-
udf_code = """
3791-
from openeo.udf import UdfData, FeatureCollection
3792-
import shapely.geometry
3793-
def process_geometries(udf_data: UdfData) -> UdfData:
3794-
[feature_collection] = udf_data.get_feature_collection_list()
3795-
gdf = feature_collection.data
3796-
gdf = gdf[gdf["pop"] > 500]
3797-
udf_data.set_feature_collection_list([
3798-
FeatureCollection(id="_", data=gdf),
3799-
])
3800-
"""
3801-
udf_code = textwrap.dedent(udf_code)
38023789
process_graph = {
3803-
"get_vector_data": {
3804-
"process_id": "load_uploaded_files",
3805-
"arguments": {"paths": [str(get_path("geojson/FeatureCollection10.json"))], "format": "GeoJSON"},
3790+
"load": {
3791+
"process_id": "load_geojson",
3792+
"arguments": {
3793+
"data": load_json("geojson/FeatureCollection10.json"),
3794+
"properties": ["pop"],
3795+
},
38063796
},
38073797
"apply_dimension": {
38083798
"process_id": "apply_dimension",
38093799
"arguments": {
3810-
"data": {"from_node": "get_vector_data"},
3800+
"data": {"from_node": "load"},
38113801
"dimension": dimension,
3812-
"process": {
3813-
"process_graph": {
3814-
"runudf1": {
3815-
"process_id": "run_udf",
3816-
"arguments": {
3817-
"data": {"from_node": "get_vector_data"},
3818-
"udf": udf_code,
3819-
"runtime": "Python",
3820-
},
3821-
"result": True,
3822-
}
3823-
},
3824-
},
3802+
"process": self._build_run_udf_callback(
3803+
"""
3804+
from openeo.udf import UdfData, FeatureCollection
3805+
import shapely.geometry
3806+
def process_geometries(udf_data: UdfData) -> UdfData:
3807+
[feature_collection] = udf_data.get_feature_collection_list()
3808+
gdf = feature_collection.data
3809+
gdf = gdf[gdf["pop"] > 500]
3810+
udf_data.set_feature_collection_list([
3811+
FeatureCollection(id="_", data=gdf),
3812+
])
3813+
"""
3814+
),
38253815
},
38263816
"result": True,
38273817
},
@@ -3859,41 +3849,32 @@ def test_apply_dimension_run_udf_add_properties(self, api100, dimension):
38593849
"""
38603850
Test to use `apply_dimension(dimension="...", process=UDF)` to add properties
38613851
"""
3862-
udf_code = """
3863-
from openeo.udf import UdfData, FeatureCollection
3864-
import shapely.geometry
3865-
def process_geometries(udf_data: UdfData) -> UdfData:
3866-
[feature_collection] = udf_data.get_feature_collection_list()
3867-
gdf = feature_collection.data
3868-
gdf["poppop"] = gdf["pop"] ** 2
3869-
udf_data.set_feature_collection_list([
3870-
FeatureCollection(id="_", data=gdf),
3871-
])
3872-
"""
3873-
udf_code = textwrap.dedent(udf_code)
38743852
process_graph = {
3875-
"get_vector_data": {
3876-
"process_id": "load_uploaded_files",
3877-
"arguments": {"paths": [str(get_path("geojson/FeatureCollection02.json"))], "format": "GeoJSON"},
3853+
"load": {
3854+
"process_id": "load_geojson",
3855+
"arguments": {
3856+
"data": load_json("geojson/FeatureCollection02.json"),
3857+
"properties": ["pop"],
3858+
},
38783859
},
38793860
"apply_dimension": {
38803861
"process_id": "apply_dimension",
38813862
"arguments": {
3882-
"data": {"from_node": "get_vector_data"},
3863+
"data": {"from_node": "load"},
38833864
"dimension": dimension,
3884-
"process": {
3885-
"process_graph": {
3886-
"runudf1": {
3887-
"process_id": "run_udf",
3888-
"arguments": {
3889-
"data": {"from_node": "get_vector_data"},
3890-
"udf": udf_code,
3891-
"runtime": "Python",
3892-
},
3893-
"result": True,
3894-
}
3895-
},
3896-
},
3865+
"process": self._build_run_udf_callback(
3866+
"""
3867+
from openeo.udf import UdfData, FeatureCollection
3868+
import shapely.geometry
3869+
def process_geometries(udf_data: UdfData) -> UdfData:
3870+
[feature_collection] = udf_data.get_feature_collection_list()
3871+
gdf = feature_collection.data
3872+
gdf["poppop"] = gdf["pop"] ** 2
3873+
udf_data.set_feature_collection_list([
3874+
FeatureCollection(id="_", data=gdf),
3875+
])
3876+
"""
3877+
),
38973878
},
38983879
"result": True,
38993880
},

0 commit comments

Comments
 (0)