Skip to content

Commit 24afbe1

Browse files
authored
Merge pull request #1507 from esm-tools/esm-catalog/pr-a1d-datacube-extension
feat(esm_catalog): PR-A1d — datacube STAC extension
2 parents 3f42e6f + bba1906 commit 24afbe1

21 files changed

Lines changed: 880 additions & 17 deletions

File tree

.github/workflows/esm-catalog-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ jobs:
3434
# with --no-deps and add only the deps it actually imports (plus a modern
3535
# pytest; the base pins pytest==7.1.2, which predates 3.12 support).
3636
pip install -e . --no-deps
37-
pip install -U "pytest>=7.4" click loguru pystac shapely universal-pathlib
37+
pip install -U "pytest>=7.4" click loguru pystac shapely universal-pathlib jsonschema
3838
- name: Run esm_catalog tests
3939
run: pytest tests/test_esm_catalog -v

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 6.66.0
2+
current_version = 6.66.1
33
commit = True
44
tag = True
55

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,6 @@
126126
test_suite="tests",
127127
tests_require=test_requirements,
128128
url="https://github.com/esm-tools/esm_tools",
129-
version="6.66.0",
129+
version="6.66.1",
130130
zip_safe=False,
131131
)

src/esm_archiving/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
__author__ = """Paul Gierz"""
66
__email__ = "pgierz@awi.de"
7-
__version__ = "6.66.0"
7+
__version__ = "6.66.1"
88

99
from .esm_archiving import (archive_mistral, check_tar_lists,
1010
delete_original_data, determine_datestamp_location,

src/esm_calendar/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
__author__ = """Dirk Barbi"""
44
__email__ = "dirk.barbi@awi.de"
5-
__version__ = "6.66.0"
5+
__version__ = "6.66.1"
66

77
from .esm_calendar import *

src/esm_catalog/datacube.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""Datacube STAC extension: cube:dimensions and cube:variables.
2+
3+
Expected metadata shapes (the contract the file scanners must meet):
4+
5+
metadata["dimensions"]: dict mapping dimension name to a STAC datacube
6+
Dimension Object, e.g.
7+
{"time": {"type": "temporal", "extent": ["2000-01-01T00:00:00Z",
8+
"2000-12-31T00:00:00Z"]},
9+
"lon": {"type": "spatial", "axis": "x", "extent": [-180.0, 180.0]}}
10+
11+
metadata["variables"]: list of dicts with keys
12+
name (str, required — entries without it are skipped),
13+
dimensions (list[str]), units (str), and any of
14+
description / long_name / standard_name (str).
15+
16+
The v2.2.0 schema requires cube:dimensions whenever the extension URL is
17+
declared, so the extension is a no-op unless dimensions are present.
18+
"""
19+
20+
from __future__ import annotations
21+
22+
from typing import TYPE_CHECKING
23+
24+
from esm_catalog.registry import EXTENSION_URLS
25+
26+
if TYPE_CHECKING:
27+
import pystac
28+
29+
30+
def add_datacube_extension(item: "pystac.Item", metadata: dict) -> None:
31+
"""Inject datacube extension fields into *item* from *metadata*.
32+
33+
Sets item.properties["cube:dimensions"] (pass-through) and
34+
item.properties["cube:variables"] (mapped), and appends the datacube
35+
schema URL to item.stac_extensions (idempotent). No-op when *metadata*
36+
carries no dimensions.
37+
"""
38+
dims = metadata.get("dimensions", {})
39+
if not dims:
40+
return
41+
42+
item.properties["cube:dimensions"] = dims
43+
44+
cube_vars = _to_cube_variables(metadata.get("variables", []))
45+
if cube_vars:
46+
item.properties["cube:variables"] = cube_vars
47+
48+
url = EXTENSION_URLS["datacube"]
49+
if url not in item.stac_extensions:
50+
item.stac_extensions.append(url)
51+
52+
53+
def _to_cube_variables(variables: list) -> dict:
54+
"""Map scanner variable entries to datacube Variable Objects."""
55+
cube_vars = {}
56+
for v in variables:
57+
name = v.get("name")
58+
if not name:
59+
continue
60+
entry: dict = {"dimensions": v.get("dimensions", [])}
61+
if "units" in v:
62+
entry["unit"] = v["units"]
63+
for key in ("description", "long_name", "standard_name"):
64+
if key in v:
65+
entry["description"] = v[key]
66+
break
67+
cube_vars[name] = entry
68+
return cube_vars

src/esm_catalog/item.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from pystac import Asset, Item, Link
1111
from upath import UPath
1212

13+
from esm_catalog.datacube import add_datacube_extension
14+
1315

1416
def make_item(
1517
path: Union[Path, UPath, str],
@@ -58,6 +60,8 @@ def make_item(
5860
)
5961
)
6062

63+
add_datacube_extension(item, metadata)
64+
6165
return item
6266

6367

src/esm_cleanup/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = """Dirk Barbi"""
44
__email__ = "dirk.barbi@awi.de"
5-
__version__ = "6.66.0"
5+
__version__ = "6.66.1"

src/esm_database/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = """Dirk Barbi"""
44
__email__ = "dirk.barbi@awi.de"
5-
__version__ = "6.66.0"
5+
__version__ = "6.66.1"

src/esm_environment/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
__author__ = """Dirk Barbi"""
44
__email__ = "dirk.barbi@awi.de"
5-
__version__ = "6.66.0"
5+
__version__ = "6.66.1"
66

77
from .esm_environment import *

0 commit comments

Comments
 (0)