Skip to main content

tfilterspy logo

TFiltersPy

Bayesian state estimation for Python — sklearn-compatible, scalable, modular.

PyPI Version Python Versions License Downloads Stars


TFiltersPy provides 5 production-ready Bayesian filters with a unified fit / predict / score API. Built on NumPy/SciPy with optional Dask parallelism for large-scale problems.

pip install tfilterspy

Filters at a Glance

Filter Best For Linearity Jacobians? Scales To
KalmanFilter GPS tracking, signal denoising Linear N/A 10K+ steps
ExtendedKalmanFilter Radar, navigation Nonlinear Required 10K+ steps
UnscentedKalmanFilter Highly nonlinear systems Nonlinear Not needed 10K+ steps
EnsembleKalmanFilter Weather, ocean models Nonlinear Not needed High-dim states
ParticleFilter Robot localization, multimodal Any Not needed Non-Gaussian

Architecture

tfilterspy/
  __init__.py               # Top-level exports
  base_estimator.py          # BaseEstimator (sklearn API: fit/predict/score)
  state_estimation/
    linear_filters.py        # KalmanFilter, DaskKalmanFilter
    extended_kalman.py       # ExtendedKalmanFilter
    unscented_kalman.py      # UnscentedKalmanFilter
    ensemble_kalman.py       # EnsembleKalmanFilter (Dask-parallel)
    particle_filters.py      # ParticleFilter, DaskParticleFilter
  utils/
    optimisation_utils.py    # ParameterEstimator
                    +-----------------+
                    | BaseEstimator   |
                    |-----------------|
                    | fit(X)          |
                    | predict()       |
                    | score(X_true)   |
                    | fit_predict(X)  |
                    | filter_step(z)  |
                    | get_params()    |
                    | set_params()    |
                    +--------+--------+
                             |
          +------------------+-------------------+
          |                  |                   |
  +-------v-------+  +------v--------+  +-------v--------+
  | KalmanFilter  |  | Nonlinear     |  | ParticleFilter |
  |               |  | Filters       |  |                |
  | F, H matrices |  | f(), h()      |  | f(), h() or    |
  | smooth()      |  | callables     |  | F, H matrices  |
  | forecast()    |  |               |  |                |
  +---------------+  +---+-------+---+  | n_particles    |
                         |       |      | ESS monitoring |
              +----------+   +---+---+  +----------------+
              |              |       |
        +-----v-----+  +----v--+ +--v--------+
        |    EKF    |  | UKF   | |   EnKF    |
        | Jacobians |  | Sigma | | Ensemble  |
        | F_jac,    |  | points| | Dask      |
        | H_jac     |  |       | | parallel  |
        +-----------+  +-------+ +-----------+

Quick Start

Kalman Filter — GPS Tracking

A vehicle drives a figure-8. GPS gives noisy 2D position. The Kalman filter estimates the true trajectory, and RTS smoothing refines it further.

import numpy as np
from tfilterspy import KalmanFilter

dt = 0.1  # 10 Hz GPS

# Constant-velocity model: state = [x, vx, y, vy]
F = np.array([[1, dt, 0,  0],
              [0,  1, 0,  0],
              [0,  0, 1, dt],
              [0,  0, 0,  1]])

H = np.array([[1, 0, 0, 0],    # GPS observes position only
              [0, 0, 1, 0]])

Q = np.diag([0.1, 1.0, 0.1, 1.0])   # process noise
R = np.eye(2) * 25.0                  # GPS noise (5m std)^2
x0 = np.zeros(4)
P0 = np.eye(4) * 100.0

kf = KalmanFilter(F, H, Q, R, x0, P0)
kf.fit(gps_measurements)           # shape (n_steps, 2)
filtered = kf.predict()            # shape (n_steps, 4)
smoothed, _ = kf.smooth()          # RTS smoother
forecast, _ = kf.forecast(50)      # 50 steps ahead
score = kf.score(true_states)      # negative MSE
Filter Pipeline:
                                          +----------+
  GPS measurements ──> fit() ──> predict() ──> filtered states
                                     |
                                  smooth() ──> smoothed states (better)
                                     |
                                 forecast(n) ──> future prediction

