Question: Given one satellite overpass with a detected plume, what is the posterior over the source’s instantaneous emission rate ?
This sub-page is the glue between the per-event physics tiers (I–IV) and the population tier (V). It defines the formal interface that turns a per-event posterior into evidence for the population-scale fit. The cross-tier payload schema is pinned in the Tier V index; this page formalises how each payload is converted into a mark-likelihood contribution.
Two regimes of “instantaneous Q”¶
A. Full-physics posterior (Tier I / II / III output)¶
When you have radiance / column data and the wind field, run the per-event inversion described in Tier I (or II / III for richer transport):
This is the gold-standard per-event evidence — calibrated, with proper UQ, accounting for wind, transport, and instrument noise. Both and the prior are exposed downstream because the population fit needs to divide out the prior (see § Mark likelihood below).
B. Catalog with wind-source consistency rescaling¶
For published plume catalogs (IMEO, Carbon Mapper alerts [carbon_mapper], Tanager monthly reports, GHGSat releases [ghgsat,jervis2021ghgsat]), what’s available is typically a single point estimate of (mass flux, t/h or kg/s) per detection plus a per-event uncertainty estimate.
Catalog is not — it’s already wind-multiplied. Operational catalogs use the IME (Integrated Mass Enhancement) method [varon2018quantifying]: , where is the wind value the catalog producer used at retrieval time. When fusing catalogs that used different wind sources (IMEO uses GEOS-FP, Tanager uses HRRR, Carbon Mapper uses ECMWF, GHGSat uses its 1 km downscaled product), inconsistent winds give inconsistent . The fix is wind-source consistency rescaling:
with from a single agreed-upon reanalysis (default: ERA5).
Per-event uncertainty comes from controlled-release calibration. Sherwin et al. (2024) report 1σ log-scale errors per instrument:
Per-instrument 1σ (log-scale) per-event errors from Sherwin et al. 2024 controlled-release flights.
| Instrument | Per-event 1σ (log scale) |
|---|---|
| TROPOMI ([s5p_tropomi]) | ~0.50 (≈ ±50%) |
| GHGSat ([ghgsat]) | ~0.25 (≈ ±25%) |
| EMIT ([emit]) | ~0.30 |
| Tanager ([carbon_mapper]) | ~0.30 |
Mark likelihood — importance-weighted Monte Carlo¶
The TMTPP mark-likelihood contribution at detection is (see Tier V index § TMTPP foundations):
with the per-event likelihood, not the posterior. In sample-based practice (per-event posterior samples ):
The ratio is the importance weight that re-points the per-event posterior at the population mark distribution.
Three implementation regimes — with importance correction in each¶
Mark-integration regimes by per-event posterior representation.
| Regime | Per-event input | Mark integration |
|---|---|---|
| Point | (MAP / median) | ; ignores per-event uncertainty |
| Gaussian summary | (lognormal) | Closed form when is a power-law: . The full integrand requires a model — for sigmoidal POD with logistic form, the integral is tractable via Gauss–Hermite quadrature (≤ 10 nodes for 4-decimal accuracy) |
| Full posterior | sample set from Tier I–IV MCMC | — the importance-weighted MC estimator |
Each row evaluates the same integrand; the only difference is the per-event posterior representation.
Regime selection rule¶
def pick_regime(per_event: PosteriorPayload, mark_class: type[MarkDistribution]) -> Regime:
cv = per_event.coefficient_of_variation()
if cv < 0.20 and mark_class.is_smooth_on_scale(cv):
return "point"
elif cv < 0.50 and mark_class in CONJUGATE_FAMILIES:
return "gaussian"
else:
return "full" # CV > 0.50 (detection-floor events), multimodal posteriorsOperational rule:
Point acceptable only when per-event AND is approximately constant on that scale.
Gaussian summary suffices when AND .
Full posterior required when (typical for detection-floor, very-low- events), when has structure on the per-event uncertainty scale, or when the per-event posterior is multimodal.
Detection-floor and non-detection — explicit handling¶
Detected events with posterior mass below the threshold¶
The importance-weighted MC handles this automatically — is small for small so the contribution is naturally downweighted. No special code path. Just don’t point-summarise these events; promote to Full-posterior regime.
Non-detection events (catalog gaps)¶
Non-detections do not flow through the per-event payload — there’s no posterior to ingest. They contribute through the integrated thinned-rate term in the TMTPP likelihood:
What the cross-tier interface needs from the catalog: per-instrument overpass coverage (which times each instrument was looking at the basin), so the integral can be computed correctly.
The catalog ingestion module owns the distinction between “non-detect” and “noisy-detect-near-floor” — it’s a catalog/ingestion concern, not a per-event-payload concern.
Multi-source per overpass¶
Tier I Step 6 (RJMCMC), Tier IV §1 ( first-class), and Tier V index all assume is supported. The mark-likelihood contribution at a multi-source overpass is a product over sources, assuming within-overpass independence:
Per-event payload for is a list of sub-payloads, each with its own samples / summary / prior. v2 relaxes within-overpass independence — sources sharing a met realisation have correlated marks.
Per-event payload schema (full)¶
Pinned in the Tier V index; reproduced here for the implementation cycle:
@dataclass
class PerEventPayload:
sources: list[SourcePayload] # K_i entries; K_i ≥ 1
instrument_id: str # per-satellite POD dispatch
t_detection: float # UTC seconds, for λ(t)
quality: dict # bitmask from Tier I–IV
@dataclass
class SourcePayload:
posterior_samples: jax.Array | None # (S,) draws of Q
posterior_summary: tuple[float, float] | None # (μ_logQ, σ_logQ) lognormal shorthand
per_event_prior_logpdf: Callable[[float], float] # required for importance correction
x0_posterior: tuple[jax.Array, jax.Array] # (mu_xy, Cov_xy) — for spatial Cox v2 + de-dupper_event_prior_logpdf is the load-bearing field — without it the importance correction can’t be done.
Catalog ingestion — heterogeneous sources¶
Per-source ingestion adapters because schemas, units, wind sources, and quality conventions differ:
Catalog ingestion — schema, units, wind source, quality flags per provider.
| Catalog | Format | Units | Wind source | Quality flags |
|---|---|---|---|---|
| IMEO (UNEP) | CSV | t/h | GEOS-FP | provider-supplied |
| Tanager monthly ([carbon_mapper]) | parquet | kg/s | HRRR | confidence tier |
| Carbon Mapper alerts ([carbon_mapper]) | JSON | kg/h | ECMWF | per-pixel mask |
| GHGSat releases ([ghgsat]) | CSV | t/h | 1-km downscaled GHGSat product | binary detection |
Each ingestion adapter normalises to the internal PerEventPayload, applies wind-source consistency rescaling against , and emits a unified catalog with explicit provenance fields.
De-duplication¶
Same physical leak detected by multiple satellites → multiple catalog rows. v1’s independence assumption (see Tier V index § Independence assumption) requires de-duplication before the population fit. Default rule: spatial-temporal clustering with thresholds . Multi-instrument detections of the same cluster either collapse to one event with a fused per-event payload (preferred, when posteriors are compatible) or to the highest-confidence detection (fallback).
Module layout¶
Tier V.A module layout — concern, target module, status.
| Concern | Module | Status |
|---|---|---|
| Per-event posterior (Tier I) | gauss_plume.inference | ✓ — per_event_prior_logpdf / samples via #107 |
| Per-event posterior (Tier II/III) | lagrangian.inversion (closed form) / les_fvm.fourdvar (Laplace) | ✓ — payload extension via #107 |
| Per-event posterior export adapter | extended PerEventPosterior Protocol implemented by every tier | ☐ #107 |
| Cross-tier posterior catalog (Gaussian-summary v1) | plumax.population.catalog (event_from_posterior / EmissionCatalog) | 🚧 — duck-typed adapter over GaussianPosterior / LognormalPosterior / FusionPosterior; full-sample + prior-recall payload #107 |
| Population size distribution (V.A hierarchical fit) | plumax.population.size_distribution | 🚧 — hierarchical lognormal NUTS fit with per-event uncertainty propagation; importance correction #108 |
| Per-event payload summariser | plumax.population.catalog | ☐ #107 |
| Per-event prior recall | plumax.population.catalog (prior_logpdf) | ☐ #107 |
| Importance-weight calculator | plumax.population.importance | ☐ #108 |
| Regime selector | plumax.population.importance.Regime | ☐ #108 |
| De-duplication / spatial-temporal clustering | plumax.population.dedup | ☐ #111 |
| Wind-source consistency rescaling | plumax.population.wind_rescale | ☐ #111 |
| Catalog ingest — IMEO | plumax.population.ingest.imeo | ☐ #111 |
| Catalog ingest — Tanager | plumax.population.ingest.tanager | ☐ #111 |
| Catalog ingest — Carbon Mapper | plumax.population.ingest.carbon_mapper | ☐ #111 |
| Catalog ingest — GHGSat | plumax.population.ingest.ghgsat | ☐ #111 |
| Per-instrument overpass coverage (for non-detection integral) | plumax.population.ingest.overpass_coverage | ☐ #111 |
Validation strategy¶
Round trip on synthetic releases. Generate a known , run Tier I forward → noisy observation → Tier I inversion → check sits in the reported credible region. Standard sanity check.
Importance-correction round trip. Generate per-event posteriors using one prior ; run the population fit. Re-run with (informative). The recovered population posterior on should not move beyond IS noise. Failure here means the importance correction is mis-implemented — single most diagnostic test.
Importance-weight ESS diagnostic. Synthetic scenario where is a wide power-law and per-event posteriors are tight lognormals far from the bulk of . The ESS-per-event report should warn (); the population fit should not silently absorb biased estimates.
Regime-selector consistency. All three regimes (Point, Gaussian, Full) on the same per-event posterior should give the same population posterior modulo regime-appropriate noise. Catches importance-correction bugs in the Gaussian closed-form.
Wind-source consistency rescaling. Synthesize a catalog with for half the rows; before rescaling, the population fit on should be biased; after rescaling, bias gone.
De-duplication test. Two synthetic catalogs that are identical up to instrument label; correct de-duplication should collapse them to a single-instrument result.
Catalog-vs-full-inversion bias. Run the full Tier I inversion on a synthetic radiance, compute the you’d get from the IME method ([varon2018quantifying]) on the same data. Quantify systematic bias direction (Sherwin et al. 2024 documents this; replicate).
Proxy idempotency. Apply the per-event → mark-likelihood adapter on a degenerate case (point posterior, identity POD, uniform ): the population fit should reduce exactly to a uniform-weight max-likelihood fit on the point estimates. Catches indexing / weighting bugs.