API reference

Algorithms

Observation-space increments for ensemble filters.

Ports of obs_increment_eakf.m, obs_increment_enkf.m and obs_increment_rhf.m from DART_LAB/matlab/private.

Each function takes a 1-D prior ensemble, a scalar observation and the observation error variance and returns the increments that move the prior ensemble members to the posterior. State variables are then updated by regressing these increments (see pydartlab.algorithms.regression).

exception pydartlab.algorithms.increments.InvalidVarianceError

Raised when both the prior and observation error variance are non-positive.

pydartlab.algorithms.increments.obs_increment_eakf(ensemble: ArrayLike, observation: float, obs_error_var: float) ndarray[tuple[Any, ...], dtype[float64]]

Increments for an ensemble adjustment Kalman filter (EAKF).

The prior ensemble is shifted to the posterior mean and linearly contracted to the posterior variance, preserving its shape.

Parameters:
  • ensemble (array_like) – Prior ensemble (1-D).

  • observation (float) – Observed value.

  • obs_error_var (float) – Observation error variance.

Returns:

obs_increments – Increments to add to the prior ensemble members.

Return type:

ndarray

pydartlab.algorithms.increments.obs_increment_enkf(ensemble: ArrayLike, observation: float, obs_error_var: float, rng: Generator | None = None) ndarray[tuple[Any, ...], dtype[float64]]

Increments for a perturbed-observations ensemble Kalman filter (EnKF).

Each member is paired with an observation perturbed by a draw from Normal(0, obs_error_var); the perturbed observations are recentered on the observation (the “mean correction” enhancement). The algorithm is stochastic: repeated calls with the same inputs give different results unless rng is seeded.

Parameters:
  • ensemble (array_like) – Prior ensemble (1-D).

  • observation (float) – Observed value.

  • obs_error_var (float) – Observation error variance.

  • rng (numpy.random.Generator, optional) – Source of randomness; defaults to a fresh default generator.

Returns:

obs_increments – Increments to add to the prior ensemble members.

Return type:

ndarray

class pydartlab.algorithms.increments.RHFResult(increments: ndarray[tuple[Any, ...], dtype[float64]], prior_pdf: tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]], post_pdf: tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]])

Result of a rank histogram filter update.

increments

Increments to add to the (unsorted) prior ensemble members.

Type:

ndarray

prior_pdf

(x, y) points tracing the continuous prior PDF, for plotting.

Type:

tuple of ndarray

post_pdf

(x, y) points tracing the continuous posterior PDF.

Type:

tuple of ndarray

pydartlab.algorithms.increments.obs_increment_rhf(ensemble: ArrayLike, observation: float, obs_error_var: float, bounded_left: bool = False) RHFResult

Increments for a rank histogram filter (RHF).

The prior is represented by a rank histogram: 1/(n+1) probability mass between each pair of adjacent sorted members, with Gaussian tails. The likelihood multiplies the mass in each bin and new members are placed so each has 1/(n+1) posterior mass below it (quantile conservation).

Parameters:
  • ensemble (array_like) – Prior ensemble (1-D).

  • observation (float) – Observed value.

  • obs_error_var (float) – Observation error variance.

  • bounded_left (bool) – If True the variable is bounded below at zero (the BNRHF of the bounded_oned_ensemble tool) and the left tail respects the bound.

Returns:

Increments plus (x, y) curves for the continuous prior and posterior PDFs.

Return type:

RHFResult

pydartlab.algorithms.increments.obs_increment(ensemble: ArrayLike, observation: float, obs_error_var: float, filter_type: str = 'EAKF', rng: Generator | None = None) ndarray[tuple[Any, ...], dtype[float64]]

Dispatch to one of the filters by name and return just the increments.

filter_type is one of "EAKF", "EnKF" or "RHF" (case insensitive), matching the radio buttons of the MATLAB tools.

Bounded-variable observation-space filters.

The gamma filter and the bounded normal rank histogram filter (BNRHF) used by bounded_oned_ensemble.m. Unlike the EAKF these respect a lower bound at zero, so non-negative quantities stay non-negative.

