ChatPPG Editorial

Continuous Wavelet Transform for PPG: Scalograms, Ridge Tracking, and Use Cases

Practical CWT for PPG: scalograms, extract and score cardiac ridges, choose mother wavelets and scales, and evaluate heart-rate tracking across activities.

ChatPPG Research Team
5 min read
Continuous Wavelet Transform for PPG: Scalograms, Ridge Tracking, and Use Cases

The continuous wavelet transform (CWT) produces a scalogram that shows how energy distributes across time and frequency-like scales. For photoplethysmography (PPG), scalograms let you see the cardiac ridge, its harmonics, respiratory modulation, and transient motion artifacts simultaneously with adaptive resolution.

Quick answer

Pick a Morlet mother wavelet, map scales to frequencies covering roughly 0.5 to 5 Hz, compute the scalogram on overlapping windows, extract persistent ridges, and track the ridge with a continuity penalty. Use the resulting ridge for heart rate estimates and the scalogram texture as features for classification.

Why CWT is useful for PPG

PPG is non-stationary: heart rate, amplitude, and morphology change over seconds. STFT uses a fixed time-frequency tile while CWT changes resolution with scale. That gives CWT two principal advantages for PPG:

  • Better frequency resolution at low frequencies, useful for respiratory or slow modulation.
  • Better time resolution at high frequencies, useful for sudden waveform transients or harmonic structure.

These properties make CWT especially helpful when cardiac energy and motion energy overlap in time but differ in their time-scale signatures. For complementary techniques see wavelet denoising and STFT tracking.

Choosing the mother wavelet and scales

  • Morlet (complex) is the default for spectral tracking because it gives a cleaner quasi-frequency interpretation and provides phase for sub-scale refinement.
  • Real wavelets such as Mexican hat (Ricker) or second-derivative Gaussians are useful when matched filtering to detect pulse peaks or second-derivative features.

A practical rule for scale selection with Morlet is:

a = f_c / (f * dt)

where f is the target frequency in Hz, dt is the sampling period, and f_c is the wavelet center frequency for the chosen Morlet parameterization. For wearable PPG sampled at 50 to 200 Hz, use a pseudo-frequency range of 0.5 to 5 Hz for heart-rate and harmonic content, and grid it with 60 to 120 scales depending on compute budget.

Mapping scales to frequency and resolution tradeoffs

Scales are not linear frequency bins, so convert each scale to a pseudo-frequency for interpretation when plotting or scoring ridges. A denser scale grid improves interpolation and harmonic alignment but increases computation and numerical smoothing. Prefer logarithmic or mixed-linear grids that concentrate resolution in the cardiac band and spread coverage for slower respiratory or movement components.

Reading scalograms and identifying ridges

A scalogram is |W(a,t)| plotted versus time t and pseudo-frequency f(a). Heuristics for ridge extraction that work well in practice:

  1. Per frame, find local maxima across scales restricted to the cardiac band.
  2. Link maxima across frames with a continuity penalty that favors small jumps in scale and energy. A dynamic programming approach (Viterbi) yields globally optimal linking for a ridge under additive jump costs.
  3. Score candidate ridges by persistence, integrated energy, and harmonic support.

Phase information from a complex Morlet transform can refine the ridge location within a scale bin by applying a phase-based instantaneous frequency correction. When motion produces a strong, short-lived ridge across many scales, harmonic support and persistence separate cardiac ridges from motion.

Ridge scoring and confidence

Combine these metrics into a single confidence score:

  • Persistence: number of consecutive frames above an energy threshold.
  • Integrated energy: sum of scalogram magnitudes along the ridge.
  • Harmonic support: energy at integer multiples of the ridge frequency.
  • Local SNR: ridge energy relative to median background energy in nearby scales.

Use three operational bands: accept, suspect, reject. Accept when persistence and harmonic support pass thresholds. Use suspect to flag segments for fallback methods such as ensemble STFT trackers or accelerometer-informed masking.

Implementation recipe (Python sketch)

Use pywt or FFT-based convolution for speed. Minimal pipeline:

  1. Preprocess: remove DC and large baseline wander with a high-pass filter or local median subtraction. See our preprocessing pipeline.
  2. Optional denoise with stationary wavelet transform or a short median filter to suppress spikes.
  3. Compute CWT with Morlet across the target scales.
  4. Compute magnitude scalogram and normalize per frame by median energy.
  5. Detect local maxima per frame and link them into ridges using dynamic programming.
  6. Score ridges and select the best candidate, convert scale to frequency, and to BPM.

