pynumdiff


Namepynumdiff JSON
Version 0.2 PyPI version JSON
download
home_pageNone
Summarypynumdiff: numerical derivatives in python
upload_time2025-10-09 01:16:48
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseMIT
keywords derivative smoothing curve fitting optimization total variation
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PyNumDiff

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

<p align="center">
  <a href="https://pynumdiff.readthedocs.io/master/">
    <img alt="Python for Numerical Differentiation of noisy time series data" src="https://raw.githubusercontent.com/florisvb/PyNumDiff/master/logo.png" width="300" height="200" />
  </a>
</p>

<p align="center">
    <img src='https://github.com/florisvb/pynumdiff/actions/workflows/test.yml/badge.svg'/>
    <a href='https://pynumdiff.readthedocs.io/master/'>
        <img src='https://app.readthedocs.org/projects/pynumdiff/badge/?version=master' alt='Documentation Status' /></a>
    <a href='https://coveralls.io/github/florisvb/PyNumDiff?branch=master'>
        <img src='https://coveralls.io/repos/github/florisvb/PyNumDiff/badge.svg?branch=master' alt='Coverage Status' /></a>
    <a href="https://badge.fury.io/py/pynumdiff">
        <img src="https://badge.fury.io/py/pynumdiff.svg" alt="PyPI"></a>
    <a href="https://zenodo.org/badge/latestdoi/159711175">
        <img src="https://zenodo.org/badge/159711175.svg" alt="DOI"></a>
    <a href="https://joss.theoj.org/papers/102257ee4b0142bf49bc18d7c810e9d5">
        <img src="https://joss.theoj.org/papers/102257ee4b0142bf49bc18d7c810e9d5/status.svg"></a>
</p>

