# Water Mask Operation
#
# Binary surface-water mask via MNDWI threshold. Wrapper over
# imagery_radiometric_indices (MNDWI) + raster_calc threshold, exposed
# as a single named op for recipe ergonomics. Mirrors analysis/cloud_mask
# precedent — a named, threshold-based mask op.

id: imagery_water_mask
name: Water Mask
description: >
  Per-pixel binary surface-water mask derived from MNDWI
  (Modified Normalized Difference Water Index, Xu 2006). Output is uint8
  where 1 = water, 0 = non-water.

  The default threshold (MNDWI > 0) is the water-community convention
  (Xu 2006) and reliably separates open water from soil and vegetation
  at 10-30 m resolution. Override the threshold for application-specific
  needs: sediment-laden or turbid waters often require MNDWI > 0.3 to
  avoid commission errors; snow and glacier ice have high green
  reflectance and can be misclassified as water (pair with a snow/ice
  mask in cryosphere applications); shadowed terrain and dark built-up
  surfaces are also common confounders.

  Two modes are supported: `from-scene` (default) computes MNDWI
  internally from a multispectral scene's green and SWIR1 bands;
  `from-mndwi` thresholds a pre-computed MNDWI raster (useful when
  chaining from imagery_radiometric_indices).

version: 1.0.0
category: imagery
type: raster-to-raster

inputs:
  - name: image
    type: raster
    format: cog
    description: >
      Input raster. In `from-scene` mode (default), a multispectral
      scene with green and SWIR1 bands (e.g. Sentinel-2 B3+B11,
      Landsat 8/9 B3+B6). In `from-mndwi` mode, a single-band
      pre-computed MNDWI raster.
    required: true

outputs:
  - name: mask
    type: raster
    format: cog
    dtype: uint8
    description: >
      Binary water mask. 1 = water, 0 = non-water. NoData passed
      through from input.

params:
  mode:
    type: string
    enum: [from-scene, from-mndwi]
    default: from-scene
    description: >
      `from-scene`: compute MNDWI internally from green + SWIR1 bands
      of a multispectral scene. `from-mndwi`: threshold a pre-computed
      single-band MNDWI raster (use when chaining from
      imagery_radiometric_indices).

  threshold:
    type: number
    default: 0.0
    description: >
      MNDWI threshold above which a pixel is classified as water.
      Default 0.0 is the canonical Xu 2006 threshold and works for
      most open-water scenarios at 10-30 m. Override per use case:
      use ~0.3 for sediment-laden or turbid waters to reduce false
      positives; lower thresholds may be needed for shallow or
      vegetated wetlands. Snow, glacier ice, and deep terrain shadow
      are known confounders — combine with auxiliary masks where
      relevant.

  green_band:
    type: string
    default: green
    description: >
      Name (or index) of the green band in the input scene. Used only
      when mode=from-scene. Sentinel-2 B3, Landsat 8/9 B3.

  swir1_band:
    type: string
    default: swir1
    description: >
      Name (or index) of the SWIR1 band in the input scene. Used only
      when mode=from-scene. Sentinel-2 B11, Landsat 8/9 B6.

execution:
  realtime_max_km2: 1000
  cost_per_km2: 0.001
  time_per_km2_sec: 0.3
  memory_profile: low
  profile:
    cpu: low
    memory: low
    io: medium
  scaling:
    model: linear
    parallelizable: true
    min_chunk_km2: 1

cache_policy:
  ttl_days: 30
  invalidate_on: [source_update, param_change]

# backends: audited 2026-08-14 (defect 50). NOTHING dispatches this op: no arm in folia-engine
# `dispatch_op`, no `registerOp`/OP_TABLE entry in packages/compute, no `_BUILTIN_OP_MAP`
# key in folia/compute.py, no backend manifest. Declared EMPTY on purpose — an absent
# block would be indistinguishable from one nobody ever wrote.
backends: {}

display_hints:
  map:
    renderer: maplibre
    palette: water
    opacity: 0.7
  info:
    fields: [water]
    format: "{value}"
    section: Hydrology

examples:
  - name: Water mask from Sentinel-2 scene
    description: >
      One-call water mask from a Sentinel-2 L2A scene using the
      canonical MNDWI > 0 threshold.
    inputs:
      image: "sentinel2_l2a.tif"
    params:
      mode: from-scene
      threshold: 0.0
      green_band: B3
      swir1_band: B11

  - name: Water mask from pre-computed MNDWI
    description: >
      Threshold an MNDWI raster produced by imagery_radiometric_indices.
      Use the stricter 0.3 threshold for a sediment-laden estuary.
    inputs:
      image: "mndwi.tif"
    params:
      mode: from-mndwi
      threshold: 0.3

sources:
  - title: "Xu 2006 — Modification of NDWI to enhance open water features in remotely sensed imagery"
    citation: "Xu, H. (2006). International Journal of Remote Sensing, 27(14), 3025-3033."
    doi: 10.1080/01431160600589179
  - title: "JRC Global Surface Water (Pekel et al. 2016)"
    url: https://global-surface-water.appspot.com/
  - title: "awesome-spectral-indices (MNDWI entry)"
    url: https://github.com/awesome-spectral-indices/awesome-spectral-indices
