|
| 1 | +function [decomp_signal] = ecog_decomp_wavelet(data, freqs, srate, wave_num) |
| 2 | +% Function for decomposing time series data into time-frequency |
| 3 | +% representation (spectral decomposition) using wavelet transform. Employs |
| 4 | +% Morlet wavelet method (gaussian taper sine wave) to obtain the analytic |
| 5 | +% signal for specified frequencies (via convolution). |
| 6 | +% Inputs: |
| 7 | +% data - vector of time series to be decomposed |
| 8 | +% freqs - vector of center frequencies for decomposition |
| 9 | +% srate - sample rate (in Hz) |
| 10 | +% wave_num - desired number of cycles in wavelet (typically 5-10). |
| 11 | +% |
| 12 | +% Brett Foster, Stanford Memory Lab, Feb. 2015 |
| 13 | + |
| 14 | +%% Variables |
| 15 | +%sample rate |
| 16 | +srate = round(srate); |
| 17 | + |
| 18 | +%wavelet cycles |
| 19 | +wavelet_cycles = wave_num; |
| 20 | + |
| 21 | +%set wavelet window size, using lowest freq, wave number and sample rate |
| 22 | +%high-freqs will have greater zero padding |
| 23 | +lowest_freq = freqs(1); |
| 24 | +max_win_size = (1/lowest_freq)*(wavelet_cycles/2); |
| 25 | +max_win_size = max_win_size*1.1; %add 10% length to ensure zero is reached |
| 26 | + |
| 27 | +%wavelet window |
| 28 | +wavelet_win = -max_win_size:1/srate:max_win_size; |
| 29 | + |
| 30 | +%initialize variables |
| 31 | +tmp_amplitude = zeros(length(freqs),length(data)); |
| 32 | +tmp_phase = zeros(length(freqs),length(data)); |
| 33 | + |
| 34 | +%% Decompose |
| 35 | +% Decomposition iterates through each center frequency (wavelet), with |
| 36 | +% specified width, performing a convolution between the signal and complex |
| 37 | +% wavelet. |
| 38 | + |
| 39 | +%loop through frequencies, build new wavelet, convolve |
| 40 | +for fi=1:length(freqs) |
| 41 | + |
| 42 | + %initialize variables |
| 43 | + tmp_freq_analytic = zeros(size(data)); |
| 44 | + tmp_sine = zeros(size(wavelet_win)); |
| 45 | + tmp_gaus_win = zeros(size(wavelet_win)); |
| 46 | + tmp_wavelet = zeros(size(wavelet_win)); |
| 47 | + |
| 48 | + %% create sign wave at center frequency |
| 49 | + tmp_sine = exp(2*1i*pi*freqs(fi).*wavelet_win); |
| 50 | + %make gaussian window, with a width/sd = cycles |
| 51 | + tmp_gaus_win = exp(-wavelet_win.^2./(2*(wavelet_cycles/(2*pi*freqs(fi)))^2)); |
| 52 | + %make wavelet as dot-product of sine wave and gaussian window |
| 53 | + tmp_wavelet = tmp_sine.*tmp_gaus_win; |
| 54 | + |
| 55 | + %convolve data with wavelet - remove zero padding ('same' length as input) |
| 56 | + %BF - pre-flip kernel, to deal with flip in conv, keeps phase ok? |
| 57 | + tmp_freq_analytic = conv(data,tmp_wavelet(end:-1:1), 'same'); |
| 58 | + |
| 59 | + %extract amplitude and phase data |
| 60 | + %BF: apply amplitude normalization in function? |
| 61 | + tmp_amplitude(fi,:) = abs(tmp_freq_analytic); %amplitude |
| 62 | + tmp_phase(fi,:) = angle(tmp_freq_analytic); %phase |
| 63 | + |
| 64 | +end %end frequency loop |
| 65 | + |
| 66 | +%% collect data |
| 67 | +decomp_signal.amplitude = tmp_amplitude; |
| 68 | +decomp_signal.phase = tmp_phase; |
| 69 | + |
| 70 | +%finish |
0 commit comments