Skip to main content

pynumdiff: numerical derivatives in python

Project description

PyNumDiff

Python methods for numerical differentiation of noisy data, including multi-objective optimization routines for automated parameter selection.

Python for Numerical Differentiation of noisy time series data

Documentation Status Coverage Status PyPI

Introduction

PyNumDiff is a Python package that implements various methods for computing numerical derivatives of noisy data, which can be a critical step in developing dynamic models or designing control. There are seven different families of methods implemented in this repository:

  1. prefiltering followed by finite difference calculation
  2. iterated finite differencing
  3. polynomial fit methods
  4. basis function fit methods
  5. total variation regularization of a finite difference derivative
  6. generalized Kalman smoothing
  7. local approximation with linear model

For a full list, explore modules in the Sphinx documentation, or read section 7 of our Taxonomy Paper.

Most of these methods have multiple parameters, so we take a principled approach and propose a multi-objective optimization framework for choosing parameters that minimize a loss function to balance the faithfulness and smoothness of the derivative estimate. For more details, refer to this paper.

Installing

Dependencies are listed in pyproject.toml. They include the usual suspects like numpy and scipy, but also optionally cvxpy.

The code is compatible with >=Python 3.10. Install from PyPI with pip install pynumdiff, from source with pip install git+https://github.com/florisvb/PyNumDiff, or from local download with pip install .. Call pip install pynumdiff[advanced] to automatically install optional dependencies from the advanced list, like CVXPY.

Usage

For more details, read our Sphinx documentation. The basic pattern of all differentiation methods is:

somethingdiff(x, dt, **kwargs)

where x is data, dt is a step size, and various keyword arguments control the behavior. Some methods support variable step size, in which case the second parameter is renamed dt_or_t and can receive either a constant step size or an array of values to denote sample locations. Some methods support multidimensional data, in which case there is an axis argument to control the dimension differentiated along.

You can set the hyperparameters:

from pynumdiff.submodule import method

x_hat, dxdt_hat = method(x, dt, param1=val1, param2=val2, ...)     

Or you can find hyperparameter settings by calling the multi-objective optimization algorithm from the optimize module:

from pynumdiff.optimize import optimize

# estimate cutoff_frequency by (a) counting the number of true peaks per second in the data or (b) look at power spectra and choose cutoff
tvgamma = np.exp(-1.6*np.log(cutoff_frequency) -0.71*np.log(dt) - 5.1) # see https://ieeexplore.ieee.org/abstract/document/9241009

params, val = optimize(somethingdiff, x, dt, tvgamma=tvgamma, # smoothness hyperparameter which defaults to None if dxdt_truth given
            dxdt_truth=None, # give ground truth data if available, in which case tvgamma goes unused
            search_space_updates={'param1':[vals], 'param2':[vals], ...})

print('Optimal parameters: ', params)
x_hat, dxdt_hat = somethingdiff(x, dt, **params)

If no search_space_updates is given, a default search space is used. See the top of optimize.py.

The following heuristic works well for choosing tvgamma, where cutoff_frequency is the highest frequency content of the signal in your data, and dt is the timestep: tvgamma=np.exp(-1.6*np.log(cutoff_frequency)-0.71*np.log(dt)-5.1). Larger values of tvgamma produce smoother derivatives. The value of tvgamma is largely universal across methods, making it easy to compare method results. Be aware the optimization is a fairly heavy process.

Notebook examples

Much more extensive usage is demonstrated in Jupyter notebooks:

See the README in the notebooks/ folder for a full guide to all demos and experiments.