## 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. convolutional smoothing followed by finite difference calculation
2. polynomial fit methods
3. basis function fit methods
4. iterated finite differencing
5. total variation regularization of a finite difference derivative
6. Kalman (RTS) smoothing
7. local approximation with linear model

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](https://doi.org/10.1109/ACCESS.2020.3034077).

## Installing

Dependencies are listed in [pyproject.toml](https://github.com/florisvb/PyNumDiff/blob/master/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](https://www.cvxpy.org).

## Usage

For more details, read our [Sphinx documentation](https://pynumdiff.readthedocs.io/master/). The basic pattern of all differentiation methods is:

```python
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 `_t` and can receive either a constant step size or an array of values to denote sample locations.

You can provide the parameters:
```python
from pynumdiff.submodule import method

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

Or you can find parameter by calling the multi-objective optimization algorithm from the `optimize` module:
```python
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:
* Differentiation with different methods: [1_basic_tutorial.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/1_basic_tutorial.ipynb)
* Parameter Optimization with known ground truth (only for demonstration purpose):  [2a_optimizing_parameters_with_dxdt_known.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/2a_optimizing_parameters_with_dxdt_known.ipynb)
* Parameter Optimization with unknown ground truth: [2b_optimizing_parameters_with_dxdt_unknown.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/2b_optimizing_parameters_with_dxdt_unknown.ipynb)
* Automatic method suggestion: [3_automatic_method_suggestion.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/3_automatic_method_suggestion.ipynb)

## 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`.
- `examples/` 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.
- `.editorconfig` ensures tabs are displayed as 4 characters wide.
- `.gitignore` ensures files generated by local `pip install`s, 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.
- `linting.py` is a script to run `pylint`.
- `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}
    }

### 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
```bash
> 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](https://github.com/florisvb/PyNumDiff/blob/master/LICENSE.txt).
100% open-source, feel free to utilize the code however you like. 

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pynumdiff",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": "Floris van Breugel <fvanbreugel@unr.edu>, Pavel Komarov <pvlkmrv@uw.edu>, Yuying Liu <yliu814@uw.edu>",
    "keywords": "derivative, smoothing, curve fitting, optimization, total variation",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/a6/a2/0b3fa9974a5737ad3005b68e031196e7e3a94abeb592f143a7587d9b1098/pynumdiff-0.2.tar.gz",
    "platform": null,
    "description": "# PyNumDiff\n\nPython methods for numerical differentiation of noisy data, including multi-objective optimization routines for automated parameter selection.\n\n<p align=\"center\">\n  <a href=\"https://pynumdiff.readthedocs.io/master/\">\n    <img alt=\"Python for Numerical Differentiation of noisy time series data\" src=\"https://raw.githubusercontent.com/florisvb/PyNumDiff/master/logo.png\" width=\"300\" height=\"200\" />\n  </a>\n</p>\n\n<p align=\"center\">\n    <img src='https://github.com/florisvb/pynumdiff/actions/workflows/test.yml/badge.svg'/>\n    <a href='https://pynumdiff.readthedocs.io/master/'>\n        <img src='https://app.readthedocs.org/projects/pynumdiff/badge/?version=master' alt='Documentation Status' /></a>\n    <a href='https://coveralls.io/github/florisvb/PyNumDiff?branch=master'>\n        <img src='https://coveralls.io/repos/github/florisvb/PyNumDiff/badge.svg?branch=master' alt='Coverage Status' /></a>\n    <a href=\"https://badge.fury.io/py/pynumdiff\">\n        <img src=\"https://badge.fury.io/py/pynumdiff.svg\" alt=\"PyPI\"></a>\n    <a href=\"https://zenodo.org/badge/latestdoi/159711175\">\n        <img src=\"https://zenodo.org/badge/159711175.svg\" alt=\"DOI\"></a>\n    <a href=\"https://joss.theoj.org/papers/102257ee4b0142bf49bc18d7c810e9d5\">\n        <img src=\"https://joss.theoj.org/papers/102257ee4b0142bf49bc18d7c810e9d5/status.svg\"></a>\n</p>\n\n## Introduction\n\nPyNumDiff 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:\n\n1. convolutional smoothing followed by finite difference calculation\n2. polynomial fit methods\n3. basis function fit methods\n4. iterated finite differencing\n5. total variation regularization of a finite difference derivative\n6. Kalman (RTS) smoothing\n7. local approximation with linear model\n\nMost 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](https://doi.org/10.1109/ACCESS.2020.3034077).\n\n## Installing\n\nDependencies are listed in [pyproject.toml](https://github.com/florisvb/PyNumDiff/blob/master/pyproject.toml). They include the usual suspects like `numpy` and `scipy`, but also optionally `cvxpy`.\n\nThe 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](https://www.cvxpy.org).\n\n## Usage\n\nFor more details, read our [Sphinx documentation](https://pynumdiff.readthedocs.io/master/). The basic pattern of all differentiation methods is:\n\n```python\nsomethingdiff(x, dt, **kwargs)\n```\n\nwhere `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 `_t` and can receive either a constant step size or an array of values to denote sample locations.\n\nYou can provide the parameters:\n```python\nfrom pynumdiff.submodule import method\n\nx_hat, dxdt_hat = method(x, dt, param1=val1, param2=val2, ...)     \n```\n\nOr you can find parameter by calling the multi-objective optimization algorithm from the `optimize` module:\n```python\nfrom pynumdiff.optimize import optimize\n\n# 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\ntvgamma = np.exp(-1.6*np.log(cutoff_frequency) -0.71*np.log(dt) - 5.1) # see https://ieeexplore.ieee.org/abstract/document/9241009\n\nparams, val = optimize(somethingdiff, x, dt, tvgamma=tvgamma, # smoothness hyperparameter which defaults to None if dxdt_truth given\n            dxdt_truth=None, # give ground truth data if available, in which case tvgamma goes unused\n            search_space_updates={'param1':[vals], 'param2':[vals], ...})\n\nprint('Optimal parameters: ', params)\nx_hat, dxdt_hat = somethingdiff(x, dt, **params)\n```\nIf no `search_space_updates` is given, a default search space is used. See the top of `_optimize.py`.\n\nThe 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.\n\n### Notebook examples\n\nMuch more extensive usage is demonstrated in Jupyter notebooks:\n* Differentiation with different methods: [1_basic_tutorial.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/1_basic_tutorial.ipynb)\n* Parameter Optimization with known ground truth (only for demonstration purpose):  [2a_optimizing_parameters_with_dxdt_known.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/2a_optimizing_parameters_with_dxdt_known.ipynb)\n* Parameter Optimization with unknown ground truth: [2b_optimizing_parameters_with_dxdt_unknown.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/2b_optimizing_parameters_with_dxdt_unknown.ipynb)\n* Automatic method suggestion: [3_automatic_method_suggestion.ipynb](https://github.com/florisvb/PyNumDiff/blob/master/examples/3_automatic_method_suggestion.ipynb)\n\n## Repo Structure\n\n- `.github/workflows` contains `.yaml` that configures our GitHub Actions continuous integration (CI) runs.\n- `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`.\n- `examples/` contains Jupyter notebooks that demonstrate some usage of the library.\n- `pynumdiff/` contains the source code. For a full list of modules and further navigation help, see the readme in this subfolder.\n- `.editorconfig` ensures tabs are displayed as 4 characters wide.\n- `.gitignore` ensures files generated by local `pip install`s, Jupyter notebook runs, caches from code runs, virtual environments, and more are not picked up by `git` and accidentally added to the repo.\n- `.pylintrc` configures `pylint`, a tool for autochecking code quality.\n- `.readthedocs.yaml` configures `readthedocs` and is necessary for documentation to get auto-rebuilt.\n- `CITATION.cff` is citation information for the Journal of Open-Source Software (JOSS) paper associated with this project.\n- `LICENSE.txt` allows free usage of this project.\n- `README.md` is the text you're reading, hello.\n- `linting.py` is a script to run `pylint`.\n- `pyproject.toml` governs how this package is set up and installed, including dependencies.\n\n## Citation\n\nSee CITATION.cff file as well as the following references.\n\n### PyNumDiff python package:\n\n    @article{PyNumDiff2022,\n      doi = {10.21105/joss.04078},\n      url = {https://doi.org/10.21105/joss.04078},\n      year = {2022},\n      publisher = {The Open Journal},\n      volume = {7},\n      number = {71},\n      pages = {4078},\n      author = {Floris van Breugel and Yuying Liu and Bingni W. Brunton and J. Nathan Kutz},\n      title = {PyNumDiff: A Python package for numerical differentiation of noisy time-series data},\n      journal = {Journal of Open Source Software}\n    }\n\n### Optimization algorithm:\n\n    @article{ParamOptimizationDerivatives2020, \n    doi={10.1109/ACCESS.2020.3034077}\n    author={F. {van Breugel} and J. {Nathan Kutz} and B. W. {Brunton}}, \n    journal={IEEE Access}, \n    title={Numerical differentiation of noisy data: A unifying multi-objective optimization framework}, \n    year={2020}\n    }\n\n## Running the tests\n\nWe are using GitHub Actions for continuous intergration testing.\n\nRun tests locally by navigating to the repo in a terminal and calling\n```bash\n> pytest -s\n```\n\nAdd 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).\n\n## License\n\nThis project utilizes the [MIT LICENSE](https://github.com/florisvb/PyNumDiff/blob/master/LICENSE.txt).\n100% open-source, feel free to utilize the code however you like. \n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "pynumdiff: numerical derivatives in python",
    "version": "0.2",
    "project_urls": {
        "documentation": "https://pynumdiff.readthedocs.io/",
        "homepage": "https://github.com/florisvb/PyNumDiff",
        "package": "https://pypi.org/project/pynumdiff/"
    },
    "split_keywords": [
        "derivative",
        " smoothing",
        " curve fitting",
        " optimization",
        " total variation"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6b6e84de64571be57eb4f1f4800aa5ff11a9e8c6c342a6cdd6e3be7405745764",
                "md5": "6f7b82061bc234ee8fe700ce1d9973d0",
                "sha256": "d53ed57cb7c7cdc80a3541e607f03d01aa94cfeca590faa939288ae803e36bcd"
            },
            "downloads": -1,
            "filename": "pynumdiff-0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6f7b82061bc234ee8fe700ce1d9973d0",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 60101,
            "upload_time": "2025-10-09T01:16:46",
            "upload_time_iso_8601": "2025-10-09T01:16:46.964981Z",
            "url": "https://files.pythonhosted.org/packages/6b/6e/84de64571be57eb4f1f4800aa5ff11a9e8c6c342a6cdd6e3be7405745764/pynumdiff-0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a6a20b3fa9974a5737ad3005b68e031196e7e3a94abeb592f143a7587d9b1098",
                "md5": "8e5e6a76b13336e4671ad762cb2cf25e",
                "sha256": "62e290df47febdc051c098c0c3492c3457651e039267b081c580afcb93456436"
            },
            "downloads": -1,
            "filename": "pynumdiff-0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "8e5e6a76b13336e4671ad762cb2cf25e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 12145520,
            "upload_time": "2025-10-09T01:16:48",
            "upload_time_iso_8601": "2025-10-09T01:16:48.090849Z",
            "url": "https://files.pythonhosted.org/packages/a6/a2/0b3fa9974a5737ad3005b68e031196e7e3a94abeb592f143a7587d9b1098/pynumdiff-0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-09 01:16:48",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "florisvb",
    "github_project": "PyNumDiff",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pynumdiff"
}
        
Elapsed time: 1.10924s