Skip to content

Commit d086d30

Browse files
committed
Issue #666 load_stac: fallback temporal dimension when no cube:dimensions
1 parent 37ba260 commit d086d30

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
### Fixed
1919

20+
- `load_stac`: use fallback temporal dimension when no "cube:dimensions" in STAC Collection ([#666](https://github.com/Open-EO/openeo-python-client/issues/666))
2021

2122
## [0.35.0] - 2024-11-19
2223

openeo/metadata.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pystac.extensions.item_assets
1212

1313
from openeo.internal.jupyter import render_component
14-
from openeo.util import deep_get
14+
from openeo.util import Rfc3339, deep_get
1515

1616
_log = logging.getLogger(__name__)
1717

@@ -691,6 +691,11 @@ def get_temporal_dimension(self, stac_obj: pystac.STACObject) -> Union[TemporalD
691691
if len(temporal_dims) == 1:
692692
name, extent = temporal_dims[0]
693693
return TemporalDimension(name=name, extent=extent)
694+
elif isinstance(stac_obj, pystac.Collection) and stac_obj.extent.temporal:
695+
# No explicit "cube:dimensions": fallback from "extent"
696+
# and openEO API recommendation to use "t" as dimension name
697+
extent = [Rfc3339(propagate_none=True).normalize(d) for d in stac_obj.extent.temporal.intervals[0]]
698+
return TemporalDimension(name="t", extent=extent)
694699
else:
695700
if isinstance(stac_obj, pystac.Item):
696701
cube_dimensions = stac_obj.properties.get("cube:dimensions", {})

openeo/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ def parse_date_or_datetime(
172172
@classmethod
173173
def _format_datetime(cls, d: dt.datetime) -> str:
174174
"""Format given datetime as RFC-3339 date-time string."""
175-
if d.tzinfo not in {None, dt.timezone.utc}:
175+
if not (d.tzinfo is None or d.tzinfo.tzname(d) == "UTC"):
176176
# TODO: add support for non-UTC timezones?
177177
raise ValueError(f"No support for non-UTC timezone {d.tzinfo}")
178178
return d.strftime(cls._FMT_DATETIME)

tests/rest/test_connection.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import openeo
1919
from openeo.capabilities import ApiVersionException
2020
from openeo.internal.graph_building import FlatGraphableMixin, PGNode
21+
from openeo.metadata import _PYSTAC_1_9_EXTENSION_INTERFACE, TemporalDimension
2122
from openeo.rest import (
2223
CapabilitiesException,
2324
OpenEoApiError,
@@ -40,7 +41,7 @@
4041
)
4142
from openeo.rest.vectorcube import VectorCube
4243
from openeo.testing.stac import StacDummyBuilder
43-
from openeo.util import ContextTimer, dict_no_none
44+
from openeo.util import ContextTimer, deep_get, dict_no_none
4445

4546
from .auth.test_cli import auth_config, refresh_token_store
4647

@@ -2622,6 +2623,38 @@ def test_load_stac_reduce_temporal(self, con120, tmp_path, temporal_dim):
26222623
},
26232624
}
26242625

2626+
@pytest.mark.skipif(
2627+
not _PYSTAC_1_9_EXTENSION_INTERFACE,
2628+
reason="No backport of implementation/test below PySTAC 1.9 extension interface",
2629+
)
2630+
@pytest.mark.parametrize(
2631+
["collection_extent", "dim_extent"],
2632+
[
2633+
(
2634+
{"spatial": {"bbox": [[3, 4, 5, 6]]}, "temporal": {"interval": [["2024-01-01", "2024-05-05"]]}},
2635+
["2024-01-01T00:00:00Z", "2024-05-05T00:00:00Z"],
2636+
),
2637+
(
2638+
{"spatial": {"bbox": [[3, 4, 5, 6]]}, "temporal": {"interval": [[None, "2024-05-05"]]}},
2639+
[None, "2024-05-05T00:00:00Z"],
2640+
),
2641+
],
2642+
)
2643+
def test_load_stac_no_cube_extension_temporal_dimension(self, con120, tmp_path, collection_extent, dim_extent):
2644+
"""
2645+
Metadata detection when STAC metadata does not use "cube" extension
2646+
https://github.com/Open-EO/openeo-python-client/issues/666
2647+
"""
2648+
stac_path = tmp_path / "stac.json"
2649+
stac_data = StacDummyBuilder.collection(extent=collection_extent)
2650+
# No cube:dimensions, but at least "temporal" extent is set as indicator for having a temporal dimension
2651+
assert "cube:dimensions" not in stac_data
2652+
assert deep_get(stac_data, "extent", "temporal")
2653+
stac_path.write_text(json.dumps(stac_data))
2654+
2655+
cube = con120.load_stac(str(stac_path))
2656+
assert cube.metadata.temporal_dimension == TemporalDimension(name="t", extent=dim_extent)
2657+
26252658

26262659
@pytest.mark.parametrize(
26272660
"data",

tests/test_metadata.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,10 @@ def test_metadata_from_stac_collection_bands_from_item_assets(test_data, tmp_pat
849849
assert warn_count == (0 if eo_extension_is_declared else 1)
850850

851851

852+
@pytest.mark.skipif(
853+
not _PYSTAC_1_9_EXTENSION_INTERFACE,
854+
reason="No backport of implementation/test below PySTAC 1.9 extension interface",
855+
)
852856
@pytest.mark.parametrize(
853857
["stac_dict", "expected"],
854858
[
@@ -868,7 +872,7 @@ def test_metadata_from_stac_collection_bands_from_item_assets(test_data, tmp_pat
868872
),
869873
(
870874
StacDummyBuilder.collection(),
871-
None,
875+
("t", ["2024-01-01T00:00:00Z", "2024-05-05T00:00:00Z"]),
872876
),
873877
(
874878
StacDummyBuilder.collection(

0 commit comments

Comments
 (0)