From 6afdced0df5b16f4e3149daae4a651ece70deafd Mon Sep 17 00:00:00 2001 From: Wei8007 <189627153@qq.com> Date: Mon, 13 Jul 2026 19:34:24 +0800 Subject: [PATCH] Preserve metadata when merging cubes without bands --- CHANGELOG.md | 2 +- openeo/rest/datacube.py | 20 +++++++++---------- tests/rest/datacube/test_datacube100.py | 26 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e570aba6e..65fc7318d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Better error message when passing a bounding box with field typos in `Connection.load_collection()` and alike ([#910](https://github.com/Open-EO/openeo-python-client/issues/910)) - +- Preserve available band metadata when merging data cubes if one cube has no band dimension. ([#783](https://github.com/Open-EO/openeo-python-client/issues/783)) ## [0.50.0] - 2026-05-18 diff --git a/openeo/rest/datacube.py b/openeo/rest/datacube.py index 8df992621..d3bdddd12 100644 --- a/openeo/rest/datacube.py +++ b/openeo/rest/datacube.py @@ -2183,18 +2183,16 @@ def merge_cubes( arguments = {"cube1": self, "cube2": other} if overlap_resolver: arguments["overlap_resolver"] = build_child_callback(overlap_resolver, parent_parameters=["x", "y"]) - if ( - self.metadata - and self.metadata.has_band_dimension() - and isinstance(other, DataCube) - and other.metadata - and other.metadata.has_band_dimension() - ): - # Minimal client side metadata merging + if self.metadata and isinstance(other, DataCube) and other.metadata: + # Minimal client-side metadata merging: preserve metadata when one or + # both cubes have no band dimension, and merge bands when both do. merged_metadata = self.metadata - for b in other.metadata.band_dimension.bands: - if b not in merged_metadata.bands: - merged_metadata = merged_metadata.append_band(b) + if self.metadata.has_band_dimension() and other.metadata.has_band_dimension(): + for b in other.metadata.band_dimension.bands: + if b not in merged_metadata.bands: + merged_metadata = merged_metadata.append_band(b) + elif other.metadata.has_band_dimension(): + merged_metadata = other.metadata else: merged_metadata = None # Overlapping bands without overlap resolver will give an error in the backend diff --git a/tests/rest/datacube/test_datacube100.py b/tests/rest/datacube/test_datacube100.py index 40f7ef10f..84b60e5ef 100644 --- a/tests/rest/datacube/test_datacube100.py +++ b/tests/rest/datacube/test_datacube100.py @@ -1185,6 +1185,32 @@ def test_merge_cubes_band_merging_with_overlap(con100, requests_mock, overlap_re assert s4_f_m_s3_f.metadata.band_names == ["B6", "B5", "B8"] +def test_merge_cubes_band_metadata_one_sided(con100): + bands = con100.load_collection("S2") + no_bands = bands.ndvi() + + assert bands.metadata.has_band_dimension() + assert not no_bands.metadata.has_band_dimension() + assert bands.merge_cubes(no_bands).metadata.band_names == ["B02", "B03", "B04", "B08"] + assert no_bands.merge_cubes(bands).metadata.band_names == ["B02", "B03", "B04", "B08"] + + +def test_merge_cubes_metadata_without_band_dimensions(con100): + no_bands = con100.load_collection("S2").ndvi() + merged = no_bands.merge_cubes(no_bands) + + assert merged.metadata is no_bands.metadata + assert not merged.metadata.has_band_dimension() + + +def test_merge_cubes_missing_metadata(con100): + with_metadata = con100.load_collection("S2") + without_metadata = con100.load_collection("S2", fetch_metadata=False) + + assert with_metadata.merge_cubes(without_metadata).metadata is None + assert without_metadata.merge_cubes(with_metadata).metadata is None + + def test_resample_cube_spatial(con100: Connection): data = con100.load_collection("S2") target = con100.load_collection("MASK")