morlet wavelet
See also wavelets
0.1. definition
It's a complex sine wave windowed by a Gaussian \[ \psi_{f}(t) = e^{2\pi ift}e^{\frac{-t^2}{2\sigma^2}} \]
where \(\sigma = \frac{n}{2\pi f}\).
Explanation of components:
- The first term is a complex sine wave
- The second term is the Gaussian envelope
Important things:
- \(f\) is the frequency-of-interest. This is the frequency that will be "matched"
- \(\sigma\) controls the temporal resolution. We can increase the number of cycles, \(n\), to get better frequency resolution, but lose temporal resolution
Now, I think that \(\sigma\) does not need \(\frac{1}{f}\), but it is rather by convention to set the scale that way. We could make \(\sigma\) any old number, as long as we multiply by the correct normalizing term. I think
1. properties
The morlet wavelet is not admissable. We can add a correction term but this is not done in practice
2. relevant links
def morlet(sfreq, freqs, n_cycles=7.0, sigma=None, zero_mean=False): """Compute Morlet wavelets for the given frequency range. Parameters ---------- sfreq : float The sampling Frequency. freqs : array Frequency range of interest (1 x Frequencies). n_cycles : float | array of float, default 7.0 Number of cycles. Fixed number or one per frequency. sigma : float, default None It controls the width of the wavelet ie its temporal resolution. If sigma is None the temporal resolution is adapted with the frequency like for all wavelet transform. The higher the frequency the shorter is the wavelet. If sigma is fixed the temporal resolution is fixed like for the short time Fourier transform and the number of oscillations increases with the frequency. zero_mean : bool, default False Make sure the wavelet has a mean of zero. Returns ------- Ws : list of array The wavelets time series. """ Ws = list() n_cycles = np.atleast_1d(n_cycles) freqs = np.array(freqs) if np.any(freqs <= 0): raise ValueError("all frequencies in 'freqs' must be " "greater than 0.") if (n_cycles.size != 1) and (n_cycles.size != len(freqs)): raise ValueError("n_cycles should be fixed or defined for " "each frequency.") for k, f in enumerate(freqs): if len(n_cycles) != 1: this_n_cycles = n_cycles[k] else: this_n_cycles = n_cycles[0] # fixed or scale-dependent window if sigma is None: sigma_t = this_n_cycles / (2.0 * np.pi * f) else: sigma_t = this_n_cycles / (2.0 * np.pi * sigma) # this scaling factor is proportional to (Tallon-Baudry 98): # (sigma_t*sqrt(pi))^(-1/2); t = np.arange(0., 5. * sigma_t, 1.0 / sfreq) t = np.r_[-t[::-1], t[1:]] oscillation = np.exp(2.0 * 1j * np.pi * f * t) gaussian_enveloppe = np.exp(-t ** 2 / (2.0 * sigma_t ** 2)) if zero_mean: # to make it zero mean real_offset = np.exp(- 2 * (np.pi * f * sigma_t) ** 2) oscillation -= real_offset W = oscillation * gaussian_enveloppe W /= np.sqrt(0.5) * np.linalg.norm(W.ravel()) Ws.append(W) return Ws
- note that in the above implementation from the MNE library, \(\sigma\) can be set independently of \(f\). For almost all continuous wavelet transforms, the \(\sigma\) is proportional to \(\frac{1}{f}\), so that low frequencies have poor temporal resolution.
- note that for scipy cwt and scipy morelet, they build the foi into the width. That is, you don't have a choice to separately specify them. It is assumed that \(width = \frac{w\cdot fs}{foi\cdot 2f\pi}\) where \(fs\) is the sampling rate
- In the superlets paper, they do the same thing. If you want to use a different sigma, you need to change the implementation
- in brainstorm you can set the temporal resolution per frequency
- math introduction
- stack overflow question I haven't read