name: ambrym
version: "0.1"
category: events-hazards
themes: [hazards]
family: active-lava-flow-mapping
description: >
  Active lava lake monitoring and eruption mapping at Ambrym volcano, Vanuatu,
  using Sentinel-2 SWIR and NBR. Ambrym is a basaltic caldera that hosted
  persistent lava lakes at Marum and Benbow craters until a December 2018
  submarine dyke intrusion drained them abruptly. The recipe captures the
  lava-lake era and its sudden end; B12 SWIR tracks the lake thermal signal
  through near-constant tropical cloud cover. The active-lava-mask layer is
  the primary signal for the lake period, while dNBR documents the caldera
  floor change following drainage.

settings:
  default_bbox: [167.97, -16.4, 168.27, -16.1]   # Ambrym caldera, Vanuatu
  default_crs: EPSG:32759                          # UTM 59S, metric
  active_lava_b12_threshold: 0.5    # B12 reflectance > this → thermally active lava
  cooled_lava_nbr_threshold: -0.5   # NBR < this → dark cooled lava / severe burn
  cloud_cover_max_pct: 70           # Near-constant tropical cloud; SWIR still penetrates
  prefire_reference:
    start: "2017-01-01"
    end: "2017-09-01"               # Stable lava-lake era reference window

inputs:
  aoi:
    bbox: [167.97, -16.4, 168.27, -16.1]
    crs_target: EPSG:32759
    notes: Covers Ambrym caldera including Marum and Benbow crater complexes

  date_range:
    start: "2017-01-01"
    end: "2026-06-01"

  collection:
    uri: "@sentinel-2-l2a"
    stac_endpoint: "https://earth-search.aws.element84.com/v1"

layers:

  # ── SOURCE ──────────────────────────────────────────────────────────────────

  source/s2:
    type: raster_timeseries
    uri: "@sentinel-2-l2a"
    description: >
      Sentinel-2 L2A, bi-weekly scenes (not composited — individual acquisitions
      preserve active-flow evolution). Minimum bands for NBR + thermal anomaly.
    params:
      bbox: [167.97, -16.4, 168.27, -16.1]   # COG spatial window
      datetime: "2017-01-01/2026-06-01"
      assets:
        - B04    # Red — for NBR denominator context; also RGB
        - B08    # NIR — numerator of NBR; dark over cooled lava
        - B12    # SWIR2 — saturates at lava temperatures; penetrates SO2 plume
        - SCL    # Scene classification — mask cloud and cloud shadow
      query:
        "eo:cloud_cover": { lt: 70 }

  source/s2-prefire:
    type: raster
    uri: "@sentinel-2-l2a"
    description: Stable lava-lake era reference composite for dNBR calculation.
    params:
      bbox: [167.97, -16.4, 168.27, -16.1]
      datetime: "2017-01-01/2017-09-01"
      assets: [B08, B12, SCL]
      query:
        "eo:cloud_cover": { lt: 40 }
      aggregate: median

  # ── COMPUTE ─────────────────────────────────────────────────────────────────

  compute/cloud-masked:
    type: raster_timeseries
    compute:
      op: cloud_mask_sentinel2
      inputs:
        data: { layer: source/s2 }
      params:
        scl_classes: [4, 5, 6, 11]   # keep: vegetation, bare soil, water, snow/ice

  compute/nbr:
    type: raster_timeseries
    description: NBR = (B08 - B12) / (B08 + B12). High = healthy veg; low = bare/burned.
    compute:
      op: raster_calc
      inputs:
        data: { layer: compute/cloud-masked }
      params:
        expression: "(B08 - B12) / (B08 + B12)"
        output_band: nbr

  compute/active-lava-mask:
    type: raster_timeseries
    description: >
      Active lava: B12 > 0.5 (SWIR2 saturation from thermal emission at ~600°C+).
      Primary signal for the lava-lake era — tracks the persistent Marum and
      Benbow thermal anomalies and captures the abrupt December 2018 drainage.
    compute:
      op: raster_calc
      inputs:
        data: { layer: compute/cloud-masked }
      params:
        expression: "(B12 > active_lava_b12_threshold).astype('uint8')"
        active_lava_b12_threshold: "${settings.active_lava_b12_threshold}"
        output_band: active_lava

  compute/prefire-nbr:
    type: raster
    description: Stable lava-lake era NBR reference from the Jan-Sep 2017 composite.
    compute:
      op: raster_calc
      inputs:
        data: { layer: source/s2-prefire }
      params:
        expression: "(B08 - B12) / (B08 + B12)"
        output_band: nbr_prefire

  compute/dnbr-stack:
    type: raster_timeseries
    # raster_calc reads ONE raster and binds bands positionally (b1..bN), so two-layer
    # arithmetic composes through stack_concat: stack the pair, difference the bands.
    compute:
      op: stack_concat
      inputs:
        rasters:
          - { layer: compute/prefire-nbr }   # band 1: prefire NBR
          - { layer: compute/nbr }   # band 2: postfire NBR

  compute/dnbr:
    type: raster_timeseries
    description: >
      dNBR = NBR_prefire - NBR_postfire. Positive = vegetation/surface loss.
      USGS severity classes: low 0.1-0.27, mod-low 0.27-0.44, mod-high 0.44-0.66, high >0.66.
    compute:
      op: raster_calc
      inputs:
        data: { layer: compute/dnbr-stack }
      params:
        expression: "b1 - b2"   # NBR_prefire - NBR_postfire
        output_band: dnbr

  # ── RESULTS ─────────────────────────────────────────────────────────────────

  result/lava-flow-extent:
    type: vector
    description: >
      Dated lava anomaly polygons: cooled/altered surface (NBR < -0.5) per
      acquisition. The active-lava-mask (B12 thermal) is the primary signal for
      the lake period; this flow-extent layer documents the caldera floor
      alteration following the December 2018 dyke-drainage event.
      Attributes: date, area_km2, type (active | cooled), dnbr_mean.
    compute:
      op: raster_to_vector_timeseries
      inputs:
        active: { layer: compute/active-lava-mask }
        dnbr: { layer: compute/dnbr }
      params:
        cooled_threshold: "${settings.cooled_lava_nbr_threshold}"
        min_area_ha: 0.5

  result/dnbr-severity:
    type: raster
    description: Peak dNBR severity COG — maximum dNBR value per pixel across all post-drainage scenes.
    compute:
      op: raster_reduce
      inputs:
        timeseries: { layer: compute/dnbr }
      params:
        reducer: max
        format: cog
        dtype: float32

outputs:
  primary:
    - result/lava-flow-extent   # GeoParquet — dated anomaly polygons
    - result/dnbr-severity      # COG — peak burn severity map
  show_your_work:
    - compute/nbr               # zarr — per-scene NBR
    - compute/active-lava-mask  # zarr — active lava detections (primary signal)

cache:
  scope:
    - inputs.aoi.bbox
    - inputs.date_range
    - settings.active_lava_b12_threshold
    - settings.cooled_lava_nbr_threshold
  storage: ./cache/
  reuse_policy: hash_inputs

license:
  recipe: Apache-2.0
  output_dataset: CC-BY-4.0
  upstream_data:
    - { source: sentinel-2-l2a, license: copernicus-open }
