Skip to content

Commit

Permalink
Issue #705 initial support for "geometry" dimension in CubeMetadata
Browse files Browse the repository at this point in the history
refs #424
  • Loading branch information
soxofaan committed Jan 15, 2025
1 parent 354a79e commit ddd2185
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `show_error_logs` argument to `cube.execute_batch()`/`job.start_and_wait()`/... to toggle the automatic printing of error logs on failure ([#505](https://github.com/Open-EO/openeo-python-client/issues/505))
- Added `Connection.web_editor()` to build link to the openEO backend in the openEO Web Editor
- Add support for `log_level` in `create_job()` and `execute_job()` ([#704](https://github.com/Open-EO/openeo-python-client/issues/704))
- Add initial support for "geometry" dimension type in `CubeMetadata` ([#705](https://github.com/Open-EO/openeo-python-client/issues/705))

### Changed

Expand Down
29 changes: 27 additions & 2 deletions openeo/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,19 @@ def rename_labels(self, target, source) -> Dimension:
def rename(self, name) -> Dimension:
return BandDimension(name=name, bands=self.bands)


class GeometryDimension(Dimension):
# TODO: how to model/store labels of geometry dimension?
def __init__(self, name: str):
super().__init__(name=name, type="geometry")

def rename(self, name) -> Dimension:
return GeometryDimension(name=name)

def rename_labels(self, target, source) -> Dimension:
return GeometryDimension(name=self.name)


class CubeMetadata:
"""
Interface for metadata of a data cube.
Expand All @@ -229,7 +242,7 @@ def __init__(self, dimensions: Optional[List[Dimension]] = None):
if dimensions is not None:
for dim in self._dimensions:
# TODO: here we blindly pick last bands or temporal dimension if multiple. Let user choose?
# TODO: add spacial dimension handling?
# TODO: add spatial dimension handling?
if dim.type == "bands":
if isinstance(dim, BandDimension):
self._band_dimension = dim
Expand Down Expand Up @@ -284,6 +297,16 @@ def temporal_dimension(self) -> TemporalDimension:
def spatial_dimensions(self) -> List[SpatialDimension]:
return [d for d in self._dimensions if isinstance(d, SpatialDimension)]

def has_geometry_dimension(self):
return any(isinstance(d, GeometryDimension) for d in self._dimensions)

@property
def geometry_dimension(self) -> GeometryDimension:
for d in self._dimensions:
if isinstance(d, GeometryDimension):
return d
raise MetadataException("No geometry dimension")

@property
def bands(self) -> List[Band]:
"""Get band metadata as list of Band metadata tuples"""
Expand Down Expand Up @@ -365,7 +388,7 @@ def reduce_spatial(self) -> CubeMetadata:
dimensions = [d for d in self._dimensions if not isinstance(d, SpatialDimension)]
return self._clone_and_update(dimensions=dimensions)

def add_dimension(self, name: str, label: Union[str, float], type: str = None) -> CubeMetadata:
def add_dimension(self, name: str, label: Union[str, float], type: Optional[str] = None) -> CubeMetadata:
"""Create new CubeMetadata object with added dimension"""
if any(d.name == name for d in self._dimensions):
raise DimensionAlreadyExistsException(f"Dimension with name {name!r} already exists")
Expand All @@ -375,6 +398,8 @@ def add_dimension(self, name: str, label: Union[str, float], type: str = None) -
dim = SpatialDimension(name=name, extent=[label, label])
elif type == "temporal":
dim = TemporalDimension(name=name, extent=[label, label])
elif type == "geometry":
dim = GeometryDimension(name=name)
else:
dim = Dimension(type=type or "other", name=name)
return self._clone_and_update(dimensions=self._dimensions + [dim])
Expand Down
16 changes: 15 additions & 1 deletion tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ def test_collectionmetadata_add_band_dimension_duplicate():
_ = metadata.add_dimension("layer", "red", "bands")


def test_cubemetadata_add_band_dimension_dublicate():
def test_cubemetadata_add_band_dimension_duplicate():
metadata = CubeMetadata(dimensions=[TemporalDimension(name="t", extent=None)])
metadata = metadata.add_dimension("layer", "red", "bands")
with pytest.raises(DimensionAlreadyExistsException, match="Dimension with name 'layer' already exists"):
Expand Down Expand Up @@ -679,6 +679,20 @@ def test_cubemetadata_add_temporal_dimension_duplicate():
_ = metadata.add_dimension("date", "2020-05-15", "temporal")


def test_cube_metadata_add_dimension_geometry():
orig = CubeMetadata(dimensions=[TemporalDimension(name="t", extent=None)])
new = orig.add_dimension(name="fields", label="Mol", type="geometry")

assert orig.dimension_names() == ["t"]
assert not orig.has_geometry_dimension()
with pytest.raises(MetadataException):
orig.geometry_dimension()

assert new.dimension_names() == ["t", "fields"]
assert new.has_geometry_dimension()
assert new.geometry_dimension.name == "fields"
assert new.geometry_dimension.type == "geometry"

def test_collectionmetadata_drop_dimension():
metadata = CollectionMetadata(
{
Expand Down

0 comments on commit ddd2185

Please sign in to comment.