Wavelets and Time-Frequency Analysis
Beyond Fourier: Adaptive Time-Frequency Analysis
The STFT uses a fixed window, giving the same time-frequency resolution everywhere. Wavelets overcome this limitation by using short windows at high frequencies and long windows at low frequencies, naturally matching the behavior of many real-world signals (transients are brief and wideband, while tonal components are long and narrowband). The wavelet transform is the foundation of JPEG 2000 compression, denoising algorithms, and multi-resolution signal analysis.
Definition: Continuous Wavelet Transform (CWT)
Continuous Wavelet Transform (CWT)
The CWT of a signal with respect to a mother wavelet is:
where is the scale (inversely related to frequency) and is the translation (time shift). The factor ensures energy normalization across scales.
import pywt
scales = np.arange(1, 128)
coeffs, freqs = pywt.cwt(x, scales, 'morl', sampling_period=1/fs)
Definition: Discrete Wavelet Transform (DWT)
Discrete Wavelet Transform (DWT)
The DWT decomposes a signal into approximation coefficients (low frequency) and detail coefficients (high frequency) at each level using a pair of complementary filters:
followed by downsampling by 2.
import pywt
cA, cD = pywt.dwt(x, 'db4') # single-level DWT
coeffs = pywt.wavedec(x, 'db4', level=5) # multi-level DWT
x_rec = pywt.waverec(coeffs, 'db4') # reconstruction
The DWT is critically sampled (no redundancy) and perfectly invertible. Each level halves the time resolution and doubles the frequency resolution.
Definition: Common Wavelet Families
Common Wavelet Families
Different wavelet families have different properties:
| Family | PyWavelets Name | Vanishing Moments | Properties |
|---|---|---|---|
| Haar | 'haar' |
1 | Simplest, discontinuous |
| Daubechies | 'db1'-'db20' |
1-20 | Compact support, smooth for high order |
| Symlets | 'sym2'-'sym20' |
2-20 | Near-symmetric Daubechies |
| Coiflets | 'coif1'-'coif17' |
2-34 | Symmetric, vanishing moments for scaling fn |
| Morlet | 'morl' |
CWT only, Gaussian-modulated sinusoid | |
| Mexican Hat | 'mexh' |
2 | CWT only, second derivative of Gaussian |
wavelet = pywt.Wavelet('db4')
print(f"Filter length: {wavelet.dec_len}")
print(f"Vanishing moments: {wavelet.dec_len // 2}")
Definition: Multi-Resolution Analysis (MRA)
Multi-Resolution Analysis (MRA)
Multi-resolution analysis decomposes a signal into components at different resolution levels. At level , the signal is represented as:
where and are scaled and translated versions of the scaling and wavelet functions. Each level captures a specific frequency band:
- Level 1 details:
- Level 2 details:
- Level details:
Definition: Wavelet Denoising (Thresholding)
Wavelet Denoising (Thresholding)
Wavelet denoising exploits the fact that signal energy concentrates in a few large wavelet coefficients, while noise spreads across all coefficients. The procedure is:
- Compute the DWT:
- Threshold the detail coefficients
- Reconstruct:
Common thresholding rules:
- Hard:
- Soft:
Universal threshold: where (median absolute deviation of level-1 detail coefficients).
Theorem: Perfect Reconstruction in the DWT
If the analysis filters and synthesis filters satisfy the perfect reconstruction conditions:
then the DWT followed by the inverse DWT recovers the original signal exactly (up to floating-point precision).
The first condition ensures no gain distortion (the signal energy is preserved). The second condition ensures no aliasing (the downsampling artifacts from the analysis stage are exactly cancelled during synthesis).
Example: Multi-Level DWT Decomposition
Decompose a noisy ECG-like signal into 5 levels using the Daubechies-4 wavelet. Examine the detail coefficients at each level.
Decompose and visualize
import pywt
import numpy as np
fs = 500
t = np.arange(0, 2, 1/fs)
# Simulate ECG-like signal: sharp QRS + slow P/T waves + noise
x = (np.exp(-((t % 0.8 - 0.4) * 50)**2) * 2
+ 0.3 * np.sin(2*np.pi*1.25*t)
+ 0.2 * np.random.randn(len(t)))
coeffs = pywt.wavedec(x, 'db4', level=5)
# coeffs[0] = approximation, coeffs[1..5] = details (coarse to fine)
for i, c in enumerate(coeffs):
label = "Approx" if i == 0 else f"Detail {len(coeffs)-i}"
print(f"{label}: {len(c)} coefficients")
Example: Wavelet Denoising with Soft Thresholding
Add Gaussian noise to a piecewise-smooth signal and denoise it using soft thresholding with the universal threshold.
Denoise using PyWavelets
import pywt
import numpy as np
# Noisy signal
np.random.seed(42)
t = np.linspace(0, 1, 1024)
x_clean = np.piecewise(t, [t < 0.3, (t >= 0.3) & (t < 0.7), t >= 0.7],
[lambda t: np.sin(4*np.pi*t),
lambda t: 0.5,
lambda t: -np.cos(6*np.pi*t)])
sigma = 0.3
x_noisy = x_clean + sigma * np.random.randn(len(t))
# Wavelet denoising
wavelet = 'sym8'
coeffs = pywt.wavedec(x_noisy, wavelet, level=5)
# Universal threshold
sigma_est = np.median(np.abs(coeffs[-1])) / 0.6745
threshold = sigma_est * np.sqrt(2 * np.log(len(x_noisy)))
# Soft threshold detail coefficients
coeffs_thresh = [coeffs[0]] # keep approximation
for c in coeffs[1:]:
coeffs_thresh.append(pywt.threshold(c, threshold, mode='soft'))
x_denoised = pywt.waverec(coeffs_thresh, wavelet)
mse = np.mean((x_clean - x_denoised[:len(x_clean)])**2)
print(f"Denoised MSE: {mse:.6f}")
Example: CWT Scalogram of a Non-Stationary Signal
Generate a signal with a chirp component and a transient burst. Compute the CWT using the Morlet wavelet and display the scalogram.
Compute CWT and visualize
import pywt
import numpy as np
fs = 1000
t = np.arange(0, 1, 1/fs)
# Chirp from 50 to 200 Hz + transient at t=0.5
from scipy.signal import chirp
x = chirp(t, 50, 1, 200) + 3*np.exp(-((t-0.5)*100)**2)
scales = np.arange(1, 128)
coeffs, freqs = pywt.cwt(x, scales, 'morl', sampling_period=1/fs)
scalogram = np.abs(coeffs)**2
The scalogram shows the chirp as a curve from low to high frequency and the transient as a vertical stripe at spanning all frequencies.
Wavelet Denoising Explorer
Adjust the wavelet family, decomposition level, and threshold to observe the effect on denoising quality.
Parameters
Wavelet Transform Recipes
# Code from: ch07/python/wavelets.py
# Load from backend supplements endpointQuick Check
What is the key advantage of the wavelet transform over the STFT?
Wavelets are always faster to compute
Wavelets provide adaptive time-frequency resolution
Wavelets can analyze non-stationary signals while STFT cannot
Wavelets require fewer parameters to configure
Wavelets use short windows at high frequencies (good time resolution) and long windows at low frequencies (good frequency resolution).
Quick Check
In wavelet denoising, the universal threshold is estimated using:
The standard deviation of the original signal
The median absolute deviation of the finest-scale detail coefficients
The mean of all wavelet coefficients
The peak value of the approximation coefficients
The MAD of level-1 detail coefficients divided by 0.6745 gives a robust estimate of the noise standard deviation.
Common Mistake: Ignoring Boundary Effects in the DWT
Mistake:
Applying the DWT to a short signal without considering boundary
extension. The default mode in PyWavelets is 'symmetric',
which can introduce artifacts for signals that are not symmetric
at the boundaries.
Correction:
Choose the boundary mode appropriate for your signal:
coeffs = pywt.wavedec(x, 'db4', mode='periodization') # periodic signals
coeffs = pywt.wavedec(x, 'db4', mode='zero') # zero-padded
Key Takeaway
Wavelets provide adaptive time-frequency resolution: fine time resolution at high frequencies and fine frequency resolution at low frequencies. The DWT is fast (), critically sampled, and perfectly invertible. Wavelet denoising with soft thresholding is near-optimal for piecewise-smooth signals.
Why This Matters: Wavelets in Wireless Channel Estimation
Wireless channels often exhibit sparse multipath structure: a few strong reflections arriving at specific delays. Wavelet-based channel estimation exploits this sparsity by decomposing the channel impulse response with the DWT and thresholding small coefficients. This approach denoises the channel estimate without blurring the sharp multipath arrivals, outperforming linear smoothing filters that assume continuous channel variation.
See full treatment in Chapter 18
Historical Note: Wavelets: From Seismology to JPEG 2000
1980sJean Morlet, a French geophysicist, introduced wavelets in the early 1980s for analyzing seismic data. Ingrid Daubechies constructed the first families of compactly supported orthogonal wavelets in 1988, making the DWT practical. Stephane Mallat connected wavelets to multi-resolution analysis in 1989. Today wavelets are used in JPEG 2000 image compression, FBI fingerprint compression, and numerous scientific applications.
CWT (Continuous Wavelet Transform)
A time-frequency representation that correlates a signal with scaled and translated versions of a mother wavelet, providing adaptive resolution across frequencies.
Related: Discrete Wavelet Transform (DWT), Scalogram
DWT (Discrete Wavelet Transform)
A critically-sampled wavelet transform that decomposes a signal into approximation and detail coefficients at dyadic scales using complementary lowpass and highpass filters.
Related: Continuous Wavelet Transform (CWT), multi-resolution analysis
Scalogram
The squared magnitude of the CWT coefficients, , displayed as a 2D image with time on the horizontal axis and scale (or frequency) on the vertical axis.
STFT vs Wavelet Transform
| Property | STFT | Wavelet Transform |
|---|---|---|
| Time-Frequency Resolution | Fixed (set by window length) | Adaptive (varies with frequency) |
| Basis Functions | Complex exponentials window | Scaled/translated wavelets |
| Redundancy | Adjustable (overlap) | CWT: highly redundant; DWT: critically sampled |
| Computational Cost | per frame | DWT: ; CWT: |
| Best For | Stationary or slowly varying signals | Transients, multi-scale analysis, denoising |
| Invertibility | Always (with overlap-add) | DWT: perfect reconstruction; CWT: depends on wavelet |