pypfda.filter¶
High-level particle filter orchestration.
The ParticleFilter class wires together the primitives in
pypfda.weights and pypfda.resampling. Its
ParticleFilter.assimilate() method takes one analysis step
(weight + optional resampling) and returns the updated ensemble
together with diagnostic information.
The filter is intentionally model-agnostic: it does not run the forward model itself. Callers are expected to integrate their own model between analysis steps and pass the resulting state and predicted observations back in.
Classes
|
Diagnostics returned by |
|
Sequential importance resampling (SIR) particle filter. |
- class pypfda.filter.AssimilationInfo(weights, log_weights, ess, ess_fraction, entropy, resampled, indices)[source]¶
Bases:
objectDiagnostics returned by
ParticleFilter.assimilate().- Parameters:
- weights¶
Normalized analysis weights.
- Type:
ndarray, shape (n_members,)
- log_weights¶
Unnormalized log-weights, useful for downstream log-domain ops.
- Type:
ndarray, shape (n_members,)
- class pypfda.filter.ParticleFilter(ess_threshold=0.5, resampling='systematic', max_weight=None, rng=None)[source]¶
Bases:
objectSequential importance resampling (SIR) particle filter.
- Parameters:
ess_threshold (float, default 0.5) – Resample whenever the effective sample size fraction drops below this value. Must lie in \((0, 1]\). Setting it to 1 forces resampling at every step; setting it close to 0 disables resampling almost entirely.
resampling ({'systematic', 'stratified', 'residual', 'multinomial'}, default 'systematic') – Resampling scheme to use when triggered.
max_weight (float, optional) – If given, the largest normalized weight is capped at this value and the surplus is redistributed among the remaining particles. Useful as a degeneracy-prevention safeguard. Must lie strictly above
1 / n_membersand not exceed 1.rng (numpy.random.Generator, optional) – Random number generator used for resampling. If omitted, a default generator is created and reused across calls.
Notes
The current implementation assumes a diagonal Gaussian observation error model; richer likelihoods can be obtained by passing pre-computed log-weights to
assimilate_log_weights()instead.- assimilate(ensemble, ensemble_obs, observations, obs_err)[source]¶
Run one analysis (and possibly resampling) step.
- Parameters:
ensemble (array_like, shape (n_members, ...)) – Ensemble state. Any trailing dimensions are preserved when resampling.
ensemble_obs (array_like, shape (n_members, n_obs)) – Predicted observations for each ensemble member.
observations (array_like, shape (n_obs,)) – Actual observations.
obs_err (float or array_like of shape (n_obs,)) – Observation-error standard deviations.
- Returns:
ensemble_out (ndarray, shape (n_members, …)) – Resampled ensemble (or the input unchanged if no resampling occurred).
info (AssimilationInfo) – Diagnostics for this step.
- Return type:
tuple[ndarray[tuple[Any, …], dtype[floating[Any]]], AssimilationInfo]
- assimilate_log_weights(ensemble, log_weights)[source]¶
Like
assimilate()but takes externally-computed log-weights.Use this when you have a non-Gaussian likelihood, a custom proxy forward model, or pre-localized weights that do not factor as a single Gaussian product.