Skip to content

Commit 2c9608e

Browse files
committed
fixup! WIP implement filter_bbox on CubeMetadata
1 parent bf11f73 commit 2c9608e

2 files changed

Lines changed: 128 additions & 9 deletions

File tree

‎openeo/metadata/__init__.py‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,25 @@ def filter_bbox(self, extent: Any) -> SpatialDimensionsXY:
149149
# TODO: support more types and forms of the extent (geometries, etc.) ... e.g. using the BBoxDict factories?
150150
if isinstance(extent, dict) and {"west", "east", "south", "north"}.issubset(extent):
151151
bbox = BBoxDict.from_dict(extent)
152-
if bbox["crs"] == self.x.crs and bbox["crs"] == self.y.crs:
152+
bbox_crs = bbox.get("crs", SpatialDimension.DEFAULT_CRS)
153+
if bbox_crs == self.x.crs and bbox_crs == self.y.crs:
153154
# No reprojection needed
154-
return SpatialDimensionsXY(
155-
x=self.x.filter_extent(extent=(bbox["west"], bbox["east"])),
156-
y=self.y.filter_extent(extent=(bbox["south"], bbox["north"])),
157-
)
155+
extent_x = bbox["west"], bbox["east"]
156+
extent_y = bbox["south"], bbox["north"]
158157
else:
159158
# TODO: reproject
160-
pass
161-
# As lenient fallback, handle as non-concrete extent
159+
extent_x, extent_y = _NonConcreteExtent(), _NonConcreteExtent()
160+
elif isinstance(extent, _EmptyExtent):
161+
extent_x, extent_y = _EmptyExtent(), _EmptyExtent()
162+
elif isinstance(extent, _NonConcreteExtent):
163+
extent_x, extent_y = _NonConcreteExtent(), _NonConcreteExtent()
164+
else:
165+
# As lenient fallback, handle as non-concrete extent
166+
extent_x, extent_y = _NonConcreteExtent(), _NonConcreteExtent()
167+
162168
return SpatialDimensionsXY(
163-
x=self.x.filter_extent(extent=_NonConcreteExtent()),
164-
y=self.y.filter_extent(extent=_NonConcreteExtent()),
169+
x=self.x.filter_extent(extent=extent_x),
170+
y=self.y.filter_extent(extent=extent_y),
165171
)
166172

167173

‎tests/metadata/test_metadata.py‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,67 @@ def test_filter_extent_parameterized(self):
197197
assert isinstance(dim2.extent, _NonConcreteExtent)
198198

199199

200+
class TestSpatialDimensionsXY:
201+
def test_basic(self):
202+
dim_x = SpatialDimension(name="x", axis="x", extent=(3, 6), crs=4326)
203+
dim_y = SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326)
204+
dim_xy = SpatialDimensionsXY(dim_x, dim_y)
205+
assert (dim_xy.x.name, dim_xy.x.axis, dim_xy.x.extent) == ("x", "x", (3, 6))
206+
assert (dim_xy.y.name, dim_xy.y.axis, dim_xy.y.extent) == ("y", "y", (49, 52))
207+
208+
def test_eq_tuple(self):
209+
dim_x = SpatialDimension(name="x", axis="x", extent=(3, 6), crs=4326)
210+
dim_y = SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326)
211+
dim_xy = SpatialDimensionsXY(dim_x, dim_y)
212+
assert dim_xy == (
213+
SpatialDimension(name="x", axis="x", extent=(3, 6), crs=4326),
214+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
215+
)
216+
217+
@pytest.mark.parametrize(
218+
["extent", "expected"],
219+
[
220+
({"west": 4, "south": 50, "east": 5, "north": 51, "crs": 4326}, ((4, 5), (50, 51))),
221+
({"west": 1, "south": 40, "east": 4, "north": 50, "crs": 4326}, ((2, 4), (49, 50))),
222+
({"west": 5, "south": 50, "east": 8, "north": 60, "crs": 4326}, ((5, 7), (50, 52))),
223+
],
224+
)
225+
def test_filter_bbox_simple(self, extent, expected):
226+
"""Simple case: all in same CRS (EPSG:4326)"""
227+
dim_xy = SpatialDimensionsXY(
228+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326),
229+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
230+
)
231+
dim_xy_filtered = dim_xy.filter_bbox(extent=extent)
232+
233+
assert (dim_xy.x.extent, dim_xy.y.extent) == ((2, 7), (49, 52))
234+
assert (dim_xy_filtered.x.extent, dim_xy_filtered.y.extent) == expected
235+
236+
def test_filter_bbox_empty(self):
237+
dim_xy = SpatialDimensionsXY(
238+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326),
239+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
240+
)
241+
extent = _EmptyExtent()
242+
dim_xy_filtered = dim_xy.filter_bbox(extent=extent)
243+
244+
assert (dim_xy.x.extent, dim_xy.y.extent) == ((2, 7), (49, 52))
245+
assert dim_xy_filtered.x.extent == _EmptyExtent()
246+
assert dim_xy_filtered.y.extent == _EmptyExtent()
247+
248+
def test_filter_bbox_non_concrete(self):
249+
dim_xy = SpatialDimensionsXY(
250+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326),
251+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
252+
)
253+
extent = openeo.api.process.Parameter.spatial_extent()
254+
dim_xy_filtered = dim_xy.filter_bbox(extent=extent)
255+
256+
assert (dim_xy.x.extent, dim_xy.y.extent) == ((2, 7), (49, 52))
257+
assert isinstance(dim_xy_filtered.x.extent, _NonConcreteExtent)
258+
assert isinstance(dim_xy_filtered.y.extent, _NonConcreteExtent)
259+
260+
200261
class TestBand:
201262
def test_band_minimal(self):
202263
band = Band("red")
@@ -1396,6 +1457,58 @@ def test_repr_html_with_dimensions(self):
13961457
regex_flags=re.DOTALL | re.VERBOSE,
13971458
)
13981459