Extended Kalman Filter — Radar Tracking

An aircraft in a coordinated turn. Radar measures range and bearing (nonlinear). The EKF linearizes at each step using Jacobians.

from tfilterspy import ExtendedKalmanFilter

def f_aircraft(x):
    return np.array([x[0] + dt*x[1], x[1], x[2] + dt*x[3], x[3]])

def h_radar(x):
    r = np.sqrt(x[0]**2 + x[2]**2)
    theta = np.arctan2(x[2], x[0])
    return np.array([r, theta])

def F_jac(x):
    return np.array([[1, dt, 0, 0], [0, 1, 0, 0],
                     [0, 0, 1, dt], [0, 0, 0, 1]])

def H_jac(x):
    px, _, py, _ = x
    r = np.sqrt(px**2 + py**2) + 1e-10
    return np.array([[px/r, 0, py/r, 0],
                     [-py/r**2, 0, px/r**2, 0]])

ekf = ExtendedKalmanFilter(
    f=f_aircraft, h=h_radar,
    F_jacobian=F_jac, H_jacobian=H_jac,
    Q=Q, R=R, x0=x0, P0=P0,
)
ekf.fit(radar_measurements)
states = ekf.predict()
smoothed, _ = ekf.smooth()

Unscented Kalman Filter — No Jacobians Needed

Same radar problem, but the UKF uses sigma points instead of Jacobians. Often more accurate for highly nonlinear systems.

from tfilterspy import UnscentedKalmanFilter

ukf = UnscentedKalmanFilter(
    f=f_aircraft, h=h_radar,
    Q=Q, R=R, x0=x0, P0=P0,
    alpha=1e-3, beta=2.0, kappa=0.0,
)
ukf.fit(radar_measurements)
states = ukf.predict()

Ensemble Kalman Filter — High-Dimensional Systems

Weather models, ocean simulations, and other systems with thousands of state variables. Uses a Monte Carlo ensemble instead of full covariance matrices. Supports Dask for parallel ensemble propagation.

from tfilterspy import EnsembleKalmanFilter

enkf = EnsembleKalmanFilter(
    f=dynamics_fn, h=observation_fn,
    Q=Q, R=R, x0=x0,
    n_ensemble=100,
    use_dask=True,      # parallel ensemble propagation
)
enkf.fit(measurements)
states = enkf.predict()

Particle Filter — Robot Localization

A robot navigates using range measurements to known landmarks. The particle filter handles the nonlinear observation model and can represent multimodal distributions.

from tfilterspy import ParticleFilter

def robot_dynamics(x):
    heading = x[2]
    return np.array([x[0] + 0.5*np.cos(heading),
                     x[1] + 0.5*np.sin(heading),
                     x[2] + 0.05])

def range_to_landmarks(x):
    pos = x[:2]
    return np.sqrt(np.sum((landmarks - pos)**2, axis=1))

pf = ParticleFilter(
    f=robot_dynamics, h=range_to_landmarks,
    Q=Q, R=R, x0=x0,
    n_particles=2000,
    resample_threshold=0.5,
)
pf.fit(range_measurements)
states = pf.predict()
ess = pf.effective_sample_sizes_   # monitor particle health

Online Filtering (Streaming Data)

All filters support step-by-step updates for real-time applications:

kf = KalmanFilter(F, H, Q, R, x0, P0)
for measurement in sensor_stream:
    x_est, P_est = kf.filter_step(measurement)
    print(f"State estimate: {x_est}")

Choosing a Filter

Start
  |
  v
Is the system linear? ──yes──> KalmanFilter
  |                              (fastest, optimal for linear-Gaussian)
  no
  |
  v
Is noise Gaussian? ──no──> ParticleFilter
  |                          (handles any distribution)
  yes
  |
  v
Can you compute Jacobians? ──yes──> ExtendedKalmanFilter
  |                                   (fast, needs analytical derivatives)
  no
  |
  v
Is the state dimension large (>100)? ──yes──> EnsembleKalmanFilter
  |                                             (scales to millions of states)
  no
  |
  v
UnscentedKalmanFilter
  (no Jacobians, sigma-point accuracy)

