Skip to content

Commit da5ac25

Browse files
Merge pull request #36 from EOPF-Explorer/updated_stac
feat: align register.py with ADR-111 STAC item standards
2 parents 4bdd64c + 245a035 commit da5ac25

File tree

1 file changed

+91
-9
lines changed

1 file changed

+91
-9
lines changed

scripts/register.py

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import httpx
1414
import zarr
15-
from pystac import Item, Link
15+
from pystac import Asset, Item, Link
1616
from pystac.extensions.projection import ProjectionExtension
1717
from pystac_client import Client
1818

@@ -139,17 +139,14 @@ def add_visualization_links(item: Item, raster_base: str, collection_id: str) ->
139139
)
140140
)
141141
elif coll_lower.startswith(("sentinel-2", "sentinel2")):
142-
# S2: True color quicklook
143-
var_path = "/quality/l2a_quicklook/r10m:tci"
144-
query = (
145-
f"variables={urllib.parse.quote(var_path, safe='')}&bidx=1&bidx=2&bidx=3&assets=TCI_10m"
146-
)
142+
# S2: True color from reflectance bands (B04=Red, B03=Green, B02=Blue)
143+
query = "rescale=0%2C1&color_formula=gamma+rgb+1.3%2C+sigmoidal+rgb+6+0.1%2C+saturation+1.2&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab04&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab03&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab02&bidx=1"
147144
item.add_link(
148145
Link(
149146
"xyz",
150147
f"{base_url}/tiles/WebMercatorQuad/{{z}}/{{x}}/{{y}}.png?{query}",
151148
"image/png",
152-
"Sentinel-2 L2A True Color",
149+
"Sentinel-2 L2A True Color (60m)",
153150
)
154151
)
155152
item.add_link(
@@ -171,6 +168,82 @@ def add_visualization_links(item: Item, raster_base: str, collection_id: str) ->
171168
)
172169

173170

171+
def add_thumbnail_asset(item: Item, raster_base: str, collection_id: str) -> None:
172+
"""Add thumbnail preview asset for STAC browsers."""
173+
if "thumbnail" in item.assets:
174+
return
175+
176+
base_url = f"{raster_base}/collections/{collection_id}/items/{item.id}"
177+
coll_lower = collection_id.lower()
178+
179+
# Mission-specific thumbnail parameters
180+
if coll_lower.startswith(("sentinel-2", "sentinel2")):
181+
params = "format=png&rescale=0%2C1&color_formula=gamma+rgb+1.3%2C+sigmoidal+rgb+6+0.1%2C+saturation+1.2&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab04&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab03&variables=%2Fmeasurements%2Freflectance%2Fr60m%3Ab02&bidx=1"
182+
title = "Sentinel-2 L2A True Color (60m)"
183+
elif coll_lower.startswith(("sentinel-1", "sentinel1")):
184+
# Use VH band for S-1 thumbnail
185+
if (vh := item.assets.get("vh")) and ".zarr/" in (vh.href or ""):
186+
var_path = f"/{vh.href.split('.zarr/')[1]}:grd"
187+
params = f"format=png&variables={urllib.parse.quote(var_path, safe='')}&bidx=1&rescale=0%2C219&assets=vh"
188+
title = "Sentinel-1 GRD VH Preview"
189+
else:
190+
logger.debug("No VH asset found for S-1 thumbnail")
191+
return
192+
else:
193+
logger.debug(f"Unknown mission for thumbnail: {collection_id}")
194+
return
195+
196+
thumbnail = Asset(
197+
href=f"{base_url}/preview?{params}",
198+
media_type="image/png",
199+
roles=["thumbnail"],
200+
title=title,
201+
)
202+
item.add_asset("thumbnail", thumbnail)
203+
logger.debug(f"Added thumbnail asset: {title}")
204+
205+
206+
def add_derived_from_link(item: Item, source_url: str) -> None:
207+
"""Add derived_from link pointing to original source item."""
208+
# Remove existing derived_from links to avoid duplicates
209+
item.links = [link for link in item.links if link.rel != "derived_from"]
210+
211+
item.add_link(
212+
Link(
213+
"derived_from",
214+
source_url,
215+
"application/json",
216+
"Derived from original Zarr STAC item",
217+
)
218+
)
219+
logger.debug(f"Added derived_from link: {source_url}")
220+
221+
222+
def remove_xarray_integration(item: Item) -> None:
223+
"""Remove XArray-specific fields from assets (ADR-111 compliance)."""
224+
removed_count = 0
225+
for asset in item.assets.values():
226+
if hasattr(asset, "extra_fields"):
227+
# Remove xarray-specific fields
228+
if asset.extra_fields.pop("xarray:open_dataset_kwargs", None):
229+
removed_count += 1
230+
if asset.extra_fields.pop("xarray:open_datatree_kwargs", None):
231+
removed_count += 1
232+
233+
# Remove alternate xarray configurations
234+
if "alternate" in asset.extra_fields and isinstance(
235+
asset.extra_fields["alternate"], dict
236+
):
237+
if asset.extra_fields["alternate"].pop("xarray", None):
238+
removed_count += 1
239+
# Remove empty alternate section
240+
if not asset.extra_fields["alternate"]:
241+
asset.extra_fields.pop("alternate")
242+
243+
if removed_count > 0:
244+
logger.debug(f"Removed {removed_count} XArray integration field(s)")
245+
246+
174247
# === Registration Workflow ===
175248

176249

@@ -233,11 +306,20 @@ def run_registration(
233306
# 3. Add projection metadata from zarr
234307
add_projection_from_zarr(item)
235308

236-
# 4. Add visualization links (viewer, xyz, tilejson)
309+
# 4. Remove XArray integration fields (ADR-111 compliance)
310+
remove_xarray_integration(item)
311+
312+
# 5. Add visualization links (viewer, xyz, tilejson)
237313
add_visualization_links(item, raster_api_url, collection)
238314
logger.info(" 🎨 Added visualization links")
239315

240-
# 5. Register to STAC API
316+
# 6. Add thumbnail asset for STAC browsers
317+
add_thumbnail_asset(item, raster_api_url, collection)
318+
319+
# 7. Add derived_from link to source item
320+
add_derived_from_link(item, source_url)
321+
322+
# 8. Register to STAC API
241323
client = Client.open(stac_api_url)
242324
upsert_item(client, collection, item)
243325

0 commit comments

Comments
 (0)