Skip to content

Commit f6e8e4a

Browse files
moved metadata_from_stac function from connection to metadata module Open-EO#527
1 parent a34abd1 commit f6e8e4a

File tree

2 files changed

+68
-60
lines changed

2 files changed

+68
-60
lines changed

openeo/metadata.py

+59
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import logging
4+
import pystac
45
import warnings
56
from typing import Any, Callable, List, NamedTuple, Optional, Tuple, Union
67

@@ -522,3 +523,61 @@ def _repr_html_(self):
522523
def __str__(self) -> str:
523524
bands = self.band_names if self.has_band_dimension() else "no bands dimension"
524525
return f"CollectionMetadata({self.extent} - {bands} - {self.dimension_names()})"
526+
527+
528+
def metadata_from_stac(url: str) -> CubeMetadata:
529+
"""
530+
Reads the band metadata a static STAC catalog or a STAC API Collection and returns it as a :py:class:`CubeMetadata`
531+
532+
:param url: The URL to a static STAC catalog (STAC Item, STAC Collection, or STAC Catalog) or a specific STAC API Collection
533+
:return: A :py:class:`CubeMetadata` containing the DataCube band metadata from the url.
534+
"""
535+
536+
def get_band_names(asst: pystac.Asset) -> List[Band]:
537+
return [Band(eo_band["name"]) for eo_band in asst.extra_fields["eo:bands"]]
538+
539+
def is_band_asset(asset: pystac.Asset) -> bool:
540+
return "eo:bands" in asset.extra_fields
541+
542+
stac_object = pystac.read_file(href=url)
543+
544+
band_names = []
545+
collection = None
546+
547+
if isinstance(stac_object, pystac.Item):
548+
item = stac_object
549+
if "eo:bands" in item.properties:
550+
eo_bands_location = item.properties
551+
elif item.get_collection() is not None:
552+
collection = item.get_collection()
553+
eo_bands_location = item.get_collection().summaries.lists
554+
else:
555+
eo_bands_location = {}
556+
band_names = [Band(b["name"]) for b in eo_bands_location.get("eo:bands", [])]
557+
558+
elif isinstance(stac_object, pystac.Collection):
559+
collection = stac_object
560+
band_names = [Band(b["name"]) for b in collection.summaries.lists.get("eo:bands", [])]
561+
562+
# Summaries is not a required field in a STAC collection, so also check the assets
563+
for itm in collection.get_items():
564+
band_assets = {
565+
asset_id: asset
566+
for asset_id, asset in dict(sorted(itm.get_assets().items())).items()
567+
if is_band_asset(asset)
568+
}
569+
570+
for asset in band_assets.values():
571+
asset_band_names = get_band_names(asset)
572+
for asset_band_name in asset_band_names:
573+
if asset_band_name not in band_names:
574+
band_names.append(asset_band_name)
575+
576+
else:
577+
assert isinstance(stac_object, pystac.Catalog)
578+
catalog = stac_object
579+
band_names = [Band(b["name"]) for b in catalog.extra_fields.get("summaries", {}).get("eo:bands", [])]
580+
581+
band_dimension = BandDimension(name="bands", bands=band_names)
582+
metadata = CubeMetadata(dimensions=[band_dimension])
583+
return metadata

openeo/rest/connection.py

+9-60
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import json
88
import logging
99
import os
10-
import pystac
1110
import shlex
1211
import sys
1312
import warnings
@@ -28,7 +27,14 @@
2827
from openeo.internal.jupyter import VisualDict, VisualList
2928
from openeo.internal.processes.builder import ProcessBuilderBase
3029
from openeo.internal.warnings import deprecated, legacy_alias
31-
from openeo.metadata import Band, BandDimension, CollectionMetadata, CubeMetadata, SpatialDimension, TemporalDimension
30+
from openeo.metadata import (
31+
Band,
32+
BandDimension,
33+
CollectionMetadata,
34+
SpatialDimension,
35+
TemporalDimension,
36+
metadata_from_stac,
37+
)
3238
from openeo.rest import (
3339
CapabilitiesException,
3440
OpenEoApiError,
@@ -1150,63 +1156,6 @@ def datacube_from_json(self, src: Union[str, Path], parameters: Optional[dict] =
11501156
"""
11511157
return self.datacube_from_flat_graph(load_json_resource(src), parameters=parameters)
11521158

1153-
def metadata_from_stac(self, url: str) -> CubeMetadata:
1154-
"""
1155-
Reads the band metadata a static STAC catalog or a STAC API Collection and returns it as a :py:class:`CubeMetadata`
1156-
1157-
:param url: The URL to a static STAC catalog (STAC Item, STAC Collection, or STAC Catalog) or a specific STAC API Collection
1158-
:return: A :py:class:`CubeMetadata` containing the DataCube band metadata from the url.
1159-
"""
1160-
1161-
def get_band_names(asst: pystac.Asset) -> List[Band]:
1162-
return [Band(eo_band["name"]) for eo_band in asst.extra_fields["eo:bands"]]
1163-
1164-
def is_band_asset(asset: pystac.Asset) -> bool:
1165-
return "eo:bands" in asset.extra_fields
1166-
1167-
stac_object = pystac.read_file(href=url)
1168-
1169-
band_names = []
1170-
collection = None
1171-
1172-
if isinstance(stac_object, pystac.Item):
1173-
item = stac_object
1174-
if "eo:bands" in item.properties:
1175-
eo_bands_location = item.properties
1176-
elif item.get_collection() is not None:
1177-
collection = item.get_collection()
1178-
eo_bands_location = item.get_collection().summaries.lists
1179-
else:
1180-
eo_bands_location = {}
1181-
band_names = [Band(b["name"]) for b in eo_bands_location.get("eo:bands", [])]
1182-
1183-
elif isinstance(stac_object, pystac.Collection):
1184-
collection = stac_object
1185-
band_names = [Band(b["name"]) for b in collection.summaries.lists.get("eo:bands", [])]
1186-
1187-
# Summaries is not a required field in a STAC collection, so also check the assets
1188-
for itm in collection.get_items():
1189-
band_assets = {
1190-
asset_id: asset
1191-
for asset_id, asset in dict(sorted(itm.get_assets().items())).items()
1192-
if is_band_asset(asset)
1193-
}
1194-
1195-
for asset in band_assets.values():
1196-
asset_band_names = get_band_names(asset)
1197-
for asset_band_name in asset_band_names:
1198-
if asset_band_name not in band_names:
1199-
band_names.append(asset_band_name)
1200-
1201-
else:
1202-
assert isinstance(stac_object, pystac.Catalog)
1203-
catalog = stac_object
1204-
band_names = [Band(b["name"]) for b in catalog.extra_fields.get("summaries", {}).get("eo:bands", [])]
1205-
1206-
band_dimension = BandDimension(name="bands", bands=band_names)
1207-
metadata = CubeMetadata(dimensions=[band_dimension])
1208-
return metadata
1209-
12101159
@openeo_process
12111160
def load_collection(
12121161
self,
@@ -1420,7 +1369,7 @@ def load_stac(
14201369
}
14211370
cube = self.datacube_from_process(process_id="load_stac", **arguments)
14221371
try:
1423-
cube.metadata = self.metadata_from_stac(url)
1372+
cube.metadata = metadata_from_stac(url)
14241373
except Exception:
14251374
_log.warning("Python client could not read band metadata from URL.")
14261375
return cube

0 commit comments

Comments
 (0)