Memory Efficiency

For long time series, disable covariance storage to save ~80% memory:

kf = KalmanFilter(F, H, Q, R, x0, P0, store_covariances=False)
kf.fit(million_step_data)     # only stores state estimates
states = kf.predict()         # works fine
# kf.smooth()                 # raises error (needs stored covariances)

Examples

Full working examples are included in the repository:

Example File Description
GPS Vehicle Tracking examples/example_gps_tracking.py KF + RTS smoother on figure-8 trajectory, 86% noise reduction
Radar Target Tracking examples/example_radar_tracking.py EKF vs UKF on coordinated-turn aircraft with polar radar
Robot Localization examples/example_robot_localization.py Particle filter with range measurements to landmarks

Notebooks

Notebook Description
Kalman-filters-use-cases.ipynb Image denoising, EEG filtering, NLP topic smoothing
particle-filters-usecases.ipynb Computer vision, EEG, topic tracking with particle filters
nonlinear-filters-usecases.ipynb EKF, UKF, and EnKF on nonlinear problems
benchmarks.ipynb Speed and accuracy comparison of all 5 filters

Run any example:

python examples/example_gps_tracking.py

API Reference

All filters inherit from BaseEstimator and share this interface:

Method Description
fit(X) Run the forward filter pass on measurements X (n_steps, n_obs)
predict() Return filtered state estimates (n_steps, n_state)
score(X_true) Negative MSE vs ground truth (higher = better, sklearn convention)
fit_predict(X) Shorthand for fit(X).predict()
filter_step(z) Process a single measurement for online/streaming use
get_params() Get estimator parameters (sklearn-compatible)
set_params(**p) Set estimator parameters (sklearn-compatible)

KalmanFilter also provides:

Method Description
smooth() RTS backward smoother, returns (smoothed_states, smoothed_covs)
forecast(n_steps) Predict n steps into the future, returns (states, covariances)

ParticleFilter also provides:

Attribute Description
effective_sample_sizes_ ESS at each time step (monitors particle degeneracy)

Installation

pip install tfilterspy

From source:

git clone https://github.com/ubunye-ai-ecosystems/tfilterspy.git
cd tfilterspy
pip install -e .[dev]

Requirements: Python >= 3.8, NumPy, SciPy, Dask

Development

git clone https://github.com/ubunye-ai-ecosystems/tfilterspy.git
cd tfilterspy
pip install -e .[dev]
pytest tests/

The test suite covers all 5 filters with 37+ tests including edge cases, backward compatibility, and a 10K-step large dataset test.

Contributing

  • Found a bug? Open an issue.
  • Want to add a feature? Fork, implement, and open a pull request.
  • Write tests for any new filter or feature.

License

MIT License. See LICENSE for details.

Documentation

Full documentation: ubunye-ai-ecosystems.github.io/tfilterspy

Metadata

Release files for tfilterspy 1.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tfilterspy 1.0.6
File Size Uploaded
tfilterspy-1.0.6.tar.gz 2.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for tfilterspy 1.0.6
File Interpreter ABI Platform
tfilterspy-1.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 2.8 MB

Release files / tfilterspy-1.0.6.tar.gz

Download URL tfilterspy-1.0.6.tar.gz
Size 2.8 MB
Tags Source
SHA-256 checksum
How to use checksums
9d5ce2d365a03e50d141d1c04789da26e188362d88a5ec25a757fbf525c5fb05
BLAKE2b-256 checksum
How to use checksums
71d27f5bb70bfae483739f0aca440dbecbb473c461956d26e24efc9fc5a12894
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.20

Release files / tfilterspy-1.0.6-py3-none-any.whl

Download URL tfilterspy-1.0.6-py3-none-any.whl
Size 23.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d5c7c77630eb10feebfd4a4cfd2575a932d100a55d15c6d6c654ce13a78ec4e0
BLAKE2b-256 checksum
How to use checksums
5ed51c7ac99a7f664aeeda77418809da3394d6b5e385cda6bcf7b98e307343dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.20

Release history Release notifications | RSS feed

This release

1.0.6 This release

2 release files

1.0.5

2 release files

1.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page