Synchrosqueezing in Python

Synchrosqueezing is a powerful reassignment method that focuses time-frequency representations, and allows extraction of instantaneous amplitudes and frequencies.

Features

  • Continuous Wavelet Transform (CWT), forward & inverse, and its Synchrosqueezing
  • Short-Time Fourier Transform (STFT), forward & inverse, and its Synchrosqueezing
  • Wavelet visualizations and testing suite
  • Generalized Morse Wavelets
  • Ridge extraction
  • Fastest wavelet transforms in Python1, beating MATLAB

1: feel free to open Issue showing otherwise

Installation

pip install ssqueezepy. Or, for latest version (most likely stable):

pip install git+https://github.com/OverLordGoldDragon/ssqueezepy

GPU & CPU acceleration

Multi-threaded execution is enabled by default (disable via os.environ['SSQ_PARALLEL'] = '0'). GPU requires CuPy >= 8.0.0
and PyTorch >= 1.8.0 installed (enable via os.environ['SSQ_GPU'] = '1'). pyfftw optionally supported for maximum CPU FFT speed.
See Performance guide.

Benchmarks

Code. Transforms use padding, float32 precision (float64 supported), and output shape
(300, len(x)), averaged over 10 runs. pyfftw not used, which'd speed 1-thread & parallel further. Benched on author's i7-7700HQ, GTX 1070.

len(x)-transform 1-thread CPU parallel gpu pywavelets scipy librosa
10k-cwt 0.126 0.0462 0.00393 3.58 0.523 -
10k-stft 0.108 0.0385 0.00534 - 0.118 0.0909
10k-ssq_cwt 0.372 0.148 0.00941 - - -
10k-ssq_stft 0.282 0.147 0.0278 - - -
160k-cwt 2.99 1.25 0.0367 12.7 10.7 -
160k-stft 1.66 0.418 0.0643 - 1.93 1.38
160k-ssq_cwt 8.38 3.16 0.0856 - - -
160k-ssq_stft 4.65 2.48 0.159 - - -

Examples

1. Signal recovery under severe noise

99879090-b9f12c00-2c23-11eb-8a40-2011ce84df61

2. Medical: EEG

99880110-c88f1180-2c2a-11eb-8932-90bf3406a20d

104537035-9f8b6b80-5632-11eb-9fa4-444efec6c9be

3. Testing suite: CWT vs STFT, reflect-added parallel linear chirp

107452011-e7ce7880-6b61-11eb-972f-8aa5ea093dc8

4. Ridge extraction: cubic polynom. F.M. + pure tone; noiseless & 1.69dB SNR

107919540-f4e5d000-6f84-11eb-9f86-dbfd34733084

More

5. Testing suite: GMW vs Morlet, reflect-added hyperbolic chirp (extreme time-loc.)

107903903-d9b69880-6f63-11eb-9478-8ead016cf6f8

6. Higher-order GMW CWT, reflect-added parallel linear chirp, 3.06dB SNR

107921072-66bf1900-6f87-11eb-9bf5-afd0a6bbbc4d

More examples

Introspection

ssqueezepy is equipped with a visualization toolkit, useful for exploring wavelet behavior across scales and configurations. (Also see explanations and code)

anim_tf_morlet20

morlet_5vs20_tf

107297978-e6338080-6a8d-11eb-8a11-60bfd6e4137d


Minimal example

import numpy as np
import matplotlib.pyplot as plt
from ssqueezepy import ssq_cwt, ssq_stft

def viz(x, Tx, Wx):
    plt.imshow(np.abs(Wx), aspect='auto', cmap='jet')
    plt.show()
    plt.imshow(np.abs(Tx), aspect='auto', vmin=0, vmax=.2, cmap='jet')
    plt.show()

#%%# Define signal ####################################
N = 2048
t = np.linspace(0, 10, N, endpoint=False)
xo = np.cos(2 * np.pi * 2 * (np.exp(t / 2.2) - 1))
xo += xo[::-1]  # add self reflected
x = xo + np.sqrt(2) * np.random.randn(N)  # add noise

plt.plot(xo); plt.show()
plt.plot(x);  plt.show()

#%%# CWT + SSQ CWT ####################################
Twxo, Wxo, *_ = ssq_cwt(xo)
viz(xo, Twxo, Wxo)

Twx, Wx, *_ = ssq_cwt(x)
viz(x, Twx, Wx)

#%%# STFT + SSQ STFT ##################################
Tsxo, Sxo, *_ = ssq_stft(xo)
viz(xo, np.flipud(Tsxo), np.flipud(Sxo))

Tsx, Sx, *_ = ssq_stft(x)
viz(x, np.flipud(Tsx), np.flipud(Sx))

Also see ridge extraction README.

GitHub

https://github.com/OverLordGoldDragon/ssqueezepy