diff --git a/CHANGELOG.md b/CHANGELOG.md index fe65c0475..241f60fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Automatically use `load_url` when providing a URL as geometries to `DataCube.aggregate_spatial()`, `DataCube.mask_polygon()`, etc. ([#104](https://github.com/Open-EO/openeo-python-client/issues/104), [#457](https://github.com/Open-EO/openeo-python-client/issues/457)) +- Argument `spatial_extent` in `load_collection` supports type `shapely` and loading geometry from a local path. ### Changed diff --git a/openeo/rest/connection.py b/openeo/rest/connection.py index 79ee478f8..a1befaa79 100644 --- a/openeo/rest/connection.py +++ b/openeo/rest/connection.py @@ -1230,7 +1230,7 @@ def datacube_from_json(self, src: Union[str, Path], parameters: Optional[dict] = def load_collection( self, collection_id: Union[str, Parameter], - spatial_extent: Union[Dict[str, float], Parameter, None] = None, + spatial_extent: Union[Dict[str, float], Parameter, shapely.geometry.base.BaseGeometry, None] = None, temporal_extent: Union[Sequence[InputDate], Parameter, str, None] = None, bands: Union[None, List[str], Parameter] = None, properties: Union[ @@ -1243,7 +1243,12 @@ def load_collection( Load a DataCube by collection id. :param collection_id: image collection identifier - :param spatial_extent: limit data to specified bounding box or polygons + :param spatial_extent: limit data to specified bounding box or polygons. Can be provided in different ways: + - a shapely geometry + - a GeoJSON-style dictionary, + - a path (:py:class:`str` or :py:class:`~pathlib.Path`) to a local, client-side GeoJSON file, + which will be loaded automatically to get the geometries as GeoJSON construct. + - a :py:class:`~openeo.api.process.Parameter` instance. :param temporal_extent: limit data to specified temporal interval. Typically, just a two-item list or tuple containing start and end date. See :ref:`filtering-on-temporal-extent-section` for more details on temporal extent handling and shorthand notation. diff --git a/openeo/rest/datacube.py b/openeo/rest/datacube.py index 4a0b26a70..4629c37d5 100644 --- a/openeo/rest/datacube.py +++ b/openeo/rest/datacube.py @@ -158,7 +158,12 @@ def load_collection( :param collection_id: image collection identifier :param connection: The backend connection to use. Can be ``None`` to work without connection and collection metadata. - :param spatial_extent: limit data to specified bounding box or polygons + :param spatial_extent: limit data to specified bounding box or polygons. Can be provided in different ways: + - a shapely geometry + - a GeoJSON-style dictionary, + - a path (:py:class:`str` or :py:class:`~pathlib.Path`) to a local, client-side GeoJSON file, + which will be loaded automatically to get the geometries as GeoJSON construct. + - a :py:class:`~openeo.api.process.Parameter` instance. :param temporal_extent: limit data to specified temporal interval. Typically, just a two-item list or tuple containing start and end date. See :ref:`filtering-on-temporal-extent-section` for more details on temporal extent handling and shorthand notation. @@ -188,7 +193,7 @@ def load_collection( f" expected schema with type 'object' but got {spatial_extent.schema!r}." ) valid_geojson_types = [ - "Polygon", "MultiPolygon", "GeometryCollection", "FeatureCollection" + "Polygon", "MultiPolygon", "Feature", "FeatureCollection" ] if spatial_extent and not (isinstance(spatial_extent, dict) and spatial_extent.keys() & {"west", "east", "north", "south"}): spatial_extent = _get_geometry_argument(argument=spatial_extent,valid_geojson_types=valid_geojson_types,connection=connection) diff --git a/tests/rest/datacube/test_datacube.py b/tests/rest/datacube/test_datacube.py index 7e8745109..820f720a4 100644 --- a/tests/rest/datacube/test_datacube.py +++ b/tests/rest/datacube/test_datacube.py @@ -149,6 +149,20 @@ def test_load_collection_connectionless_shapely_spatial_extent(self): } } + @pytest.mark.parametrize("path_factory", [str, pathlib.Path]) + def test_load_collection_connectionless_local_path_spatial_extent(self, path_factory, test_data): + path = path_factory(test_data.get_path("geojson/polygon02.json")) + cube = DataCube.load_collection("T3", spatial_extent=path) + assert cube.flat_graph() == { + "loadcollection1": { + "arguments": {"id": "T3", "spatial_extent": + {"type": "Polygon", "coordinates": [[[3, 50], [4, 50], [4, 51], [3, 50]]]}, + "temporal_extent": None}, + "process_id": "load_collection", + "result": True, + } + } + def test_load_collection_connectionless_save_result(self): cube = DataCube.load_collection("T3").save_result(format="GTiff") assert cube.flat_graph() == {