Skip to main content

A pure-Python fast continuous wavelet transform (fCWT) implementation

Project description

pyFCWT

Test Python 3.10+ License: MIT

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 pip on 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 complex64 or complex128 to 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.py to 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyfcwt-0.1.0.tar.gz (105.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyfcwt-0.1.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

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

Hashes for pyfcwt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d469b7a9311bb2663e4be99b389f410b127f8adae95cbd1c93cd73735e09ac18
MD5 0da194a9488a4671e7ca46378a63b320
BLAKE2b-256 433d2008095bd1bbe017ca61cd53dbb73d2716908e8239d0a0f712447f3da90a

See more details on using hashes here.

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

Hashes for pyfcwt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 318d3bad37e7d9376d4c2231d7886b5c9f976f0c3d60d2f68478d9500c4229cf
MD5 620939483208bba03926b33fcc9f3c6d
BLAKE2b-256 858a2f025be1411293fe2b4393b1fb5a0331d1c89b0b50371c25b3a047b636c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page