Skip to content

BruninLima/PydaptiveFiltering

Repository files navigation

pydaptivefiltering

Adaptive filtering in Python
Implementations based on Adaptive Filtering: Algorithms and Practical Implementation (Paulo S. R. Diniz).

PyPI version Docs License

📌 Table of Contents


Install

pip install pydaptivefiltering

Requirements

  • Python 3.10+ (tested on )
  • NumPy, SciPy

Implementation and Examples

All algorithms follow the same pattern:

  1. Instantiate the filter/model
  2. Run optimize(input_signal, desired_signal)
  3. Inspect outputs, errors, coefficients, and optional extra

Returned dictionary keys:

  • outputs: model output
  • errors: error sequence (see error_type)
  • coefficients: coefficient history (snapshots over time)
  • runtime_s: runtime in seconds
  • error_type: "a_priori", "a_posteriori", or "output_error"
  • extra: optional internal states (when enabled)

System identification (Complex example with RLS):

import numpy as np
import pydaptivefiltering as pdf

rng = np.random.default_rng(0)

# True system (complex FIR)
w_true = np.array([0.5+0.2j, -0.4+0.5j, 0.1-0.1j, 0.2+0j, -0.1+0.1j, 0.0+0.05j])
M = len(w_true) - 1

# Data
N = 5000
x = (rng.standard_normal(N) + 1j*rng.standard_normal(N)) / np.sqrt(2)
noise = 0.05 * (rng.standard_normal(N) + 1j*rng.standard_normal(N)) / np.sqrt(2)

# Desired: d[k] = w^H x_k + noise
x_pad = np.concatenate([np.zeros(M, dtype=complex), x])
d = np.array([np.vdot(w_true, x_pad[k:k+M+1][::-1]) for k in range(N)]) + noise

# RLS
rls = pdf.RLS(filter_order=M, delta=1.0, forgetting_factor=0.995)
res = rls.optimize(x, d)

Coefficients convergence plot


Example: Neural Adaptive Filtering (MLP)

Nonlinear system:

$$d(k) = x(k)^2 + 0.5,x(k-1) + \eta(k) $$

import numpy as np
import matplotlib.pyplot as plt
import pydaptivefiltering as pdf

rng = np.random.default_rng(1)

# Data
N = 3000
x = rng.uniform(-1, 1, N)
d = np.zeros(N)
for k in range(1, N):
    d[k] = (x[k]**2) + 0.5*x[k-1] + 0.01*rng.standard_normal()

# MLP
mlp = pdf.MultilayerPerceptron(
    n_neurons=8,
    input_dim=3,
    step_size=0.01,
    momentum=0.9,
    activation="tanh",
)

res = mlp.optimize(x, d)

plt.plot(10*np.log10(res.errors**2 + 1e-12), alpha=0.8)
plt.title(f"MLP Convergence (Final MSE: {np.mean(res.errors[-500:]**2):.6f})")
plt.xlabel("Iteration")
plt.ylabel("Squared Error (dB)")
plt.show()

RBF learning curve

RBF weights convergence


arget-tracking example using a 2-state constant-velocity (CV) Kalman filter (position/velocity). The target performs piecewise acceleration maneuvers, while we measure position only with additive noise; the filter estimates both position and velocity from the noisy measurements.

import numpy as np
import pydaptivefiltering as pdf

rng = np.random.default_rng(7)

# 1) Synthetic target: constant-velocity model with acceleration maneuvers
N, dt = 400, 1.0
x_true = np.zeros((N, 2), dtype=float)   # [pos, vel]

a = np.zeros(N)
a[60:120]  =  0.08
a[180:230] = -0.12
a[300:340] =  0.05

x_true[0] = [0.0, 1.0]
for k in range(1, N):
    pos_prev, vel_prev = x_true[k - 1]
    x_true[k, 1] = vel_prev + a[k] * dt
    x_true[k, 0] = pos_prev + vel_prev * dt + 0.5 * a[k] * dt**2

sigma_meas = 0.8
y = x_true[:, 0] + sigma_meas * rng.standard_normal(N)

# 2) Kalman filter (CV: position/velocity), measuring position only
A = np.array([[1.0, dt],
              [0.0, 1.0]])

C_T = np.array([[1.0, 0.0]])  # shape (p=1, n=2)

sigma_a = 0.15
Q = (sigma_a**2) * np.array([[dt**4/4, dt**3/2],
                             [dt**3/2, dt**2]])

Rn  = Q
Rn1 = np.array([[sigma_meas**2]])

kf = pdf.Kalman(
    A=A,
    C_T=C_T,
    Rn=Rn,
    Rn1=Rn1,
    x_init=np.array([y[0], 0.0]),
    Re_init=np.eye(2) * 50.0,
)

res = kf.optimize(y)

x_hat = res.outputs
innov = res.errors

rmse_pos = np.sqrt(np.mean((x_hat[:, 0] - x_true[:, 0])**2))
rmse_vel = np.sqrt(np.mean((x_hat[:, 1] - x_true[:, 1])**2))

print(f"RMSE position: {rmse_pos:.3f}")
print(f"RMSE velocity: {rmse_vel:.3f}")
print(f"Innovation std: {innov.std():.3f}")

Kalman tracking

Kalman innovation


Algorithms (overview)

This is an overview. For the full list, check the documentation: Docs

Algorithms categories are based on the chapters of the book Adaptive Filtering: Algorithms and Practical Implementation (Paulo S. R. Diniz).

Module / Category Exported classes (examples) Data type
lms/ (LMS family) LMS, NLMS, AffineProjection, SignData, SignError, DualSign, LMSNewton, Power2ErrorLMS, TDomainLMS, TDomainDCT, TDomainDFT Real/Complex
rls/ (RLS family) RLS, RLSAlt Complex
set_membership/ (Set-membership) SMNLMS, SMBNLMS, SMAffineProjection, SimplifiedSMAP, SimplifiedSMPUAP Real/Complex
lattice/ (Lattice-based RLS) LRLSPosteriori, LRLSErrorFeedback, LRLSPriori, NormalizedLRLS Complex
fast_rls/ (Fast Transversal RLS) FastRLS, StabFastRLS Real
qr_decomposition/ (QR-RLS) QRRLS Real
iir/ (Adaptive IIR) ErrorEquation, GaussNewton, GaussNewtonGradient, RLSIIR, SteiglitzMcBride Real
nonlinear/ (Nonlinear models) VolterraLMS, VolterraRLS, BilinearRLS, RBF, ComplexRBF, MultilayerPerceptron Real/Complex
subband/ (Subband) OLSBLMS, DLCLLMS, CFDLMS Real
blind/ (Blind equalization) CMA, Godard, Sato, AffineProjectionCM Complex
kalman/ (Kalman) Kalman Complex
base/ (Core API) AdaptiveFilter N/A

Notebooks


📝 License

This project is under the license found at LICENSE.

GitHub repo size GitHub language count GitHub forks

References

  • Diniz, P. S. R. (2020). Adaptive Filtering: Algorithms and Practical Implementation. Springer.
  • MATLAB Adaptive Filtering Toolbox v4.

Documentation and docstrings were refined using AI assistance to ensure the NumPy/SciPy documentation standards and mathematical clarity.

About

Modern Python package of the Adaptive Filtering Toolbox

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages