@@ -3628,7 +3628,14 @@ class TestVectorCubeRunUDF:
3628
3628
- https://github.com/Open-EO/openeo-geopyspark-driver/issues/437
3629
3629
"""
3630
3630
3631
- def test_apply_dimension_run_udf_change_geometry (self , api100 ):
3631
+ @pytest .mark .parametrize (
3632
+ "dimension" ,
3633
+ [
3634
+ "properties" ,
3635
+ "geometries" ,
3636
+ ],
3637
+ )
3638
+ def test_apply_dimension_run_udf_change_geometry (self , api100 , dimension ):
3632
3639
udf_code = """
3633
3640
from openeo.udf import UdfData, FeatureCollection
3634
3641
def process_geometries(udf_data: UdfData) -> UdfData:
@@ -3649,7 +3656,7 @@ def process_geometries(udf_data: UdfData) -> UdfData:
3649
3656
"process_id" : "apply_dimension" ,
3650
3657
"arguments" : {
3651
3658
"data" : {"from_node" : "get_vector_data" },
3652
- "dimension" : "properties" ,
3659
+ "dimension" : dimension ,
3653
3660
"process" : {
3654
3661
"process_graph" : {
3655
3662
"runudf1" : {
@@ -3689,19 +3696,17 @@ def process_geometries(udf_data: UdfData) -> UdfData:
3689
3696
@pytest .mark .parametrize (
3690
3697
"dimension" ,
3691
3698
[
3699
+ # TODO: this "dimension="properties" use case does not strictly follow the openEO API spec
3700
+ # `apply_dimension` only allows changing the cardinality of the provided dimension ("properties"),
3701
+ # not any other dimension ("geometries" here).
3692
3702
"properties" ,
3693
3703
"geometries" ,
3694
3704
],
3695
3705
)
3696
- def test_apply_dimension_run_udf_filter_geometries_dimension_properties (self , api100 , dimension ):
3706
+ def test_apply_dimension_run_udf_filter_on_geometries (self , api100 , dimension ):
3697
3707
"""
3698
3708
Test to use `apply_dimension(dimension="...", process=UDF)` to filter out certain
3699
- entries from geometries dimension.
3700
-
3701
- Note in case of dimension="properties":
3702
- strictly speaking, this approach draws outside the lines of the openEO API spec
3703
- as apply_dimension only allows changing the cardinality of the provided dimension ("properties" in this case),
3704
- not any other dimension (like "geometries" in this case).
3709
+ entries from geometries dimension based on geometry (e.g. intersection with another geometry)
3705
3710
"""
3706
3711
udf_code = """
3707
3712
from openeo.udf import UdfData, FeatureCollection
@@ -3761,3 +3766,153 @@ def process_geometries(udf_data: UdfData) -> UdfData:
3761
3766
],
3762
3767
}
3763
3768
)
3769
+
3770
+ @pytest .mark .parametrize (
3771
+ "dimension" ,
3772
+ [
3773
+ # TODO: this "dimension="properties" use case does not strictly follow the openEO API spec
3774
+ # `apply_dimension` only allows changing the cardinality of the provided dimension ("properties"),
3775
+ # not any other dimension ("geometries" here).
3776
+ "properties" ,
3777
+ "geometries" ,
3778
+ ],
3779
+ )
3780
+ def test_apply_dimension_run_udf_filter_on_properties (self , api100 , dimension ):
3781
+ """
3782
+ Test to use `apply_dimension(dimension="...", process=UDF)` to filter out certain
3783
+ entries from geometries dimension, based on feature properties
3784
+
3785
+ Note in case of dimension="properties":
3786
+ strictly speaking, this approach draws outside the lines of the openEO API spec
3787
+ as apply_dimension only allows changing the cardinality of the provided dimension ("properties" in this case),
3788
+ not any other dimension (like "geometries" in this case).
3789
+ """
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 )
3802
+ process_graph = {
3803
+ "get_vector_data" : {
3804
+ "process_id" : "load_uploaded_files" ,
3805
+ "arguments" : {"paths" : [str (get_path ("geojson/FeatureCollection10.json" ))], "format" : "GeoJSON" },
3806
+ },
3807
+ "apply_dimension" : {
3808
+ "process_id" : "apply_dimension" ,
3809
+ "arguments" : {
3810
+ "data" : {"from_node" : "get_vector_data" },
3811
+ "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
+ },
3825
+ },
3826
+ "result" : True ,
3827
+ },
3828
+ }
3829
+ resp = api100 .check_result (process_graph )
3830
+ assert resp .json == DictSubSet (
3831
+ {
3832
+ "type" : "FeatureCollection" ,
3833
+ "features" : [
3834
+ {
3835
+ "type" : "Feature" ,
3836
+ "geometry" : ApproxGeoJSONByBounds (6.0 , 2.0 , 12.0 , 6.0 , types = ["Polygon" ], abs = 0.1 ),
3837
+ "properties" : {"id" : "third" , "pop" : 789 },
3838
+ },
3839
+ {
3840
+ "type" : "Feature" ,
3841
+ "geometry" : ApproxGeoJSONByBounds (- 2.0 , 7.0 , 5.0 , 14.0 , types = ["Polygon" ], abs = 0.1 ),
3842
+ "properties" : {"id" : "fourth" , "pop" : 101112 },
3843
+ },
3844
+ ],
3845
+ }
3846
+ )
3847
+
3848
+ @pytest .mark .parametrize (
3849
+ "dimension" ,
3850
+ [
3851
+ "properties" ,
3852
+ # TODO: this "dimension="geometries" use case does not strictly follow the openEO API spec
3853
+ # `apply_dimension` only allows changing the cardinality of the provided dimension ("geometries"),
3854
+ # not any other dimension ("properties" here).
3855
+ "geometries" ,
3856
+ ],
3857
+ )
3858
+ def test_apply_dimension_run_udf_add_properties (self , api100 , dimension ):
3859
+ """
3860
+ Test to use `apply_dimension(dimension="...", process=UDF)` to add properties
3861
+ """
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 )
3874
+ process_graph = {
3875
+ "get_vector_data" : {
3876
+ "process_id" : "load_uploaded_files" ,
3877
+ "arguments" : {"paths" : [str (get_path ("geojson/FeatureCollection02.json" ))], "format" : "GeoJSON" },
3878
+ },
3879
+ "apply_dimension" : {
3880
+ "process_id" : "apply_dimension" ,
3881
+ "arguments" : {
3882
+ "data" : {"from_node" : "get_vector_data" },
3883
+ "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
+ },
3897
+ },
3898
+ "result" : True ,
3899
+ },
3900
+ }
3901
+ resp = api100 .check_result (process_graph )
3902
+ assert resp .json == DictSubSet (
3903
+ {
3904
+ "type" : "FeatureCollection" ,
3905
+ "features" : [
3906
+ {
3907
+ "type" : "Feature" ,
3908
+ "geometry" : ApproxGeoJSONByBounds (1.0 , 1.0 , 3.0 , 3.0 , types = ["Polygon" ], abs = 0.1 ),
3909
+ "properties" : {"id" : "first" , "pop" : 1234 , "poppop" : 1234 * 1234 },
3910
+ },
3911
+ {
3912
+ "type" : "Feature" ,
3913
+ "geometry" : ApproxGeoJSONByBounds (3.0 , 2.0 , 5.0 , 4.0 , types = ["Polygon" ], abs = 0.1 ),
3914
+ "properties" : {"id" : "second" , "pop" : 5678 , "poppop" : 5678 * 5678 },
3915
+ },
3916
+ ],
3917
+ }
3918
+ )
0 commit comments