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.1.tar.gz (106.0 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.1-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file pyfcwt-0.1.1.tar.gz.

File metadata

  • Download URL: pyfcwt-0.1.1.tar.gz
  • Upload date:
  • Size: 106.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","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.1.tar.gz
Algorithm Hash digest
SHA256 0d9dfef372b4e8fe57554660bfdab16572ac10e257be64a5438a4b9fa5c223cb
MD5 18dfd8e1229d69708216e32fcefdde66
BLAKE2b-256 f90a61bd5055b77751340031928529acbd1a8661c63ca1f4e4e249cae435c1a9

See more details on using hashes here.

File details

Details for the file pyfcwt-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pyfcwt-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9283147a4338f8fd7af7a65b1f76b82f8ba0b6279d8727a1836f1e84d33ec65e
MD5 5c1eb8d57ddbca5ae0f38deda8d8d437
BLAKE2b-256 96cd6878e426f07ec3367a9149f8ba221d0f0d98916d7b718ab29e9a25724703

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