Skip to main content

Phase 2 — Processing Pipeline

Duration: ~14 working days Critical-path predecessor: Phase 1 (locked) Status: in progress

Deliverables (§5.4)

  1. Atmospheric correction — Py6S radiative transfer + Ross-Li BRDF + SCS+C topographic
  2. Cloud / shadow masking — Fmask 4.0 + s2cloudless + Himalayan tuning
  3. Endmember unmixing — LSMA + MESMA + CUDA kernel (swir_unmix_kernel.cu)
  4. Snow decision tree — multi-criterion fusion (NDSI / NIR / TIR / DEM / cloud / temporal)
  5. CV subsystem — pyramidal LK, Farnebäck, SIFT co-registration
  6. SAR pipeline — σ⁰ calibration, Refined Lee, Nagler & Rott wet-snow
  7. Thermal / energy balance — full snowmelt energy budget Q_m
  8. Biosphere masking — Liu et al. canopy-gap correction + RF classifier
  9. Validation — R² ≥ 0.85 vs MOD10A1 (acceptance gate)

Acceptance Gate

Daily basin-wide FSC R² ≥ 0.85 vs MOD10A1, demonstrated over a 30-day rolling window.

Run:

cd snow-ir-backend
pytest tests/processing -v --cov=snow_ir.processing
python -m snow_ir.validation.fsc_vs_mod10a1 \
--snow-ir data/work/snow/<asset>_FSC.tif \
--reference data/mod10a1/<date>.tif \
--asset-id <asset>

Run a Scene End-to-End

from datetime import datetime, timezone
from pathlib import Path
from snow_ir.processing.atmospheric.six_s_correction import AtmosphericState
from snow_ir.orchestration.scene_pipeline import SceneInputs, process_scene

inputs = SceneInputs(
asset_id="S2_T43SDV_20240115",
sensor="S2-L2A",
acquired_at=datetime(2024, 1, 15, tzinfo=timezone.utc),
band_paths={
"B02": Path("data/raw/B02.tif"),
"B03": Path("data/raw/B03.tif"),
"B04": Path("data/raw/B04.tif"),
"B08": Path("data/raw/B08.tif"),
"B11": Path("data/raw/B11.tif"),
"B12": Path("data/raw/B12.tif"),
},
dem_path=Path("data/dem/copernicus_glo30.tif"),
)
atm = AtmosphericState(
aot_550nm=0.12, water_vapour_g_cm2=0.8, ozone_du=300.0,
altitude_km=3.5, solar_zenith_deg=55.0, solar_azimuth_deg=160.0,
view_zenith_deg=5.0, view_azimuth_deg=100.0, month=1, day=15,
)
process_scene(inputs, atm)