A pure-Python fast continuous wavelet transform (fCWT) implementation
Project description
pyFCWT
pyFCWT is a pure-Python port of fCWT that relies on pyFFTW, Numba and NumPy. It is faster than other Python CWT packages while remaining limited to Morlet wavelets. While performance is slower than the original C++ fCWT it has the added benefit of easy installation on any platform — no compiler required.
Features
- Fast — frequency-domain convolution via FFTW with Numba-parallelised daughter-wavelet multiplication.
- Pure Python — no C/C++ extensions to compile; installs with
pipon Linux, macOS and Windows. - FFTW wisdom — save and reload FFTW plans to skip the planning overhead on subsequent runs.
- Flexible frequency grids — linear or logarithmic spacing between any two frequencies.
- Spectral utilities — built-in methods for amplitude, power, PSD, and ASD directly from CWT coefficients.
- Single & double precision — choose
complex64orcomplex128to trade accuracy for speed/memory.
Installation
pip install pyfcwt
Or with uv:
uv add pyfcwt
conda-forge
conda install -c conda-forge pyfcwt
Quick Start
import numpy as np
from pyfcwt import PyFCWT, Wavelet, Frequencies
# Parameters
fs = 1000.0 # Sampling rate (Hz)
t = np.arange(0, 1.0, 1 / fs)
signal = np.sin(2 * np.pi * 20 * t) + np.sin(2 * np.pi * 80 * t)
# Configure the transform
wavelet = Wavelet(fs=fs, n_cycles=7.0)
freqs = Frequencies(wavelet, f0=1.0, f1=100.0, fn=200, fs=fs, scaling="log")
fcwt = PyFCWT(wavelet, freqs, threads=-1)
# Run the CWT
result = fcwt.cwt(signal) # shape: (200, 1000), complex128
# Derive spectral quantities
amplitude = fcwt.amplitude(result)
power = fcwt.power(result)
psd = fcwt.psd(result)
asd = fcwt.asd(result)
API Overview
Wavelet
Defines the Morlet wavelet. Key parameters:
| Parameter | Default | Description |
|---|---|---|
fs |
— | Sampling rate in Hz |
n_cycles |
7.0 |
Number of cycles (time–frequency trade-off) |
gauss_sd |
5.0 |
Gaussian envelope truncation (std devs each side) |
sigma |
-1 |
Fixed bandwidth (-1 = frequency-adaptive) |
zero_mean |
True |
Enforce zero-mean admissibility condition |
imaginary |
True |
Complex (analytic) wavelet |
Frequencies
Generates the analysis frequency/scale grid.
| Parameter | Default | Description |
|---|---|---|
wavelet |
— | Wavelet instance |
f0 |
— | Lowest frequency (Hz) |
f1 |
— | Highest frequency (Hz) |
fn |
— | Number of frequency bins |
fs |
— | Sampling rate (Hz) |
scaling |
"log" |
"log" or "linear" spacing |
PyFCWT
The CWT engine.
| Parameter | Default | Description |
|---|---|---|
wavelet |
— | Wavelet instance |
frequencies |
— | Frequencies instance |
threads |
-1 |
FFTW threads (-1 = half of CPU cores) |
norm |
True |
Normalise output by FFT length |
dtype |
"complex128" |
"complex128" or "complex64" |
Methods:
| Method | Returns |
|---|---|
cwt(signal) |
Complex CWT coefficients (n_freqs, n_samples) |
amplitude(cwt) |
|W(f,t)| |
power(cwt) |
|W(f,t)|² |
psd(cwt) |
Power spectral density (signal_units² / Hz) |
asd(cwt) |
Amplitude spectral density (signal_units / √Hz) |
enbw() |
Equivalent noise bandwidth at each frequency |
FFTW Wisdom Utilities
FFTW plans can be expensive to create. Save and reload them to avoid repeated planning:
from pyfcwt import save_wisdom, load_wisdom
# After running a transform, persist the plans:
save_wisdom() # writes to ~/.pyfcwt/
# On the next run, restore them before creating PyFCWT:
load_wisdom()
Speed Comparison with fCWT
Benchmarks comparing pyFCWT against the original C++ fCWT on the same hardware. Columns are formatted as signal_length-num_frequencies.
Setup: Morlet wavelet, log-spaced frequencies 1–100 Hz. PyWavelets is single thread while fCWT and pyFCWT use all physical cores (os.cpu_count()//2). Results are the median of 10 iterations. fCWT and pyFCWT were run with float32 input and complex64 output.
| Implementation | 10k-100 | 10k-200 | 50k-100 | 50k-200 |
|---|---|---|---|---|
| fCWT | 0.002s | 0.004s | 0.008s | 0.013s |
| pyFCWT | 0.022s | 0.044s | 0.049s | 0.100s |
| PyWavelets | 0.969s | 1.978s | DNR | DNR |
Note: Fill in the values above with your own measurements. Run
python benchmarks/bench_pyfcwt_vs_fcwt.pyto generate the table. Times will vary with CPU, thread count, and whether FFTW wisdom is pre-loaded. The first pyFCWT call includes Numba JIT compilation overhead; subsequent calls are significantly faster.
Wavelet Utility Functions
The pyfcwt.wavelet_utils module provides standalone helpers:
| Function | Description |
|---|---|
f_to_s(fc, fs, n_cycles) |
Centre frequency → wavelet scale |
s_to_f(s, fs, n_cycles) |
Wavelet scale → centre frequency |
fwhm_freq(freq, n_cycles) |
FWHM of the Gaussian envelope (seconds) |
fwhm_to_cycles(fwhm, freqs) |
FWHM → equivalent number of cycles |
get_wavelet_length(fc, fs, ...) |
Sample length of a Morlet wavelet |
gen_freqs(f0, f1, n, scaling) |
Generate a frequency vector |
Requirements
- Python ≥ 3.10
- NumPy ≥ 2.2.6
- Numba ≥ 0.65.1
- pyFFTW ≥ 0.15.0
Development
git clone https://github.com/larshnelson/pyfcwt.git
cd pyfcwt
uv sync --group dev
uv run pytest
License
MIT — Lars Henrik Nelson
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyfcwt-0.1.0.tar.gz.
File metadata
- Download URL: pyfcwt-0.1.0.tar.gz
- Upload date:
- Size: 105.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d469b7a9311bb2663e4be99b389f410b127f8adae95cbd1c93cd73735e09ac18
|
|
| MD5 |
0da194a9488a4671e7ca46378a63b320
|
|
| BLAKE2b-256 |
433d2008095bd1bbe017ca61cd53dbb73d2716908e8239d0a0f712447f3da90a
|
File details
Details for the file pyfcwt-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyfcwt-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
318d3bad37e7d9376d4c2231d7886b5c9f976f0c3d60d2f68478d9500c4229cf
|
|
| MD5 |
620939483208bba03926b33fcc9f3c6d
|
|
| BLAKE2b-256 |
858a2f025be1411293fe2b4393b1fb5a0331d1c89b0b50371c25b3a047b636c5
|