Time-domain analysis (ERP)Studying how a system reacts to perturbations is a very effective way to learn about that system. This is also true in brain research. The perturbations in the background EEG activity produced by a given stimulation are called evoked potentials (EPs). When EEG voltages are measured with respect to an eliciting stimulus, a good strategy to visualize even small EPs, which are not easily discernable in the continuous EEG recording, is to take the average over a number of repetitions of that stimulus. The result is referred to as an event-related potential (ERP). The logic underlying the computation of an ERP is quite straightforward. Each trial (i.e., repetition) contains both signal (i.e., evoked potential) and noise (i.e., background EEG activity). If we assume that the signal is similar over trials, whereas the noise is random in each trial, then averaging over many trials will lead to a dramatic noise reduction and a consequent improvement in the ability to detect the ERP. The signal-to-noise ratio (SNR) is a typical measure of the capacity to distinguish signal from noise. It is simply calculated as the ratio of the signal amplitude to the noise amplitude. It can be shown that, in the computation of an ERP, the SNR increases as a function of the square root of the number of trials, provided the noise is Gaussian distributed. This means, for instance, that we need to increase the number of trials by a factor of four to double the SNR. To recap, studying an ERP is rather simple: we first align the time-domain EEG signals to the time = 0 (i.e., we align to the onset of an eliciting event), and then we average across trials at each time point. In ERP terminology, the term component denotes a particular feature of an ERP waveform and, in most cases, the features of interest are peaks or troughs. Therefore, ERP components are generally identified by their polarity (i.e., peak or trough) and their temporal latency. For instance, the N100 component is a negative modulation of the waveform that reaches its minimum at about 100 ms. It is worth emphasizing that ERP components (i.e., the voltage peaks and troughs in the ERP waveform) do not necessarily correspond with transient electrical potentials elicited by the activity of localized populations of neurons in the brain. In fact, because of volume conduction, the ERP voltage is the sum of the activity of many populations of neurons. In other words, ERP components do not represent independent components (ICs), but rather can be interpreted as a combination of ICs. A common method to elicit ERPs is by using the so-called oddball paradigm. In an oddball paradigm, two different stimuli are presented following a pseudo-random sequence. One of them (standard stimulus) appears frequently, whereas the other one (deviant stimulus) appears less often and unexpectedly. We will analyze some datasets in which standard and deviant stimuli are tones of different frequencies. To this end, we will use FieldTrip, a Matlab toolbox for MEG and EEG analysis. The main advantage of FieldTrip is that it offers advanced non-parametric statistical testing, as well as advanced methods for frequency and time-frequency analysis. The main disadvantage (for some users) is the lack of any interactive GUI, which prompts the users to develop their own scripts. In general, an analysis implemented in FieldTrip consists of a sequence of calls to specific functions that produce a data object as an output. The input to these functions is always a configuration (cfg) structure, which specifies the parameters used by the function. Usually, the data is passed as a second input argument. Let us start analyzing the first dataset (click here to download all datasets). The datasets were preprocessed using EEGLAB and following the steps illustrated in the previous section. To begin with, let us have a look at the different trigger codes present in the dataset S01OddballSession1. To do this, let us run the following snippet of code. |
Return to the wiki
|
% Looking at the different trigger codes present in the dataset cfg = []; cfg.dataset = 'C:\Users\CIMeC\Desktop\wikiDatasets\S01\S01Oddball.vhdr'; % file path cfg.trialfun = 'ft_trialfun_general'; % the default trial function is fine % when trials are defined according % to specified trigger values cfg.trialdef.eventtype = '?'; ft_definetrial(cfg); |
↑ Go up |
As show in Figure 3.1, all event types and values are displayed in the Matlab command window. The most relevant events are those marked as ‘Stimulus’. In our dataset, the values ‘S 103’, ‘S 104’, ‘S 105’, ‘S 106’, ‘S 107’, ‘S 108’, ‘S 109’, ‘S 113’, ‘S 118’ represent standard tones, whereas the values ‘S 203’, ‘S 204’, ‘S 205’, ‘S 206’, ‘S 207’, ‘S 208’, ‘S 209’, ‘S 213’, ‘S 218’ represent deviant tones.
Figure 3.1: Events detectionEach tone lasted 80 ms and was separated from the following tone by a gap of 700 ms. We can segment our dataset into epochs from -250 ms to 750 ms, where the time-point 0 is defined by the trigger associated with a given tone. To this end, we will first use the ft_definetrial function, and then we will use the ft_preprocessing function. |
|
% Defining trials using trigger values – Standard tones cfg = []; cfg.dataset = 'C:\Users\CIMeC\Desktop\wikiDatasets\S01\S01Oddball.set'; % file path. You may need to edit the path cfg.trialfun = 'ft_trialfun_general'; % the default trial function is fine % when trials are defined according % to specified trigger values cfg.trialdef.eventtype = 'Stimulus'; cfg.trialdef.eventvalue = {'S 103','S 104','S 105','S 106', ... 'S 107','S 108','S 109','S 113','S 118'}; % standard tones cfg.trialdef.prestim = 0.25; % in seconds cfg.trialdef.poststim = 0.75; % in seconds cfg = ft_definetrial(cfg); |
↑ Go up |
The output resulting from ft_definetrial contains the trial definition as a Nx4 matrix, as shown by the variable cfg.trl. The first column of the matrix is the begin sample of each trial, the second column is the end sample, the third column contains the offset that defines where the relative t = 0 point is for each trial, and the fourth column contains the corresponding event value. It is desirable to discard trials containing discontinuities that have been created after continuous artifactual segments have been removed. |
|
% Removing trials containing discontinuities trialsToReject = zeros(length(cfg.trl),1); for eventId = 1:length(cfg.event) if isempty(cfg.event(eventId).type) tmpSample = cfg.event(eventId).sample; for trialInfoId = 1:length(cfg.trl) if (tmpSample - cfg.trl(trialInfoId,1)) * ... (tmpSample - cfg.trl(trialInfoId,2)) < 0 trialsToReject(trialInfoId) = trialInfoId; end end end endtrialsToReject = trialsToReject(trialsToReject ~= 0); cfg.trl(trialsToReject,:) = []; |
↑ Go up |
We will use the cfg configuration to read the previously defined trials from the original data file on disk. We will also apply a baseline correction. |
|
% Reading trials and applying baseline correction – Standard tones cfg.demean = 'yes'; cfg.baselinewindow = [-0.1 0]; % in seconds dataStd = ft_preprocessing(cfg); |
↑ Go up |
dataStd is a structure variable whose most important fields are trial, which contains the individual trials, and time, which contains the time vector for each trials. To visualize a single trial (e.g., trial 1) from one channel (e.g., channel 5), run the following command: |
|
% Plotting a single trial from one channel figure; plot(dataStd.time{1}, dataStd.trial{1}(5,:)) % trial 1 from channel 5 (Fz) |
↑ Go up |
The previous steps will be repeated for the second experimental condition (i.e., deviant tones). |
|
% Defining trials using trigger values – Deviant tones cfg = []; cfg.dataset = 'C:\Users\CIMeC\Desktop\wikiDatasets\S01\S01Oddball.set'; % file path cfg.trialfun = 'ft_trialfun_general'; % the default trial function is fine % when trials are defined according % to specified trigger values cfg.trialdef.eventtype = 'Stimulus'; cfg.trialdef.eventvalue = {'S 203','S 204','S 205','S 206','S 207',... 'S 208','S 209','S 213','S 218'}; % deviant tones cfg.trialdef.prestim = 0.25; % in seconds cfg.trialdef.poststim = 0.75; % in seconds cfg = ft_definetrial(cfg); % Removing trials containing discontinuities trialsToReject = zeros(length(cfg.trl),1); for eventId = 1:length(cfg.event) if isempty(cfg.event(eventId).type) tmpSample = cfg.event(eventId).sample; for trialInfoId = 1:length(cfg.trl) if (tmpSample - cfg.trl(trialInfoId,1)) * ... (tmpSample - cfg.trl(trialInfoId,2)) < 0 trialsToReject(trialInfoId) = trialInfoId; end end end end trialsToReject = trialsToReject(trialsToReject ~= 0); cfg.trl(trialsToReject,:) = []; % Reading trials and applying baseline correction – Deviant tones cfg.demean = 'yes'; cfg.baselinewindow = [-0.1 0]; % in seconds dataDev = ft_preprocessing(cfg); |
↑ Go up |
A convenient way to apply the previous analyses to all subjects is to use a for-loop, as shown below: |
|
%% Initializations dataPath = 'C:\Users\CIMeC\Desktop\wikiDatasets\'; % It depends on where % the wikiDatasets folder % is stored fileNameDescription = 'Oddball.set'; subjects = {'S01' 'S02' 'S03' ... 'S04' 'S05'}; % the variable subjects contains the list % of subject-specific directories nSubjs = numel(subjects); %% Defining trials (or epochs) using trigger values for i = 1:nSubjs fileName = strcat(subjects{i},fileNameDescription); dataSet = fullfile(dataPath,subjects{i},fileName); % Defining trials using trigger values - Standard tones cfg = []; cfg.dataset = dataSet; % file path cfg.trialfun = 'ft_trialfun_general'; % the default trial function is fine % when trials are defined according % to specified trigger values cfg.trialdef.eventtype = 'Stimulus'; cfg.trialdef.eventvalue = {'S 103','S 104','S 105','S 106','S 107',... 'S 108','S 109','S 113','S 118'}; % standard tones cfg.trialdef.prestim = 0.25; % in seconds cfg.trialdef.poststim = 0.75; % in seconds cfg = ft_definetrial(cfg); % Removing trials containing discontinuities trialsToReject = zeros(length(cfg.trl),1); for eventId = 1:length(cfg.event) if isempty(cfg.event(eventId).type) tmpSample = cfg.event(eventId).sample; for trialInfoId = 1:length(cfg.trl) if (tmpSample - cfg.trl(trialInfoId,1)) * ... (tmpSample - cfg.trl(trialInfoId,2)) < 0 trialsToReject(trialInfoId) = trialInfoId; end end end end trialsToReject = trialsToReject(trialsToReject ~= 0); cfg.trl(trialsToReject,:) = []; % Reading trials and applying baseline correction - Standard tones cfg.demean = 'yes'; cfg.baselinewindow = [-0.1 0]; % in seconds cfg.outputfile = fullfile(dataPath,subjects{i},'dataStd'); ft_preprocessing(cfg); % Defining trials using trigger values - Deviant tones cfg = []; cfg.dataset = dataSet; % file path cfg.trialfun = 'ft_trialfun_general'; % the default trial function is fine % when trials are defined according % to specified trigger values cfg.trialdef.eventtype = 'Stimulus'; cfg.trialdef.eventvalue = {'S 203','S 204','S 205','S 206','S 207',... 'S 208','S 209','S 213','S 218'}; % deviant tones cfg.trialdef.prestim = 0.25; % in seconds cfg.trialdef.poststim = 0.75; % in seconds cfg = ft_definetrial(cfg); % Removing trials containing discontinuities trialsToReject = zeros(length(cfg.trl),1); for eventId = 1:length(cfg.event) if isempty(cfg.event(eventId).type) tmpSample = cfg.event(eventId).sample; for trialInfoId = 1:length(cfg.trl) if (tmpSample - cfg.trl(trialInfoId,1)) * ... (tmpSample - cfg.trl(trialInfoId,2)) < 0 trialsToReject(trialInfoId) = trialInfoId; end end end end trialsToReject = trialsToReject(trialsToReject ~= 0); cfg.trl(trialsToReject,:) = []; % Reading trials and applying baseline correction - Deviant tones cfg.demean = 'yes'; cfg.baselinewindow = [-0.1 0]; % in seconds cfg.outputfile = fullfile(dataPath,subjects{i},'dataDev'); ft_preprocessing(cfg); end |
↑ Go up |
To compute the ERPs for each subject, we will use the ft_timelockanalysis function, which averages the epoched time series. |
|
%% Computing ERP for each subject % Standard tones for i = 1:nSubjs fileName = 'dataStd.mat'; dataSet = fullfile(dataPath,subjects{i},fileName); load(dataSet); % loading the variable 'data' % Averaging across trials cfg = []; cfg.channel = {'all'}; cfg.outputfile = fullfile(dataPath,subjects{i},'erpStd'); ft_timelockanalysis(cfg,data); clear data end % Deviant tones for i = 1:nSubjs fileName = 'dataDev.mat'; dataSet = fullfile(dataPath,subjects{i},fileName); load(dataSet); % loading the variable 'data' % Averaging across trials cfg = []; cfg.channel = {'all'}; cfg.outputfile = fullfile(dataPath,subjects{i},'erpDev'); ft_timelockanalysis(cfg,data); clear data end |
↑ Go up |
The ft_timelockgrandaverage allows computing the grand mean ERP, including all individual subjects’ ERP as an input argument. |
|
%% Computing group average ERP % Standard tones % Loading single subject ERPs in a single cell array allErpStd = cell(1,nSubjs); for i = 1:nSubjs fileName = 'erpStd.mat'; dataSet = fullfile(dataPath,subjects{i},fileName); load(dataSet); % loading the variable 'timelock' allErpStd{i} = timelock; clear timelock end % Computing grand average across subjects cfg = []; cfg.latency = [-0.1 0.6]; cfg.keepindividual = 'yes'; % it is sometimes useful to keep individual... % representations in the output cfg.outputfile = fullfile(dataPath,'grandAvgErpStd'); ft_timelockgrandaverage(cfg,allErpStd{:}); % Deviant tones % Loading single subject ERPs in a single cell array allErpDev = cell(1,nSubjs); for i = 1:nSubjs fileName = 'erpDev.mat'; dataSet = fullfile(dataPath,subjects{i},fileName); load(dataSet); % loading the variable 'timelock' allErpDev{i} = timelock; clear timelock end % Computing grand average across subjects cfg = []; cfg.latency = [-0.1 0.6]; cfg.keepindividual = 'yes'; % it is sometimes useful to keep individual... % representations in the output cfg.outputfile = fullfile(dataPath,'grandAvgErpDev'); ft_timelockgrandaverage(cfg,allErpDev{:}); |
↑ Go up |
FieldTrip offers several ways to visualize the spatiotemporal structure of EEG data. The ft_multiplotER allows displaying a set of ERP time courses on a channel layout (see below for further information about the channel layout); the ft_singleplotER allows displaying a single ERP time course or an average time course across a set of specified channels; the ft_topoplotER allows displaying a spatial topography in a specified latency window. All these functions require a layout representing a 2-dimensional projection of the electrode locations. We will define a channel layout by using one of the template layouts included in FieldTrip. In the present tutorial, we will adopt the general template EEG1005.lay and then we will increase the layout width and height. |
|
%% Defining channel layout templateLayout = 'EEG1005.lay'; % one of the template layouts included % in FieldTrip cfg = []; cfg.layout = which(templateLayout); layout = ft_prepare_layout(cfg); figure ft_plot_lay(layout); title(templateLayout) % Increasing layout width and height layout.width = 0.0615 * ones(length(layout.width),1); layout.height = 0.0356 * ones(length(layout.height),1); |
↑ Go up |
Now we are ready to plot the grand average ERP. |
|
%% Visualization of the group average ERP % Plotting a channel layout with the ERP time courses of standard and... % deviant tones at each electrode fileName = 'grandAvgErpStd'; dataSet = fullfile(dataPath,fileName); standard = load(dataSet); % loading the variable 'grandavg' fileName = 'grandAvgErpDev'; dataSet = fullfile(dataPath,fileName); deviant = load(dataSet); % loading the variable 'grandavg' cfg = []; cfg.layout = layout; cfg.graphcolor = 'br'; cfg.showcomment = 'no'; cfg.showscale = 'no'; %cfg.showlabels = 'yes'; figure; ft_multiplotER(cfg,standard.grandavg,deviant.grandavg); % Plotting mean ERPs over fronto-central electrodes cfg = []; %cfg.ylim = [-1 1]; cfg.channel = {'Fz','FCz','Cz'}; cfg.linewidth = 2; cfg.graphcolor = 'br'; figure; ft_singleplotER(cfg,standard.grandavg,deviant.grandavg); legend({'Standard','Deviant'}) % Matlab commands to make the figure intelligible set(gca,'Fontsize',14); %title('Mean over central electrodes'); set(gca,'box','on'); xlabel('time (s)'); ylabel('amplitude (\muV)'); % Plotting mean ERP of deviant tones over fronto-central electrodes... % toghether with standard deviation cfg = []; cfg.channel = {'Fz','FCz','Cz'}; cfg.avgoverchan = 'yes'; % averaging over channels grandavgSel = ft_selectdata(cfg,deviant.grandavg); x = grandavgSel.time'; % defining x axis y = mean(squeeze(grandavgSel.individual),1)'; % defining y axis e = std(squeeze(grandavgSel.individual),1)'; % standard deviation low = y - e; % lower bound high = y + e; % upper bound figure; hp = patch([x; x(end:-1:1); x(1)], [low; high(end:-1:1); low(1)], 'r'); hold on; hl = line(x,y); set(hp,'facecolor',[1 0.8 0.8],'edgecolor','none'); set(hl,'color','r','linewidth',2); set(gca,'FontSize',12); title ('Mean and Standard deviation over fronto-central electrodes'); set(gca,'box','on'); xlabel('time (s)'); ylabel('amplitude (\muV)'); legend({'Deviant (StD)','Deviant (Mean)'}) % Plotting topography of the N100 component cfg = []; cfg.layout = layout; cfg.xlim = [0.1 0.12]; cfg.zlim = [-2 2]; cfg.colormap = parula; cfg.marker = 'off'; cfg.style = 'fill'; cfg.comment = ' '; cfg.colorbar = 'yes'; figure; subplot(2,1,1);ft_topoplotER(cfg,standard.grandavg); title('Standard'); c = colorbar; c.LineWidth = 1; c.FontSize = 14; title(c,'\muV'); subplot(2,1,2);ft_topoplotER(cfg,deviant.grandavg); title('Deviant'); c = colorbar; c.LineWidth = 1; c.FontSize = 14; title(c,'\muV'); suptitle('N100 topography'); |
↑ Go up |
As for statistical analysis, FieldTrip offers both parametric and non-parametric tests. To address the family-wise error rate, we suggest using non-parametric tests with spatiotemporal clustering. The general idea is that EEG signals have specific spatiotemporal structure that can be exploited to maximize statistical sensitivity. Because neighboring channels and neighboring time-points are likely to reflect the same neural phenomena, aggregating spatiotemporal neighbors into clusters is equivalent to aggregating the evidence for an effect to be significant. For further details on cluster-based statistical testing, we refer the reader to Maris and Oostenveld's paper (see References below). We recommend reading the aforementioned reference before continuing with the tutorial. To be able to define clusters across channels, we need a neighborhood structure. |
|
%% Creating a neighbourhood structure to define how spatial clusters... % are formed fileName = 'dataStd.mat'; dataSet = fullfile(dataPath,subjects{1},fileName); load(dataSet); % loading the variable 'data' templateElec = 'standard_1005.elc'; elec = ft_read_sens(which(templateElec)); idx = ismember(elec.label,data.label); elec.chanpos = elec.chanpos(idx,:); elec.chantype = elec.chantype(idx); elec.chanunit = elec.chanunit(idx); elec.elecpos = elec.elecpos(idx,:); elec.label = elec.label(idx); cfg = []; cfg.method = 'distance'; %'template' or 'distance' or 'triangulation' cfg.neighbourdist = 80; % maximum distance between neighbouring sensors... % (only for 'distance') cfg.feedback = 'yes'; % show a neighbour plot neighbours = ft_prepare_neighbours(cfg,elec); |
↑ Go up |
Now we can run the statistical analysis at the group level. |
|
%% Statistical analysis of time-domain data at the group level % Creating a FieldTrip design matrix design = zeros(1,2*nSubjs); % for within-subjects analysis,... % the design matrix contains two rows for i = 1:nSubjs design(1,i) = i; end for i = 1:nSubjs design(1,nSubjs+i) = i; end design(2,1:nSubjs) = 1; design(2,nSubjs+1:2*nSubjs) = 2; % Computing the difference as a T-statistic and running an inferential test cfg = []; cfg.channel = {'all'}; %cfg.latency = [0.05 0.15]; cfg.method = 'montecarlo'; cfg.statistic = 'ft_statfun_depsamplesT'; cfg.clusterthreshold = 'nonparametric_common'; cfg.correctm = 'cluster'; cfg.alpha = 0.025; % 0.05/2 because two-sided cfg.numrandomization = 1000; cfg.neighbours = neighbours; cfg.design = design; cfg.uvar = 1; cfg.ivar = 2; statErp = ft_timelockstatistics(cfg,allErpStd{:},allErpDev{:}); % Plotting stat output cfg = []; cfg.layout = layout; cfg.parameter = 'stat'; cfg.maskparameter = 'mask'; cfg.graphcolor = 'r'; cfg.showcomment = 'no'; cfg.showscale = 'no'; figure; ft_multiplotER(cfg,statErp); % Plotting stat difference ERP over fronto-central electrodes cfg = []; cfg.ylim = [-6 16]; cfg.channel = {'Fz','FCz','Cz'}; cfg.parameter = 'stat'; cfg.maskparameter = 'mask'; cfg.linewidth = 2; cfg.graphcolor = 'r'; figure; ft_singleplotER(cfg,statErp); set(gca,'Fontsize',14); title ('Mean over fronto-central electrodes'); set(gca,'box','on'); xlabel('time (s)'); ylabel('std vs. dev (t-val)'); % Plotting N100 topography in units of t-value cfg = []; cfg.layout = layout; cfg.xlim = [0.1 0.12]; cfg.parameter = 'stat'; cfg.zlim = [-5 5]; cfg.colormap = parula; cfg.marker = 'off'; cfg.style = 'fill'; cfg.comment = ' '; cfg.colorbar = 'yes'; figure; ft_topoplotER(cfg,statErp); title('N100 topography') c = colorbar; c.LineWidth = 1; c.FontSize = 14; title(c,'t-val') |
↑ Go up |
It is also possible to analyze single-subject data. Here the aim is to test whether there is a systematic difference between trials in different experimental conditions. |
|
%% Single-subject analysis of time-domain data subjId = 1; % subject that we will analyze % Loading the trials with standard tones fileName = 'dataStd.mat'; dataSet = fullfile(dataPath,subjects{subjId},fileName); load(dataSet); % loading the variable 'data' % Averaging across trials cfg = []; cfg.channel = {'all'}; cfg.keeptrials = 'yes'; timeLockStd = ft_timelockanalysis(cfg,data); % Loading the trials with deviant tones fileName = 'dataDev.mat'; dataSet = fullfile(dataPath,subjects{subjId},fileName); load(dataSet); % loading the variable 'data' % Averaging across trials cfg = []; cfg.channel = {'all'}; cfg.keeptrials = 'yes'; timeLockDev = ft_timelockanalysis(cfg,data); % Creating a FieldTrip design matrix design = zeros(1,size(timeLockStd.trial,1) + size(timeLockDev.trial,1)); % for between-trials analysis, the design matrix contains only one row design(1,1:size(timeLockStd.trial,1)) = 1; design(1,(size(timeLockStd.trial,1)+1):(size(timeLockStd.trial,1) + size(timeLockDev.trial,1)))= 2; % Computing the difference as a T-statistic and running an inferential test cfg = []; cfg.channel = {'all'}; %cfg.latency = [0.05 0.15]; cfg.method = 'montecarlo'; cfg.statistic = 'ft_statfun_indepsamplesT'; % independent samples T-statistic for a between-trials analysis cfg.clusterthreshold = 'nonparametric_common'; cfg.correctm = 'cluster'; cfg.alpha = 0.025; % 0.05/2 because two-sided cfg.numrandomization = 1000; cfg.neighbours = neighbours; cfg.design = design; cfg.ivar = 1; statErp2 = ft_timelockstatistics(cfg,timeLockStd,timeLockDev); % Plotting stat output cfg = []; cfg.layout = layout; cfg.parameter = 'stat'; cfg.maskparameter = 'mask'; cfg.graphcolor = 'r'; cfg.showcomment = 'no'; cfg.showscale = 'no'; figure; ft_multiplotER(cfg,statErp2); |
↑ Go up |
It is noteworthy to point out that the number of trials should be similar in each condition when analyzing the effects of different factors. If there are large differences in trial count (e.g., 93 trials in condition 1 and 28 trials in condition 2), potential biases may be introduced. Finally, in FieldTrip we can analyze each experimental condition individually, by comparing the early ERP component with the pre-stimulus baseline window. In doing this, it is important that the length of pre-stimulus and post-stimulus windows be matched. By means of the ft_selectdata function, we split the single participant ERP data into two data structures: ‘act’ (i.e., activity) and ‘bl’ (i.e., baseline). |
|
%% Group analysis of time-domain data (activity vs. baseline) % Splitting data into activity and baseline act = cell(1,nSubjs); bl = cell(1,nSubjs); for i = 1:nSubjs cfg = []; cfg.latency = [-0.1 0]; bl{i} = ft_selectdata(cfg,allErpStd{i}); cfg.latency = [0.05 0.15]; act{i} = ft_selectdata(cfg,allErpStd{i}); bl{i}.time = act{i}.time; % FieldTrip allows for a direct comparison only if the time-axes are equal end % Creating a FieldTrip design matrix, conditions: 1 = act, 2 = bl design = zeros(2,2*nSubjs); for i = 1:nSubjs design(1,i) = i; end for i = 1:nSubjs design(1,nSubjs+i) = i; end design(2,1:nSubjs) = 1; design(2,nSubjs+1:2*nSubjs) = 2; % Computing the difference as a T-statistic, and running an inferential test cfg = []; cfg.channel = {'all'}; cfg.method = 'montecarlo'; cfg.statistic = 'ft_statfun_depsamplesT'; % dependent samples T-statistics cfg.clusterthreshold = 'nonparametric_common'; cfg.correctm = 'cluster'; cfg.alpha = 0.025;% .05/2 because two-sided cfg.numrandomization = 1000; cfg.neighbours = neighbours; cfg.design = design; cfg.uvar = 1; cfg.ivar = 2; statErp3 = ft_timelockstatistics(cfg,act{:},bl{:}); % Plotting stat output cfg = []; cfg.layout = layout; cfg.parameter = 'stat'; cfg.maskparameter = 'mask'; cfg.graphcolor = 'r'; cfg.showcomment = 'no'; cfg.showscale = 'no'; figure; ft_multiplotER(cfg,statErp3); |
↑ Go up |
References
|
↑ Go up |