Zero-padding and epoch-reflection for small epochs

343 views
Skip to first unread message

maca...@colorado.edu

unread,
Aug 2, 2017, 4:36:51 PM8/2/17
to AnalyzingNeuralTimeSeriesData
Hi,

I have a few questions about certain processing techniques used to increase frequency resolution and maximum frequency band with small epochs. These are admittedly two separate topics so I apologize for putting them in one post, but I do think both topics are worth considering for how to manage power spectra with small epochs.

Zero Padding:

1. Given that zero padding will create big jumps in the EEG signal prior to the first sample of the data and at the last sample of the data, why not pad pre-epoch at the amplitude of the first sample and post-epoch at the amplitude of the last sample? So for instance, if the first sample in an epoch has an amplitude of 30 and the last sample 20, why not pad pre-epoch with 30's and post-epoch with 20's?

2. In the below code*, N is the number of samples per epoch prior to zero-padding, so the actual range of frequencies doesn't change. I think this is correct, but do I still divide fft(data) by N on line 56, or should that be size(data,2), or in other words the length after zero-padding?

3. Likewise, what would be the appropriate way to scale the frequency band with the power spectrum? For instance, on line 65 I do the following:
    fft_subset = abs(fft_data(:,1:size(fft_data,2)/2+1,:)).^2;
Where, had I not zero-padded, I would have done the following:
    fft_subset = abs(fft_data(:,1:N/2+1,:)).^2;
My thought process is that the range of the power spectrum which corresponds to the frequency band should still be the length of the zero-padded fft_data/2+1. However, I'm not sure if my math is quite right, and maybe it's a bit more complicated than that... 

Epoch-reflection

