Ramsden methane/ethane model#

Status#

The openghg_inversions.experimental.ramsden2022 module implements the shared-state methane/ethane model described by Ramsden et al. (2022). It is intended for historical comparison and as a requirements fixture for future generic linked-tracer work. It is not a stable public API.

The model starts at the prepared-input boundary. It accepts two canonical RHIME-style datasets and uses the current PyMC model components and RhimeSampler. It deliberately does not port the historical ACRG/OpenGHG retrieval layer, pickle cache, configuration parser, custom Metropolis-Hastings sampler, isotope extensions, or bespoke country/NetCDF post-processing.

Scientific model#

For fossil-fuel and non-fossil methane scaling states, the two observation models are

\[\mu_{\mathrm{CH_4}} = H_{\mathrm{CH_4,FF}} x_{\mathrm{FF}} + H_{\mathrm{CH_4,nonFF}} x_{\mathrm{nonFF}} + H_{\mathrm{bc,CH_4}} b_{\mathrm{CH_4}},\]
\[\mu_{\mathrm{C_2H_6}} = H_{\mathrm{C_2H_6,FF}} (R x_{\mathrm{FF}}) + H_{\mathrm{bc,C_2H_6}} b_{\mathrm{C_2H_6}}.\]

The fossil-fuel scaling state is shared between channels. Non-fossil methane does not contribute to the ethane likelihood. The channels can have different sites, timestamps, observation counts, boundary states, and absolute model-error states.

For channel \(g\), the observation standard deviation is

\[\epsilon_g = \max\left( \sqrt{\sigma_{\mathrm{measurement},g}^2 + \sigma_{\mathrm{model},g}^2}, \epsilon_{\min,g} \right).\]

Set min_error to zero for the paper-shaped likelihood. A positive value retains the modern RHIME numerical floor intentionally.

Prepared inputs#

Each channel dataset must use the canonical names below. The two observation axes can differ, but every coupled sector must use exactly matching labelled state coordinates.

Required channel variables#

Variable

Required dimensions

Meaning

H

observation, state, source

Labelled sensitivity matrix mapping scaling states into observation space.

mf

observation

Measured mole fraction in the channel’s declared numeric units.

mf_error

observation

Measurement contribution to likelihood uncertainty.

min_error

observation

Optional positive floor applied after combining measurement and model uncertainty.

site_indicator

observation

Integer site index used to align site-level model error.

H_bc

observation, boundary state

Boundary sensitivity; required when the channel enables boundary scaling.

If state labels are positional numbers, retain and pass both BasisFunctions objects. The builder then verifies the spatial maps instead of assuming that two 0..N-1 indexes describe the same regions.

Ratio contracts#

The model supports two explicit ratio conventions:

Direct physical ratio

reference_ratio=None means the tracer sensitivity is ratio-free. The sampled or fixed value is the dimensionless molar emission ratio, moles of tracer divided by moles of primary gas.

Historical multiplier

A positive reference_ratio means the tracer sensitivity already contains that ratio. The sampled or fixed value is a multiplier, and the model exposes

\[R_{\mathrm{physical}} = R_{\mathrm{reference}} R_{\mathrm{multiplier}}.\]

The independent tracer_design_reference_ratios mapping records what is already present in every tracer sensitivity. The builder rejects inconsistent declarations to prevent applying a ratio twice or omitting it.

Units#

The builder validates supported unit declarations by mole-fraction scale but does not convert numeric values. Observations, measurement errors, minimum errors, forward sensitivities, and model-error prior values must already share each channel’s declared scale.

For the retained Ramsden case, methane values are numeric ppb and ethane values numeric ppt. The paper prints the ethane model-error bounds as ppb, but its figures, retained data, and historical configuration support ppt.

API reference#

class openghg_inversions.experimental.ramsden2022.RamsdenPreparedInputs(primary: Dataset, tracer: Dataset, tracer_design_reference_ratios: Mapping[str, float | None], primary_basis_functions: FluxWeightedBasis | None = None, tracer_basis_functions: FluxWeightedBasis | None = None)

Canonical primary-gas and tracer inputs for one joint inversion.

Each dataset requires H, mf, mf_error, min_error, and site_indicator on nmeasure; H_bc is required when that channel’s boundary component is enabled. Observation axes may differ. Coupled sector designs must have exactly matching labelled state coordinates and, for positional numeric labels, retained basis objects.

Parameters:
  • primary – Canonical RHIME-style dataset for the primary gas.

  • tracer – Canonical RHIME-style dataset for the tracer gas. Its H matrix must use the same labelled state layout as primary.H.

  • tracer_design_reference_ratios – Reference ratio already included in each tracer H source, keyed by tracer source label. Use None for a ratio-free design. These declarations are checked against each sector specification to prevent applying a ratio twice or omitting it.

  • primary_basis_functions – Retained basis used to construct primary.H. Required together with tracer_basis_functions when state labels are positional numbers.

  • tracer_basis_functions – Retained basis used to construct tracer.H. Its source-specific spatial map must equal the primary map for every coupled sector.

class openghg_inversions.experimental.ramsden2022.RamsdenChannelSpec(species: str, observation_units: str, sigma_prior: dict[str, Any], sigma_per_site: bool = True, sigma_frequency: str | None = None, sigma_frequency_anchor: str | datetime | datetime64 | Timestamp | None = None, use_bc: bool = False, bc_prior: dict[str, Any] | None = None)

Likelihood and boundary settings for one observed gas.

