{"id":16739755,"url":"https://github.com/overlordgolddragon/ssqueezepy","last_synced_at":"2025-05-14T13:06:12.828Z","repository":{"id":37707355,"uuid":"236909723","full_name":"OverLordGoldDragon/ssqueezepy","owner":"OverLordGoldDragon","description":"Synchrosqueezing, wavelet transforms, and time-frequency analysis in Python","archived":false,"fork":false,"pushed_at":"2025-02-02T01:03:43.000Z","size":44580,"stargazers_count":703,"open_issues_count":18,"forks_count":99,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-13T11:22:43.058Z","etag":null,"topics":["cwt","morse-wavelet","python","ridge-extraction","signal-processing","stft","synchrosqueezing","time-frequency","time-frequency-analysis","visualization","wavelet-transform"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OverLordGoldDragon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-29T05:25:10.000Z","updated_at":"2025-05-13T02:09:19.000Z","dependencies_parsed_at":"2023-02-08T19:15:44.834Z","dependency_job_id":"c72e19f2-45b6-4390-88f4-f7a230a1588e","html_url":"https://github.com/OverLordGoldDragon/ssqueezepy","commit_stats":{"total_commits":80,"total_committers":3,"mean_commits":"26.666666666666668","dds":"0.025000000000000022","last_synced_commit":"1e6132ad5dc02c7ef81df0e1dad6180104d9dec3"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OverLordGoldDragon%2Fssqueezepy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OverLordGoldDragon%2Fssqueezepy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OverLordGoldDragon%2Fssqueezepy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OverLordGoldDragon%2Fssqueezepy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OverLordGoldDragon","download_url":"https://codeload.github.com/OverLordGoldDragon/ssqueezepy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254149953,"owners_count":22022851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cwt","morse-wavelet","python","ridge-extraction","signal-processing","stft","synchrosqueezing","time-frequency","time-frequency-analysis","visualization","wavelet-transform"],"created_at":"2024-10-13T00:53:35.480Z","updated_at":"2025-05-14T13:06:12.799Z","avatar_url":"https://github.com/OverLordGoldDragon.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/16495490/99882586-faa86f80-2c3a-11eb-899c-b3984e98b1c7.png\" width=\"300\"\u003e\u003c/p\u003e\n\n\n# Synchrosqueezing in Python\n\n[![ssqueezepy CI](https://github.com/OverLordGoldDragon/ssqueezepy/actions/workflows/conda.yml/badge.svg)](https://github.com/OverLordGoldDragon/ssqueezepy/actions/workflows/conda.yml)\n[![codecov](https://codecov.io/gh/OverLordGoldDragon/ssqueezepy/branch/master/graph/badge.svg?token=8L7YPN5N19)](https://codecov.io/gh/OverLordGoldDragon/ssqueezepy)\n[![PyPI version](https://badge.fury.io/py/ssqueezepy.svg)](https://badge.fury.io/py/ssqueezepy)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/7cee422639034bcebe0f10ca4b95a506)](https://www.codacy.com/gh/OverLordGoldDragon/ssqueezepy/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=OverLordGoldDragon/ssqueezepy\u0026amp;utm_campaign=Badge_Grade)\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5080508.svg)](https://doi.org/10.5281/zenodo.5080508)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n\u003c!-- [![Build Status](https://travis-ci.com/OverLordGoldDragon/ssqueezepy.svg?branch=master)](https://travis-ci.com/OverLordGoldDragon/ssqueezepy)\n[![Coverage Status](https://coveralls.io/repos/github/OverLordGoldDragon/ssqueezepy/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/OverLordGoldDragon/ssqueezepy) --\u003e\n\nSynchrosqueezing is a powerful _reassignment method_ that focuses time-frequency representations, and allows extraction of instantaneous amplitudes and frequencies. [Friendly overview.](https://dsp.stackexchange.com/a/71399/50076)\n\n\n## Features\n  - Continuous Wavelet Transform (CWT), forward \u0026 inverse, and its Synchrosqueezing\n  - Short-Time Fourier Transform (STFT), forward \u0026 inverse, and its Synchrosqueezing\n  - Wavelet visualizations and testing suite\n  - Generalized Morse Wavelets\n  - Ridge extraction\n  - Fastest wavelet transforms in Python\u003csup\u003e1\u003c/sup\u003e, beating MATLAB\n\n\u003csub\u003e1: feel free to open Issue showing otherwise\u003c/sub\u003e\n\n\n## Installation\n`pip install ssqueezepy`. Or, for latest version (most likely stable):\n\n`pip install git+https://github.com/OverLordGoldDragon/ssqueezepy`\n\n## GPU \u0026 CPU acceleration\n\nMulti-threaded execution is enabled by default (disable via `os.environ['SSQ_PARALLEL'] = '0'`). GPU requires [CuPy \u003e= 8.0.0](https://docs.cupy.dev/en/stable/install.html)\nand [PyTorch \u003e= 1.8.0](https://pytorch.org/get-started/locally/) installed (enable via `os.environ['SSQ_GPU'] = '1'`). `pyfftw` optionally supported for maximum CPU FFT speed.\nSee [Performance guide](https://github.com/OverLordGoldDragon/ssqueezepy/blob/master/ssqueezepy/README.md#performance-guide).\n\n## Benchmarks\n\n[Code](https://github.com/OverLordGoldDragon/ssqueezepy/blob/master/examples/benchmarks.py). Transforms use padding, `float32` precision (`float64` supported), and output shape\n`(300, len(x))`, averaged over 10 runs. `pyfftw` not used, which'd speed 1-thread \u0026 parallel further. Benched on author's i7-7700HQ, GTX 1070.\n\n`len(x)`-transform | 1-thread CPU | parallel | gpu | pywavelets | scipy | librosa\n:----------------:|:----------------:|:-----------------:|:-----------------:|:-----------------:|:-----------------:|:-----------------:\n10k-cwt       | 0.126 | 0.0462 | 0.00393 | 3.58 | 0.523 | -\n10k-stft      | 0.108 | 0.0385 | 0.00534 | -    | 0.118 | 0.0909\n10k-ssq_cwt   | 0.372 | 0.148  | 0.00941 | -    | -     | -\n10k-ssq_stft  | 0.282 | 0.147  | 0.0278  | -    | -     | -\n160k-cwt      | 2.99  | 1.25   | 0.0367  | 12.7 | 10.7  | -\n160k-stft     | 1.66  | 0.418  | 0.0643  | -    | 1.93  | 1.38\n160k-ssq_cwt  | 8.38  | 3.16   | 0.0856  | -    | -     | -\n160k-ssq_stft | 4.65  | 2.48   | 0.159   | -    | -     | -\n\n\n## Questions?\n\nSee [here](#asking-questions).\n\n## Examples\n\n### 1. Signal recovery under severe noise\n\n![image](https://user-images.githubusercontent.com/16495490/99879090-b9f12c00-2c23-11eb-8a40-2011ce84df61.png)\n\n### 2. Medical: EEG\n\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/99880110-c88f1180-2c2a-11eb-8932-90bf3406a20d.png\"\u003e\n\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/150314341-df5c3092-4bef-4895-99ed-2765504329fd.png\"\u003e\n\n### 3. Testing suite: CWT vs STFT, reflect-added parallel A.M. linear chirp\n\n\u003cimg src=\"https://github.com/OverLordGoldDragon/ssqueezepy/assets/16495490/c89727db-1bb3-4cf0-ac8c-c524cba75b2d\"\u003e\n\n### 4. Ridge extraction: cubic polynom. F.M. + pure tone; noiseless \u0026 1.69dB SNR\n\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/107919540-f4e5d000-6f84-11eb-9f86-dbfd34733084.png\"\u003e\n\n[More](https://github.com/OverLordGoldDragon/ssqueezepy/tree/master/examples/ridge_extraction)\n\n### 5. Testing suite: GMW vs Morlet, reflect-added hyperbolic chirp (extreme time-loc.)\n\n\u003cimg src=\"https://github.com/OverLordGoldDragon/ssqueezepy/assets/16495490/8c41d5f2-4bdd-4537-8d82-6d5a5c0315d3\"\u003e\n\n### 6. Higher-order GMW CWT, reflect-added parallel linear chirp, 3.06dB SNR\n\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/107921072-66bf1900-6f87-11eb-9bf5-afd0a6bbbc4d.png\"\u003e\n\n[More examples](https://overlordgolddragon.github.io/test-signals/)\n\n\n## Introspection\n\n`ssqueezepy` is equipped with a visualization toolkit, useful for exploring wavelet behavior across scales and configurations. (Also see [explanations and code](https://dsp.stackexchange.com/a/72044/50076))\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/OverLordGoldDragon/ssqueezepy/master/examples/imgs/anim_tf_morlet20.gif\" width=\"500\"\u003e\n\u003c/p\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/OverLordGoldDragon/ssqueezepy/master/examples/imgs/morlet_5vs20_tf.png\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/107297978-e6338080-6a8d-11eb-8a11-60bfd6e4137d.png\"\u003e\n\n## How's it work?\n\nIn a nutshell, synchrosqueezing exploits _redundancy_ of a time-frequency representation to sparsely localize oscillations, by imposing a _prior_. That is, we _assume_ `x` is well-captured by AM-FM components, e.g. based on our knowledge of the underlying process. We surpass Heisenberg's limitations, but only for a _subset_ of all possible signals. It's also akin to an _attention_ mechanism.\n\nConvolve with localized, analytic kernels\n\n\u003cimg src=\"https://raw.githubusercontent.com/OverLordGoldDragon/StackExchangeAnswers/main/SignalProcessing/Q78512%20-%20Wavelet%20Scattering%20explanation/cwt.gif\" width=\"650\"\u003e\n\ncompute phase transform, then combine oscillations with a shared rate\n\n\u003cimg src=\"https://user-images.githubusercontent.com/16495490/150680428-4a651934-85c6-45e8-8a19-c9b4165e5381.png\" width=\"700\"\u003e\n\n\u003chr\u003e\n\n## Minimal example\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom ssqueezepy import ssq_cwt, ssq_stft\nfrom ssqueezepy.experimental import scale_to_freq\n\ndef viz(x, Tx, Wx):\n    plt.imshow(np.abs(Wx), aspect='auto', cmap='turbo')\n    plt.show()\n    plt.imshow(np.abs(Tx), aspect='auto', vmin=0, vmax=.2, cmap='turbo')\n    plt.show()\n\n#%%# Define signal ####################################\nN = 2048\nt = np.linspace(0, 10, N, endpoint=False)\nxo = np.cos(2 * np.pi * 2 * (np.exp(t / 2.2) - 1))\nxo += xo[::-1]  # add self reflected\nx = xo + np.sqrt(2) * np.random.randn(N)  # add noise\n\nplt.plot(xo); plt.show()\nplt.plot(x);  plt.show()\n\n#%%# CWT + SSQ CWT ####################################\nTwxo, Wxo, *_ = ssq_cwt(xo)\nviz(xo, Twxo, Wxo)\n\nTwx, Wx, *_ = ssq_cwt(x)\nviz(x, Twx, Wx)\n\n#%%# STFT + SSQ STFT ##################################\nTsxo, Sxo, *_ = ssq_stft(xo)\nviz(xo, np.flipud(Tsxo), np.flipud(Sxo))\n\nTsx, Sx, *_ = ssq_stft(x)\nviz(x, np.flipud(Tsx), np.flipud(Sx))\n\n#%%# With units #######################################\nfrom ssqueezepy import Wavelet, cwt, stft, imshow\nfs = 400\nt = np.linspace(0, N/fs, N)\nwavelet = Wavelet()\nWx, scales = cwt(x, wavelet)\nSx = stft(x)[::-1]\n\nfreqs_cwt = scale_to_freq(scales, wavelet, len(x), fs=fs)\nfreqs_stft = np.linspace(1, 0, len(Sx)) * fs/2\n\nikw = dict(abs=1, xticks=t, xlabel=\"Time [sec]\", ylabel=\"Frequency [Hz]\")\nimshow(Wx, **ikw, yticks=freqs_cwt)\nimshow(Sx, **ikw, yticks=freqs_stft)\n```\n\nAlso see ridge extraction [README](https://github.com/OverLordGoldDragon/ssqueezepy/tree/master/examples/ridge_extraction).\n\n\n## Interesting use cases (with code)\n\n 1. [Identify abrupt changes in audio](https://dsp.stackexchange.com/a/87512/50076) - `ssq_cwt` and `ssq_stft` used together to solve an ML problem without ML\n \nFeel free to share yours [here](https://github.com/OverLordGoldDragon/ssqueezepy/issues/9).\n\n\n## Learning resources\n\n 1. [Continuous Wavelet Transform, \u0026 vs STFT](https://ccrma.stanford.edu/~unjung/mylec/WTpart1.html)\n 2. [Synchrosqueezing's phase transform, intuitively](https://dsp.stackexchange.com/a/72238/50076)\n 3. [Wavelet time \u0026 frequency resolution visuals](https://dsp.stackexchange.com/a/72044/50076)\n 4. [Why oscillations in SSQ of mixed sines? Separability visuals](https://dsp.stackexchange.com/a/72239/50076)\n 5. [Zero-padding's effect on spectrum](https://dsp.stackexchange.com/a/70498/50076)\n\n**DSP fundamentals**: I recommend starting with 3b1b's [Fourier Transform](https://youtu.be/spUNpyF58BY), then proceeding with [DSP Guide](https://www.dspguide.com/CH7.PDF) chapters 7-11.\nThe Discrete Fourier Transform lays the foundation of signal processing with real data. Deeper on DFT coefficients [here](https://dsp.stackexchange.com/a/70395/50076), also [3b1b](https://youtu.be/g8RkArhtCc4).\n\n\n## Contributors (noteworthy)\n\n - [David Bondesson](https://github.com/DavidBondesson): ridge extraction (`ridge_extraction.py`; `examples/`: `extracting_ridges.py`, `ridge_extraction/README.md`)\n\n## Asking questions\n\nOpen an Issue, and follow the [Issues Template](https://github.com/OverLordGoldDragon/ssqueezepy/issues/new/choose). Mainly code-related questions go to [Stack Overflow](https://stackoverflow.com/) (SO). Applications, theory questions, etc go elsewhere, e.g. [DSP.SE](https://dsp.stackexchange.com/). I may or may not respond, but others may (or may not) help. I don't follow SO.\n\n**Do not** send e-mail, LinkedIn messages, etc - they will be ignored.\n\n## How to cite\n\nShort form:\n\n\u003e John Muradeli, ssqueezepy, 2020. GitHub repository, https://github.com/OverLordGoldDragon/ssqueezepy/. DOI: 10.5281/zenodo.5080508\n\nBibTeX:\n\n```bibtex\n@article{OverLordGoldDragon2020ssqueezepy,\n  title={ssqueezepy},\n  author={John Muradeli},\n  journal={GitHub. Note: https://github.com/OverLordGoldDragon/ssqueezepy/},\n  year={2020},\n  doi={10.5281/zenodo.5080508},\n}\n```\n\n## References\n\n`ssqueezepy` was originally ported from MATLAB's [Synchrosqueezing Toolbox](https://github.com/ebrevdo/synchrosqueezing), authored by E. Brevdo and G. Thakur [1]. Synchrosqueezed Wavelet Transform was introduced by I. Daubechies and S. Maes [2], which was followed-up in [3], and adapted to STFT in [4]. Many implementation details draw from [5]. Ridge extraction based on [6].\n\n  1. G. Thakur, E. Brevdo, N.-S. Fučkar, and H.-T. Wu. [\"The Synchrosqueezing algorithm for time-varying spectral analysis: robustness properties and new paleoclimate applications\"](https://arxiv.org/abs/1105.0010), Signal Processing 93:1079-1094, 2013.\n  2. I. Daubechies, S. Maes. [\"A Nonlinear squeezing of the Continuous Wavelet Transform Based on Auditory Nerve Models\"](https://services.math.duke.edu/%7Eingrid/publications/DM96.pdf).\n  3. I. Daubechies, J. Lu, H.T. Wu. [\"Synchrosqueezed Wavelet Transforms: a Tool for Empirical Mode Decomposition\"](https://arxiv.org/pdf/0912.2437.pdf), Applied and Computational Harmonic Analysis 30(2):243-261, 2011.\n  4. G. Thakur, H.T. Wu. [\"Synchrosqueezing-based Recovery of Instantaneous Frequency from Nonuniform Samples\"](https://arxiv.org/abs/1006.2533), SIAM Journal on Mathematical Analysis, 43(5):2078-2095, 2011.\n  5. Mallat, S. [\"Wavelet Tour of Signal Processing 3rd ed\"](https://www.di.ens.fr/~mallat/papiers/WaveletTourChap1-2-3.pdf).\n  6. D. Iatsenko, P. V. E. McClintock, A. Stefanovska. [\"On the extraction of instantaneous frequencies from ridges in time-frequency representations of signals\"](https://arxiv.org/pdf/1310.7276.pdf).\n\n\n## License\n\nssqueezepy is MIT licensed, as found in the [LICENSE](https://github.com/OverLordGoldDragon/ssqueezepy/blob/master/LICENSE) file. Some source functions may be under other authorship/licenses; see [NOTICE.txt](https://github.com/OverLordGoldDragon/ssqueezepy/blob/master/NOTICE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foverlordgolddragon%2Fssqueezepy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foverlordgolddragon%2Fssqueezepy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foverlordgolddragon%2Fssqueezepy/lists"}