Skip to content

S1 RTC STAC items: metadata incoherences & gaps vs the S2 L2A reference (cube + per-acquisition) #195

Closed

Description

@lhoupert

Summary

A metadata-coherence review of the live staging S1 RTC STAC items, benchmarked against the Sentinel‑2 L2A reference, surfaces several incoherences (bugs) and missing fields. Both item types are built by build_s1_rtc_stac_item in this repo (the data-pipeline register step only adds alternate-assets/storage/store/via/render links).

Items reviewed (2026-06-18, …explorer.eopf.copernicus.eu/stac):

  • cube / "tile" item: sentinel-1-grd-rtc-staging/items/s1-rtc-30TWM
  • per-acquisition item: sentinel-1-grd-rtc-acquisitions-staging/items/s1-rtc-30TWM-20260610t061718

Reference: sentinel-2-l2a/items/S2A_MSIL2A_20260617T135751_N0512_R010_T26WME_20260617T221913.

Reference baseline (S2 L2A)

  • Extensions: timestamps, eo v2, sat, projection v2, mgrs, grid, view, processing v1.2, product, scientific, eopf, version, raster v2, alternate-assets, storage.
  • Properties: platform (sentinel-2a), constellation (sentinel-2), instruments ([msi]), mission, gsd, created, updated, processing:level/software/facility/version, providers, proj:bbox+proj:code, sat:*, view:*.
  • Data assets carry data_type, nodata, gsd, raster:scale/offset, description.

S1 RTC items carry only: sar:*, sat:orbit_state, proj:code, renders (+ datetime/range). Big delta.

Incorrect (bugs)

  1. vv and vh data assets have identical hrefs (both → the orbit group …/s1-rtc-{tile}.zarr/{orbit}, not the VV vs VH arrays). Two data assets, different titles, byte-identical href → a non-titiler client cannot resolve VV vs VH. Affects both item types.
  2. Cube item represents a dual-orbit cube as ascending-only. The store has both /ascending and /descending groups, but sat:orbit_state: "ascending" and the vv/vh/thumbnail/render reference /ascending only → there is no dedicated typed vv/vh asset for the /descending group. Its data is reachable only via the whole-store zarr-store asset (the store root contains both groups), not as a polarization asset, and sat:orbit_state is a misleading single value for a dual-orbit cube.
  3. Per-acquisition data assets don't represent the item's own acquisition. The single-datetime per-acq item's vv/vh point at the whole cube orbit group (all time slices); only the render links carry sel=time={datetime}. A 1-datetime item whose data assets span N datetimes is incoherent for any non-render consumer.

Ambiguity (borderline bug vs gap)

  • sar:product_type: "GRD" does not capture the RTC nature. GRD is the legitimate source product, and the SAR extension defines no standard RTC value — so this is not strictly a wrong value, but nothing marks the item as radiometric-terrain-corrected γ⁰ or records the radiometry. Worth an explicit RTC/radiometry indication.