class pydartlab.algorithms.filters.GammaFilterResult(increments: ndarray[tuple[Any, ...], dtype[float64]], prior_shape: float, prior_scale: float, post_shape: float, post_scale: float)

Result of a gamma-filter update.

The prior and posterior gamma parameters are kept for plotting the continuous distributions.

pydartlab.algorithms.filters.obs_increment_gamma(ensemble: ArrayLike, observation: float, obs_error_sd: float) GammaFilterResult

Increments for a gamma filter for non-negative variables.

The prior ensemble is fit with a gamma distribution and the likelihood is a gamma with mean observation and sd obs_error_sd. The product of the two gammas has known shape and scale; new members are placed by quantile conservation (members keep their prior quantiles in the posterior distribution).

pydartlab.algorithms.filters.obs_increment_bnrhf(ensemble: ArrayLike, observation: float, obs_error_var: float) RHFResult

Increments for a bounded (at zero) normal rank histogram filter.

Regression of observation increments onto state variables.

Port of get_state_increments.m: the heart of multivariate ensemble assimilation. Increments computed for an observed quantity are mapped to any state variable with linear regression on the joint prior ensemble.

pydartlab.algorithms.regression.get_state_increments(state_ens: ArrayLike, obs_ens: ArrayLike, obs_incs: ArrayLike) tuple[ndarray[tuple[Any, ...], dtype[float64]], float]

State increments from observation increments by linear regression.

Parameters:
  • state_ens (array_like) – Prior ensemble of the (unobserved) state variable.

  • obs_ens (array_like) – Prior ensemble of the observed variable.

  • obs_incs (array_like) – Observation-space increments for each member.

Returns:

  • state_incs (ndarray) – Increments for the state variable: obs_incs * cov(x, y) / var(y).

  • r_xy (float) – Sample covariance between the state and observed ensembles.

Covariance localization (port of comp_cov_factor.m).

pydartlab.algorithms.localization.comp_cov_factor(z_in: ArrayLike, c: float) ndarray[tuple[Any, ...], dtype[float64]] | float

Gaspari-Cohn localization factor.

A compactly supported 5th-order polynomial correlation function that decreases from 1 at distance 0 to exactly 0 at distance 2c.

Parameters:
  • z_in (array_like) – Distance(s) between the observation and the state variable.

  • c (float) – Half-width: the factor reaches zero at 2c.

Returns:

cov_factor – Regression/covariance reduction factor in [0, 1].

Return type:

ndarray or float

pydartlab.algorithms.localization.cyclic_distance(i: int | ArrayLike, j: int | ArrayLike, domain_size: int) ndarray[tuple[Any, ...], dtype[float64]] | float

Distance between grid indices i and j on a cyclic domain.

Returned as a fraction of the domain (in [0, 0.5]) as used by the Lorenz 96 tools: dist = |i - j| / N, wrapped around the cycle.

Ensemble inflation: fixed multiplicative and adaptive algorithms.

Ports of update_inflate.m (Anderson 2009 Gaussian flavor and El Gharamti 2018 inverse-gamma flavor), compute_new_density.m, enh_compute_new_density.m, change_GA_IG.m, inflate_gamma.m and inflate_bnrh.m from DART_LAB/matlab/private.

pydartlab.algorithms.inflation.inflate_ensemble(ens: ArrayLike, inflation: float) ndarray[tuple[Any, ...], dtype[float64]]

Multiplicative covariance inflation about the ensemble mean.

The ensemble variance is multiplied by inflation; each member moves away from the mean by a factor sqrt(inflation).

pydartlab.algorithms.inflation.compute_new_density(dist_2: float, sigma_p_2: float, sigma_o_2: float, lambda_mean: float, lambda_sd: float, gamma_corr: float, lam: float) float

Posterior density of inflation lam for the Gaussian flavor.

pydartlab.algorithms.inflation.enh_compute_new_density(dist_2: float, sigma_p_2: float, sigma_o_2: float, alpha: float, beta: float, gamma_corr: float, lam: float, ens_size: int) float

Posterior density of inflation lam for the inverse-gamma flavor.

pydartlab.algorithms.inflation.change_ga_ig(mode: float, var: float) float