Parameters:
  • species – Gas name used to namespace model variables.

  • observation_units – Units shared by observations, measurement errors, minimum errors, forward-model outputs, and the model-error prior. Supported dataset unit attributes are checked by mol/mol scale; values are not converted.

  • sigma_prior – PyMC prior mapping accepted by parse_prior() for absolute model error. The prior is expanded by site and period, not multiplied by the modelled enhancement.

  • sigma_per_site – Whether model error is independent by observation site.

  • sigma_frequency – Optional pandas-compatible frequency for model-error periods.

  • sigma_frequency_anchor – Optional anchor for fixed-duration periods.

  • use_bc – Whether this channel has an independent boundary component.

  • bc_prior – Prior mapping for the state that scales this channel’s H_bc design.

class openghg_inversions.experimental.ramsden2022.RamsdenSectorSpec(name: str, primary_flux_source: str, x_prior: dict[str, Any], tracer_flux_source: str | None = None, ratio_prior: dict[str, Any] | None = None, fixed_ratio: float | None = None, ratio_resolution: Literal['scalar', 'spatial'] = 'spatial', reference_ratio: float | None = None)

Shared primary-gas state and optional tracer coupling for one sector.

Parameters:
  • name – Semantic sector name.

  • primary_flux_source – Source-provenance label selected from primary.H.

  • x_prior – Prior mapping for the primary-gas scaling state. It must broadcast to the selected state dimension.

  • tracer_flux_source – Source-provenance label selected from tracer.H. None means this sector contributes no tracer, as for the non-fossil methane sector in Ramsden et al. (2022).

  • ratio_prior – Prior for a sampled direct emission ratio or historical ratio multiplier. Exactly one of ratio_prior and fixed_ratio is required for a tracer-emitting sector. The distribution must have non-negative support.

  • fixed_ratio – Fixed direct emission ratio or historical multiplier.

  • ratio_resolution"spatial" creates one sampled/fixed ratio value per state element, so its prior must broadcast to that state; "scalar" shares one value across the sector.

  • reference_ratioNone selects the paper’s direct-ratio contract: tracer.H must be ratio-free and the ratio parameter is applied directly. A positive value selects historical compatibility: tracer.H must already include this reference ratio, the sampled parameter is a dimensionless multiplier, and emission_ratio = reference_ratio * ratio_multiplier is exposed for interpretation. Direct and reference ratios are dimensionless molar ratios (moles tracer per mole primary).

class openghg_inversions.experimental.ramsden2022.RamsdenModelSpec(primary: RamsdenChannelSpec, tracer: RamsdenChannelSpec, sectors: tuple[RamsdenSectorSpec, ...])

Complete specification for the historical two-gas model.

Parameters:
  • primary – Primary-gas likelihood settings.

  • tracer – Tracer-gas likelihood settings.

  • sectors – Ordered primary sectors. At least one sector must also emit the tracer. Sanitized channel names must be distinct, and sanitized sector names must be non-empty and unique.

class openghg_inversions.experimental.ramsden2022.RamsdenResult(prepared_inputs: RamsdenPreparedInputs, model_spec: RamsdenModelSpec, model: Model, idata: InferenceData, sampler: RhimeSampler)

Result returned by run_ramsden_from_prepared_inputs().

Parameters:
  • prepared_inputs – Labelled inputs consumed by the model.

  • model_spec – Historical model specification.

  • model – Built PyMC model.

  • idata – Joint inference data preserving shared-state/ratio covariance and the two namespaced likelihood and predictive variables.

  • sampler – Modern RHIME sampler used for the run.

openghg_inversions.experimental.ramsden2022.build_ramsden_model(prepared_inputs: RamsdenPreparedInputs, model_spec: RamsdenModelSpec) Model

Build the historical Ramsden methane/ethane model with modern PyMC.

Parameters:
  • prepared_inputs – Two canonical gas datasets. Each requires H, mf, mf_error, min_error, and site_indicator on nmeasure; H_bc is required for enabled boundary states. Observation coordinates may differ, but coupled sector state coordinates must match exactly.

  • model_spec – Shared-state, ratio, likelihood, unit, and boundary metadata. Direct ratios require ratio-free tracer sensitivities; reference-ratio mode requires tracer sensitivities that already include the declared reference ratio.

Returns:

Built PyMC model ready for RhimeSampler.

Raises:

ValueError – If model metadata, required input variables, source labels, or shared state coordinates are invalid.

Notes

This function builds a PyMC graph only. It performs no data retrieval, sampling, unit conversion, or postprocessing. Observation, error, sigma-prior, and forward-model values must already use each channel’s declared observation_units.

openghg_inversions.experimental.ramsden2022.run_ramsden_from_prepared_inputs(*, prepared_inputs: RamsdenPreparedInputs, model_spec: RamsdenModelSpec, sampler: RhimeSampler | None = None) RamsdenResult

Build and sample a historical two-gas model from canonical inputs.

Parameters:
  • prepared_inputs – Canonical primary and tracer datasets.

  • model_spec – Historical model specification.

  • sampler – Modern RHIME sampling configuration controlling seeds, chains, draws, and predictive output. When omitted, the standard sampler is used with both namespaced gas observations included in posterior predictive sampling.

Returns:

Joint result containing the built model and labelled inference data.

Raises:

ValueError – If model metadata or prepared inputs are invalid.

Notes

This function samples the model and may run multiple chains. It does not retrieve data, convert units, or write postprocessed products. Sampling exceptions raised by RhimeSampler are propagated.

Design history#

The detailed historical comparison and porting decision is retained in adding_multi_gas_model_historical_comparison.md. It documents the behavior preserved from the old branch, the behavior deliberately excluded, and known historical correctness defects.