Small code fragment (conceptual):

import numpy as np
from scipy.signal import morlet2, fftconvolve

# x: PPG samples, fs: sampling rate
# scales: array of scales
# morlet2 from scipy provides complex Morlet
wavelets = [morlet2(M=round(10*scale), w=5.0) for scale in scales]
# FFT convolution per scale improves speed for many scales
# compute magnitudes, then proceed with local maxima detection and DP linking

Keep implementation modular so you can swap wavelets, change scoring, or add accelerometer-informed masks.

Scalogram features for downstream models

Scalograms are strong inputs for CNNs and hybrid models. Useful features:

  • Time-frequency patches (image inputs)
  • Ridge-derived sequences: instantaneous HR, slope, harmonic ratios
  • Local entropy or spectral flatness per frame
  • Tile-level energy centroids and bandwidth

When ground-truth ECG is available, train models to map scalogram patches to HR or rhythm labels. For noisy labels, combine ridge confidence as a sample weight.

Computational considerations

CWT computes many convolutions. Practical optimizations:

  • Restrict scales to the cardiac band instead of a full broadband grid.
  • Use FFT convolution and batch transforms when possible.
  • Cache wavelet FFTs and reuse for overlapping windows.
  • Downsample when only low-frequency content is required, but avoid aliasing.

On modern mobile CPUs a focused CWT for heart-rate tracking can run near real time for 4 to 10 second windows with FFT optimizations.

Where CWT outperforms STFT

  • Nonstationary events such as rapid HR changes or ectopic beats where harmonic energy shifts abruptly.
  • Multi-source periodic signals, for example fetal versus maternal heart rates in abdominal recordings where separate ridges appear.
  • When scalogram texture itself is a model input for arrhythmia or blood-pressure regression tasks.

For hybrid approaches, use STFT for fast gross tracking and CWT for local refinement and morphology-sensitive tasks. See our note on STFT tracking.

Failure modes and mitigation

  • Low perfusion: ridge SNR drops. Mitigate with longer windows, SWT denoising, and adaptive thresholds.
  • Motion at cardiac frequency: accelerometer-informed masks or sensor fusion reduce ambiguity. See motion artifact removal for filtering strategies.
  • Overly dense scale grids: increases compute and smooths features. Choose density based on fs and target frequency resolution.

Suggested experiments and evaluation

  • Benchmark mean absolute error (MAE) against ECG across activities: rest, walking, running, and common daily tasks.
  • Measure ridge detection sensitivity and false discovery rate in annotated datasets such as MIMIC or wearable validation cohorts.
  • Perform ablation: CWT only, STFT only, and fusion to quantify tradeoffs.

Report per-activity MAE, coverage (percent time with accepted ridge), and a confusion matrix for rhythm classes when applicable.

References

Final recommendations

If you need adaptive time-frequency resolution, implement a Morlet CWT scalogram focused on cardiac scales and add ridge scoring with harmonic checks. Use CWT to complement fast STFT-based trackers and always validate against ECG in the target collection protocol.

Run a small pilot on representative devices, report per-device MAE and coverage, and log failure cases. Tune ridge and confidence thresholds by cohort. Sharing scalogram examples and typical failure modes in the repo speeds validation and cross-team review.

Frequently Asked Questions

Which wavelet should I use for scalograms?
For heart-rate tracking use complex Morlet. For beat detection use Mexican hat or db4 variants depending on morphology needs.
How do I map scales to frequencies?
Convert scale a to pseudo-frequency f using a = f_c / (f * dt) for Morlet, where f_c depends on the Morlet parameterization and dt is sampling period.
Can CWT run in real time on wearables?
Yes for focused cardiac bands and optimized FFT convolution. Use cached wavelet FFTs, restrict scales, and process sliding windows to meet real-time constraints.
How do I handle motion that overlaps the cardiac band?
Use accelerometer-informed masks, prefer ridges with harmonic support, and fall back to ensemble STFT trackers when ridge confidence is low.
How dense should my scale grid be?
Start with 60 to 120 scales across 0.5 to 5 Hz for 100 Hz sampling. Increase density only if interpolation error harms ridge alignment.
What metrics should I report?
Report MAE against ECG, coverage (percent time with accepted ridge), sensitivity and false discovery rate for ridge detection, and per-activity breakdowns.