Pairwise Kalman Filter (PKF) and variants (EPKF, UPKF, PPF) for linear and nonlinear state estimation
Project description
AwesomePKF
This repository contains a set of programs illustrating the Pairwise Kalman Filter (PKF), a generalization of the classical Kalman Filter, extended to non-linear models. It includes several variants of non-linear filters:
- Extended Pairwise Kalman Filter (EPKF)
- Unscented Pairwise Kalman Filter (UPKF), with multiple variants depending on the choice of sigma points
- Pairwise Particle Filter (PPF)
Table of Contents
- AwesomePKF
Installation
From PyPI (recommended)
pip install awesomepkf
From source
git clone https://github.com/sderrode/awesomepkf.git
cd awesomepkf
pip install .
Development install
pip install -e ".[dev]"
Requirements
- Python >= 3.10
- numpy, scipy, matplotlib, pandas, rich, sympy
Quick Start
from prg.classes.linear_pkf import Linear_PKF
from prg.models.linear import ModelFactoryLinear
model = ModelFactoryLinear.create("model_x1_y1_AQ_pairwise")
pkf = Linear_PKF(model)
# ... run the filter step by step
Or use the CLI entry points installed with the package:
awesomepkf-simulate --N 2000 --linear-model-name "model_x1_y1_AQ_pairwise" --data-filename "testL.csv" --s-key 303
awesomepkf-pkf --linear-model-name "model_x1_y1_AQ_pairwise" --data-filename "testL.csv" --plot
Tutorials
Interactive Jupyter notebooks are available in the notebooks/ directory:
| # | Notebook | Description |
|---|---|---|
| 01 | tutorial_01_getting_started.ipynb |
Introduction to the PKF framework: linear models, running the filter, visualizing estimates, error metrics (MSE, NEES, NIS), comparing PKF / EPKF / UPKF |
| 02 | tutorial_02_nonlinear_models.ipynb |
Nonlinear models: EPKF, UPKF, PPF and PF — classic vs pairwise, sigma-point sets, particle count impact, filter comparison |
| 03 | tutorial_03_sigma_points.ipynb |
Sigma-point sets for the UPKF: wan2000, cpkf, lerner2002, ito2000 — impact on estimation accuracy |
| 04 | tutorial_04_particle_filters.ipynb |
Particle filters (PPF and PF): tuning the number of particles, resampling, comparison with EPKF/UPKF |
| 05 | tutorial_05_new_model_lotkavolterra.ipynb |
How to add a new nonlinear pairwise model: Lotka-Volterra prey-predator (dim_x=1, dim_y=1), augmented version, filtering with EPKF/UPKF/PPF |
| 06 | tutorial_06_filter_runner_and_config.ipynb |
High-level orchestration with FilterRunner and RunOptions; parameter sweeps via model_kwargs; saving and replaying experiments through TOML session configs |
Models and Simulations
The repository provides a program called run_simulator.py to simulate data according to linear and non-linear models.
Filters
Each filter has two types of programs:
- Simulate data and filter it directly
- Filter data from a previously saved file
Pairwise Kalman Filter (PKF)
- run_linear_pkf.py – filter linear data either from simulated data or from a previously saved file (e.g., generated with
run_simulator.py)
Extended Pairwise Kalman Filter (EPKF)
- run_nonlinear_epkf.py – filter non-linear data either from simulated data or from a previously saved file (e.g., generated with
run_simulator.py)
Unscented Pairwise Kalman Filter (UPKF)
- run_nonlinear_upkf.py – filter non-linear data either from simulated data or from a previously saved file (e.g., generated with
run_simulator.py)
Pairwise Particle Filter (PPF)
- run_nonlinear_ppf.py – filter non-linear data either from simulated data or from a previously saved file (e.g., generated with
run_simulator.py)
Paper Reproducibility Scripts
The following scripts reproduce all figures and tables from the article "Non-linear extensions to Gaussian pairwise Kalman filter". Each script can be run independently from the repository root.
Section 4 — Simulation Results
| Script | Figures generated |
|---|---|
run_paper_section4.py |
epkf_observations_x1_y1_Retroactions.png, epkf_x1_y1_Retroactions.png, upkf_x1_y1_Retroactions.png, ppf_x1_y1_Retroactions.png + Tables 1 & 2 |
run_paper_section4_backaction.py |
backaction_mse_nees_vs_b.png |
run_paper_section4_multip.py |
multip_mse_nees_vs_sigma.png |
run_paper_section4_sensitivity.py |
console output — mean ± std of MSE over 30 seeds |
python3 -m prg.run_paper_section4
python3 -m prg.run_paper_section4_backaction
python3 -m prg.run_paper_section4_multip
python3 -m prg.run_paper_section4_sensitivity
Section 5 — Real Data Experiment (S&P 500 Stochastic Volatility)
| Script | Figures generated |
|---|---|
run_paper_section5.py |
nn_gx_gy_sv.png, epkf_sv.png, upkf_sv.png, ppf_sv.png |
run_paper_section5_enso.py |
archived ENSO experiment (Niño 3.4 / SOI), kept for reference |
python3 -m prg.run_paper_section5 # requires: pip install yfinance
python3 -m prg.run_paper_section5_enso # archived version
Note: all figures are saved in
papier_NonLinearPKF/figures/.
Usage Examples
Simulate Linear Data and Filter with PKF
awesomepkf-simulate --N 2000 --linear-model-name "model_x1_y1_AQ_pairwise" --data-filename "testL.csv" --verbose 1 --s-key 303
awesomepkf-pkf --linear-model-name "model_x1_y1_AQ_pairwise" --data-filename "testL.csv" --verbose 1 --save-history --plot
Simulate Non-Linear Data and Filter with EPKF, UPKF and PPF
awesomepkf-simulate --N 1000 --nonlinear-model-name "model_x2_y1_pairwise" --data-filename "testNL.csv" --verbose 1 --s-key 303
awesomepkf-epkf --nonlinear-model-name "model_x2_y1_pairwise" --data-filename "testNL.csv" --verbose 1 --save-history --plot
awesomepkf-upkf --nonlinear-model-name "model_x2_y1_pairwise" --data-filename "testNL.csv" --sigma-set "wan2000" --verbose 1 --save-history --plot
awesomepkf-ppf --nonlinear-model-name "model_x2_y1_pairwise" --data-filename "testNL.csv" --n-particles 300 --verbose 1 --save-history --plot
Folders structure
./
├── data/
│ ├── datafile/
│ ├── historyTracker/
│ ├── plot/
│ └── clean_dirs.sh
├── notebooks/
├── prg/
│ ├── base_classes/
│ │ ├── __init__.py
│ │ ├── filter_runner.py
│ │ ├── filter_specs.py
│ │ ├── runner_base.py
│ │ ├── simulator_base.py
│ │ ├── simulator_linear.py
│ │ └── simulator_nonlinear.py
│ ├── classes/
│ │ ├── history_tracker/
│ │ │ ├── __init__.py
│ │ │ ├── _core.py
│ │ │ ├── _demo.py
│ │ │ ├── _metrics_mixin.py
│ │ │ └── _plot_mixin.py
│ │ ├── matrix_diagnostics/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── covariance.py
│ │ │ ├── invertible.py
│ │ │ ├── results.py
│ │ │ ├── stability.py
│ │ │ ├── status.py
│ │ │ └── tolerances.py
│ │ ├── __init__.py
│ │ ├── _base_particle_filter.py
│ │ ├── linear_pkf.py
│ │ ├── nonlinear_epkf.py
│ │ ├── nonlinear_pf.py
│ │ ├── nonlinear_ppf.py
│ │ ├── nonlinear_ukf.py
│ │ ├── nonlinear_upkf.py
│ │ ├── param_linear.py
│ │ ├── param_nonlinear.py
│ │ ├── pkf.py
│ │ ├── seed_generator.py
│ │ └── sigma_points_set.py
│ ├── models/
│ │ ├── linear/
│ │ │ ├── __init__.py
│ │ │ ├── _amq.py
│ │ │ ├── _base.py
│ │ │ ├── _dynamics.py
│ │ │ ├── _plotting.py
│ │ │ ├── _sigma.py
│ │ │ ├── _symbolic.py
│ │ │ ├── base_model_linear.py
│ │ │ └── configs.py
│ │ ├── nonlinear/
│ │ │ ├── __init__.py
│ │ │ ├── _latex_helpers.py
│ │ │ ├── base_model_fxhx.py
│ │ │ ├── base_model_gxgy.py
│ │ │ ├── base_model_nonlinear.py
│ │ │ ├── configs.py
│ │ │ ├── model_x1_y1_augmented.py
│ │ │ ├── model_x1_y1_lotkavolterra_augmented.py
│ │ │ ├── model_x1_y1_markov_naive.py
│ │ │ ├── model_x1_y1_multiplicative.py
│ │ │ ├── model_x1_y1_multiplicative_augmented.py
│ │ │ ├── model_x1_y1_pairwise_param.py
│ │ │ ├── model_x2_y1_augmented.py
│ │ │ ├── model_x2_y1_classic.py
│ │ │ └── model_x2_y2_augmented.py
│ │ └── __init__.py
│ ├── tests/
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_cli.py
│ │ ├── test_linear_pkf.py
│ │ ├── test_models.py
│ │ ├── test_nonlinear_filters.py
│ │ ├── test_particle_filters.py
│ │ └── test_simulators.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── csv_to_parquet.py
│ │ ├── display.py
│ │ ├── exceptions.py
│ │ ├── generate_matrix_cov.py
│ │ ├── io.py
│ │ ├── metrics.py
│ │ ├── nn_model.py
│ │ ├── numerics.py
│ │ ├── parser.py
│ │ └── plot_settings.py
│ ├── __init__.py
│ ├── run_filter.py
│ ├── run_linear_pkf.py
│ ├── run_nonlinear_epkf.py
│ ├── run_nonlinear_pf.py
│ ├── run_nonlinear_ppf.py
│ ├── run_nonlinear_ukf.py
│ ├── run_nonlinear_upkf.py
│ ├── run_paper_section4.py
│ ├── run_paper_section4_backaction.py
│ ├── run_paper_section4_multip.py
│ ├── run_paper_section4_sensitivity.py
│ ├── run_paper_section5.py
│ ├── run_paper_section5_enso.py
│ └── run_simulator.py
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── pyproject.toml
├── requirements.txt
└── update_readme_structure.sh
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file awesomepkf-2.1.2.tar.gz.
File metadata
- Download URL: awesomepkf-2.1.2.tar.gz
- Upload date:
- Size: 142.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0589a35aa50f1eb730395226ff91e2d5d465ec42a9a2325e46a5e31bea27b45
|
|
| MD5 |
c8fc323f9ae3ae11cf13bed37a115628
|
|
| BLAKE2b-256 |
b3656cbd8a79f0cd2bd243b33ad3f18561fcacbe1d1c8cae5abba48ad9a54d6f
|
Provenance
The following attestation bundles were made for awesomepkf-2.1.2.tar.gz:
Publisher:
publish.yml on SDerrode/awesomepkf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awesomepkf-2.1.2.tar.gz -
Subject digest:
b0589a35aa50f1eb730395226ff91e2d5d465ec42a9a2325e46a5e31bea27b45 - Sigstore transparency entry: 1441024900
- Sigstore integration time:
-
Permalink:
SDerrode/awesomepkf@92e64064163484be7a6e6ae1614a9cc02401e12f -
Branch / Tag:
refs/tags/v2.1.2 - Owner: https://github.com/SDerrode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92e64064163484be7a6e6ae1614a9cc02401e12f -
Trigger Event:
push
-
Statement type:
File details
Details for the file awesomepkf-2.1.2-py3-none-any.whl.
File metadata
- Download URL: awesomepkf-2.1.2-py3-none-any.whl
- Upload date:
- Size: 193.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f4d87e14c2a6b373a05506599a83f2073493d6e7518137203a1543af311108e
|
|
| MD5 |
3d489be482b92a073432b4ed73692aaf
|
|
| BLAKE2b-256 |
6ae3d34dde152f198070591c6993e9d5e4d7ad9decbb6ab546bd41cdc45fb2e0
|
Provenance
The following attestation bundles were made for awesomepkf-2.1.2-py3-none-any.whl:
Publisher:
publish.yml on SDerrode/awesomepkf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awesomepkf-2.1.2-py3-none-any.whl -
Subject digest:
3f4d87e14c2a6b373a05506599a83f2073493d6e7518137203a1543af311108e - Sigstore transparency entry: 1441025095
- Sigstore integration time:
-
Permalink:
SDerrode/awesomepkf@92e64064163484be7a6e6ae1614a9cc02401e12f -
Branch / Tag:
refs/tags/v2.1.2 - Owner: https://github.com/SDerrode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@92e64064163484be7a6e6ae1614a9cc02401e12f -
Trigger Event:
push
-
Statement type: