Rainforest-based intra- and inter-calibration of C-band scatterometer backscatter data records (ERS-1/2 ESCAT and Metop ASCAT), after Reimer (2014).
Stable natural targets (tropical rainforest cells selected for low azimuthal anisotropy, low temporal variability, and spatial homogeneity) provide a common reference: a reference satellite's backscatter–incidence-angle polynomial is fit over the targets, and per-observation deviations of the target satellites from that polynomial yield inter-calibration corrections (c_ies) per beam, orbit direction, and swath side — plus optional time-resolved intra-calibration corrections (c_ias).
uv pip install -e '.[dev,figs]' # or pip; figs adds matplotlib + cartopyInput is dense (gpi, obs, beam) Zarr time-series stores. Each data record
to calibrate is described in the run config as a named dataset: a mission
type (ers or metop — fixes the store layout, extra variables, and QC
filter; new types are added via MISSION_TYPES in data.py), the zarr
store path, and the satellite id value within that store. Any number of
target datasets can be calibrated against one reference dataset. The
artifact store root comes from --store, the config's store field, or
the SCATTERCAL_STORE env var.
A run is specified by a JSON config file naming the datasets involved, the calibration mode(s), and every parameter:
scattercal init > run.json # interactive: prompts for the store
# path and each dataset (name,
# mission type, zarr path, sat id);
# --no-prompt emits placeholders
scattercal run run.json # run it
scattercal figs run.json # + publication figure set
scattercal list --store DIR # what's in the artifact store
scattercal compare RUN_A RUN_B # diff two c_ies parameter sets
scattercal run --help # incl. --set KEY=VALUE overridesscattercal init --template intercal (default) inter-calibrates the target
datasets against the reference dataset; --template intracal calibrates a
single dataset on its own targets (run_intercal/run_intracal in the
config select the modes); --template smoke is a small end-to-end sanity
run. After the wizard, set each satellite's ref_period (and any
seasonality/exclusion windows) in the config.
Pipeline stages (extraction → criteria → target selection → reference
polynomial → inter-/intra-calibration → validation) are cached
content-addressed under the store root; every artifact directory carries a
manifest.json with its full parameter provenance. Re-running an experiment
is a no-op; changing a parameter re-runs exactly the affected stages.
import scattercal as sc
ref = sc.DatasetSpec("myref", "metop", "/path/to/store.zarr", sat_id=3)
ds = sc.extract(ref, gpi_indices) # canonical ragged format
ds = sc.filter_mission(ds, ref.mission) # QC
criteria, norm = sc.compute_criteria(ds)
targets = sc.select_targets(criteria, max_azi_ani_db=0.2,
max_temp_var_db=0.4, max_spatial_db=0.15)See examples/calibrate_small_region.py for the full chain through to
c_ies parameters, and the module docstrings for the rest of the surface.
- Backscatter in dB; gamma0 = sigma0 − 10·log10(cos θ); beams ordered (fore, mid, aft)
- Polynomial coefficients ascending, evaluated at (θ − 40°)
- Reimer, C. (2014): Calibration of space-borne scatterometers: towards a consistent climate data record for soil moisture retrieval. PhD thesis, TU Wien.
- Harrison, C. et al. (2026): Practical Implementation and Adaptation of Rainforest-Based Inter-calibration for ESCAT-ASCAT Scatterometer Data Records. ISPRS Ann. Photogramm. Remote Sens. Spatial Inf. Sci., XI-3-2026, 411–417. https://doi.org/10.5194/isprs-annals-XI-3-2026-411-2026