# Methodology — Ignition Density Layer v0.3 ## Overview The Petrel Ignition Density Layer answers "where do fires start?" at native ~5 km (0.05°) globally. It composes two independent ignition sources: 1. **Anthropic** — a gradient-boosted classifier that predicts the probability of observed fire presence from the human + biome context of a cell. 2. **Lightning** — a relative index: observed flash climatology times an empirical per-climate-zone probability that a flash starts a fire. and combines them into a single **total ignition propensity** used by Cell2Fire's ignition sampler in the Petrel Wildfire Hazard. ``` GHSL pop/built/smod ─┐ HYDE crop/grazing ───┼─> HistGradientBoosting ──> anthro P(fire|human) ∈ [0,1] Köppen class ────────┘ (FIRMS labels) │ ├─> total = 1-(1-Pa)(1-Pl) LIS/OTD flash climatology ──┐ │ (relative, 0-1) per-Köppen p(ignition|flash)┴─> lightning relative 0-1 ─┘ ``` ## Working grid — why ~5 km, not 90 m Everything is computed on a common 0.05° grid (7200 × 2900 cells, 60° S–84° N, EPSG:4326). This is the **native** product resolution, deliberately: - The coarsest driver (LIS/OTD flash climatology) is 0.5°; GHSL inputs are 1 km; HYDE is 5′ (~9 km). A 90 m output would be pure interpolation — storage without skill. - ~5 km resolves the signals that matter for ignition — settlement clusters, the wildland-urban interface, agricultural belts, convective climatology. Downstream consumers that need finer grids (e.g. the Petrel wildfire pipeline's 90 m fuel grid) resample on read. ## Anthropic composer ### Features Six covariates, resampled onto the working grid: | Feature | Source | Native res | Transform | |---|---|---|---| | `ghsl_pop` | GHSL GHS-POP R2023A (2020 epoch) | 1 km | log1p | | `ghsl_built` | GHSL GHS-BUILT-S R2023A (2020 epoch) | 1 km | log1p | | `ghsl_smod` | GHSL GHS-SMOD R2023A settlement class (2020 epoch) | 1 km | raw (ordinal) | | `hyde_cropland` | HYDE 3.3 cropland area, 2020 AD slice | 5′ | log1p | | `hyde_grazing` | HYDE 3.3 grazing-land area, 2020 AD slice | 5′ | log1p | | `koppen` | Beck 2018 Köppen-Geiger class | ~1 km | raw (categorical) | Heavy-tailed density predictors are log1p-transformed; the ordinal settlement degree and the Köppen class are left raw for the trees to threshold-split. ### Labels NASA FIRMS active-fire detections (MODIS + VIIRS, 2015–2023), reduced to a binary **fire-presence** label per cell: has a satellite fire detection been observed here or not. ### Model A single global `HistGradientBoostingClassifier` (scikit-learn): 400 boosting iterations, learning rate 0.05, max 63 leaf nodes, min 200 samples per leaf, L2 regularization 1.0, early stopping on a 10% validation split. Trained on up to 1.5 M randomly sampled valid cells. The output is the classifier's predicted probability, `P(fire presence | human + biome context)`. **Why a tree ensemble and not a regression?** Human wildfire ignition is empirically **hump-shaped in population**: near zero in wilderness (no people), rising through rural and wildland-urban-interface densities (people plus fuel), then falling again in fuel-less dense-urban cores (Syphard et al. 2007; Bistinas et al. 2014; Knorr et al. 2014). A monotonic (logistic) fit cannot represent that shape, and with three collinear human-presence proxies (pop / built / smod) it splits the signal into unstable, sign-flipping coefficients. The gradient-boosted trees recover the hump and the population × biome interactions directly; Köppen enters as a context feature rather than a hard region split, so structure is shared across climate zones. ## Lightning composer ### Flash climatology NASA LIS/OTD 0.5° High Resolution Full Climatology (HRFC v2.3.2015, combined OTD + TRMM-LIS record), giving the long-term mean flash density in flashes km⁻² yr⁻¹, bilinearly resampled onto the working grid. ### Per-Köppen ignition efficiency Most flashes do not start fires, and the fraction that do varies strongly with climate (fuel moisture, dry-lightning frequency). For each Köppen-Geiger class we estimate ``` p(ignition | flash, class) = Σ FIRMS fire density / Σ flash density ``` over the cells of that class, using a FIRMS-derived lightning-attributable fire density map. The ratio is clipped to the physically sensible range [0, 0.1] fires per flash; classes with fewer than 50 valid flash cells are skipped (they carry no lightning estimate and contribute zero to the total). ### Output ``` lightning = flash_density × p(ignition | flash, Köppen class) ``` normalised by the global maximum to a **relative index in [0,1]**. It is **not** an absolute rate. Through v0.2 this band was labelled `events km⁻² yr⁻¹` and this document called it a physical rate. That was wrong by roughly three orders of magnitude: integrated over the 129.3 M km² land footprint, the v0.2 band implies ~1.16 × 10⁸ lightning ignitions per year globally, against a real-world figure of order 5 × 10⁴. The cause is in the conversion step — `p(ignition|flash)` is formed by dividing a **record-total** burned count by an **annual** flash rate, and the ratio is then clipped at 0.1, so for many regions the absolute level was set by the clip ceiling rather than by data. The **relative** pattern (flash density × regional efficiency) is unaffected by this, and is what every downstream consumer actually uses — including the total, which normalises by its own p99. Recovering a true rate requires fixing the time-base mismatch and removing the clip: a v1.0 item. ## Combining into the total The two sources live on different scales — `anthro` is a probability, `lightning` is a **relative index** (it is NOT a rate; see above). To combine them: 1. Lightning is converted to a probability by a Poisson transform, **`P_lightning = 1 − exp(−l / l₀)`**, where `l` is the shipped lightning index and **`l₀ = 0.220418`**. This replaced v0.1's `clip(l / p99, 0, 1)`, which pinned 2.26% of land at exactly 1.0 — the probabilistic OR below is only *defined* on probabilities, so normalising and clipping a non-probability was invalid on its own terms. 2. The sources are combined as a probabilistic OR: ``` total = 1 − (1 − P_anthro) × (1 − P_lightning) = 1 − (1 − P_anthro) × exp(−l / 0.220418) ``` **Reproducing `total` from the shipped bands.** The second form above is exact (median residual ~2e−05 against the shipped raster). ⚠ **`l₀` is NOT recoverable from the delivered product**: it is a build-time percentile taken over a different pixel population than the coast-clipped raster you receive, so recomputing p99 from the shipped `lightning` band gives ~0.299, not 0.220418. Use the published constant. It is also the scale currently under review (see `RELEASE_NOTES.md`), so treat it as **provisional and vintage-specific** — do not carry it across vintages. — the chance a cell sees an ignition from *either* source. The result is the **relative spatial ignition weight** Cell2Fire's sampler consumes. **What `total` is not:** an absolute ignition rate. The p99 normalization makes it a within-vintage relative field — "ignitions per year" calibration against ground-truth ignition databases is the flagged v1.0 item. A cell where one source is missing takes the other source alone; a cell is NoData only where both are missing. ## Post-processing (Petrel canonical promote) Each of the three fields goes through the standard Petrel product chain: 1. **Coast clip** to the GSHHG-f full-resolution shoreline (~100 m native, `all_touched` — any cell touching real land keeps its value). Ocean is NoData. Antarctica is excluded by standard (GSHHG L1 only). 2. **Compact uint16 re-encode**: physical values map linearly onto the uint16 range below the NoData sentinel (65535), with the factor recorded in the `PETREL_SCALE` tag (`physical = raw × PETREL_SCALE`). Caps: 1.0 for all three bands (`lightning` capped at 16.0 through v0.2, when it was mislabelled a rate). 3. **Internal tiling + overviews** (2× through 64×) for efficient windowed and zoomed-out reads. 4. **Audit** — automated checks on encoding tags, overviews, coastal reference points, and bundle completeness before any release. ## Code references - `petrelml/features/ignition.py` — both composers, the combination, and the working-grid resamplers - `configs/ignition_layer.yaml` — the full build + promote configuration - `petrelml/postprocess/` — the canonical promote chain (coast clip, re-encode, overviews, bundle, STAC, previews, audit) - `docs/layers/ignition_design.md` — original design note (predates v0.3 implementation decisions; this document reflects what actually shipped) ## References - Syphard, A. D., et al. (2007). Human influence on California fire regimes. *Ecological Applications*, 17(5), 1388–1402. - Bistinas, I., et al. (2014). Causal relationships versus emergent patterns in the global controls of fire frequency. *Biogeosciences*, 11, 5087–5101. - Knorr, W., et al. (2014). Impact of human population density on fire frequency at the global scale. *Biogeosciences*, 11, 1085–1102. - Cecil, D. J., Buechler, D. E., & Blakeslee, R. J. (2014). Gridded lightning climatology from TRMM-LIS and OTD: dataset description. *Atmospheric Research*, 135–136, 404–414.