I am implementing the localizer method from this paper. One of the steps is not hard to understand and implement, but I don't understand why it is applied or what is the rationale behind it.
Each data epoch is a 60x500 array corresponding to 500 points on 60 channels sampled at 500 Hz. The paper states:
Fourier transform with 1 Hz resolution was applied to determine the frequency in 8–13 Hz band that had maximum power per Hz (frequency of maximum power (FMP)). Since the amplitude-modulated sound occurred in 40 Hz, the Fourier transform was applied to extract real and imaginary parts of 40 Hz as well as in FMP for each epoch.
8-13 Hz corresponds to the alpha band. The amplitude-modulated audio sound occuring in 40 Hz is called ASSR. My python implementation of this step:
for i, epoch in enumerate(epochs):
# epoch.shape = (60, 500)
# Util function to return the fq associated to each bin
fft_freq = np.fft.rfftfreq(epoch.shape[1], 1.0/fs) # 0 to 250, step 1
# FFT
fft_val = np.fft.rfft(epoch, axis=1) # (60, 251)
# Keep the FFT for alpha band and ASSR
alpha_band = np.where(np.logical_and(fft_freq>=8, fft_freq<=13))[0]
alpha_band_fft = fft_val[:, alpha_band] # (60, 6)
ASSR = np.where(fft_freq == 40)[0]
ASSR_fft = fft_val[:, ASSR] # (60, 1)
# Find FMP
psd = np.square(np.abs(alpha_band_fft)) # (60, 6), equivalent to a periodogram
FMP = 2 # FMP determine in 0,1,2,3,4,5 with 0 corresponding to 8 Hz and 5 to 13 Hz
FMP_fft = alpha_band_fft[:, [FMP]] # (60, 1), In this example, I selected 10 Hz
As I am not yet sure how the FMP is chosen, I simply took 2 (corresponding to 10 Hz) as an example here.
We applied SVD on real and imaginary parts on FMP and 40 Hz separately to calculate two different topographies of the brain in each epoch. The first column of u for 40 Hz is the topography of 40 Hz and the first column of u for FMP is the topography of FMP.
The relation between u
and SVD is explicitly given in the paper, just in case. I used numpy
for the implementation.
u, s, v = np.linalg.svd(ASSR_fft, full_matrices=False)
u, s, v = np.linalg.svd(FMP_fft, full_matrices=False)
With the parameter full_matrices
set to True
, the shapes returned are: u.shape = (60, 60), s.shape = (1, ), v.shape = (1, 1)
. However, since only the first column from u
is interesting, I have set full_matrices
to False
to reduce computation and to return an array u
of shape (60, 1)
.
Question: What is the information extracted here? Why is the first column of u
the topography of a given frequency? I do not get what the SVD is achieving here.