Rate parameter of the inverse-gamma matching a Gaussian’s mode and variance.

Port of change_GA_IG.m: the rate is the real solution of a cubic.

pydartlab.algorithms.inflation.update_inflate(x_p: float, r_var: float, y_o: float, sigma_o_2: float, ss_inflate_base: float, lambda_mean: float, lambda_sd: float, inf_lower_bound: float, inf_upper_bound: float, gamma_corr: float, sd_lower_bound: float, ens_size: int, flavor: str = 'Gaussian') tuple[float, float]

Bayesian update of the adaptive inflation mean and standard deviation.

Port of update_inflate.m. Supports two flavors:

  • "Gaussian" – Anderson (2009), Tellus A 61, 72-83.

  • "I-Gamma" – El Gharamti (2018), MWR 146, 623-640.

Parameters:
  • x_p (float) – Prior ensemble mean of the observed quantity.

  • r_var (float) – Prior ensemble variance of the observed quantity (inflated by ss_inflate_base).

  • y_o (float) – Observed value.

  • sigma_o_2 (float) – Observation error variance.

  • ss_inflate_base (float) – Inflation already applied to the sample whose variance is r_var.

  • lambda_mean (float) – Mean and standard deviation of the prior inflation distribution.

  • lambda_sd (float) – Mean and standard deviation of the prior inflation distribution.

  • inf_lower_bound (float) – Bounds on the updated inflation mean.

  • inf_upper_bound (float) – Bounds on the updated inflation mean.

  • gamma_corr (float) – Correlation factor for spatially varying inflation (1 for the observed variable itself).

  • sd_lower_bound (float) – Lower bound for the updated inflation standard deviation.

  • ens_size (int) – Ensemble size (used by the inverse-gamma flavor).

  • flavor (str) – "Gaussian" or "I-Gamma".

Returns:

new_cov_inflate, new_cov_inflate_sd – Updated inflation mean and standard deviation.

Return type:

float

pydartlab.algorithms.inflation.inflate_gamma(ens: ArrayLike, var_inf: float) ndarray[tuple[Any, ...], dtype[float64]]

Inflate an ensemble in a gamma/probit transformed space.

Fits a gamma distribution to the ensemble, transforms members to probit space via their gamma quantiles, inflates there, and transforms back. Preserves the non-negative support of the ensemble.

pydartlab.algorithms.inflation.inflate_bnrh(ens: ArrayLike, var_inf: float, bounded_below: bool = False, bounded_above: bool = False, lower_bound: float = 0.0, upper_bound: float = 0.0) ndarray[tuple[Any, ...], dtype[float64]]

Inflate an ensemble in a BNRH/probit transformed space.

Like inflate_gamma() but with a bounded normal rank histogram distribution, supporting arbitrary bounds.

Distribution machinery for rank-histogram and bounded filters.

Ports of weighted_norm_inv.m, ens_quantiles.m, bnrh_cdf.m, bnrh_cdf_initialized.m, inv_bnrh_cdf.m and plot_rhf_pdf.m from DART_LAB/matlab/private, plus a gamma-distribution fit matching MATLAB’s gamfit.

The bounded normal rank histogram (BNRH) distribution places 1/(n+1) probability mass between adjacent sorted ensemble members with (possibly bounded) Gaussian tails outside the outermost members. It is the non-parametric workhorse of the QCEFF framework.

pydartlab.algorithms.distributions.weighted_norm_inv(alpha: float, mean: float, sd: float, p: float) float

Value of x where the cdf of alpha * N(mean, sd) equals p.

pydartlab.algorithms.distributions.fit_gamma(ens: ArrayLike) tuple[float, float]

Maximum-likelihood gamma fit, returning (shape, scale).

Matches MATLAB’s gamfit (two-parameter gamma, location fixed at 0).

pydartlab.algorithms.distributions.ens_quantiles(sorted_ens: ArrayLike, bounded_below: bool = False, bounded_above: bool = False, lower_bound: float = 0.0, upper_bound: float = 0.0) ndarray[tuple[Any, ...], dtype[float64]]

Quantiles of a sorted ensemble for a BNRH distribution.

