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 many methods for computing numerical derivatives and smooth estimates 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

All are ultimately smoothing with similar runtime and accuracy, but some have situational advantages over others: For example, robustdiff is specialized to handle outliers; splinediff, polydiff, rtsdiff, and robustdiff can handle missing data; splinediff, polydiff, rbfdiff, rtsdiff, and robustdiff can handle irregularly-spaced data; and rtsdiff can handle inputs on a wrapped domain, like angles. All methods can accept blocks of multidimensional data, differentiating all vectors along the dimension given by the axis parameter.

For a full list and comparison, see section 7 of our Taxonomy Paper and explore modules in the Sphinx documentation.

All methods have hyperparameters, so we take a principled approach and propose a multi-objective optimization framework for choosing settings 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. All major methods support multidimensional data, so look for 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.3.tar.gz (11.6 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.3-py3-none-any.whl (69.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for pynumdiff-0.2.3.tar.gz
Algorithm Hash digest
SHA256 3e255cabeec98d439726bdac111609d9314d8632ae53cc8cc811595d793abd77
MD5 82fce1b7aed0ee4645897ba924cd1839
BLAKE2b-256 e9935de20d28b54904fd19ff68d442b48d4aaa8545247d7bb8d45c281c3faf96

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for pynumdiff-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 fdef72b933b4a48c21d3375306df7b39ad47461d57dc36b3a34665d6d13e2ec3
MD5 a4d2764a0582d1124c4bc7fe520c6d97
BLAKE2b-256 db746ffacdb7789be02e295c6c8cd83e62400f5c2cb5cf5e09cf6581a5a05aa8

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