Skip to content

Allow versions dropdown to span multiple STAC collections #323

Description

@cboettig

Summary

The versions layer form (dropdown selector for variants of a logical layer) currently only resolves asset_ids within a single STAC collection. This couples a presentation concern (which layers the user can flip between in one dropdown) to a data-modeling concern (STAC collection/asset boundaries). Scenario/projection ensembles — a common case — legitimately live in separate collections and so can't use the dropdown today.

Where it's constrained

In app/dataset-catalog.js (extractMapLayers), the version resolver reads every variant from the one collection's assets:

// dataset-catalog.js ~L304
for (const v of config.versions) {
    const vAsset = stacAssets[v.asset_id];   // stacAssets = collection.assets — single collection only
    if (!vAsset) continue;
    ...
}

_validateAssetIds (~L260) and the version→MapLibre builder in app/map-manager.js (~L174) share the same single-collection assumption.

Motivating example

HydroBASINS works with a dropdown because levels L3–L6 are all assets of one collection (hydrobasins-v1c) — they're alternate representations (resolutions) of one dataset. Correct STAC.

GLOBIO 4 MSA cannot, because it ships as a parent globio collection (empty assets) with 12 child collections — one per taxon × scenario/time slice (overall/plants/warm-blooded verts × 2015 baseline + three 2050 SSP-RCP scenarios). Each child has its own temporal extent (2015 vs 2050), its own band statistics, and its own provenance, so modeling them as separate collections is arguably more STAC-correct, not an error. But that means a client app must expose them as 12 flat checkboxes instead of the natural dropdown(s).

This generalizes to any scenario ensemble or time series (climate projections, SSP-RCP, dated snapshots) where variants are correctly separate collections.

Proposed change

Let each versions entry optionally carry its own collection reference, falling back to the parent collection when omitted:

{
  "id": "globio-msa-overall",
  "display_name": "Overall MSA",
  "group": "Biodiversity Intactness (GLOBIO MSA)",
  "versions": [
    { "label": "2015 baseline",
      "collection_url": ".../globio-msa-2015-overall/stac-collection.json",
      "asset_id": "globio-msa-2015-overall-cog" },
    { "label": "2050 Sustainability (SSP1×RCP2.6)",
      "collection_url": ".../globio-msa-ssp1rcp26-2050-overall/stac-collection.json",
      "asset_id": "globio-msa-ssp1rcp26-2050-overall-cog" }
    // ...
  ],
  "default_version": "2015 baseline"
}
  • Accept collection_url (and/or collection_id) on a version entry.
  • When present, resolve asset_id against that collection's assets; when absent, keep today's behavior (parent collection).
  • Backward-compatible: existing hydrobasins/GFW configs are untouched.

Implementation touches:

  • dataset-catalog.js: extractMapLayers version loop + _validateAssetIds need to fetch/lookup the referenced sibling collection(s). The catalog loader currently resolves one collection at a time, so this adds a prefetch of any collections referenced by version entries before the version list is built.
  • map-manager.js (~L174): version→MapLibre source/layer builder should already be agnostic once each version carries a resolved url/cogUrl + sourceLayer, but worth confirming.

Alternatives considered

  • Dual-home the COGs on the parent collection (attach all 12 -cog hrefs to the empty globio collection as convenience assets). Zero client-code change, but redundant and pushes a UI concern into the catalog.
  • Keep flat layers. Works, busier UI, doesn't scale to larger ensembles.

Making the client flexible (this issue) decouples UX grouping from STAC structure and fixes the whole class, so it's preferred over per-dataset catalog workarounds.

Context

Surfaced while adding the GLOBIO 4 MSA layers to the global-30x30 app (boettiger-lab/global-30x30). Code references against geo-agent@c76da27.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions