# LSPOpt
![Build and Test](https://github.com/hbldh/lspopt/workflows/Build%20and%20Test/badge.svg)
[![PyPI version](https://img.shields.io/pypi/v/lspopt.svg)](https://pypi.org/project/lspopt/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
This module is a Python implementation of the multitaper window method
described in [\[1\]](#references) for estimating Wigner spectra for certain locally
stationary processes.
Abstract from [\[1\]](#references):
> This paper investigates the time-discrete multitapers that give a mean square error optimal Wigner spectrum estimate for a class
> of locally stationary processes (LSPs). The accuracy in the estimation of the time-variable Wigner spectrum of the LSP is evaluated
> and compared with other frequently used methods. The optimal multitapers are also approximated by Hermite functions, which is
> computationally more efficient, and the errors introduced by this approximation are studied. Additionally, the number of windows
> included in a multitaper spectrum estimate is often crucial and an investigation of the error caused by limiting this number is made.
> Finally, the same optimal set of weights can be stored and utilized for different window lengths. As a result, the optimal multitapers
> are shown to be well approximated by Hermite functions, and a limited number of windows can be used for a mean square error
> optimal spectrogram estimate.
## Installation
Install via pip:
pip install lspopt
If you prefer to use `conda`, see [instructions in this repo](https://github.com/conda-forge/lspopt-feedstock).
## Testing
Test with `pytest`:
pytest tests/
See test badge at the top of this README for link to test coverage and reports.
## Usage
To generate the taper windows only, use the `lspopt` method:
```python
from lspopt import lspopt
H, w = lspopt(n=256, c_parameter=20.0)
```
There is also a convenience method for using the [SciPy spectrogram method](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html#scipy.signal.spectrogram)
with the `lspopt` multitaper windows:
```python
from lspopt import spectrogram_lspopt
f, t, Sxx = spectrogram_lspopt(x, fs, c_parameter=20.0)
```
This can then be plotted with e.g. [matplotlib](http://matplotlib.org/).
### Example
One can generate a [chirp](https://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.signal.chirp.html)
process realisation and run spectrogram methods on this.
```python
import numpy as np
from scipy.signal import chirp, spectrogram
import matplotlib.pyplot as plt
from lspopt.lsp import spectrogram_lspopt
fs = 10000
N = 100000
amp = 2 * np.sqrt(2)
noise_power = 0.001 * fs / 2
time = np.arange(N) / fs
freq = np.linspace(1000, 2000, N)
x = amp * chirp(time, 1000, 2.0, 6000, method='quadratic') + \
np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
f, t, Sxx = spectrogram(x, fs)
ax = plt.subplot(211)
ax.pcolormesh(t, f, Sxx)
ax.set_ylabel('Frequency [Hz]')
ax.set_xlabel('Time [sec]')
f, t, Sxx = spectrogram_lspopt(x, fs, c_parameter=20.0)
ax = plt.subplot(212)
ax.pcolormesh(t, f, Sxx)
ax.set_ylabel('Frequency [Hz]')
ax.set_xlabel('Time [sec]')
plt.tight_layout()
plt.show()
```
![Spectrogram plot](https://github.com/hbldh/lspopt/blob/master/plot.png "Top: Using SciPy's spectrogram method. Bottom: Using LSPOpt's spectrogram solution.")
*Top: Using SciPy's spectrogram method. Bottom: Using LSPOpt's spectrogram solution.*
## References
\[1\] [Hansson-Sandsten, M. (2011). Optimal multitaper Wigner spectrum
estimation of a class of locally stationary processes using Hermite functions.
EURASIP Journal on Advances in Signal Processing, 2011, 10.](https://dx.doi.org/10.1155/2011/980805)
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.4.0] - 2025-01-07
### Added
- Support for Python 3.12
- Support for `pip>=25`
- Support for `numpy>=2`
- Support for Windows and macOS
- Converted `setup.py` to `setup.cfg`
### Removed
- Support for Python 3.7 and 3.8
- Unused imports
## [1.3.0] - 2023-01-24
### Changed
- Modified test matrix in CI
### Removed
- Support for Python 2.7 and 3.6.
- Dependency on `six`.
## [1.2.0] - 2022-06-08
### Added
- New plot file
### Fixed
- Source distribution was broken on PyPI. Modified `MANIFEST.in` to correct that (#5 and #6)
- Url to missing plot file
- Fixed some incorrect int declarations using `1e3` notation
### Removed
- Removed Pipfile
## [1.1.1] - 2020-09-28
### Added
- Added `CHANGELOG.md`
### Changed
- Change CI from Azure Devops to Github Actions
## [1.1.0] - 2019-06-19
### Added
- First PyPI-released version
## [1.0.0] - 2016-08-22
### Added
- Regarded as a feature-complete, stable library.
[Unreleased]: https://github.com/hbldh/lspopt/compare/v1.3.0...HEAD
[1.3.0]: https://github.com/hbldh/lspopt/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/hbldh/lspopt/compare/v1.1.1...v1.2.0
[1.1.1]: https://github.com/hbldh/lspopt/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/hbldh/lspopt/compare/v1.0.0...v1.1.0
Raw data
{
"_id": null,
"home_page": "https://github.com/hbldh/lspopt",
"name": "lspopt",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "Mathematical Statistics, Multitaper, Spectrogram",
"author": "Henrik Blidh",
"author_email": "henrik.blidh@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/87/0a/3de9f71251d6d62ab29265fb68b270bfdfe629584fbb8db7d025c429a532/lspopt-1.4.0.tar.gz",
"platform": null,
"description": "# LSPOpt\n\n![Build and Test](https://github.com/hbldh/lspopt/workflows/Build%20and%20Test/badge.svg)\n[![PyPI version](https://img.shields.io/pypi/v/lspopt.svg)](https://pypi.org/project/lspopt/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\nThis module is a Python implementation of the multitaper window method \ndescribed in [\\[1\\]](#references) for estimating Wigner spectra for certain locally\nstationary processes.\n\nAbstract from [\\[1\\]](#references):\n\n> This paper investigates the time-discrete multitapers that give a mean square error optimal Wigner spectrum estimate for a class\n> of locally stationary processes (LSPs). The accuracy in the estimation of the time-variable Wigner spectrum of the LSP is evaluated\n> and compared with other frequently used methods. The optimal multitapers are also approximated by Hermite functions, which is\n> computationally more efficient, and the errors introduced by this approximation are studied. Additionally, the number of windows\n> included in a multitaper spectrum estimate is often crucial and an investigation of the error caused by limiting this number is made.\n> Finally, the same optimal set of weights can be stored and utilized for different window lengths. As a result, the optimal multitapers\n> are shown to be well approximated by Hermite functions, and a limited number of windows can be used for a mean square error\n> optimal spectrogram estimate.\n \n## Installation\n\nInstall via pip:\n\n pip install lspopt\n\nIf you prefer to use `conda`, see [instructions in this repo](https://github.com/conda-forge/lspopt-feedstock).\n\n## Testing\n\nTest with `pytest`:\n\n pytest tests/\n\nSee test badge at the top of this README for link to test coverage and reports.\n\n## Usage\n\nTo generate the taper windows only, use the `lspopt` method:\n\n```python\nfrom lspopt import lspopt\nH, w = lspopt(n=256, c_parameter=20.0)\n```\n \nThere is also a convenience method for using the [SciPy spectrogram method](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html#scipy.signal.spectrogram)\nwith the `lspopt` multitaper windows:\n\n```python\nfrom lspopt import spectrogram_lspopt\nf, t, Sxx = spectrogram_lspopt(x, fs, c_parameter=20.0)\n```\n \nThis can then be plotted with e.g. [matplotlib](http://matplotlib.org/).\n\n### Example\n\nOne can generate a [chirp](https://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.signal.chirp.html)\nprocess realisation and run spectrogram methods on this. \n\n```python\nimport numpy as np\nfrom scipy.signal import chirp, spectrogram\nimport matplotlib.pyplot as plt\n\nfrom lspopt.lsp import spectrogram_lspopt\n\nfs = 10000\nN = 100000\namp = 2 * np.sqrt(2)\nnoise_power = 0.001 * fs / 2\ntime = np.arange(N) / fs\nfreq = np.linspace(1000, 2000, N)\nx = amp * chirp(time, 1000, 2.0, 6000, method='quadratic') + \\\n np.random.normal(scale=np.sqrt(noise_power), size=time.shape)\n\nf, t, Sxx = spectrogram(x, fs)\n\nax = plt.subplot(211)\nax.pcolormesh(t, f, Sxx)\nax.set_ylabel('Frequency [Hz]')\nax.set_xlabel('Time [sec]')\n\nf, t, Sxx = spectrogram_lspopt(x, fs, c_parameter=20.0)\n\nax = plt.subplot(212)\nax.pcolormesh(t, f, Sxx)\nax.set_ylabel('Frequency [Hz]')\nax.set_xlabel('Time [sec]')\n\nplt.tight_layout()\nplt.show()\n```\n\n![Spectrogram plot](https://github.com/hbldh/lspopt/blob/master/plot.png \"Top: Using SciPy's spectrogram method. Bottom: Using LSPOpt's spectrogram solution.\")\n\n*Top: Using SciPy's spectrogram method. Bottom: Using LSPOpt's spectrogram solution.*\n\n## References\n\n\\[1\\] [Hansson-Sandsten, M. (2011). Optimal multitaper Wigner spectrum \nestimation of a class of locally stationary processes using Hermite functions. \nEURASIP Journal on Advances in Signal Processing, 2011, 10.](https://dx.doi.org/10.1155/2011/980805)\n\n# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [1.4.0] - 2025-01-07\n\n### Added\n\n- Support for Python 3.12\n- Support for `pip>=25`\n- Support for `numpy>=2`\n- Support for Windows and macOS\n- Converted `setup.py` to `setup.cfg`\n\n### Removed\n\n- Support for Python 3.7 and 3.8\n- Unused imports\n\n\n## [1.3.0] - 2023-01-24\n\n### Changed\n\n- Modified test matrix in CI\n\n### Removed\n\n- Support for Python 2.7 and 3.6.\n- Dependency on `six`.\n\n\n## [1.2.0] - 2022-06-08\n\n### Added\n\n- New plot file\n\n### Fixed\n\n- Source distribution was broken on PyPI. Modified `MANIFEST.in` to correct that (#5 and #6)\n- Url to missing plot file\n- Fixed some incorrect int declarations using `1e3` notation\n\n### Removed\n\n- Removed Pipfile\n\n## [1.1.1] - 2020-09-28\n\n### Added\n\n- Added `CHANGELOG.md`\n\n### Changed\n\n- Change CI from Azure Devops to Github Actions\n\n\n## [1.1.0] - 2019-06-19\n\n### Added\n\n- First PyPI-released version\n\n\n## [1.0.0] - 2016-08-22\n\n### Added\n\n- Regarded as a feature-complete, stable library.\n\n\n[Unreleased]: https://github.com/hbldh/lspopt/compare/v1.3.0...HEAD\n[1.3.0]: https://github.com/hbldh/lspopt/compare/v1.2.0...v1.3.0\n[1.2.0]: https://github.com/hbldh/lspopt/compare/v1.1.1...v1.2.0\n[1.1.1]: https://github.com/hbldh/lspopt/compare/v1.1.0...v1.1.1\n[1.1.0]: https://github.com/hbldh/lspopt/compare/v1.0.0...v1.1.0\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Python implementation of a multitaper window method for estimating Wigner spectra for certain locally stationary processes",
"version": "1.4.0",
"project_urls": {
"Homepage": "https://github.com/hbldh/lspopt"
},
"split_keywords": [
"mathematical statistics",
" multitaper",
" spectrogram"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "39913a1959aa91eb7d50f2aaf4d8a1a49cd4a3db7315be7bdec742d16eba2810",
"md5": "95b2e36f37c6e7491dc16596a5bff329",
"sha256": "2c1bc134126a5168248e444760468fa75df70e59d8de98184571ea150f4b494d"
},
"downloads": -1,
"filename": "lspopt-1.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "95b2e36f37c6e7491dc16596a5bff329",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 35235,
"upload_time": "2025-01-07T16:24:45",
"upload_time_iso_8601": "2025-01-07T16:24:45.408354Z",
"url": "https://files.pythonhosted.org/packages/39/91/3a1959aa91eb7d50f2aaf4d8a1a49cd4a3db7315be7bdec742d16eba2810/lspopt-1.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "870a3de9f71251d6d62ab29265fb68b270bfdfe629584fbb8db7d025c429a532",
"md5": "b6d1428aba7ca8ac5b58316321d76820",
"sha256": "6ea32d90cc2e6536e7c6ea559889e529bdae6d0d3795956432c9ad7d0844131e"
},
"downloads": -1,
"filename": "lspopt-1.4.0.tar.gz",
"has_sig": false,
"md5_digest": "b6d1428aba7ca8ac5b58316321d76820",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 39459,
"upload_time": "2025-01-07T16:24:46",
"upload_time_iso_8601": "2025-01-07T16:24:46.681861Z",
"url": "https://files.pythonhosted.org/packages/87/0a/3de9f71251d6d62ab29265fb68b270bfdfe629584fbb8db7d025c429a532/lspopt-1.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-07 16:24:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hbldh",
"github_project": "lspopt",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [
{
"name": "numpy",
"specs": [
[
">=",
"1.21.6"
]
]
},
{
"name": "scipy",
"specs": [
[
">=",
"1.7.3"
]
]
}
],
"lcname": "lspopt"
}