diff --git a/CHANGELOG.md b/CHANGELOG.md index 751979036..31b3bcaa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add `DataCube.filter_labels()` + ### Changed ### Removed diff --git a/openeo/rest/datacube.py b/openeo/rest/datacube.py index 2e3b70d2b..656d9dd45 100644 --- a/openeo/rest/datacube.py +++ b/openeo/rest/datacube.py @@ -15,7 +15,7 @@ import typing import warnings from builtins import staticmethod -from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union +from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union, Callable import numpy as np import shapely.geometry @@ -475,6 +475,28 @@ def filter_bands(self, bands: Union[List[Union[str, int]], str]) -> DataCube: ) return cube + @openeo_process + def filter_labels( + self, condition: Union[PGNode, Callable], dimension: str, context: Optional[dict] = None + ) -> DataCube: + """ + Filters the dimension labels in the data cube for the given dimension. + Only the dimension labels that match the specified condition are preserved, + all other labels with their corresponding data get removed. + + :param condition: the "child callback" which will be given a single label value (number or string) + and returns a boolean expressing if the label should be preserved. + Also see :ref:`callbackfunctions`. + :param dimension: The name of the dimension to filter on. + + .. versionadded:: 0.27.0 + """ + condition = build_child_callback(condition, parent_parameters=["value"]) + return self.process( + process_id="filter_labels", + arguments=dict_no_none(data=THIS, condition=condition, dimension=dimension, context=context), + ) + band_filter = legacy_alias(filter_bands, "band_filter", since="0.1.0") def band(self, band: Union[str, int]) -> DataCube: diff --git a/openeo/rest/vectorcube.py b/openeo/rest/vectorcube.py index 6f4e7b0f5..8806d97bd 100644 --- a/openeo/rest/vectorcube.py +++ b/openeo/rest/vectorcube.py @@ -388,9 +388,17 @@ def filter_labels( self, condition: Union[PGNode, Callable], dimension: str, context: Optional[dict] = None ) -> VectorCube: """ + Filters the dimension labels in the data cube for the given dimension. + Only the dimension labels that match the specified condition are preserved, + all other labels with their corresponding data get removed. + + :param condition: the "child callback" which will be given a single label value (number or string) + and returns a boolean expressing if the label should be preserved. + Also see :ref:`callbackfunctions`. + :param dimension: The name of the dimension to filter on. + .. versionadded:: 0.22.0 """ - # TODO #459 docs condition = build_child_callback(condition, parent_parameters=["value"]) return self.process( process_id="filter_labels", diff --git a/tests/rest/datacube/test_datacube100.py b/tests/rest/datacube/test_datacube100.py index ffb6fd1c8..24ad90173 100644 --- a/tests/rest/datacube/test_datacube100.py +++ b/tests/rest/datacube/test_datacube100.py @@ -2223,6 +2223,29 @@ def test_filter_spatial_callback(con100): } +def test_filter_labels_callback(con100): + cube = con100.load_collection("S2") + cube = cube.filter_labels(condition=lambda t: t.text_contains("-02-2"), dimension="t") + assert get_download_graph(cube, drop_save_result=True, drop_load_collection=True) == { + "filterlabels1": { + "process_id": "filter_labels", + "arguments": { + "data": {"from_node": "loadcollection1"}, + "condition": { + "process_graph": { + "textcontains1": { + "process_id": "text_contains", + "arguments": {"data": {"from_parameter": "value"}, "pattern": "-02-2"}, + "result": True, + } + } + }, + "dimension": "t", + }, + }, + } + + def test_custom_process_kwargs_datacube(con100: Connection): img = con100.load_collection("S2") res = img.process(process_id="foo", data=img, bar=123)