Handles ensemble members identical to the bounds and duplicate interior members (duplicates share the mean quantile of their run).

class pydartlab.algorithms.distributions.BNRH(sort_x: ndarray[tuple[Any, ...], dtype[float64]], quantiles: ndarray[tuple[Any, ...], dtype[float64]], sorted_quantiles: ndarray[tuple[Any, ...], dtype[float64]], tail_amp_left: float, tail_mean_left: float, tail_sd_left: float, tail_amp_right: float, tail_mean_right: float, tail_sd_right: float, do_uniform_tail_left: bool, do_uniform_tail_right: bool, bounded_below: bool, bounded_above: bool, lower_bound: float, upper_bound: float)

A fitted bounded normal rank histogram distribution.

Build with bnrh_fit(); cdf and ppf evaluate the fitted distribution. quantiles holds the quantiles of the fitting ensemble in its original (unsorted) order.

cdf(x: float) float

Quantile of a value x in the fitted distribution.

ppf(quantiles: ArrayLike) ndarray[tuple[Any, ...], dtype[float64]]

Inverse cdf for an array of quantiles.

pydartlab.algorithms.distributions.bnrh_fit(x: ArrayLike, bounded_below: bool = False, bounded_above: bool = False, lower_bound: float = 0.0, upper_bound: float = 0.0) BNRH

Fit a BNRH distribution to the ensemble x (port of bnrh_cdf.m).

pydartlab.algorithms.distributions.bnrh_cdf_initialized(x: float, dist: BNRH) float

Quantile of a single value in a fitted BNRH distribution.

pydartlab.algorithms.distributions.inv_bnrh_cdf(quantiles: ArrayLike, dist: BNRH) ndarray[tuple[Any, ...], dtype[float64]]

Inverse cdf of a fitted BNRH distribution (port of inv_bnrh_cdf.m).

pydartlab.algorithms.distributions.rhf_pdf_points(x: ArrayLike, mass: ArrayLike, left_mean: float, left_sd: float, left_amp: float, right_mean: float, right_sd: float, right_amp: float, bounded_left: bool = False) tuple[ndarray[tuple[Any, ...], dtype[float64]], ndarray[tuple[Any, ...], dtype[float64]]]

(x, y) points tracing a rank histogram filter PDF, for plotting.

Port of plot_rhf_pdf.m. x is the sorted ensemble and mass the probability mass in each of the n+1 bins.

Quantile-conserving ensemble filter framework (QCEFF) updates.

Ports of ppi_update.m and gamma_ppi_update.m from DART_LAB/matlab/private.

The probit probability integral (PPI) transform maps ensemble members to a standard normal space via the quantiles of a chosen continuous prior distribution. Linear regression of observation increments is performed in the transformed space, then the result is mapped back. This respects bounds and handles non-Gaussian priors and nonlinear relationships.

pydartlab.algorithms.qceff.OBS_DIST_TYPES = ('Normal', 'RHF')

Distribution choices for the PPI transform, matching the MATLAB tools.

class pydartlab.algorithms.qceff.PPIResult(post_state: ndarray[tuple[Any, ...], dtype[float64]], prior_obs_ppi: ndarray[tuple[Any, ...], dtype[float64]], post_obs_ppi: ndarray[tuple[Any, ...], dtype[float64]], prior_state_ppi: ndarray[tuple[Any, ...], dtype[float64]], post_state_ppi: ndarray[tuple[Any, ...], dtype[float64]])

Result of a PPI/QCEFF update of an unobserved state variable.

The *_ppi arrays are the ensembles in the probit-transformed space, used by twod_ppi_ensemble to display the transformed update.

pydartlab.algorithms.qceff.ppi_update(prior_obs: ArrayLike, prior_state: ArrayLike, post_obs: ArrayLike, state_dist_type: str = 'Normal', obs_dist_type: str = 'Normal') PPIResult

Update an unobserved variable using probit-transformed regression.