Proposed asset model (resolves bugs #1–#2)

Replace the two duplicate vv/vh assets (identical href, indistinguishable) with one data asset per orbit group, named for what it is — γ⁰ RTC backscatter — with the polarizations expressed as bands:

  • Cube item (dual-orbit) → two assets:
    • gamma0-rtc-backscatter-asc → href …/s1-rtc-{tile}.zarr/ascending
    • gamma0-rtc-backscatter-desc → href …/s1-rtc-{tile}.zarr/descending
  • Per-acquisition item (single orbit) → one asset gamma0-rtc-backscatter-{asc|desc} for the item's orbit.

Each asset carries bands: [{name: vv, …}, {name: vh, …}] plus data_type, nodata, unit (γ⁰ linear), gsd: 10, statistics. This makes VV vs VH addressable via bands (no more duplicate hrefs, bug #1) and gives the /descending group a first-class asset on the cube item (bug #2). The titiler render expressions (/{orbit}:vv;…) reference zarr paths, so the asset-key rename doesn't affect rendering.

Missing (vs S2)

Both item types lack:

  • Identity: platform, constellation: sentinel-1, instruments: [c-sar], mission (note the cube mixes S1A+S1C → platform is multi-valued, an argument it belongs per-acquisition).
  • gsd (10 m), item and asset level.
  • Projection detail: only proj:code; add proj:bbox, proj:shape, proj:transform (S2 has proj:bbox+proj:code).
  • Band/asset metadata on vv/vh: data_type, nodata, unit (γ⁰ linear), statistics (cf. Add statstics for visualization to bands or assets #157), raster:*. (S2 data assets have all of these.)
  • Processing provenance (processing: ext): processing:level, processing:software (eopf-geozarr / s1tiling / OTB versions), processing:facility, and the DEM used for terrain correction (lineage). Essential for an RTC product.
  • Timestamps: created / updated (timestamps ext). updated especially — the cube is appended over time.
  • providers, title, description.
  • border_mask variable exists in the store but is not exposed as a valid-data mask asset.

Per-acquisition only:

  • derived_from link to its parent cube item and/or the source S1 GRD product (provenance); consider the version ext.

Cube ("tile") items: add the datacube extension

The cube items are genuine datacubes (dims time, y, x; variables vv/vh/border_mask per orbit group) but carry no structural metadata. Add the datacube extension (cube:dimensions + cube:variables) so the temporal/spatial structure is discoverable without opening the store. (S2 single-acquisition items don't need this — it's specific to the S1 cubes.)

Suggested target field set (mirror S2)

platform, constellation, instruments, mission, gsd, created, updated, providers, title/description, proj:bbox/shape/transform, per-asset data_type/nodata/unit/statistics, processing:level/software/facility + DEM lineage, datacube ext on cubes, derived_from on per-acq items; fix the vv/vh href + dual-orbit asset gap + RTC product_type label.

Notes

Activity

  1. lhoupert commented on Jun 18, 2026

    @lhoupert
    ContributorAuthor

    CDSE source already carries most of the missing metadata

    trigger_cdse.py queries the CDSE STAC (catalogue.dataspace.copernicus.eu/stac, collection sentinel-1-grd) and already holds the full source item, but discards everything except product_id, platform, datetime. The CDSE entry (e.g. S1A_IW_GRDH_1SDV_20260618T110034_..._COG) exposes nearly every field this issue flags. Mapping gap → CDSE source:

    #195 gap CDSE source field Notes
    platform platform (sentinel-1a) per-product
    constellation constellation (sentinel-1) invariant → safe on cube
    instruments instruments (["sar"]) CDSE uses sar; STAC SAR convention is c-sar — pick one
    gsd (10 m) sar:pixel_spacing_azimuth/range (10.0) basis for gsd: 10
    sat:relative_orbit / sat:absolute_orbit same, + sat:orbit_cycle, sat:platform_international_designator per-product
    view:incidence_angle view:incidence_angle, view:azimuth per-product; RTC-relevant
    SAR optionals sar:observation_direction, pixel spacing
    processing provenance processing:level (L1), processing:facility/software/version/datetime source L1, not our RTC step — see caveat
    timestamps created, updated, published source timestamps
    product type/timeliness product:type (IW_GRDH_1S), product:timeliness*
    datatake eopf:datatake_id, eopf:instrument_configuration_id per-product
    derived_from (per-acq) the CDSE item id / self href direct provenance link

    Caveats

    • Most CDSE fields are per-product (orbit, incidence angle, datatake, platform) → they belong on the per-acquisition items; the cube item can only aggregate the invariants (constellation, instruments, gsd, sar:frequency_band/center_frequency/polarizations) + datacube dims. A cube mixing S1A+S1C can't carry a single platform/orbit.
    • CDSE processing:* describes the source L1 GRD step, not our RTC γ⁰. Record it as source lineage (via derived_from and/or processing:lineage), and set our own processing:software (eopf-geozarr / s1tiling / OTB) + the DEM used for the RTC step.
    • proj:bbox/shape/transform should come from our output zarr, not CDSE — RTC reprojects onto the S2 MGRS/UTM grid, so projection is ours. register_v1.add_projection_from_zarr already reads spatial_ref; extend it to emit proj:shape/transform/bbox.

    Plumbing

    trigger_cdse.py already has the CDSE pystac Item in query_products() — cheapest path is to pass the relevant CDSE properties through the emitted record (or re-fetch by product_id at register time) and have register_per_acquisition copy them onto the item. No extra CDSE round-trip needed for discover.

  2. lhoupert commented on Jun 18, 2026

    @lhoupert
    ContributorAuthor

    Update — PR #196 (data-model) + data-pipeline follow-up planned

    Construction-side fixes are implemented in #196 (onto feat/s1-rtc-stac-builder); registration + migration are specced for a data-pipeline follow-up. Root cause addressed: STAC construction was split across both repos — #196 consolidates it into the eopf_geozarr.stac.s1_rtc library so item shape has a single owner.

    Bugs

    • 1 duplicate vv/vh hrefs — ✅ fixed. One gamma0-rtc-backscatter-{asc,desc} asset per orbit group, with VV/VH as named STAC 1.1 bands (no more byte-identical, indistinguishable assets).
    • 2 dual-orbit cube as ascending-only — ✅ fixed. Each present orbit gets a first-class γ⁰ + border-mask asset; sat:orbit_state (single-valued) is omitted on dual-orbit cubes and set only on single-orbit cubes / per-acquisition items.
    • 3 per-acquisition data assets — ⚠️ improved within the no-duplication design. Per-acq items are now coherent: single datetime, their own orbit, own footprint (bbox/geometry/proj:bbox), and only their orbit's asset. The zarr data asset still references the shared cube orbit group (by design — no data duplication), and the render link selects the slice via sel=time={datetime}.

    Ambiguity

    • sar:product_type / RTC — kept "GRD" (the legitimate source type; the SAR extension defines no standard RTC value). RTC is conveyed by the asset name gamma0-rtc-backscatter-*, title, and description. A formal radiometry/processing-level field is part of the deferred provenance work.

    Proposed asset model — ✅ adopted

    One γ⁰ asset per orbit with bands:[vv,vh] + data_type/nodata/unit/gsd; a border-mask-{orbit} mask asset; render expressions unchanged (path-based, so rendering is unaffected).

    Missing vs S2 — addressed where derivable from the store

    • ✅ identity (constellation, instruments: [c-sar], gsd); per-slice platform normalized to sentinel-1a/-1c
    • ✅ projection detail (proj:bbox, proj:shape, proj:transform)
    • ✅ band/asset metadata (data_type/nodata/unit, bands)
    • ✅ timestamps (updated; created intentionally omitted — the store records no item-creation time)
    • ✅ title/description
    • ✅ border_mask exposed as a valid-data mask asset
    • ✅ datacube extension on cubes: cube:dimensions (irregular time lists its values; regular x/y use extent+step; dual-orbit cubes note that the time axis spans both orbits) + cube:variables (correct variable_type, auxiliary for the mask)

    Deferred — not in the store, tracked for the follow-up / future

    • Processing provenance + DEM lineage and band statistics (Add statstics for visualization to bands or assets #157) — need an ingest-time step that writes them into store attrs so the builder can read them.
    • Per-acquisition derived_from + CDSE per-product fields (incidence angle, orbit numbers, source GRD lineage) — injected at register time from the CDSE source (per the comment above), in data-pipeline.
    • providers — omitted until authoritative values are confirmed (avoiding invented metadata).

    Data-pipeline follow-up (specced)

    A companion PR will bump the data-model pin, replace the duplicated construction in register_per_acquisition.py / register_v1_s1_rtc.py with the library functions (build_s1_rtc_per_acquisition_items, slice_coverages/pick_slice, acquisition_id), keep the render/store/S3-alternate decoration working with the new asset keys, and migrate the existing staging items to the new model (idempotent, previews preserved).

    Verified end-to-end against real staging data (tile 30TWN, a dual-orbit / multi-slice cube): builds read-only from the live store, validates against the live extension schemas (datacube v2.2.0, timestamps v1.1.0, projection v2.0.0, sar, sat), and reproduces every existing per-acquisition id.

  3. added
    bugSomething isn't working
    sentinel-1Sentinel-1 products (GRD, SLC, OCN, GRD RTC)
    stacSTAC metadata and items
    on Sep 28, 2026
  4. emmanuelmathot commented on Sep 28, 2026

    @emmanuelmathot
    Contributor

    @lhoupert, can you give a status update? From the linked work, most of this is done:

    Not clear to me:

    1. The RTC/radiometry marker: sar:product_type is still GRD, with nothing that says γ⁰ RTC.
    2. The metadata that could come from the CDSE source item (platform, constellation, instruments, gsd, sat:*, view:*, processing:*).

    If both are done or no longer needed, please close this issue. Otherwise, list what remains here so we can plan it.

  5. lhoupert commented on Sep 29, 2026

    @lhoupert
    ContributorAuthor

    Both are not done, should I close it as not planned as we stopped producing sentinel1 data? or would it be useful to finalise this @emmanuelmathot ?

  6. lhoupert commented on Oct 27, 2026

    @lhoupert
    ContributorAuthor

    @emmanuelmathot please find a mote detailed answer below.

    I am closing that now, let me know if you think I should reopened it for some reasons

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingsentinel-1Sentinel-1 products (GRD, SLC, OCN, GRD RTC)stacSTAC metadata and items

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions