Skip to content

LinearGaussianObservation

Bases: ObservationModel

Linear-Gaussian observation model.

Observations are modeled as

\[ y_t \sim \mathcal{N}(H x_t + D u_t + b, R). \]

Here, \(H\) is the observation matrix, \(D\) is an optional control-input matrix, \(b\) is an optional observation bias, and \(R\) is the observation noise covariance.

Each parameter may be a constant array (time-invariant) or a callable (t,) -> value evaluated at each observation time (time-varying); constant and callable parameters may be mixed freely. The single time argument mirrors the observation model contract \(p(y_t | x_t, u_t, t)\) (transitions span an interval; observations happen at one time).

Note
  • Callable parameters receive only the observation time t; they must not depend on state or controls (use GaussianObservation for nonlinear measurement functions).
  • Callables must be pure, JAX-traceable functions returning a fixed shape.
  • Backend support: time-varying parameters work with the simulators and the filter_source="cuthbert" filters/smoothers; the cd_dynamax backend requires constant arrays and raises TypeError otherwise.

is_time_invariant: bool property

True iff every parameter is a constant array (no callables).

__init__(H: Float[Array, '*h_plate observation_dim state_dim'] | Callable[[float | int | Real[Array, '']], Float[Array, '*h_plate observation_dim state_dim']], R: Float[Array, '*r_plate observation_dim observation_dim'] | Callable[[float | int | Real[Array, '']], Float[Array, '*r_plate observation_dim observation_dim']], D: Float[Array, '*d_matrix_plate observation_dim control_dim'] | Callable[[float | int | Real[Array, '']], Float[Array, '*d_matrix_plate observation_dim control_dim']] | None = None, bias: Float[Array, '*bias_plate observation_dim'] | Callable[[float | int | Real[Array, '']], Float[Array, '*bias_plate observation_dim']] | None = None)

Parameters:

Name Type Description Default
H Array | Callable

Observation matrix with shape \((d_y, d_x)\), or a callable (t,) returning it.

required
R Array | Callable

Observation noise covariance with shape \((d_y, d_y)\), or a callable (t,) returning it.

required
D Array | Callable | None

Optional control matrix with shape \((d_y, d_u)\), or a callable (t,) returning it. If None, no control contribution is used.

None
bias Array | Callable | None

Optional additive bias with shape \((d_y,)\), or a callable (t,) returning it.

None

params_at(t: float | int | Real[Array, '']) -> LinearGaussianObservationParams

Resolve (H, D, bias, R) at one observation time.

Constant parameters are returned unchanged; callable parameters are evaluated at t.

Structured inference

You can instantiate equivalent observation behavior without this class (for example, with a custom callable). However, this structured linear-Gaussian observation form is what lets filtering backends use fast Kalman-family methods; see Filters, especially KFConfig and EnKFConfig (or ContinuousTimeKFConfig / ContinuousTimeEnKFConfig) in FilterConfigs.

Without this exploitable structure, parameter inference that marginalizes latent trajectories often relies on particle filters (PFConfig and related particle methods), which are typically slower.

Example

Linear Gaussian observation with control input
import jax.numpy as jnp
from dynestyx import LinearGaussianObservation

observation = LinearGaussianObservation(
    H=jnp.array([[1.0, 0.0], [0.0, 1.0]]),
    R=0.1 * jnp.eye(2),
    D=jnp.array([[1.0], [0.5]]),
    bias=jnp.array([0.0, 0.1]),
)

x_t = jnp.array([1.2, -0.3])
u_t = jnp.array([0.8])
dist_y = observation(x_t, u_t, t=0.0)  # p(y_t | x_t, u_t, t)
Time-varying observation model

Each parameter may instead be a callable (t,) -> value evaluated at the observation time. Time-varying models are supported by the simulators and by KFConfig(filter_source="cuthbert") / KFSmootherConfig(filter_source="cuthbert").

import jax.numpy as jnp
from dynestyx import LinearGaussianObservation


def observation_matrix(t):
    return jnp.eye(2) * (1.0 + 0.1 * t)


observation = LinearGaussianObservation(H=observation_matrix, R=0.1 * jnp.eye(2))
params = observation.params_at(2.5)  # LinearGaussianObservationParams(H=..., ...)

LinearGaussianObservationParams

Bases: NamedTuple

Linear-Gaussian observation parameters resolved at one time.

Returned by LinearGaussianObservation.params_at: any callable (time-varying) parameter has been evaluated at the requested time, so every entry is a plain array (or None for an absent optional term).

Expected shapes match the LinearGaussianObservation fields; they are deliberately not enforced here because plate slicing can legally hand a member-sliced (reduced-rank) parameter to __call__.