Parameters:
  • prior_obs (array_like) – Prior ensemble of the observed variable.

  • prior_state (array_like) – Prior ensemble of the unobserved state variable.

  • post_obs (array_like) – Posterior ensemble of the observed variable (prior plus increments from any observation-space filter).

  • state_dist_type (str) – Continuous distribution for the state PPI transform: "Normal", "Gamma", "RHF" (unbounded) or "BNRH" (bounded below at 0).

  • obs_dist_type (str) – Continuous distribution for the observed-variable transform: "Normal" or "RHF".

Returns:

Posterior state ensemble plus all four PPI-space ensembles.

Return type:

PPIResult

pydartlab.algorithms.qceff.gamma_ppi_update(prior_obs: ArrayLike, prior_state: ArrayLike, post_obs: ArrayLike) PPIResult

Gamma-transform update of a non-negative unobserved variable.

Port of gamma_ppi_update.m. The observed variable is normally distributed (its transform is just a normalization); the state variable is transformed through a fitted gamma distribution and probit.

Models

The Lorenz (1963) three-variable convection model.

Port of DART_LAB/matlab/private/lorenz_63_adv_1step.m and lorenz_63_static_init_model.m.

class pydartlab.models.lorenz63.Lorenz63(sigma: float = 10.0, r: float = 28.0, b: float = 2.6666666666666665, delta_t: float = 0.01)

Lorenz 63 model advanced with the two-step Runge-Kutta scheme of DART_LAB.

The classical chaotic “butterfly” system:

\[\dot x = \sigma (y - x), \quad \dot y = -xz + rx - y, \quad \dot z = xy - bz\]
Parameters:
  • sigma (float) – Model parameters; defaults are the classical chaotic values.

  • r (float) – Model parameters; defaults are the classical chaotic values.

  • b (float) – Model parameters; defaults are the classical chaotic values.

  • delta_t (float) – Non-dimensional time step (DART_LAB uses 0.01).

comp_dt(x: ArrayLike) ndarray[tuple[Any, ...], dtype[float64]]

Time tendency of the state vector x (length 3).

step(x: ArrayLike) ndarray[tuple[Any, ...], dtype[float64]]

Advance x by one time step with the DART_LAB two-step RK2 scheme.

The Lorenz (1996) model on a cyclic domain.

Port of DART_LAB/matlab/private/lorenz_96_adv_1step.m and lorenz_96_static_init_model.m (originally ported in pyDARTLAB 0.0.1).

class pydartlab.models.lorenz96.Lorenz96(model_size: int = 40, delta_t: float = 0.05, forcing: float = 8.0)

Lorenz 96 model advanced with a four-step Runge-Kutta scheme.

The model simulates an atmospheric quantity at model_size equally spaced points on a cyclic (circular) domain:

\[\dot x_j = (x_{j+1} - x_{j-2}) x_{j-1} - x_j + F\]
Parameters:
  • model_size (int) – Number of state variables (DART_LAB uses 40).

  • delta_t (float) – Non-dimensional time step (DART_LAB uses 0.05).

  • forcing (float) – Forcing term F; 8.0 gives chaotic dynamics.

comp_dt(x: ArrayLike) ndarray[tuple[Any, ...], dtype[float64]]

Time tendency of the state vector x.

state_loc

Locations of the state variables on the [0, 1) cyclic domain.

step(x: ArrayLike) ndarray[tuple[Any, ...], dtype[float64]]

Advance x by one time step with the DART_LAB RK4 scheme.

One-dimensional toy models used by oned_model and oned_cycle.

Port of DART_LAB/matlab/private/advance_oned.m plus the linear growth model used by oned_cycle.m.

class pydartlab.models.oned.LinearGrowth(growth_rate: float = 1.0)

The linear growth model of oned_cycle: x_{t+1} = G x_t.

pydartlab.models.oned.advance_oned(x: ArrayLike, alpha: float = 0.0, model_bias: float = 0.0) ndarray[tuple[Any, ...], dtype[float64]] | float

Advance the oned_model state by one step.

The time tendency is dx = (x + model_bias) + alpha * x * |x| so

\[x_{t+1} = 2 x_t + \text{bias} + \alpha\, x_t |x_t|\]

alpha controls nonlinearity and model_bias a systematic shift in the model dynamics. The truth in oned_model is always 0, so any bias or nonlinearity acts as model error. Works on scalars or ensembles.

