openghg_inversions.models.components#
Reusable PyMC model graph helpers.
These helpers operate on the active PyMC model context and are designed to be
xarray-first. They return explicit component results or PyTensor/PyMC tensors
and should not implement their own coordinate sanitization policy; coordinate
handling lives in openghg_inversions.models.coords.
All component helpers operate inside an active PyMC model context.
add_state_vector consumes an already resolved activity contract;
add_linear_component consumes a sensitivity matrix inspected by
prepare_linear_sensitivity before constructing that graph.
Naming conventions:
data_name: name for registeredpm.Datavar_name: name for the latent random variableoutput_name: name for the aligned deterministic outputplain
nameis reserved for helpers that truly create only one semantic object or where a base name is the clearest API
Frequency indicators may be supplied explicitly or derived from observation
coordinates using shared helper logic based on
openghg_inversions.inversion_inputs.make_freq_indicator.
Bases:
objectObjects created by
add_correlated_lognormal_state.- Variables:
latent (pytensor.tensor.variable.TensorVariable) – Standard-normal whitened state used by the sampler.
state (pytensor.tensor.variable.TensorVariable) – Positive user-facing state with the requested arithmetic LogNormal moments.
prior (openghg_inversions.correlated_state.CorrelatedLognormalPrior) – Validated backend-neutral moment contract used to build the graph.
- class openghg_inversions.models.components.LinearComponentResult(data: TensorVariable, latent: TensorVariable | None, state: TensorVariable, output: TensorVariable, activity: ResolvedStateActivity)#
Bases:
objectObjects created by
add_linear_component().- activity: ResolvedStateActivity#
- data: TensorVariable#
- output: TensorVariable#
- state: TensorVariable#
- class openghg_inversions.models.components.StateVectorResult(latent: TensorVariable | None, state: TensorVariable, activity: ResolvedStateActivity)#
Bases:
objectObjects created by
add_state_vector.- Variables:
latent (pytensor.tensor.variable.TensorVariable | None) – Effective sampled latent variable, or
Nonewhen every state is fixed.state (pytensor.tensor.variable.TensorVariable) – Full ordered state vector, including fixed values.
activity (openghg_inversions.models.state_activity.ResolvedStateActivity) – Resolved state-activity contract in canonical state order.
- activity: ResolvedStateActivity#
- state: TensorVariable#
- openghg_inversions.models.components.add_coherent_affine_component(fixed_contribution: DataArray, linear_signal: TensorVariable, /, *, output_name: str) TensorVariable#
Add a labelled fixed contribution to an already composed linear signal.
- Parameters:
fixed_contribution – Labelled affine intercept
mu_prior - H_alpha @ m_alpha, not the full prior-forward mean. Its name owns the registeredpm.Dataname and its coordinates own the output axis labels.linear_signal – Existing linear signal composed by the calling model recipe.
output_name – Name for the affine deterministic output.
- Returns:
The deterministic sum of the registered fixed contribution and linear signal.
Notes
This component uses the equivalent coherent-reduction identity
mu = mu_prior + H_alpha @ (x - m_alpha) =(mu_prior - H_alpha @ m_alpha) + H_alpha @ x.This helper does not construct states, sensitivities, ratios, or channel signals. The calling recipe owns those scientific choices.
Add a whitened correlated LogNormal state to the active PyMC model.
- Parameters:
prior – Validated labelled arithmetic and latent moment contract.
var_name – Name of the positive user-facing state. The whitened standard normal is named
{var_name}_latent.
- Returns:
The whitened latent, positive state, and supplied prior contract.
- Raises:
ValueError – If the arithmetic mean, latent moments, Cholesky diagonal, or exponentiated central state is not finite and positive where required in PyMC’s configured floating-point dtype.
Notes
This function must run in an active
pm.Modelcontext. After backend dtype validation completes, it mutates that model by registering the length-pstate coordinate,{var_name}_latentrandom variable, and length-p{var_name}deterministic state.priorshould contain reduced arithmetic moments produced together with the matching forward operator and Gaussian unresolved-error term. The coherent covariance, transformed-forward-model, and aggregation-error identities are exact only for a jointly Gaussian state. Reusing those first two moments with a LogNormal retained state and Gaussian unresolved contribution is a moment-matched closure, not exact LogNormal marginalization. Known-exact state fixing is handled separately byStateActivityin the state-linear component builders.
Construct a correlated LogNormal state with exact active/fixed values.
The arithmetic-moment prior is subset to sampled states before its LogNormal transformation. Inactive states keep their exact fixed values in the full public vector. This is the correlated counterpart of
add_state_vector().- Parameters:
activity – Resolved activity in canonical full-state order.
prior – Validated labelled arithmetic-moment LogNormal prior for the full state.
var_name – Name of the full user-facing state vector.
- Returns:
Effective whitened latent, full state vector, and supplied activity.
- openghg_inversions.models.components.add_inferpymc_likelihood_component(data: Dataset, /, mu: TensorVariable, mu_bc: TensorVariable | None, sigprior: dict, sigma_alignment: SigmaAlignment, offset: TensorVariable | None = None, power: dict | float = 1.99, pollution_events_from_obs: bool = False, no_model_error: bool = False, output_dim: str = 'nmeasure') TensorVariable#
Add the inferpymc observation model.
muis the non-baseline forward-model contribution.mu_bcis the baseline contribution, usuallyH_bc @ bc, plus offset if applicable.- Parameters:
data – Canonical inferpymc input dataset.
mu – Non-baseline forward-model contribution.
mu_bc – Baseline contribution, if present.
sigprior – Prior specification for sigma.
sigma_alignment – Backend-neutral site and period alignment for sigma.
offset – Optional aligned offset term.
power – Scalar or prior specification controlling pollution-event scaling.
pollution_events_from_obs – Whether to derive pollution events from the observations instead of
mu.no_model_error – Whether to bypass the model-error term.
output_dim – Observation/output dimension name.
- Returns:
The
epsilondeterministic variable used by the observation model.
- openghg_inversions.models.components.add_linear_component(prepared: PreparedLinearSensitivity, /, data_name: str, prior_args: dict, var_name: str, output_name: str, state_activity: StateActivity | None = None, output_dim: str = 'nmeasure', compute_deterministic: bool = True) LinearComponentResult#
Add one independent labelled linear component.
- Parameters:
prepared – Retained sensitivity and full-state mapping produced by
prepare_linear_sensitivity().data_name – Name used when registering the data as
pm.Data.prior_args – Prior specification for the latent random variable.
var_name – Name for the latent random variable.
output_name – Name for the aligned deterministic output.
output_dim – Observation/output dimension name.
compute_deterministic – Whether to wrap the aligned output in
pm.Deterministic.state_activity – Optional active/fixed policy over the full scientific state.
Nonesamples every retained column.
- Returns:
The registered sensitivity, effective latent, full state, aligned forward contribution, and resolved activity.
- openghg_inversions.models.components.add_linked_linear_component(prepared: PreparedLinearSensitivity, linked_state: TensorVariable, /, *, data_name: str, output_name: str) TensorVariable#
Apply a prepared sensitivity to an already constructed linked state.
- Parameters:
prepared – Sensitivity prepared by
prepare_linear_sensitivity(). It owns retained-state selection and the output dimension.linked_state – Existing full state expression in the state order owned by
prepared. The caller owns any ratio or other transformation used to construct this expression.data_name – Name used to register the prepared sensitivity as
pm.Data.output_name – Name for the output-dimension-aligned deterministic.
- Returns:
The linked linear signal registered as
output_name.
Notes
This helper creates neither a state nor a multiplier. It only registers the prepared sensitivity and owns the resulting deterministic output.
- openghg_inversions.models.components.add_model_data(data: DataArray, name: str | None = None) TensorVariable#
Add labelled xarray data to the active PyMC model.
- Parameters:
data – Xarray data to register as
pm.Data.name – Optional PyMC variable name. If omitted,
data.nameis used.
- Returns:
The registered
pm.Datatensor fordata.- Raises:
ValueError – If no name can be determined for the data variable.
- openghg_inversions.models.components.add_offset_component(observations: DataArray, /, prior_args: dict, offset_freq_indicator: DataArray | ndarray | None = None, offset_freq: str | None = None, var_name: str = 'offset_latent', output_name: str = 'offset', output_dim: str = 'nmeasure', drop_first: bool = False, per_site: bool = True) TensorVariable#
Add a global, site-only, or site-by-period offset component.
- Parameters:
observations – Observation data carrying an observation-aligned
sitecoordinate.prior_args – Prior specification for the offset latent variable.
offset_freq_indicator – Optional explicit observation-aligned offset frequency indicator.
offset_freq – Optional frequency string used to derive an indicator when
offset_freq_indicatoris not provided.var_name – Name for the latent offset variable.
output_name – Name for the aligned deterministic offset output.
output_dim – Observation/output dimension name.
drop_first – Whether to omit the first site indicator column.
per_site – Whether to create site-specific terms. If false, create one global scalar latent offset and broadcast it over observations.
- Returns:
The aligned offset deterministic variable.
- Raises:
ValueError – If
observationsdoes not have an observation-alignedsitecoordinate, or if global-offset options conflict.
- openghg_inversions.models.components.add_sigma_component(alignment: SigmaAlignment, /, prior_args: dict, compute_deterministic: bool = False) TensorVariable#
Register a latent sigma component and align it to observations.
- Parameters:
alignment – Backend-neutral site and period alignment for the component.
prior_args – Prior specification for the sigma random variable.
compute_deterministic – Whether to register the aligned sigma term as a deterministic variable.
- Returns:
The observation-aligned sigma tensor or deterministic variable.
- openghg_inversions.models.components.add_state_vector(activity: ResolvedStateActivity, /, prior_args: dict[str, Any], var_name: str) StateVectorResult#
Construct an active/fixed state graph from a resolved activity contract.
When every state is active, this creates the same base prior graph as
add_linear_component. Partial activity creates an active-only prior and restores it into a full deterministic state vector. An all-fixed policy creates no random variable and exposes the fixed values as the full deterministic state.- Parameters:
activity – Resolved activity and state-coordinate contract. Linear design inspection must be completed before calling this helper.
prior_args – Prior specification. Distribution parameters may be scalar, full-state arrays, or labelled state
DataArrayobjects.var_name – Name of the full user-facing state vector.
- Returns:
The effective latent, full state vector, and supplied activity.
- Raises:
KeyError – If the prior specification omits a required parameter.
TypeError – If the prior specification contains an unsupported value.
ValueError – If state-valued prior parameters are invalid.
Notes
This helper registers state variables and state coordinates, but it does not inspect or register a sensitivity matrix and does not construct a forward-model output. The registered activity mask is immutable build-time metadata in semantic terms; changing it with
pm.set_datawould not rebuild the latent state layout. Call this helper inside an activepm.Modelcontext.
- openghg_inversions.models.components.apply_linear_sensitivity(prepared: PreparedLinearSensitivity, state: TensorVariable, /, *, data_name: str, output_name: str, compute_deterministic: bool = True) TensorVariable#
Apply a prepared sensitivity to an already-built full state vector.
- openghg_inversions.models.components.get_model_latent(variable: TensorVariable, base_name: str) TensorVariable#
Return the effective latent variable for a named model component.
- Parameters:
variable – User-facing variable returned by
parse_prior.base_name – Base model variable name used to look up a reparameterized latent variable.
- Returns:
The reparameterized latent variable
{base_name}_latentwhen it is present on the active model, otherwisevariable.
- openghg_inversions.models.components.resolve_model_variable(model: Model, base_name: str) TensorVariable | None#
Return a named model variable, preferring the reparameterised latent form.
- Parameters:
model – PyMC model to inspect.
base_name – Base variable name to resolve.
- Returns:
The reparameterised latent variable
{base_name}_latentwhen it is present onmodel, otherwise the user-facing variable namedbase_name. ReturnsNoneif neither variable exists.