In this paper (http://www.sciencedirect.com/science/article/pii/S096098221501235X?via%3Dihub), in which you are cited and acknowledged, the authors reflect their epochs, essentially doubling the length of an epoch and making it symmetrical. However, I was under the impression that this sort of epoch concatenation could be problematic for producing a good power spectrum. Is there something that makes this method acceptable, as opposed to just concatenating multiple unrelated trials? Are there any particular considerations that should be taken with this method?

Thanks,
Max


*
    data    = EEG.data(ROI,:,:); % data across all trials continuously
    srate   = EEG.srate;  % sampling rate in Hz
    nyquist = srate/2;    % Nyquist frequency -- the highest frequency you can measure in the data
    N       = size(data,2); % length of sequence (prior to zero-padding)
    % Still using N prior to zero-padding because zero-padding should only
    % increase frequency resolution, not frequency range
    
    %% Zero-pad to get resolution of freqres
    freqres = 0.25;
    
    % The number of samples per epoch necessary, given the sampling rate, to get the frequency resolution freqres
    nFFT = ceil(srate/freqres); 
    pad_idx = (nFFT-N)/2;
    
    % Pads each trial to enough samples to gain the frequency resolution of freqres, half at the front and half at the end
    data = padarray(data, [0 pad_idx 0], 0, 'both'); 
        
    % The number of unique frequencies we can measure is
    % exactly 1/2 of the number of data points in the time series (plus DC).
    frequencies = linspace(0,nyquist,(N/2)+1);
    
    %% FFT
    fft_data = fft(data,[],3)/N; % Fast fouriet transform
    
    if avg == 1
        fft_data = mean(fft_data,1);
    end
    
    freqband = frequencies(frequencies >= freqrange(1) & frequencies <= freqrange(2)); % Subset frequencies to inputted range
    freqband_start = find(frequencies >= freqrange(1),1);
    freqband_end = find(frequencies <= freqrange(2),1, 'last');
    fft_subset = abs(fft_data(:,1:size(fft_data,2)/2+1,:)).^2;
    % Using size(fft_data,2) rather than N because the pwspctrm length is
    % a reflection of increased resolution rather than frequency range, so
    % subsetting up to size(fft_data,2)/2+1 has the equivalent effect as
    % subsetting up to N/2+1 with non-zero-padded fft_data
    % http://www.ni.com/tutorial/4880/en/ This link suggests a) that
    % zero-padding may not work and b) that what I'm doing above may not be
    % correct
    fft_subset = fft_subset(:,pad_idx+freqband_start:pad_idx+freqband_end,:); % Subsets to the inputted frequency range
    % Accounts for zero-padding by adding the padding index (1/2 the total
    % padding since it's pre and post) to the start and end frequencies
    fft_subset = mean(fft_subset,3); % Average across all trials

Mike X Cohen

unread,
Aug 3, 2017, 9:11:27 AM8/3/17
to analyzingneura...@googlegroups.com
Hi Max. All good questions, and nontrivial difficulties of data analysis.

First of all, if at all possible, I recommend re-epoching the data to have longer epochs. It might be a bit of a hassle, but it will be worth it -- it will give you more freedom and flexibility for analyses, including doing time-frequency analysis, which might be more sensitive than the FFT if the alpha effects are shorter-lasting than the epoch.

But if it's not possible, then zero-padding is fine. However, you should let Matlab do the zero-padding for you in the fft function: fft(data,[],nfft), where nfft is the total N (not the number of zeros to add). Zeros should be added to the end of the signal, which Matlab will do. The correct divisor is the original N of the data (excluding the zeros). The reason not to repeat the final value is that it will add a DC offset, while adding zeros does not add a DC offset.

Reflection is an acceptable procedure for time-frequency analysis. I would not recommend it for an FFT, because if the phase is slightly offset relative to the start of the epoch, then reflection could obliterate the finding. That's similar to the code I sent in the last email. 

I hope that's clear!
Mike



--
You received this message because you are subscribed to the Google Groups "AnalyzingNeuralTimeSeriesData" group.
To unsubscribe from this group and stop receiving emails from it, send an email to analyzingneuraltimeseriesdata+unsub...@googlegroups.com.
Visit this group at https://groups.google.com/group/analyzingneuraltimeseriesdata.
For more options, visit https://groups.google.com/d/optout.



--
Mike X Cohen, PhD
mikexcohen.com

maca...@colorado.edu

unread,
Aug 3, 2017, 10:16:12 AM8/3/17
to AnalyzingNeuralTimeSeriesData
Unfortunately re-epoching is not possible, since these are epochs around fixation crosses which are only on the screen briefly (in lieu of resting state data, which were not recorded), which is why I was considering concatenating them all together or applying that reflection approach, although it sounds like I should not do these things.

Ah, I somehow missed that I could do zero-padding simply within the fft function. That makes that a lot easier, thanks!

maca...@colorado.edu

unread,
Aug 3, 2017, 3:36:15 PM8/3/17
to AnalyzingNeuralTimeSeriesData
Hey Mike,

Another related question occurred to me. So what you're saying about reflection I think makes sense to me; if the phase at the end of the epoch is different enough from the phase at the start of the epoch, then the phase would be thrown off at the reflection point, wiping out power. However, if I extracted the phase angle time series, could I determine if the beginning and end phase of each epoch are "close enough" to the same, and if so, reflect on those trials? For reference, I got the idea incidentally from your 2014 Journal of Neuroscience paper, which I have not fully digested yet (I'm also interested in your frequency sliding but not sure if I understand it well enough to go there yet...).

Mike X Cohen

unread,
Aug 4, 2017, 2:40:28 AM8/4/17
to analyzingneura...@googlegroups.com
Hi Max. I'll be honest: That's a great idea for a Matlab exercise as a way to improve your programming and signal-processing skills. But I'm about 100% sure that's not going to be a viable solution for a real analysis.

If you have the continuous data, you could still re-epoch and then apply a time-frequency analysis. The point of having a longer epoch is to have more data for a "buffer zone" to prevent edge artifacts from contaminating the trial period. It doesn't matter what's happening cognitively in those buffer zone periods.

Mike


Reply all
Reply to author
Forward
0 new messages