Statistics

Statistical helpers shared across DART_LAB tools.

Ports of product_of_gaussians.m, kurt.m, and get_ens_rank.m, plus a rank-histogram accumulator used by the cycling apps.

pydartlab.stats.product_of_gaussians(prior_mean: float, prior_sd: float, obs: float, obs_err_sd: float) tuple[float, float, float]

Mean, standard deviation, and weight of the product of two Gaussians.

Returns:

post_mean, post_sd, weight – Mean and standard deviation of the (renormalized) product, and the integral of the raw product (the “weight”), which is the likelihood of the observation given the prior.

Return type:

float

pydartlab.stats.kurt(vals: ArrayLike) float

Kurtosis of vals (biased moment estimator, not excess: Gaussian -> 3).

pydartlab.stats.get_ens_rank(ens: ArrayLike, x: float) int

Rank of the value x within the sorted ensemble ens.

Returns a 1-based rank in 1 .. ens_size + 1 as in the MATLAB original, suitable for accumulating rank histograms.

class pydartlab.stats.RankHistogram(ens_size: int)

Accumulates a rank histogram for an ensemble of size ens_size.

The histogram has ens_size + 1 bins. add(ens, truth) computes the rank of the truth in the ensemble and increments the matching bin.

pydartlab.stats.error_and_spread(ens: ArrayLike, truth: float | ArrayLike) tuple[float, float]

RMS error of the ensemble mean and ensemble spread (standard deviation).

For a multivariate ensemble pass ens with shape (ens_size, model_size); the error is the RMS over variables of (ensemble mean - truth) and the spread is the RMS over variables of the ensemble standard deviation.

Experiments

Cycled assimilation with a continuous Kalman filter and an ensemble filter.

The experiment behind the oned_cycle tool: a scalar state with a linear error-growth model x(t+1) = G x(t), truth fixed at zero, observations drawn from Normal(0, obs_error_sd^2). A continuous (Gaussian) Kalman filter and an ensemble filter assimilate the same observations side by side.

class pydartlab.experiments.kalman_cycle.CycleRecord(observation: float, kf_prior_mean: float, kf_prior_sd: float, kf_post_mean: float, kf_post_sd: float, prior_ens: ndarray[tuple[Any, ...], dtype[float64]], post_ens: ndarray[tuple[Any, ...], dtype[float64]])

Diagnostics from one assimilation cycle of KalmanCycle.

class pydartlab.experiments.kalman_cycle.KalmanCycle(growth_rate: float = 1.0, obs_error_sd: float = 1.0, filter_type: str = 'EAKF', kf_mean: float = 1.0, kf_sd: float = 2.0, seed: int | None = None, ensemble: ~numpy.ndarray[tuple[~typing.Any, ...], ~numpy.dtype[~numpy.float64]] | None = None, history: list[~pydartlab.experiments.kalman_cycle.CycleRecord] = <factory>)

Continuous Kalman filter and ensemble filter cycling side by side.

Parameters:
  • growth_rate (float) – Linear model growth rate G; values > 1 grow forecast errors.

  • obs_error_sd (float) – Observation error standard deviation.

  • filter_type (str) – Ensemble filter: "EAKF", "EnKF" or "RHF".

  • kf_mean (float) – Initial mean and sd of the continuous Kalman filter prior.

  • kf_sd (float) – Initial mean and sd of the continuous Kalman filter prior.

  • seed (int or None) – Seed for the observation draws and the EnKF.

cycle() CycleRecord

Assimilate one observation, then advance both filters with the model.

set_ensemble(ensemble: ArrayLike) None

Set the ensemble (e.g. created interactively or programmatically).

Cycling DA for the one-variable nonlinear model (oned_model / oned_model_inf).

The truth is always zero; observations are drawn from Normal(0, obs_error_sd^2). The model x_{t+1} = 2x + bias + a x|x| grows errors, optionally with systematic bias and nonlinearity, so the filter must work to track the truth. Supports fixed and adaptive inflation.

