# CWT Disapointing Frequency Separation

I'm attempting to perform multi-resolution analysis via Continuous-Wavelet Transform (CWT) using Pywavelets. I've heard that CWT is supposed to be superior to STFT due to varying frequency content as a function of the time-window.

My test signal is two sinusoids of 1Hz and 5Hz, each lasting 10 seconds (see picture): f=np.sin(2.*np.pi*t)*((t>=10)&(t<=20))+np.sin(2*np.pi*5*t)*((t>=30)&(t<=40)). The sampling period is 20Hz.

Using Pywavelets, I perform the CWT as follows with the resulting spectrogram:

scales = np.arange(0.6,65,step=0.2)
coef, freqs=pywt.cwt(f,scales,'cgau1', sampling_period=dT)


As you can see the frequency resolution is quite lousy, and the peak (complex magnitude) doesn't even seem to line up at 5Hz for the second segment.

In contrast, a STFT using the Gaussian window with a standard deviation of 5 results in much sharper frequency resolution (at the expense of time sharpness):

Am I doing something here? I'm willing to sacrifice time resolution but I do need to sharpen up the frequency.

The family of continuous wavelet transforms (CWT) is not, per se, superior to STFT. Due to its variations in scale, the CWT can be better, for instance, when:

• you address natural signals where transients are shorter than more stationary parts,
• you do not know the appropriate scale of observation,
• deterministic or random processes follow scaling laws (like the Brownian motions).

which is not the case from your signal: precise frequency on the same support.

On the one hand, you can work with a continuous wavelet with more oscillations, and better refine the scales and voices.

On the other hand, there are so-called STFT with windows whose width vary with frequency.

Add-ons like hybrid time-scale/time-frequency transformations, reassignement, etc. may be used, but choosing the appropriate tool requires to refine your goal.

The wavelet is too time localized. Also pywt and scipy implems are flawed. On your signal w/ ssqueezepy:

Laurent is correct that CWT isn't always superior.

import numpy as np
from ssqueezepy import cwt
from ssqueezepy.visuals import imshow

t = np.linspace(0, 50, 50*20, 0)
f = np.sin(2.*np.pi*t)*((t>=10)&(t<=20))+np.sin(2*np.pi*5*t)*((t>=30)&(t<=40))

Wx0, _ = cwt(f, ('gmw', {'beta': 10}))
Wx1, _ = cwt(f, ('gmw', {'beta': 90}))

tint = np.round(t).astype(int)
imshow(Wx0, xticks=tint, abs=1, title="abs(CWT) | time-localized")
imshow(Wx1, xticks=tint, abs=1, title="abs(CWT) | freq-localized")