[FieldTrip] Single trial baseline correction in ft_preprocessing

Stephen Whitmarsh stephen.whitmarsh at gmail.com
Fri Sep 20 11:52:54 CEST 2019


Dear Duru,

1) Yes, cfg.trials does not work on ft_preprocessing, so you will end up
concatinating ntrials x ntrials :-). I thought you would be using
ft_timelockbaseline (but even there isn't a cfg.trials option. My bad. I'll
make up for it below :-))
2) After appending data, the .sampleinfo field is removed, and no reference
to the original data is made, as it is done by ft_databrowser to plot the
events from the original data (who gets some info from the .cfg field as
well, i.e. the original file). This is because typically appending data
goes over several datasets, and references to 1 original file doesn't make
sense anymore.
3) About baseline correcting with other data, i.e,. outside of the trial
duration; It seems in general you would benefit from just making your own
baseline correction, which will solve all your issues and is pretty simple.

For example (there are many ways, but this would be my way) you could do
the following in which you preprocess and epoch both the baseline period,
and trail period (including any other 'baseline' pre-stim period) separately

% preprocess data as you did before
cfg = [];
cfg.trl = 'your data trl'
data_base_end_E = ft_preprocessing(cfg);

% preprocess only your baseline periods
cfg = [];
cfg.trial = 'your "BaselineWindow" however you want to define it, including
an arbitrary offset, say 0; Of course the same amount of trials as your
data'
data_baseline = ft_preprocessing(cfg);

% Calculate baseline value, i.e. the mean of the baseline period
for itrial = 1 : size(data_baseline.trial,2)
  baseline{itrial} = mean(data_baseline.trial{itrial})
end

% now just divide your data with the baseline value, or subtract for
absolute baseline, or make a ratio, whatever you want.
data_base_end_E_baseline =  data_base_end_E;
for itrial = 1 : size( data_base_end_E.trial,2)
  data_base_end_E_baseline.trial{itrial} =  data_base_end_E.trial{itrial} /
baseline{itrial};
end

Doing it like this, also allows you even to extract baselines of unequal
duration is you want to. I now realize though that by preprocessing your
data separately, you might introduce differences in e.g. filtering between
the baseline period and the trial data, especially when using short and
variable trial lengths for either. So, even better would be to preprocess
you data first as one trial, and then use ft_redefine trials to separate it
in either baseline and baseline+data. Let's write it out:

----------

% preprocess all your data as one trial, i.e. without epoching:
cfg = [];
cfg.dataset = 'your datafile';
cfg.hpfilter = ... etc...
...
all_data = ft_preprocessing(cfg);

% epoch your trial data
cfg = [];
cfg.trl = 'your data trl'
data_base_end_E = ft_redefinetrial(cfg,all_data);

% preprocess only your baseline periods
cfg = [];
cfg.trl = your "BaselineWindow" trl, however you want to define it,
including an arbitrary offset, say 0; Of course the same amount of trials
as your data
data_baseline =  ft_redefinetrial (cfg,all_data);

% The rest is the same as above:

% Calculate baseline value, i.e. the mean of the baseline period
for itrial = 1 : size(data_baseline.trial,2)
  baseline{itrial} = mean(data_baseline.trial{itrial})
end

% now just divide your data with the baseline value, or subtract for
absolute baseline, or make a ratio, whatever you want.
data_base_end_E_baseline =  data_base_end_E;
for itrial = 1 : size( data_base_end_E.trial,2)
  data_base_end_E_baseline.trial{itrial} =  data_base_end_E.trial{itrial} /
baseline{itrial};
end

----------

This should take care of treating all data the same, and especially allows
you e.g. to define a nice high-pass filter on all your data at once. There
might be a typo in the code, but I how you get my idea.

Hope this helps,
Stephen





Op vr 20 sep. 2019 om 08:35 schreef Duru Gun Ozkan <
durugun.ozkan at uniroma1.it>:

> Dear Stephen,
>
> Thank you for your response. It seemed like your suggestion helped, but I
> thave another potential issue now.
> The problem is, when I use *ft_databrowser *to visualise the trials after
> baseline corection loop, I can no longer see the markers, even if I add * cfg.plotevents
> = 'yes'*. I can see that this information exists in the data structure,
> so I'm not sure if this is a problem per se. But the bigger issue is, after
> running these loops, the data becomes very large (even after being
> appended), impossible to save, and slows down the rest of my analysis,
> where regular baseline correction doesn't cause this.
>
>  Any ideas where I might be going wrong? I suspect I might have used the
> wrong kinds of brackets, but the curly brackets as in your suggestion
> caused an error about cell structures, and when I run it as I wrote, the
> data structures actually look fine.Or it might be the way that I made a
> loop to append the data, instead of spelling it out for all of the 360
> trials.
>
> Another somewhat related question, is it possible to have the baseline
> window outside of the defined trial length?
>
>  Here is what I did:
>
>  for trial_index = 1:360
>
>      cfg                = [];
>      cfg.demean         = 'yes';
>      cfg.baselinewindow = [BaselineWindow(trial_index,1)
> BaselineWindow(trial_index,2)];
>      cfg.trials         = trial_index;
>      bl_end_E(trial_index)  = ft_preprocessing(cfg, data_end_E);
>
>  end
>
> %% This results in the struct:
>  bl_end_E =   1×360 struct array with 8 fields:
>     hdr
>     fsample
>     trialinfo
>     sampleinfo
>     trial
>     time
>     label
>     cfg
>
> %% Then I append the data:
>  data_base_end_E = bl_end_E(1);
>
>  for trial_ind = 2:360
>
>      cfg                 = [];
>      cfg.keepsampleinfo  = 'yes';
>      data_base_end_E     =
> ft_appenddata(cfg,data_base_end_E,bl_end_E(trial_ind));
>
>  end
>
> %% This results in losing hdr and fsample fields: data_base_end_E =
> struct with fields:
>
>          label: {29×1 cell}
>      trialinfo: [360×4 double]
>     sampleinfo: [360×2 double]
>          trial: {1×360 cell}
>           time: {1×360 cell}
>            cfg: [1×1 struct]
> %% So I add them back:
>   base_end_E.hdr = data_end_E.hdr;
>   base_end_E.fsample = data_end_E.fsample;
>
>     %% Visual data inspection
>     cfg                   = [];
>     cfg.viewmode  = 'vertical';
>     cfg.continuous = 'no';
>     cfg.blocksize   = 1.5;
>     cfg.channel     = {'all'};
>     cfg                   = ft_databrowser(cfg,data_base_end_E);
>
>
> Thanks again for the help!
>
> Duru
>
> --
> *Duru G**ü**n **Ö**zkan*
>
>
> *Ph.D. student in Cognitive Social and Affective Neuroscience.*
>
>
> *Department of Psychology.University of Rome "La Sapienza".Via dei Marsi
> 78 - 00185 - Roma.*
>  *e-mail: durugun.ozkan at uniroma1.it <vanessa.era at uniroma1.it>*
> *https://agliotilab.org/lab-staff/phd-students/2nd-year#anchor
> <https://agliotilab.org/lab-staff/phd-students/2nd-year#anchor>*
>
> > Hi Duru,
>
> >   Use cfg.trials = trial_index
> >   Put the output in a struct, i.e. bl{trial_index}
> >   Then combine with ft_append_data([],bl{:});
>
> >   Hope this helps,
> >   Stephen
>
>
> >   On Tue, 17 Sep 2019, 19:30 Duru Gun Ozkan, <durugun.ozkan at uniroma1.it>
> >   wrote:
>
> > Hi everyone,
> >
> > I have a question regarding specifying a different baseline correction
> > time for each trial in ft_preprocessing.
> > I had 360 audio stimuli all of which had different lengths. My trigger is
> > located at the end of each stimuli, and I would like to place the
> baseline
> > correction between 200 ms before stimulus start and stimulus start.
> > I have a matrix for cfg.baselinewindow called BaselineWindow such as
> this:
> > -1.83018 -1.630182
> > -1.69807 -1.498071
> > -0.58653 -0.38653
> > -1.07604 -0.876039
> > -2.2608 -2.060803
> > -0.80863 -0.608632
> > -1.55663 -1.356629
> > -0.94261 -0.742605
> > -1.20845 -1.008448 ...
> > I tried to create a loop:
> >
> > for trial_index = 1:360
> >
> >      cfg = [];
> >      cfg.demean        = 'yes';
> >      cfg.baselinewindow = [BaselineWindow(trial_index,1)
> > BaselineWindow(trial_index,2)];
> >
> >      data_baselined_end_E = ft_preprocessing(cfg, data_end_E);
> >
> >  end
> >
> > This didn't work because it kept running the preprocessing with all the
> > baselines with all trials, instead of keeping to its specific trial.
> >
> > My question is, is there another way to specify individual baselines for
> > individual trials? Or can anyone suggest to improve this loop to have the
> > data preprocessed with its specific baseline windows?
> >
> > Thank you in advance.
> >
> > Best,
> >
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20190920/cf521f2f/attachment.html>


More information about the fieldtrip mailing list