class pydartlab.experiments.oned_da.OneDExperiment(ens_size: int = 4, filter_type: str = 'EAKF', model_bias: float = 0.0, alpha: float = 0.0, inflation: float = 1.0, adaptive_inflation: bool = False, inflation_flavor: str = 'Gaussian', inflation_sd: float = 0.6, inflation_sd_min: float = 0.6, inflation_min: float = 1.0, inflation_max: float = 5.0, inflation_damping: float = 1.0, obs_error_sd: float = 1.0, seed: int | None = None, truth: float = 0.0, time: int = 0, history: dict[str, list]=<factory>)

The cycling experiment behind oned_model and oned_model_inf.

Call advance() and assimilate() alternately (as the MATLAB button does), or step() for one full cycle.

Parameters:
  • ens_size (int) – Ensemble size (>= 2).

  • filter_type (str) – "EAKF", "EnKF" or "RHF".

  • model_bias (float) – Systematic model error added each advance (>= 0 in the GUI).

  • alpha (float) – Nonlinearity parameter a in x + bias + a x |x|.

  • inflation (float) – Fixed inflation, or the initial inflation mean when adaptive.

  • adaptive_inflation (bool) – Use the adaptive algorithm of oned_model_inf instead of fixed.

  • inflation_flavor (str) – "Gaussian" (Anderson 2009) or "I-Gamma" (El Gharamti 2018).

  • inflation_sd (float) – Initial standard deviation of the inflation distribution.

  • inflation_sd_min (float) – Lower bound for the inflation standard deviation.

  • inflation_min (float) – Bounds for the inflation mean.

  • inflation_max (float) – Bounds for the inflation mean.

  • inflation_damping (float) – Damping factor: inflation = 1 + damping * (lambda - 1).

  • obs_error_sd (float) – Observation error standard deviation.

  • seed (int or None) – Seed for reproducibility.

advance() ndarray[tuple[Any, ...], dtype[float64]]

Advance the ensemble one step, then apply (current) inflation.

assimilate() ndarray[tuple[Any, ...], dtype[float64]]

Draw an observation of the (zero) truth and assimilate it.

reset_histograms() None

Clear the accumulated rank histograms (the “Clear Hist” button).

set_ens_size(ens_size: int) None

Change the ensemble size, keeping or padding existing members.

step() ndarray[tuple[Any, ...], dtype[float64]]

One full advance + assimilate cycle.

Ensemble DA on the Lorenz 63 attractor (run_lorenz_63).

Truth and a 20-member ensemble evolve on the chaotic attractor; at each assimilation time all three state variables are observed with independent Normal(0, 1) errors and assimilated sequentially, with increments regressed onto every state variable.

class pydartlab.experiments.lorenz63_da.Lorenz63Experiment(ens_size: int = 20, filter_type: str = 'No Assimilation', obs_error_sd: float = 1.0, spin_up: int = 1500, seed: int | None = None, time: int = 0, history: dict[str, list]=<factory>)

Cycling DA on the Lorenz 63 model.

Parameters:
  • ens_size (int) – Number of ensemble members (the MATLAB tool uses 20).

  • filter_type (str) – "No Assimilation", "EAKF", "EnKF" or "RHF".

  • obs_error_sd (float) – Observation error standard deviation (1 in the MATLAB tool).

  • spin_up (int) – Steps to advance the initial truth onto the attractor.

  • seed (int or None) – Seed for reproducibility.

advance() None

Advance the truth and all ensemble members one model step.

assimilate() None

Observe all three variables (sequentially) and update the ensemble.

step() None

One full advance + assimilate cycle.

Ensemble DA on the 40-variable Lorenz 96 model.

The experiment behind run_lorenz_96 and run_lorenz_96_inf: sequential assimilation of noisy observations with Gaspari-Cohn localization, fixed or spatially-varying adaptive inflation, configurable observing networks, and an optional imperfect model (different forcing for the ensemble than for the truth).

class pydartlab.experiments.lorenz96_da.Lorenz96Experiment(ens_size: int = 20, filter_type: str = 'No Assimilation', localization: float = 1.0, inflation: float = 1.0, adaptive_inflation: bool = False, inflation_flavor: str = 'Gaussian', inflation_sd: float = 0.6, inflation_min: float = 1.0, inflation_max: float = 5.0, inflation_damping: float = 0.9, forcing: float = 8.0, true_forcing: float = 8.0, obs_network: str = '1:40:1', obs_error_sd: float = 4.0, seed: int | None = None, time: int = 0, history: dict[str, list]=<factory>)

