Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Tier V.A — Instantaneous emission estimation

Question: Given one satellite overpass with a detected plume, what is the posterior over the source’s instantaneous emission rate QQ?

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):

p(Q∣overpassi)  ∝  Li(Q)⋅πper-event(Q),Li(Q)  =  p(observationi∣Q)p(Q \mid \text{overpass}_i) \;\propto\; L_i(Q) \cdot \pi_\text{per-event}(Q), \qquad L_i(Q) \;=\; p(\text{observation}_i \mid Q)

This is the gold-standard per-event evidence — calibrated, with proper UQ, accounting for wind, transport, and instrument noise. Both Li(Q)L_i(Q) and the prior πper-event(Q)\pi_\text{per-event}(Q) are exposed downstream because the population fit needs to divide out the prior (see § Mark likelihood below).

B. Catalog QQ 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 QQ (mass flux, t/h or kg/s) per detection plus a per-event uncertainty estimate.

Catalog QQ is not Q/UQ/U — it’s already wind-multiplied. Operational catalogs use the IME (Integrated Mass Enhancement) method [varon2018quantifying]: Qcatalog≈IME⋅Ucatalog/LplumeQ_\text{catalog} \approx \text{IME} \cdot U_\text{catalog} / L_\text{plume}, where UcatalogU_\text{catalog} 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 QQ. The fix is wind-source consistency rescaling:

Qcorrected  =  Qcatalog⋅UtargetUcatalogQ_\text{corrected} \;=\; Q_\text{catalog} \cdot \frac{U_\text{target}}{U_\text{catalog}}

with UtargetU_\text{target} 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.

InstrumentPer-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 ii is (see Tier V index § TMTPP foundations):

p(detectedi∣f,λ,Pd)  =  ∫Pd(Q) Li(Q) f(Q) dQp(\text{detected}_i \mid f, \lambda, P_d) \;=\; \int P_d(Q)\, L_i(Q)\, f(Q)\, \mathrm{d}Q

with Li(Q)=p(observationi∣Q)L_i(Q) = p(\text{observation}_i \mid Q) the per-event likelihood, not the posterior. In sample-based practice (per-event posterior samples Qi(s)∼p(Q∣observationi)Q_i^{(s)} \sim p(Q \mid \text{observation}_i)):

p(detectedi∣f,λ,Pd)  ≈  1S ∑s=1S Pd(Qi(s)) f(Qi(s))πper-event(Qi(s))p(\text{detected}_i \mid f, \lambda, P_d) \;\approx\; \frac{1}{S}\, \sum_{s=1}^{S}\, P_d(Q_i^{(s)})\, \frac{f(Q_i^{(s)})}{\pi_\text{per-event}(Q_i^{(s)})}

The ratio f/πper-eventf / \pi_\text{per-event} 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.

RegimePer-event inputMark integration
PointQ^i\hat{Q}_i (MAP / median)Pd(Q^i)⋅f(Q^i)/πper-event(Q^i)P_d(\hat{Q}_i) \cdot f(\hat{Q}_i) / \pi_\text{per-event}(\hat{Q}_i); ignores per-event uncertainty
Gaussian summary(μlog⁡Q,σlog⁡Q2)(\mu_{\log Q}, \sigma^{2}_{\log Q}) (lognormal)Closed form when ff is a power-law: ∫Q−α LogNormal⁡(Q∣μ,σ2) dQ=exp⁡(−αμ+12α2σ2)\int Q^{-\alpha}\, \operatorname{LogNormal}(Q \mid \mu, \sigma^{2})\, \mathrm{d}Q = \exp(-\alpha\mu + \tfrac{1}{2}\alpha^{2}\sigma^{2}). The full integrand requires a PdP_d model — for sigmoidal POD with logistic form, the integral is tractable via Gauss–Hermite quadrature (≤ 10 nodes for 4-decimal accuracy)
Full posteriorsample set {Qi(s)}\{Q_i^{(s)}\} from Tier I–IV MCMC(1/S) ∑sPd(Qi(s))⋅f(Qi(s))/πper-event(Qi(s))(1/S)\, \sum_s P_d(Q_i^{(s)}) \cdot f(Q_i^{(s)}) / \pi_\text{per-event}(Q_i^{(s)}) — the importance-weighted MC estimator

Each row evaluates the same Pd⋅f/πP_d \cdot f / \pi 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 posteriors

Operational rule:


Detection-floor and non-detection — explicit handling

Detected events with posterior mass below the threshold

The importance-weighted MC handles this automatically — Pd(Q(s))P_d(Q^{(s)}) is small for small Q(s)Q^{(s)} 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:

−∫0Tλ(t)[∫Pd(Q) f(Q) dQ]dt- \int_{0}^{T} \lambda(t) \left[\int P_d(Q)\, f(Q)\, \mathrm{d}Q\right] \mathrm{d}t

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 (K=nsourcesK = n_\text{sources} first-class), and Tier V index all assume K>1K > 1 is supported. The mark-likelihood contribution at a multi-source overpass is a product over sources, assuming within-overpass independence:

p(detectionsi∣f,… )  ≈  ∏k1S∑s=1S Pd(Qk(s)) f(Qk(s))πper-event(Qk(s))p(\text{detections}_i \mid f, \dots) \;\approx\; \prod_{k} \frac{1}{S}\sum_{s=1}^{S}\, P_d(Q_k^{(s)})\, \frac{f(Q_k^{(s)})}{\pi_\text{per-event}(Q_k^{(s)})}

Per-event payload for Ki>1K_i > 1 is a list of KiK_i 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-dup

per_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.

CatalogFormatUnitsWind sourceQuality flags
IMEO (UNEP)CSVt/hGEOS-FPprovider-supplied
Tanager monthly ([carbon_mapper])parquetkg/sHRRRconfidence tier
Carbon Mapper alerts ([carbon_mapper])JSONkg/hECMWFper-pixel mask
GHGSat releases ([ghgsat])CSVt/h1-km downscaled GHGSat productbinary detection

Each ingestion adapter normalises to the internal PerEventPayload, applies wind-source consistency rescaling against UERA5U_\text{ERA5}, 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 (Δd≤5 km,Δt≤12 h)(\Delta d \leq 5\text{ km}, \Delta t \leq 12\text{ h}). 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.

ConcernModuleStatus
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 adapterextended 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 summariserplumax.population.catalog☐ #107
Per-event prior recallplumax.population.catalog (prior_logpdf)☐ #107
Importance-weight calculatorplumax.population.importance☐ #108
Regime selectorplumax.population.importance.Regime☐ #108
De-duplication / spatial-temporal clusteringplumax.population.dedup☐ #111
Wind-source consistency rescalingplumax.population.wind_rescale☐ #111
Catalog ingest — IMEOplumax.population.ingest.imeo☐ #111
Catalog ingest — Tanagerplumax.population.ingest.tanager☐ #111
Catalog ingest — Carbon Mapperplumax.population.ingest.carbon_mapper☐ #111
Catalog ingest — GHGSatplumax.population.ingest.ghgsat☐ #111
Per-instrument overpass coverage (for non-detection integral)plumax.population.ingest.overpass_coverage☐ #111

Validation strategy


Open questions