Plume vetting¶
A matched filter scores each pixel by one projection of its spectrum onto methane’s target, so anything that removes light under methane’s 2.3 μm band scores: carbonate and clay soils, salt pans, dark water, shadows, striping. A segmentation network on the matched-filter map learns plume shapes, which a plume-shaped confounder also has. Plume vetting (Xiang et al. [1]; Růžička et al. [2]) goes back to the radiances behind a candidate. It pairs the candidate’s strongest pixels with pixels outside it that have the same surface, divides them, and asks whether the ratio has the shape of methane’s transmittance. EMIT’s daily methane digest alerts without review when the misfit score is below 0.3.
The work splits along a package boundary, “radiative transfer does not know about plumes”. radtrax answers a question about spectra: given two sets of pixels, how similar is the ratio of their paired mean radiances to a gas’s transmittance? It returns the fitted column and , and knows nothing of candidates. plumax answers the questions about plume objects: which of a candidate’s pixels are in (the seeds) and which are out (the background pool), how this scene’s clutter scores in the candidate’s shape (the null), and what to decide.
Vetting is a second test on the same data, not an independent one: its pixels are chosen by the matched filter and come from the same cube. It is more selective because it tests the shape of the absorption across a window of bands, where the matched filter tests one projection.
1. The test plumax runs¶
For in-pixels and out-pixels of one radiance cube, radtrax pairs them one to one on the bands the gas does not absorb, keeps the best-matched half, and divides the pairs’ mean radiances into a ratio spectrum , with the ratio of the paired surfaces and the gas’s band transmittance from radtrax’s forward model. It fits with a Legendre continuum times , profiling over a grid of refined between its nodes, and scores the fit with Xiang et al.'s eq. 11, : 0 for a perfect fit, about 1 when nothing gas-shaped is left. The derivations, the curve of growth and the reasons for each setting are on radtrax’s absorption-shape test page.
Everything below is how plumax chooses and from a candidate, and what it does with the scores.
2. Seeds and the background pool¶
Write for the candidate’s pixels with a finite matched-filter score , and for the score’s 99th percentile over . The seeds are the strongest pixels of at or below the cap, grown by one pixel inside (select_seeds):
with one binary dilation by the 3 × 3 square and . The background pool is every pixel within a box of pixels around the seeds’ bounding box, outside every candidate of the scene, with a small matched-filter score (background_pool):
with the window’s mf_background_mol_m2 (30 ppm·m for EMIT’s CH₄ window) and . So , and for every candidate. These are the reference package’s settings [3], pv/config/config.yaml; the two sets then go to radtrax’s pairing as flat pixel indices.
Why each setting
Seeds come from the matched filter. The depth of methane’s absorption in grows with , so the strongest pixels give the deepest and best-resolved transmittance.
The seeds’ noise is not innocent. Choosing the largest scores selects pixels whose noise happens to point along methane’s target, so the seeds’ spectra are biased toward methane’s shape by the selection itself. This is one reason vetting is not independent of the matched filter. Growing the seeds by one pixel adds neighbours that were not chosen for their own noise, and it keeps the in-set a connected region rather than a scatter of isolated pixels.
The cap at the 99th percentile. The reference code does not say why it caps there. The cap drops the mask’s most extreme scores, which is where a single bad or saturated pixel would land.
Growth is one dilation. The reference code grows the seeds with a Gaussian filter of σ = 1 and keeps pixels above 0.05. On a binary mask that is exactly one 3 × 3 dilation, which plumax computes as a max-pool in JAX.
The background pool. A small matched-filter score keeps plume pixels out of , where they would cancel the signal being tested. The box keeps the pool near the seeds, so that each pair shares its sun, elevation and water vapour, which is what lets them cancel in the ratio. Every candidate of the scene is kept out, not only this one, so a second plume or confounder never serves as background.
3. A null from the same scene¶
The honest null is this scene’s clutter with no plume. Vet copies of the mask, each rotated and translated to where there is no candidate (null_masks), exactly as the candidate was vetted, and report (null_pvalue)
over the copies with a finite score. 's threshold depends on the band set, the continuum’s degree and the ratio’s noise, so travels between sensors where 0.3 does not.
Each copy draws an angle and rotates about the image centre (nearest neighbour); a rotation that keeps fewer than 90 % of the pixels is discarded. Among the integer shifts that keep the rotated mask inside the image, the free ones are those with
found exactly as the zeros of the correlation of the candidates with ’s bounding box; one free shift is drawn uniformly. Randomness comes only from the caller’s jax.random key, so the same key gives the same copies.
Reading
What it estimates. is the fraction of null copies that score at least as well as the candidate. A small says that a plume-free mask of the candidate’s shape, placed elsewhere in this scene, rarely fits methane this well.
Its resolution. With copies, moves in steps of . says only that no copy did as well, not that the probability is zero. The usual Monte Carlo form, , is never zero and is a valid p-value when the candidate and the copies are exchangeable under the null [4]. With , candidate A’s is in that form. For a score where higher is better, such as a likelihood ratio, pass both scores negated.
What the null samples. Each copy runs the whole chain, seeds to , so the selection of seeds by the matched filter happens inside the null too. The selection of the mask itself does not. Copies sit wherever there is no candidate, so they sample this scene’s background in the mask’s shape, not background that the matched filter flagged. A confounder is unusual background by construction, which is why the null calibrates the score but cannot replace the fit’s test of shape.
The copies are not independent. They overlap one another and draw on the same background pool, so the tail of the null is estimated less precisely than independent draws would estimate it.
4. One candidate¶
vet_candidate runs the steps in their fixed order with the window’s band selection: the seeds (1) and the pool (2), radtrax’s pairing on the window’s pairing bands, the ratio on its fitting bands, the fit and . Its VettingResult carries in mol/m², , the number of pairs, the ratio and the fit (continuum and transmittance , the spectra an analyst plots as against ), and the continuum-only residual at beside the fit’s residual at .
is the column of the mean transmittance over the pairs, not the mean column: is convex in , so it sits below the mean of the truth over the seeds. It is a score, not a retrieval; the column for an emission rate comes from a per-pixel retrieval of the vetted plume.
5. One scene¶
The notebook builds a 64 × 64 EMIT-like scene: 30 bands outside methane’s band, 9 inside it (2296–2356 nm), three surface classes, noise at SNR 300. Candidate A is a methane plume; candidate B is a plume-shaped patch of a surface whose reflectance dips by 6 % at 2335 nm, as a carbonate’s does.
| Matched filter, mean | ||||
|---|---|---|---|---|
| A, plume | 593 ppm·m | 1,741 ppm·m | 0.14 | 0.00 |
| B, carbonate | 1,162 ppm·m | 0 | 1.00 | 0.45 |
The matched filter scores B at twice A; vetting reverses the order. A’s column is 93 % of the truth over its kept pixels: about 3 points go to averaging transmittances, the rest to paired surfaces that do not match exactly. With a constant absorption coefficient A’s column would be 1,691 ppm·m. B’s was 0.43 when the null rejected random shifts; exact placement (4) draws other copies and gives 0.45 (A’s is 0 either way).
6. The decision¶
plumax.vetting returns scores, not verdicts. Three rules are on the table (#158): a fixed cut on (EMIT’s 0.3), which depends on the sensor’s bands and noise; the scene null’s (3), which calibrates the score against this scene’s clutter; and a likelihood ratio between the fits with and without the gas, from VettingResult’s two residuals. Until #158 settles it, report with every score.
7. What plumax computes¶
| Step | Equation | Function | Package | Issue |
|---|---|---|---|---|
| Seeds | (1) | select_seeds | plumax | #154 |
| Background pool | (2) | background_pool | plumax | #154 |
| A gas’s fitting and pairing bands | AbsorptionWindow | radtrax | radtrax#155 | |
| Transmittance on a grid of | transmittance_table | radtrax | radtrax#154 | |
| One-to-one pairs and the ratio | pair_pixels, ratio_spectrum | radtrax | radtrax#149 | |
| Profile fit and score | fit_transmittance, TransmittanceFit, d_norm | radtrax | radtrax#150 | |
| One candidate | vet_candidate, VettingResult | plumax | #156 | |
| The scene null | (4), (3) | null_masks, null_pvalue | plumax | #155 |
The radtrax names are in radtrax.retrieval.absorption (API, theory). plumax.vetting is an L1 module on arrays; the operator on carriers, plumax.geo.PlumeVetting, follows (#157).
8. Where plumax departs from the reference code¶
Exactly seeds. The reference keeps every pixel at or above the -th score, more than on ties; plumax takes the top , breaking ties by the lower flat index.
Non-finite scores. A pixel with a non-finite matched-filter score is never a seed and never in the pool, and growth stays inside ’s finite pixels.
The null avoids every candidate. The reference package draws 100 rotated and translated copies that avoid only their own plume’s boundary, and records their scores without a decision; plumax’s copies avoid every candidate, the mask itself included, and is returned with the scores.
Exact placement. Rather than rejecting random shifts that hit a candidate (which needs about 90,000 attempts for candidate A’s 100 copies), plumax finds each angle’s free shifts exactly and draws one uniformly. Given its angle, a copy is uniform over the free places; rejection would weight angles by their fraction of free places.
Xiang, C., et al. (2024). A novel spectroscopic method for vetting methane point sources. AGU Fall Meeting, abstract A21K-1903.
Růžička, V., Thompson, D. R., Fahlen, J. E., et al. (2026). Fully automatic trace gas plume detection. arXiv:2605.03372.
EMIT Science Data System (2025). plume-vetting, revision
47fc6ad. https://github .com /emit -sds /plume -vetting (Apache-2.0). Phipson, B. & Smyth, G. K. (2010). Permutation p-values should never be zero: calculating exact p-values when permutations are randomly drawn. Statistical Applications in Genetics and Molecular Biology, 9(1), Article 39.