Repo Structure

  • .github/workflows contains .yaml that configures our GitHub Actions continuous integration (CI) runs.
  • docs/ contains make files and .rst files to govern the way sphinx builds documentation, either locally by navigating to this folder and calling make html or in the cloud by readthedocs.io.
  • notebooks/ contains Jupyter notebooks that demonstrate some usage of the library.
  • pynumdiff/ contains the source code. For a full list of modules and further navigation help, see the readme in this subfolder.
  • .coveragerc governs coverage runs, listing files and functions/lines that should be excluded, e.g. plotting code.
  • .editorconfig ensures tabs are displayed as 4 characters wide.
  • .gitignore ensures files generated by local pip installs, Jupyter notebook runs, caches from code runs, virtual environments, and more are not picked up by git and accidentally added to the repo.
  • .pylintrc configures pylint, a tool for autochecking code quality.
  • .readthedocs.yaml configures readthedocs and is necessary for documentation to get auto-rebuilt.
  • CITATION.cff is citation information for the Journal of Open-Source Software (JOSS) paper associated with this project.
  • LICENSE.txt allows free usage of this project.
  • README.md is the text you're reading, hello.
  • pyproject.toml governs how this package is set up and installed, including dependencies.

Citation

See CITATION.cff file as well as the following references.

PyNumDiff python package:

@article{PyNumDiff2022,
  doi = {10.21105/joss.04078},
  url = {https://doi.org/10.21105/joss.04078},
  year = {2022},
  publisher = {The Open Journal},
  volume = {7},
  number = {71},
  pages = {4078},
  author = {Floris van Breugel and Yuying Liu and Bingni W. Brunton and J. Nathan Kutz},
  title = {PyNumDiff: A Python package for numerical differentiation of noisy time-series data},
  journal = {Journal of Open Source Software}
}

Collection of numerical differentiation methods:

@misc{komarov2025taxonomynumericaldifferentiationmethods,
  title={A Taxonomy of Numerical Differentiation Methods},
  author={Pavel Komarov and Floris van Breugel and J. Nathan Kutz},
  year={2025},
  eprint={2512.09090},
  archivePrefix={arXiv},
  primaryClass={math.NA},
  url={https://arxiv.org/abs/2512.09090}
}

Optimization algorithm:

@article{ParamOptimizationDerivatives2020, 
doi={10.1109/ACCESS.2020.3034077}
author={F. {van Breugel} and J. {Nathan Kutz} and B. W. {Brunton}}, 
journal={IEEE Access}, 
title={Numerical differentiation of noisy data: A unifying multi-objective optimization framework}, 
year={2020}
}

Running the tests

We are using GitHub Actions for continuous intergration testing.

Run tests locally by navigating to the repo in a terminal and calling

> pytest -s

Add the flag --plot to see plots of the methods against test functions. Add the flag --bounds to print $\log$ error bounds (useful when changing method behavior).

License

This project utilizes the MIT LICENSE. 100% open-source, feel free to utilize the code however you like.

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

pynumdiff-0.2.2.tar.gz (11.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pynumdiff-0.2.2-py3-none-any.whl (65.5 kB view details)

Uploaded Python 3

File details

Details for the file pynumdiff-0.2.2.tar.gz.

File metadata

  • Download URL: pynumdiff-0.2.2.tar.gz
  • Upload date:
  • Size: 11.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for pynumdiff-0.2.2.tar.gz
Algorithm Hash digest
SHA256 4a73497b7646633da8fe58fecd9c74286fa549f3aa1a291ea6e18b6aae8229d0
MD5 56eec3d15a7f59e1fd59cf5e28a548aa
BLAKE2b-256 2adfb45f3d86321936881d6422a4b4e9210e1882e7958df449bfddf486f7272f

See more details on using hashes here.

File details

Details for the file pynumdiff-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: pynumdiff-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 65.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for pynumdiff-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1f84bc38373c070b2a1aca4b3b8d7b0d761ce910bea63dc848ff6a8b52ac53b8
MD5 ba5cc5a3157b8ca29f6ddba6bfbffc36
BLAKE2b-256 bf0acd41958edd6a5ca5862f39b7765a3d4daf92236667f6154085ec5cf3d2e6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page