Cycling DA on the Lorenz 96 model.

Parameters:
  • ens_size (int) – Number of ensemble members.

  • filter_type (str) – "No Assimilation", "EAKF", "EnKF" or "RHF".

  • localization (float) – Gaspari-Cohn half-width as a fraction of the domain (factor reaches zero at twice this distance). Large values (e.g. 1e6) disable localization.

  • inflation (float) – Fixed inflation value, or initial inflation when adaptive.

  • adaptive_inflation (bool) – Use spatially-varying adaptive inflation (run_lorenz_96_inf).

  • inflation_flavor (str) – "Gaussian" or "I-Gamma".

  • inflation_sd (float) – Inflation standard deviation (also its lower bound, as in the tool).

  • inflation_min (float) – Bounds for the inflation mean.

  • inflation_max (float) – Bounds for the inflation mean.

  • inflation_damping (float) – Damping applied to the inflation field at each model advance.

  • forcing (float) – Forcing used to advance the ensemble (truth always uses 8.0); a different value gives an imperfect model.

  • obs_network (str) – One of the keys of OBS_NETWORKS.

  • obs_error_sd (float) – Observation error standard deviation (4 in the MATLAB tools).

  • seed (int or None) – Seed for reproducibility.

advance() None

Advance truth and ensemble one step; damp and apply inflation.

assimilate() None

Sequentially assimilate observations from the chosen network.

step() None

One full advance + assimilate cycle.

pydartlab.experiments.lorenz96_da.OBS_NETWORKS = {'10:30': array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,        27, 28, 29, 30]), '1:10; 30:40': array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 30, 31, 32, 33, 34, 35,        36, 37, 38, 39]), '1:20': array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,        18, 19, 20]), '1:40:1': array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,        34, 35, 36, 37, 38, 39]), '1:40:2': array([ 1,  3,  5,  7,  9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33,        35, 37, 39]), '1:40:4': array([ 1,  5,  9, 13, 17, 21, 25, 29, 33, 37])}

Observing networks of run_lorenz_96_inf (1-based MATLAB ranges -> indices)

Style

Color and style conventions for pyDARTLAB.

The defaults reproduce the MATLAB DART_LAB color semantics used throughout the tutorial slides and apps:

  • green = prior

  • red = observation / likelihood

  • blue = posterior

Colors are settable at runtime so the palette can be swapped for a colorblind-friendly one:

import pydartlab
pydartlab.style.use_colorblind_palette()
# or change individual roles
pydartlab.style.set_colors(prior="#009E73")
class pydartlab.style.Palette(prior: str = '#008000', observation: str = '#D70A53', posterior: str = '#0000FF', inflated: str = '#FF9933', truth: str = '#000000', highlight: str = '#FFFF00', background: str = '#E1E1E1', lightblue: str = '#ADEBFF', member: str = '#008000', localization: list[str] = <factory>)

Role-based colors used by all pyDARTLAB plots and apps.

pydartlab.style.colors = Palette(prior='#008000', observation='#D70A53', posterior='#0000FF', inflated='#FF9933', truth='#000000', highlight='#FFFF00', background='#E1E1E1', lightblue='#ADEBFF', member='#008000', localization=['#969696', '#1E90FF', '#FF3333', '#009900'])

The active palette. Import this and read attributes at draw time; do not copy values at import time or set_colors() will not take effect.

pydartlab.style.set_colors(**kwargs: str) None

Change individual role colors on the active palette.

Parameters are any of the Palette field names, e.g. set_colors(prior="#009E73", posterior="#0072B2").

pydartlab.style.use_colorblind_palette() None

Switch the active palette to a colorblind-friendly (Okabe-Ito) palette.

pydartlab.style.use_dartlab_palette() None

Restore the default MATLAB DART_LAB palette.

pydartlab.style.use_palette(palette: Palette) None

Make palette the active palette (copies values in place).