1460+
@pytest.mark.parametrize(
1461+
["spatial_extent", "expected"],
1462+
[
1463+
({"west": 3, "east": 5, "south": 46, "north": 51}, ((3, 5), (49, 51))),
1464+
({"west": 3, "east": 5, "south": 46, "north": 51, "crs": 4326}, ((3, 5), (49, 51))),
1465+
({"west": 3, "east": 5, "south": 46, "north": 51, "crs": "EPSG:4326"}, ((3, 5), (49, 51))),
1466+
],
1467+
)
1468+
def test_filter_bbox_basic(self, spatial_extent, expected):
1469+
metadata1 = CubeMetadata(
1470+
dimensions=[
1471+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326),
1472+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
1473+
TemporalDimension(name="t", extent=("2021-01-01", None)),
1474+
]
1475+
)
1476+
metadata2 = metadata1.filter_bbox(extent=spatial_extent)
1477+
1478+
assert metadata1.spatial_dimensions == (
1479+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326, step=None),
1480+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326, step=None),
1481+
)
1482+
expected_x, expected_y = expected
1483+
assert metadata2.spatial_dimensions == (
1484+
SpatialDimension(name="x", axis="x", extent=expected_x, crs=4326, step=None),
1485+
SpatialDimension(name="y", axis="y", extent=expected_y, crs=4326, step=None),
1486+
)
1487+
1488+
def test_filter_bbox_parameterized(self):
1489+
metadata1 = CubeMetadata(
1490+
dimensions=[
1491+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326),
1492+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326),
1493+
TemporalDimension(name="t", extent=("2021-01-01", None)),
1494+
]
1495+
)
1496+
spatial_extent = openeo.api.process.Parameter.spatial_extent()
1497+
metadata2 = metadata1.filter_bbox(extent=spatial_extent)
1498+
1499+
assert metadata1.spatial_dimensions == (
1500+
SpatialDimension(name="x", axis="x", extent=(2, 7), crs=4326, step=None),
1501+
SpatialDimension(name="y", axis="y", extent=(49, 52), crs=4326, step=None),
1502+
)
1503+
assert metadata2.spatial_dimensions == (
1504+
SpatialDimension(
1505+
name="x", axis="x", extent=dirty_equals.IsInstance(_NonConcreteExtent), crs=4326, step=None
1506+
),
1507+
SpatialDimension(
1508+
name="y", axis="y", extent=dirty_equals.IsInstance(_NonConcreteExtent), crs=4326, step=None
1509+
),
1510+
)
1511+
13991512

14001513
class TestStacMetadataParser:
14011514
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)