From sarah.kirchler at gmail.com  Fri May  1 11:48:53 2020
From: sarah.kirchler at gmail.com (Sarah Kirchler)
Date: Fri, 1 May 2020 11:48:53 +0200
Subject: [FieldTrip] Analyzing SSVEPs
In-Reply-To: <CABPNLUqbstWABU_k-BADXUv+-9naGSOi6DwsWaZ=S_1Q+hhrYA@mail.gmail.com>
References: <5eaaa2e5.1c69fb81.d62fe.d9d7@mx.google.com>
 <CABPNLUqbstWABU_k-BADXUv+-9naGSOi6DwsWaZ=S_1Q+hhrYA@mail.gmail.com>
Message-ID: <CAKLTn3e5FVSU1FphbwcTOh-gONE9GhicAMdvL3aCRwOLH5ufvg@mail.gmail.com>

Hi Eelke,

thank you for your answer!
I think you understood pretty much right, thank you also for the link to
the website.
The problem is, that I have data saved as .mat-files but already
preprocessed with Fieldtrip.
Now I want to use this data to do my SSVEP analysis, but if I try to load
the .mat-file, I get error messages. I also get the error message, that the
functions of the example script in Fieldtrip just work for ft_datatype_raw,
that "contains sensor level time domain data typically obtained after
calling ft_definetrial
<http://www.fieldtriptoolbox.org/reference/ft_definetrial> and
ft_preprocessing
<http://www.fieldtriptoolbox.org/reference/ft_preprocessing>." So it should
work for my datastructure, but it doesn't. Maybe I make a bad mistake and
should load the original vhdr-file and the mat-file together, I'm not sure,
but in my comprehension all the data that I need should be in the
preprocessed .mat-file.
Please correct me if I do wrong, I'm a beginner willing to not give up!

Thank you very much in advance,

Sarah

Am Do., 30. Apr. 2020 um 13:52 Uhr schrieb Eelke Spaak <
e.spaak at donders.ru.nl>:

> Hi Sarah,
>
> If I'm not mistaken, your question is essentially: I already have data
> in Matlab arrays, how can I make sure FieldTrip understands this? (So
> the question is independent of SSVEP or any specific analysis
> pipeline.) Have a look at
>
> http://www.fieldtriptoolbox.org/faq/how_are_the_various_data_structures_defined/
> and specifically ft_datatype_raw for pointers.
>
> Best,
> Eelke
>
> On Thu, 30 Apr 2020 at 12:05, Sarah Kirchler <sarah.kirchler at gmail.com>
> wrote:
> >
> > Hi Fieldtrip!
> >
> > I have a question About analyzing SSVEPs.
> > I don’t really know how to make a Connection from Fieldrtrip to my
> already preprocessed data. I have a Folder named „clean“, where I have
> saved the data rejected from artifacts.
> >
> > You offer only an example script „How to analyze SSVEPs with simulated
> data“, but I have real data and don’t know how to read it in.
> >
> > The function ft_read_data doesn’t support .mat-files, in which I saved
> my clean data.
> >
> > How can I create a dataset out of my clean data? Or how can I read in
> the clean data with the .mat-endings?
> >
> > Thanks for your answers!
> > And excuse my incorrect english.
> >
> > Best,
> >
> > Sarah Kirchler
> >
> > _______________________________________________
> > fieldtrip mailing list
> > https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> > https://doi.org/10.1371/journal.pcbi.1002202
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200501/2e6ce89f/attachment.htm>

From bkinkini at gmail.com  Fri May  1 13:33:32 2020
From: bkinkini at gmail.com (Kinkini .)
Date: Fri, 1 May 2020 13:33:32 +0200
Subject: [FieldTrip] Problems with ft_Channelrepair / interpolation
Message-ID: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>

Dear FieldTripers,

Hope everyone is coping well with the current situation.

I am relatively new in fieldtrip and I have been long stuck with using
ft_channelrepair for quite sometime now.

Briefly about my analysis pipeline:
1- Loading and epoching the data
2- ft_preprocessing - filtering, baselining, CAR
3- ft_databrowser - marking bad channels
4. ft_rejectvisual - rejecting bad channels; keepchannel = 'repair'
5. ft_channelrepair
6. ICA
7. TF Analysis
8. TF statististics

I have problems pertaining to step 4 and 5. In step 4 I want to keep the
bad channels so that I can interpolate them in the next step. When I use
data browser to look thorough the data, the bad channels look okay. But the
problem starts when I perform ICA on them. My first observation is that the
wchange value is very big (looks like this : 257868.69202720), but ICA runs
completely. However the ICA component topoplots look weird (screenshots
attached). However, when I look through the icabrowser plots , there are
peaks at physiological frequencies.

In order to avoid this, I tried getting rid of the bad channels completely
using ft_rejectvisual, perform ICA and then get back the missing channels
using neighbourhood average. Doing this, I was able to perform TF analysis,
but when I wanted to apply statistics on the data, I had errors. Finally, I
had to avoid the entire step of  interpolation to be able to run everything
and also perform statistics. But in a long run, I cannot avoid this step.

I am finding no clue as to where is it going wrong.

Hence, any idea, any clue from you all would help me very much. I am happy
to provide with more details if necessary.
Thank you so much for your response.

Best regards,

Kinkini Bhadra
PhD student
Department of Fundamental Neurosciences
University of Geneva
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200501/93e55123/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot 2020-05-01 11.57.28.png
Type: image/png
Size: 228619 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200501/93e55123/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot 2020-05-01 11.57.42.png
Type: image/png
Size: 287101 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200501/93e55123/attachment-0001.png>

From e.spaak at donders.ru.nl  Fri May  1 14:20:38 2020
From: e.spaak at donders.ru.nl (Eelke Spaak)
Date: Fri, 1 May 2020 14:20:38 +0200
Subject: [FieldTrip] Analyzing SSVEPs
In-Reply-To: <CAKLTn3e5FVSU1FphbwcTOh-gONE9GhicAMdvL3aCRwOLH5ufvg@mail.gmail.com>
References: <5eaaa2e5.1c69fb81.d62fe.d9d7@mx.google.com>
 <CABPNLUqbstWABU_k-BADXUv+-9naGSOi6DwsWaZ=S_1Q+hhrYA@mail.gmail.com>
 <CAKLTn3e5FVSU1FphbwcTOh-gONE9GhicAMdvL3aCRwOLH5ufvg@mail.gmail.com>
Message-ID: <CABPNLUrLt=0W6CWBN82iYVasABNu6tbH7X3yGKSX1NR0Em9hOQ@mail.gmail.com>

Hi Sarah,

If, as you say, the .mat files indeed contain data already
preprocessed with FieldTrip, then a simple "load <matfile>" should
work? (So using Matlab's own "load", rather than any FieldTrip reading
function.) If it doesn't work, then we'll need a bit more information
on what exactly is going wrong (error messages, exact script code,
etc.).

Best,
Eelke

On Fri, 1 May 2020 at 11:48, Sarah Kirchler <sarah.kirchler at gmail.com> wrote:
>
> Hi Eelke,
>
> thank you for your answer!
> I think you understood pretty much right, thank you also for the link to the website.
> The problem is, that I have data saved as .mat-files but already preprocessed with Fieldtrip.
> Now I want to use this data to do my SSVEP analysis, but if I try to load the .mat-file, I get error messages. I also get the error message, that the functions of the example script in Fieldtrip just work for ft_datatype_raw, that "contains sensor level time domain data typically obtained after calling ft_definetrial and ft_preprocessing." So it should work for my datastructure, but it doesn't. Maybe I make a bad mistake and should load the original vhdr-file and the mat-file together, I'm not sure, but in my comprehension all the data that I need should be in the preprocessed .mat-file.
> Please correct me if I do wrong, I'm a beginner willing to not give up!
>
> Thank you very much in advance,
>
> Sarah
>
> Am Do., 30. Apr. 2020 um 13:52 Uhr schrieb Eelke Spaak <e.spaak at donders.ru.nl>:
>>
>> Hi Sarah,
>>
>> If I'm not mistaken, your question is essentially: I already have data
>> in Matlab arrays, how can I make sure FieldTrip understands this? (So
>> the question is independent of SSVEP or any specific analysis
>> pipeline.) Have a look at
>> http://www.fieldtriptoolbox.org/faq/how_are_the_various_data_structures_defined/
>> and specifically ft_datatype_raw for pointers.
>>
>> Best,
>> Eelke
>>
>> On Thu, 30 Apr 2020 at 12:05, Sarah Kirchler <sarah.kirchler at gmail.com> wrote:
>> >
>> > Hi Fieldtrip!
>> >
>> > I have a question About analyzing SSVEPs.
>> > I don’t really know how to make a Connection from Fieldrtrip to my already preprocessed data. I have a Folder named „clean“, where I have saved the data rejected from artifacts.
>> >
>> > You offer only an example script „How to analyze SSVEPs with simulated data“, but I have real data and don’t know how to read it in.
>> >
>> > The function ft_read_data doesn’t support .mat-files, in which I saved my clean data.
>> >
>> > How can I create a dataset out of my clean data? Or how can I read in the clean data with the .mat-endings?
>> >
>> > Thanks for your answers!
>> > And excuse my incorrect english.
>> >
>> > Best,
>> >
>> > Sarah Kirchler
>> >
>> > _______________________________________________
>> > fieldtrip mailing list
>> > https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> > https://doi.org/10.1371/journal.pcbi.1002202
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202



From p.mccolgan at ucl.ac.uk  Fri May  1 14:22:02 2020
From: p.mccolgan at ucl.ac.uk (McColgan, Peter)
Date: Fri, 1 May 2020 12:22:02 +0000
Subject: [FieldTrip] Transforming freesurfer generated sourcemodel to CTF
 space
In-Reply-To: <AM0PR0102MB349297240DA1978312C77DC0C4AD0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
References: <AM0PR0102MB34928C5652C26EDDC20C149BC4AF0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>,
 <AM0PR0102MB3492BE9C72AD4BF8DA7ED92FC4AD0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>,
 <AM0PR0102MB349297240DA1978312C77DC0C4AD0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
Message-ID: <AM0PR0102MB349282D30EC48A4290647038C4AB0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>


Dear Experts,

I am creating a sourcemodel using the output from the ft_postfreesurfer.sh script using the following:

%% Create source model
datapath = fullfile(data_dir.folder,'/raw/','workbench');
filename = fullfile(datapath,'raw.L.midthickness.8k_fs_LR.surf.gii');
sourcemodel = ft_read_headshape({filename, strrep(filename, '.L.', '.R.')});

I then want to transform the sourcemodel into my the space the CTF space to align with my headmodel.

Could anyone advise on the best way to generate this transform?

Thanks in advance.

bw

Peter




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200501/0bd001c4/attachment.htm>

From e.spaak at donders.ru.nl  Fri May  1 16:36:08 2020
From: e.spaak at donders.ru.nl (Eelke Spaak)
Date: Fri, 1 May 2020 16:36:08 +0200
Subject: [FieldTrip] Issue with source grand averaging
In-Reply-To: <1022769010.1360694.1588158888853@mail.yahoo.com>
References: <1022769010.1360694.1588158888853.ref@mail.yahoo.com>
 <1022769010.1360694.1588158888853@mail.yahoo.com>
Message-ID: <CABPNLUpQRJYezoy8NEtSiekqmReSdKiO9pKfHmAAd73RW4R1eA@mail.gmail.com>

Dear Faizal,

I notice that you are creating a sourcemodel called 'grid' in your
code, but later on in the call to ft_prepare_leadfield you are not
using that sourcemodel, instead 'cfg.grid.pos = sourcemodel.pos;',
possibly using the (non-warped) template positions. This might cause
issues. I would try to make sure you are using the correct source
model/leadfield variables throughout the code, and see whether the
problem persists.

Best,
Eelke

On Wed, 29 Apr 2020 at 13:14, Mohd Faizal Mohd Zulkifly
<mfzl_mzly at yahoo.com> wrote:
>
> Dear all,
>
> I am doing source analysis based on subject-specific MRI and currently having an issue to do source grandaveraging. I tried to use different version of fieldtrips (i.e. Fieldtrip-20181122, Fieldtrip-20191127 and Fieltrip-20200109), and it still ended up with the same error: “Error using ft_sourcegrandaverage (line 116) the input sources vary in the field inside”. I also aware that this issue was discussed previously https://mailman.science.ru.nl/pipermail/fieldtrip/2015-October/022580.html. Unfortunately, I still facing the same error after specifying source.pos = template_grid.pos. It would be grateful if some of you can help and let me know my mistakes in the scripts below. It is a long script and I was thinking it might be helpful to provide a full script for others to help. Hope to hear from you guys soon. Thank you.
>
> ***********************************Forward model************************************************************
>
> subject_data= {'A’, ‘B’};
>
> subj={'A’, ‘B’};
>
> nsubj = numel(subject_data);
>
> % MRI Segmentation
>
> %   if do_mri_seg
>
> % read the *mgz files from FreeSurfer
>
> fprintf(['starting forward model for: ', subj{s},'\n '])
>
> mri = ft_read_mri([subject_mri, subj{s},'/','mri/','T1.mgz']);
>
> mri.coordsys = 'ctf';
>
> % interactively set fiducials to align MRI space to EEG space
>
> cfg = [];
>
> cfg.method = 'interactive';
>
> mri = ft_volumerealign(cfg, mri);
>
>
>
> cfg           = [];
>
> cfg.output    = {'brain','skull','scalp'};
>
> segmentedmri  = ft_volumesegment(cfg, mri);
>
> % save segmentedmri
>
>
>
> %%
>
> % Head mesh
>
>
>
> %if do_head_mesh
>
> addpath 'XXXXXX/fieldtrip-20181122/external/spm12'
>
> segmentedmri.dim = segmentedmri.dim;
>
> segmentedmri.coordsys = segmentedmri.coordsys;
>
> segmentedmri.unit = segmentedmri.unit;
>
> cfg = [];
>
> cfg.tissue = {'brain','skull','scalp'};
>
> cfg.method = 'projectmesh';
>
> cfg.numvertices = [3000 2000 1000];
>
> mri_bnd = [];
>
> mri_bnd.transform = segmentedmri.transform;
>
> mri_bnd.brain = segmentedmri.brain;
>
>
>
> braindil = imdilate(segmentedmri.brain, strel_bol(6));
>
> mri_bnd.skull = braindil > 0.5;
>
> mri_bnd.scalp = segmentedmri.scalp;
>
> mri_bnd.dim = segmentedmri.dim;
>
> mri_bnd.coordsys = segmentedmri.coordsys;
>
> mri_bnd.unit = segmentedmri.unit;
>
>
>
> src = ft_prepare_mesh(cfg, mri_bnd);
>
> % save src
>
> %%
>
> % COMPONENT 1: Headmodel
>
> addpath 'XXX/fieldtrip-20181122/external/dipoli'
>
> cfg = [];
>
> cfg.method = 'dipoli';
>
> hdm = ft_prepare_headmodel(cfg, src);
>
> % save hdm
>
> disp(hdm)
>
>
>
> %%
>
> % COMPONENT 2: Sensor adjustment           % getting electrodes in the right position
>
>
>
> %if do_sensor_alignment
>
> sens = ft_read_sens([XXX, subj{s}, '.sfp']);   % GEOSCAN
>
> sens = ft_convert_units(sens, 'mm');
>
>
>
> nas = mri.cfg.fiducial.nas;
>
> lpa = mri.cfg.fiducial.lpa;
>
> rpa = mri.cfg.fiducial.rpa;
>
>
>
> % warp NAS LPA and RPA
>
> nas = ft_warp_apply(mri.transform, nas, 'homogenous');
>
> lpa = ft_warp_apply(mri.transform, lpa, 'homogenous');
>
> rpa = ft_warp_apply(mri.transform, rpa, 'homogenous');
>
> fid = [];
>
> fid.elecpos       = [nas; lpa; rpa];       % ctf-coordinates of fiducials
>
> fid.chanpos       = [nas; lpa; rpa];       % ctf-coordinates of fiducials
>
> fid.label         = {char(sens.label(1)); ...
>
>                      char(sens.label(2)); ...
>
>                      char(sens.label(3))};    % same labels as in elec
>
>
>
> % alignment
>
> cfg               = [];
>
> cfg.method        = 'fiducial';
>
> cfg.target        = fid;                   % see above
>
> cfg.elec          = sens;
>
> cfg.fiducial      = {char(sens.label(1)); ...
>
>                      char(sens.label(2)); ...
>
>                      char(sens.label(3))};  % labels of fiducials in fid and in elec
>
> elec_aligned      = ft_electroderealign(cfg);
>
>
>
> cfg = [];
>
> cfg.method = 'project';
>
> cfg.elec = elec_aligned;
>
> cfg.headshape = src(3);
>
> elec_aligned = ft_electroderealign(cfg);
>
> % save elec_aligned
>
>
>
> %%
>
> %COMPONENT 3: Source model
>
> % % load a template grid
>
> % NOTE: the path to the template file is user-specific
>
> pathin ='XXX/matlab/toolbox/';
>
> load(fullfile(pathin, 'fieldtrip-20200109/template/sourcemodel/standard_sourcemodel3d5mm'));
>
> template = sourcemodel;
>
> clear sourcemodel;
>
>
>
> % create the subject specific grid, using the template grid that has just been created
>
> % inverse-warp the template grid to subject specific coordinates
>
> cfg = [];
>
> cfg.warpmni = 'yes';
>
> cfg.template = template;
>
> cfg.nonlinear = 'yes';
>
> cfg.mri =  mri; %mri - not working properly/ showing scalp
>
> cfg.unit = 'mm';
>
> grid        = ft_prepare_sourcemodel(cfg);
>
> %save grid
>
>
>
> %%
>
> % COMPONENT 4: Leadfield
>
> fname_preproc_data = fullfile(XXX,subject_data{s}]);
>
> preproc_data = load(fname_preproc_data);
>
> EEG_name = cell2mat(fieldnames(preproc_data));
>
>
>
> %
>
> cfg                     = [];
>
> cfg.elec                = elec_aligned;
>
> cfg.channel             = preproc_data.conv_data_rpost.label;                 % ensure that rejected electrodes are not present
>
> cfg.headmodel           = hdm;
>
> cfg.grid.pos            = sourcemodel.pos;
>
> cfg.normalize           = 'no';                %normalize 'yes' it when don't have a contrast to avaoid activity at the center (NAI tutorial)
>
> cfg.normalizeparam      = 0.5;
>
> cfg.grid.unit           = 'mm';
>
> leadfield               = ft_prepare_leadfield(cfg);
>
> %save leadfield
>
>
>
>  % the data consists of fewer channels than the precomputed
>
>     % leadfields, the following chunk of code takes care of this
>
> [a,b] = match_str(preproc_data.conv_data_rpost.label, leadfield.label);
>
> for k = 1:numel(leadfield.leadfield)
>
>     if ~isempty(leadfield.leadfield{k})
>
>         tmp = leadfield.leadfield{k};
>
>         tmp = tmp(b,:);
>
>         tmp = tmp-repmat(mean(tmp,1),[size(tmp,1) 1]); % average re-ref
>
>         leadfield.leadfield{k} = tmp;
>
>     end
>
> end
>
> leadfield.label = leadfield.label(b);
>
> %save leadfield
>
>
>
> *****************************************************source_analysis**************************************
>
>
>
> subject_rpost_data= {‘A’, ‘B’};
>
>
>
> subj={‘A’, ‘B’ };
>
>
>
> nsubj = numel(subj);
>
>
>
>
>
>     % Loop over subjects
>
>
>
>     for s=1:nsubj
>
>     fprintf(['starting source analysis for: ', subj{s},'\n '])
>
>
>
>
>
>     load(fname_preproc_data);
>
>     load(fname_sourcemodel);
>
>     load(fname_leadfield);
>
>     load(fname_headmodel);
>
>     load(fname_elec);
>
>
>
>     mri = ft_read_mri(fname_seg_mri);
>
>     mri.coordsys = 'ctf';
>
>
>
>     load(fname_smri )
>
>     % transform original mri to segemented mri transformation info
>
>     trns = segmentedmri.transform / mri.transform;
>
>     clear segmentedmri
>
>     % reslice mri
>
>     mri.coordsys = 'ctf';
>
>     mri = ft_volumereslice([], mri);
>
>     % transform mri to coordinates of leadfield
>
>     mri = ft_transform_geometry(trns, mri);
>
>
>
>
>
>     % Bring data as in time domain
>
>     % Cut Trial data in baseline and evoked time segments
>
>     cfg = [];
>
>     cfg.latency = [-1.0 0]; % baseline        % choose baseline as i did with sensor analysis (100ms)
>
>     datbasl = ft_selectdata(cfg, preproc_data.(EEG_name));
>
>     cfg = [];
>
>     cfg.latency = [0 3]; % evoked activity
>
>     datact = ft_selectdata(cfg,preproc_data.(EEG_name));
>
>     cfg = [];
>
>     cfg.latency = [-1 3];
>
>     datall = ft_selectdata(cfg,preproc_data.(EEG_name));
>
>
>
> %%
>
>     % Compute covariance matrix
>
>
>
>     cfg            = [];
>
>     cfg.covariance = 'yes';
>
>     cfg.keeptrials = 'no'; % 'no' creates averaged trial
>
>     cfg.removemean = 'yes';
>
>     cfg.channel = {'all', '-E257'};
>
>
>
>     datbasl_avg = ft_timelockanalysis(cfg, datbasl); %Baseline data (in time domain)
>
>     datact_avg  = ft_timelockanalysis(cfg, datact);  %Activity data
>
>     datall_avg  = ft_timelockanalysis(cfg, datall);  %Data with baseline and activity
>
>
>
>
>
>     %% Source analysis
>
>     %
>
>     % adapt leadfield channels to channel of current eeg data (199 instead
>
>     % of 256)
>
>     [~,b] = match_str(datbasl_avg.label, leadfield.label);
>
>     for k = 1:numel(leadfield.leadfield)
>
>         if ~isempty(leadfield.leadfield{k})
>
>             tmp = leadfield.leadfield{k};
>
>             tmp = tmp(b,:);
>
>             tmp = tmp-repmat(mean(tmp,1),[size(tmp,1) 1]); % average re-ref
>
>             leadfield.leadfield{k} = tmp;
>
>         end
>
>     end
>
>     leadfield.label = leadfield.label(b);
>
>
>
>
>
>     %   Compute common spatial filter
>
>     cfg                   = [];
>
>     cfg.channel           = datall_avg.label;
>
>     cfg.elec              = elec_aligned.elec_aligned;
>
>     cfg.method            = 'lcmv';
>
> %     cfg.grid            = leadfield;
>
>     cfg.headmodel         = headmodel.hdm;
>
>     cfg.sourcemodel.grid.pos   = leadfield.pos; % bei FT wird hier der output von ft_leadfield angegeben
>
>     cfg.grid.resolution   = 5;
>
>     cfg.lcmv.keepfilter   = 'yes';
>
>     cfg.lcmv.fixedori     = 'yes';
>
>     cfg.lcmv.projectnoise = 'yes';
>
>     cfg.lcmv.weightnorm = 'nai';
>
>     cfg.lcmv.lambda       = '5%';
>
>
>
>     eegsrc_all = ft_sourceanalysis(cfg, datall_avg);     %source data in all time window
>
>
>
>     % apply common filters to pre and post stimulus data
>
>     cfg.grid.filter       = eegsrc_all.avg.filter;
>
>
>
>     % Compute source for baseline and activty time window
>
>     eegsrc_basl = ft_sourceanalysis(cfg, datbasl_avg);   %source data for baseline time window
>
>     eegsrc_act  = ft_sourceanalysis(cfg, datact_avg);    %source data for activity time window
>
>
>
>
>
>     % contrast post stimulus onset activity with respect to baseline
>
>     eegsrc_act_basnrm = eegsrc_act;
>
>     eegsrc_act_basnrm.avg.pow = (eegsrc_act.avg.pow - eegsrc_basl.avg.pow)./ eegsrc_basl.avg.pow;
>
>
>
>
>
>     %% Choose time of interest
>
>
>
>    % average across time the dipole moments within the N1 latency range
>
>     ind    = find(eegsrc_act_basnrm.time>=0.1 & eegsrc_act_basnrm.time<=0.5); %at 18ms-24ms
>
>     timecourse = eegsrc_act_basnrm.avg.mom(eegsrc_act_basnrm.inside);
>
>     tc_toi    = zeros(size(eegsrc_act_basnrm.avg.pow(eegsrc_act_basnrm.inside)));
>
>
>
>     for ii = 1:length(timecourse)
>
>         tc_toi(ii) = mean(abs(timecourse{ii}(ind)));
>
>     end
>
>
>
>     source = eegsrc_act_basnrm;
>
>     source.avg.pow(eegsrc_act_basnrm.inside) = tc_toi;
>
> %     source.cfg = rmfield(source.cfg, {'headmodel' 'callinfo'}); % this is removed because it takes up a lot of memory
>
>
>
>     % Save source
>
>
>
>     % interpolate and normalize to individual mri
>
>     %first, interpolate
>
>     cfg           = [];
>
>     cfg.parameter = 'pow';
>
>     eeg_source_interp  = ft_sourceinterpolate(cfg, source, mri);
>
>
>
>
>
>     % second, normalise
>
>     cfg = [];
>
>     cfg.nonlinear     = 'no';
>
>     eeg_source_interp_norm = ft_volumenormalise(cfg, eeg_source_interp);
>
>
>
>     % save the interpolate and normalised data
>
>
>
> %%
>
>       % load source reconstructed data
>
> %     keep subjects path_data nsubj path_ft
>
>
>
>     allsource_rpost = cell(1,nsubj);
>
>     for s = 1:nsubj
>
>         datapath = strcat(fname_eeg_source_interp_norm);
>
> %         datafile = fullfile(datapath, [subj{s}, '_source.mat']);    % take _source data?
>
>         datafile = fullfile(datapath, [subj{s}, '_eeg_source_interp_norm.mat']);
>
>         load(datafile)
>
>
>
>         allsource_rpost{s}     = eeg_source_interp_norm;
>
> %         allsource_rpost{s}     = source;
>
>     end
>
>
>
>
>
>     % grand average
>
>     cfg             = [];
>
>     cfg.parameter   = 'pow';
>
> %     cfg.keepindividual='yes';
>
>     gasource_rpost  = ft_sourcegrandaverage(cfg, allsource_rpost{:});
>
>     %save gasource_rpost
>
>
>
>
>
>
>
>
>
> With best wishes,
>
> Faizal Zulkifly
>
>
>
> --------------------------------------------------------
>
> Mohd Faizal Mohd Zulkifly
>
> University Medical Center Göttingen
>
> University of Göttingen
>
> Clinic for Clinical Neurophysiology
>
> Robert-Koch-Straße 40
>
> 37075 Göttingen
>
> Germany
>
> Tel: +49 551 39-8457
>
>
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202



From e.spaak at donders.ru.nl  Fri May  1 16:42:09 2020
From: e.spaak at donders.ru.nl (Eelke Spaak)
Date: Fri, 1 May 2020 16:42:09 +0200
Subject: [FieldTrip] only NaNs in ft_freqgrandaverage output
In-Reply-To: <CABXoQMe_T5cz4ngdV8XtAC_Fnvso7XOZXmoqqJwge3KAqMp86w@mail.gmail.com>
References: <CABXoQMe_T5cz4ngdV8XtAC_Fnvso7XOZXmoqqJwge3KAqMp86w@mail.gmail.com>
Message-ID: <CABPNLUocOiC4UAxJuGHQLKqDCWssiuy0AxbEozdp5Rr1GjavMA@mail.gmail.com>

Dear Gina,

Have you checked whether the sinlge-subject TFRs (i.e. the output of
ft_freqanalysis) contain NaNs? (Pay special attention to the baseline
period; since you are later applying ft_freqbaseline, any NaNs in the
baseline would propagate through to the entire time axis after
baseline correction.)

The following might be relevant, if the single-subject TFRs indeed
contain NaNs: http://www.fieldtriptoolbox.org/faq/why_does_my_tfr_contain_nans/

Best,
Eelke

On Sun, 26 Apr 2020 at 21:41, Gina Brazof <gina.brazof at gmail.com> wrote:
>
> Dear Community,
>
> I preprocessed my EEG data in EEGlab and now I would like to run a time frequency analysis using FielTrip. I start by saying that I am new with the time frequency analysis, matlab and fieldtrip, so I say sorry in advance for my ignorance.
> For each of my experiment conditions (experimental design 2*2 within-subjects), I tried to run a wavelet tranformation and a grandavarage across all subjects. However, the values of the gandAverage powspctrm in two out of four conditions are only NaNs and I can not figure out why that is happening. Indeed, the code has been structurally the same for all conditions. In addition, the object of the ft_ freqgrandaverage in these two problematic conditions do not contain the reasonable amount of NaNs to justify the values in the gandaverage. Could someone help me to undertand where the problem could be?
> Below the example of code I used for each condition:
>
> %%%%% oggPain COONDITION 1
>
> TFreqAv_oggPain = cell(1,nSubjs);
> for i = 1:nSubjs
>
>     subs     = subjects{i};
>     fileName = '_data.mat';
>     dataSet  = strcat('C:\Users\bia\Desktop\dati carlotta\', subs, fileName);
>     %dataSet = fullfile(dataPath,subjects{i},fileName);
>     load(dataSet); % loading the variable 'data'
>
>     %%%%%%%%% Computing time-frequency representation for each trial
>     cfg = [];
>     cfg.method = 'wavelet';
>     cfg.foi    = 4:1:30;
>     cfg.toi    = -0.8:0.01:1.5;
>     cfg.width  = 7;
>    %cfg.keeptrials = 'yes';
>     cfg.channel    = 'all';
>     cfg.trials     = find(celltomat(data.trialinfo(:,1)) == 7 | celltomat(data.trialinfo(:,1)) == 8 | celltomat(data.trialinfo(:,1)) == 11 | celltomat(data.trialinfo(:,1)) == 12);  %numbers differ according to exp. condition
>     cfg.outputfile = strcat('C:\Users\bia\Desktop\dati carlotta\', subs,'_oggPain');
>     TFreqAv_oggPain{i}= ft_freqanalysis(cfg,data);
>     clear data
> end
> save TFreqAv_oggPain.mat TFreqAv_oggPain
>
> bslnTFreqAv_oggPain = cell(1,nSubjs);
> for i = 1:nSubjs
>
>     subs     = subjects{i};
>     fileName = '_oggPain.mat';
>     dataSet  = strcat('C:\Users\bia\Desktop\dati carlotta\', subs, fileName);
>     load(dataSet); % loading the variable 'freq'
>
>     %%%%%%%%% Computing the change relative to a baseline
>     cfg = [];
>     cfg.baselinetype = 'relchange';
>     cfg.baseline     = [-0.05 -0.02];
>     bslnTFreqAv_oggPain{i} = ft_freqbaseline(cfg,freq);
>     clear freq
> end
> save bslnTFreqAv_oggPain.mat bslnTFreqAv_oggPain
>
> %% Grand average time-frequency data
> cfg = [];
> gAvgTFreq_oggPain     = ft_freqgrandaverage(cfg,TFreqAv_oggPain{:});
> save gAvgTFreq_oggPain.mat gAvgTFreq_oggPain
> gAvgBslnTFreq_oggPain = ft_freqgrandaverage(cfg,bslnTFreqAv_oggPain{:});
> save gAvgBslnTFreq_oggPain.mat gAvgBslnTFreq_oggPain
>
> Thank for any kind of tips,
>
> Gina
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202



From e.spaak at donders.ru.nl  Fri May  1 16:50:42 2020
From: e.spaak at donders.ru.nl (Eelke Spaak)
Date: Fri, 1 May 2020 16:50:42 +0200
Subject: [FieldTrip] 3 x 2 Mixed ANOVA or MANOVA?
In-Reply-To: <CABqnCmCV2221Pbv3_c-3Pi=dNTXy5LhH_kbJAuVkg2Pa7wQT8Q@mail.gmail.com>
References: <CABqnCmCV2221Pbv3_c-3Pi=dNTXy5LhH_kbJAuVkg2Pa7wQT8Q@mail.gmail.com>
Message-ID: <CABPNLUrRaYtZz6jnL1k4=M5C4cW5omoC2i0Cib=Gpds6NOO2Fw@mail.gmail.com>

Dear Paul,

> I just was hoping to confirm with the community if this would be the correct approach in my case?

It's at least what I would do, yes.

> Or would I need to implement a MANOVA in my case (as seems to be implied here: http://www.fieldtriptoolbox.org/faq/how_can_i_test_an_interaction_effect_using_cluster-based_permutation_tests/

I think the approach you're sketching follows from what is described
in the linked FAQ.

Best,
Eelke

>
> Best,
> Paul
>
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202


From jan.schoffelen at donders.ru.nl  Sat May  2 13:51:19 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sat, 2 May 2020 11:51:19 +0000
Subject: [FieldTrip] Problems with ft_Channelrepair / interpolation
In-Reply-To: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>
References: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>
Message-ID: <72CCE675-2DB9-4BDA-862A-150DD1A41369@donders.ru.nl>

Hi Kinkini,

I would recommend not doing a CAR before you have removed bad channels.
Also, I would recommend not tu ‘repair’ any bad channels prior to running ICA.
Best wishes,
Jan-Mathijs


On 1 May 2020, at 13:33, Kinkini . <bkinkini at gmail.com<mailto:bkinkini at gmail.com>> wrote:

Dear FieldTripers,

Hope everyone is coping well with the current situation.

I am relatively new in fieldtrip and I have been long stuck with using ft_channelrepair for quite sometime now.

Briefly about my analysis pipeline:
1- Loading and epoching the data
2- ft_preprocessing - filtering, baselining, CAR
3- ft_databrowser - marking bad channels
4. ft_rejectvisual - rejecting bad channels; keepchannel = 'repair'
5. ft_channelrepair
6. ICA
7. TF Analysis
8. TF statististics

I have problems pertaining to step 4 and 5. In step 4 I want to keep the bad channels so that I can interpolate them in the next step. When I use data browser to look thorough the data, the bad channels look okay. But the problem starts when I perform ICA on them. My first observation is that the wchange value is very big (looks like this : 257868.69202720), but ICA runs completely. However the ICA component topoplots look weird (screenshots attached). However, when I look through the icabrowser plots , there are peaks at physiological frequencies.

In order to avoid this, I tried getting rid of the bad channels completely using ft_rejectvisual, perform ICA and then get back the missing channels using neighbourhood average. Doing this, I was able to perform TF analysis, but when I wanted to apply statistics on the data, I had errors. Finally, I had to avoid the entire step of  interpolation to be able to run everything and also perform statistics. But in a long run, I cannot avoid this step.

I am finding no clue as to where is it going wrong.

Hence, any idea, any clue from you all would help me very much. I am happy to provide with more details if necessary.
Thank you so much for your response.

Best regards,

Kinkini Bhadra
PhD student
Department of Fundamental Neurosciences
University of Geneva


<Screenshot 2020-05-01 11.57.28.png><Screenshot 2020-05-01 11.57.42.png>_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/2b2f874c/attachment.htm>

From jan.schoffelen at donders.ru.nl  Sat May  2 13:52:45 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sat, 2 May 2020 11:52:45 +0000
Subject: [FieldTrip] Transforming freesurfer generated sourcemodel to
 CTF space
In-Reply-To: <AM0PR0102MB349282D30EC48A4290647038C4AB0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
References: <AM0PR0102MB34928C5652C26EDDC20C149BC4AF0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
 <AM0PR0102MB3492BE9C72AD4BF8DA7ED92FC4AD0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
 <AM0PR0102MB349297240DA1978312C77DC0C4AD0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
 <AM0PR0102MB349282D30EC48A4290647038C4AB0@AM0PR0102MB3492.eurprd01.prod.exchangelabs.com>
Message-ID: <D3DF0D23-4619-41E5-A02B-5ECB40207284@donders.ru.nl>

Hi Peter,
Information about this transformation is present in the respective tutorial.
Best wishes,
Jan-Mathijs


On 1 May 2020, at 14:22, McColgan, Peter <p.mccolgan at ucl.ac.uk<mailto:p.mccolgan at ucl.ac.uk>> wrote:


Dear Experts,

I am creating a sourcemodel using the output from the ft_postfreesurfer.sh script using the following:

%% Create source model
datapath = fullfile(data_dir.folder,'/raw/','workbench');
filename = fullfile(datapath,'raw.L.midthickness.8k_fs_LR.surf.gii');
sourcemodel = ft_read_headshape({filename, strrep(filename, '.L.', '.R.')});

I then want to transform the sourcemodel into my the space the CTF space to align with my headmodel.

Could anyone advise on the best way to generate this transform?

Thanks in advance.

bw

Peter




_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/e17fdb6c/attachment.htm>

From jan.schoffelen at donders.ru.nl  Sat May  2 13:54:05 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sat, 2 May 2020 11:54:05 +0000
Subject: [FieldTrip] Fwd:  mexmaci64 cannot be opened
References: <73CBB6C8-73C4-40CF-B285-B8BB7FB8E05F@gmail.com>
Message-ID: <0A5D04E4-C4C1-4ADA-96A1-92D88AE931CC@donders.ru.nl>


Hi Carlijn

You may want to try and compile the mex files from scratch for your OS and Matlab version. There is some more documentation on the website about the compilation of mex-files (e.g. search for ft_compile_mex, or more generally for mex).

Best wishes,
Jan-Mathijs


On 24 Apr 2020, at 14:39, Boomen, C. van den (Carlijn) <C.vandenBoomen at uu.nl<mailto:C.vandenBoomen at uu.nl>> wrote:

Hi all,

I've a new version of MacOS and fieldtrip functions don't seem to work anymore. I get the error that mexmaci64 files cannot be opened. I've looked at the link below, and followed the instructions. However, this only seems to work for running ft_default, but I keep receiving the error for other functions (e.g. ft_preprocessing). Does anyone know what the problem might be, or have an idea for a solution?

http://www.fieldtriptoolbox.org/faq/mexmaci64_cannot_be_opened_because_the_developer_cannot_be_verified/

Thank you!
Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/a7f490fb/attachment.htm>

From mfzl_mzly at yahoo.com  Sat May  2 14:51:41 2020
From: mfzl_mzly at yahoo.com (Mohd Faizal Mohd Zulkifly)
Date: Sat, 2 May 2020 12:51:41 +0000 (UTC)
Subject: [FieldTrip] Issue with source grand averaging
In-Reply-To: <CABPNLUpQRJYezoy8NEtSiekqmReSdKiO9pKfHmAAd73RW4R1eA@mail.gmail.com>
References: <1022769010.1360694.1588158888853.ref@mail.yahoo.com>
 <1022769010.1360694.1588158888853@mail.yahoo.com>
 <CABPNLUpQRJYezoy8NEtSiekqmReSdKiO9pKfHmAAd73RW4R1eA@mail.gmail.com>
Message-ID: <1113393333.172610.1588423901388@mail.yahoo.com>

 Dear Eelke,
Thank you for your reply and yes you are right. Now I solved source grandaveraging issue if I include a line "source.pos= sourcemodel.grid.pos" after doing source analysis (https://mailman.science.ru.nl/pipermail/fieldtrip/2015-October/022580.html. ). I have some more questions which you might help:1) I tried to understand why do we need to include source.pos=sourcemodel.grid.pos after ft_sourceanalysis. If I excluded this line ft_sourcegrandaveraging throws an error (“Error using ft_sourcegrandaverage (line 116) the input sources vary in the field inside”) ?
2) When should I do ft_sourceinterpolation and ft_volumenormalise? Should it be on the individual subject or on the source grandaverage (average subject)? It seems that after including "source.pos= sourcemodel.grid.pos" and do  ft_sourceinterpolation and ft_volumenormalise on individual subject, no source activation anymore after ft_sourceplot of source grandaverage data. However, if I do not include the "source.pos= sourcemodel.grid.pos" , then interpolate and volume normalize individual subject, there was source activation. I am not sure this problem was due to"source.pos= sourcemodel.grid.pos" or the way I did ft_interpolation and ft_volumenormalise. Hope you can suggest something.  Here is the script:************************************************************ 
    cfg                   = [];    cfg.channel           = datall_avg.label;    cfg.elec              = elec_aligned.elec_aligned;    cfg.method            = 'lcmv';    cfg.headmodel         = headmodel.hdm;    cfg.sourcemodel.grid   = leadfield;     cfg.grid.resolution   = 5;    cfg.lcmv.keepfilter   = 'yes';    cfg.lcmv.fixedori     = 'yes';    cfg.lcmv.projectnoise = 'yes';    cfg.lcmv.weightnorm = 'nai';    cfg.lcmv.lambda       = '5%';        eegsrc_all = ft_sourceanalysis(cfg, datall_avg);     %source data in all time window
    % apply common filters to pre and post stimulus data    cfg.grid.filter       = eegsrc_all.avg.filter;        % Compute source for baseline and activty time window    eegsrc_basl = ft_sourceanalysis(cfg, datbasl_avg);   %source data for baseline time window    eegsrc_act  = ft_sourceanalysis(cfg, datact_avg);    %source data for activity time window                                                                                                 % contrast post stimulus onset activity with respect to baseline    eegsrc_act_basnrm = eegsrc_act;    eegsrc_act_basnrm.avg.pow = (eegsrc_act.avg.pow - eegsrc_basl.avg.pow)./ eegsrc_basl.avg.pow;
    %% Choose time of interest      % average across time the dipole moments within the N20 latency range    ind    = find(eegsrc_act_basnrm.time>=0.016 & eegsrc_act_basnrm.time<=0.024); %at 16ms-24ms    timecourse = eegsrc_act_basnrm.avg.mom(eegsrc_act_basnrm.inside);    tc_toi    = zeros(size(eegsrc_act_basnrm.avg.pow(eegsrc_act_basnrm.inside)));        for ii = 1:length(timecourse)        tc_toi(ii) = mean(abs(timecourse{ii}(ind)));    end       source = eegsrc_act_basnrm;    source.avg.pow(eegsrc_act_basnrm.inside) = tc_toi;

    source.pos = sourcemodel.grid.pos   %%  <<<I Include here??
 % interpolate and normalize to individual mri    %first, interpolate        cfg           = [];    cfg.parameter = 'pow';    eeg_source_interp  = ft_sourceinterpolate(cfg, source, mri);  %%< interpolate on individual     source??
    % second, normalise    cfg = [];    cfg.nonlinear     = 'no';    eeg_source_interp_norm = ft_volumenormalise(cfg, eeg_source_interp);

Thank you.Faizal















    On Friday, 1 May 2020, 04:43:20 pm GMT+2, Eelke Spaak <e.spaak at donders.ru.nl> wrote:  
 
 Dear Faizal,

I notice that you are creating a sourcemodel called 'grid' in your
code, but later on in the call to ft_prepare_leadfield you are not
using that sourcemodel, instead 'cfg.grid.pos = sourcemodel.pos;',
possibly using the (non-warped) template positions. This might cause
issues. I would try to make sure you are using the correct source
model/leadfield variables throughout the code, and see whether the
problem persists.

Best,
Eelke

On Wed, 29 Apr 2020 at 13:14, Mohd Faizal Mohd Zulkifly
<mfzl_mzly at yahoo.com> wrote:
>
> Dear all,
>
> I am doing source analysis based on subject-specific MRI and currently having an issue to do source grandaveraging. I tried to use different version of fieldtrips (i.e. Fieldtrip-20181122, Fieldtrip-20191127 and Fieltrip-20200109), and it still ended up with the same error: “Error using ft_sourcegrandaverage (line 116) the input sources vary in the field inside”. I also aware that this issue was discussed previously https://mailman.science.ru.nl/pipermail/fieldtrip/2015-October/022580.html. Unfortunately, I still facing the same error after specifying source.pos = template_grid.pos. It would be grateful if some of you can help and let me know my mistakes in the scripts below. It is a long script and I was thinking it might be helpful to provide a full script for others to help. Hope to hear from you guys soon. Thank you.
>
> ***********************************Forward model************************************************************
>
> subject_data= {'A’, ‘B’};
>
> subj={'A’, ‘B’};
>
> nsubj = numel(subject_data);
>
> % MRI Segmentation
>
> %  if do_mri_seg
>
> % read the *mgz files from FreeSurfer
>
> fprintf(['starting forward model for: ', subj{s},'\n '])
>
> mri = ft_read_mri([subject_mri, subj{s},'/','mri/','T1.mgz']);
>
> mri.coordsys = 'ctf';
>
> % interactively set fiducials to align MRI space to EEG space
>
> cfg = [];
>
> cfg.method = 'interactive';
>
> mri = ft_volumerealign(cfg, mri);
>
>
>
> cfg          = [];
>
> cfg.output    = {'brain','skull','scalp'};
>
> segmentedmri  = ft_volumesegment(cfg, mri);
>
> % save segmentedmri
>
>
>
> %%
>
> % Head mesh
>
>
>
> %if do_head_mesh
>
> addpath 'XXXXXX/fieldtrip-20181122/external/spm12'
>
> segmentedmri.dim = segmentedmri.dim;
>
> segmentedmri.coordsys = segmentedmri.coordsys;
>
> segmentedmri.unit = segmentedmri.unit;
>
> cfg = [];
>
> cfg.tissue = {'brain','skull','scalp'};
>
> cfg.method = 'projectmesh';
>
> cfg.numvertices = [3000 2000 1000];
>
> mri_bnd = [];
>
> mri_bnd.transform = segmentedmri.transform;
>
> mri_bnd.brain = segmentedmri.brain;
>
>
>
> braindil = imdilate(segmentedmri.brain, strel_bol(6));
>
> mri_bnd.skull = braindil > 0.5;
>
> mri_bnd.scalp = segmentedmri.scalp;
>
> mri_bnd.dim = segmentedmri.dim;
>
> mri_bnd.coordsys = segmentedmri.coordsys;
>
> mri_bnd.unit = segmentedmri.unit;
>
>
>
> src = ft_prepare_mesh(cfg, mri_bnd);
>
> % save src
>
> %%
>
> % COMPONENT 1: Headmodel
>
> addpath 'XXX/fieldtrip-20181122/external/dipoli'
>
> cfg = [];
>
> cfg.method = 'dipoli';
>
> hdm = ft_prepare_headmodel(cfg, src);
>
> % save hdm
>
> disp(hdm)
>
>
>
> %%
>
> % COMPONENT 2: Sensor adjustment          % getting electrodes in the right position
>
>
>
> %if do_sensor_alignment
>
> sens = ft_read_sens([XXX, subj{s}, '.sfp']);  % GEOSCAN
>
> sens = ft_convert_units(sens, 'mm');
>
>
>
> nas = mri.cfg.fiducial.nas;
>
> lpa = mri.cfg.fiducial.lpa;
>
> rpa = mri.cfg.fiducial.rpa;
>
>
>
> % warp NAS LPA and RPA
>
> nas = ft_warp_apply(mri.transform, nas, 'homogenous');
>
> lpa = ft_warp_apply(mri.transform, lpa, 'homogenous');
>
> rpa = ft_warp_apply(mri.transform, rpa, 'homogenous');
>
> fid = [];
>
> fid.elecpos      = [nas; lpa; rpa];      % ctf-coordinates of fiducials
>
> fid.chanpos      = [nas; lpa; rpa];      % ctf-coordinates of fiducials
>
> fid.label        = {char(sens.label(1)); ...
>
>                      char(sens.label(2)); ...
>
>                      char(sens.label(3))};    % same labels as in elec
>
>
>
> % alignment
>
> cfg              = [];
>
> cfg.method        = 'fiducial';
>
> cfg.target        = fid;                  % see above
>
> cfg.elec          = sens;
>
> cfg.fiducial      = {char(sens.label(1)); ...
>
>                      char(sens.label(2)); ...
>
>                      char(sens.label(3))};  % labels of fiducials in fid and in elec
>
> elec_aligned      = ft_electroderealign(cfg);
>
>
>
> cfg = [];
>
> cfg.method = 'project';
>
> cfg.elec = elec_aligned;
>
> cfg.headshape = src(3);
>
> elec_aligned = ft_electroderealign(cfg);
>
> % save elec_aligned
>
>
>
> %%
>
> %COMPONENT 3: Source model
>
> % % load a template grid
>
> % NOTE: the path to the template file is user-specific
>
> pathin ='XXX/matlab/toolbox/';
>
> load(fullfile(pathin, 'fieldtrip-20200109/template/sourcemodel/standard_sourcemodel3d5mm'));
>
> template = sourcemodel;
>
> clear sourcemodel;
>
>
>
> % create the subject specific grid, using the template grid that has just been created
>
> % inverse-warp the template grid to subject specific coordinates
>
> cfg = [];
>
> cfg.warpmni = 'yes';
>
> cfg.template = template;
>
> cfg.nonlinear = 'yes';
>
> cfg.mri =  mri; %mri - not working properly/ showing scalp
>
> cfg.unit = 'mm';
>
> grid        = ft_prepare_sourcemodel(cfg);
>
> %save grid
>
>
>
> %%
>
> % COMPONENT 4: Leadfield
>
> fname_preproc_data = fullfile(XXX,subject_data{s}]);
>
> preproc_data = load(fname_preproc_data);
>
> EEG_name = cell2mat(fieldnames(preproc_data));
>
>
>
> %
>
> cfg                    = [];
>
> cfg.elec                = elec_aligned;
>
> cfg.channel            = preproc_data.conv_data_rpost.label;                % ensure that rejected electrodes are not present
>
> cfg.headmodel          = hdm;
>
> cfg.grid.pos            = sourcemodel.pos;
>
> cfg.normalize          = 'no';                %normalize 'yes' it when don't have a contrast to avaoid activity at the center (NAI tutorial)
>
> cfg.normalizeparam      = 0.5;
>
> cfg.grid.unit          = 'mm';
>
> leadfield              = ft_prepare_leadfield(cfg);
>
> %save leadfield
>
>
>
>  % the data consists of fewer channels than the precomputed
>
>    % leadfields, the following chunk of code takes care of this
>
> [a,b] = match_str(preproc_data.conv_data_rpost.label, leadfield.label);
>
> for k = 1:numel(leadfield.leadfield)
>
>    if ~isempty(leadfield.leadfield{k})
>
>        tmp = leadfield.leadfield{k};
>
>        tmp = tmp(b,:);
>
>        tmp = tmp-repmat(mean(tmp,1),[size(tmp,1) 1]); % average re-ref
>
>        leadfield.leadfield{k} = tmp;
>
>    end
>
> end
>
> leadfield.label = leadfield.label(b);
>
> %save leadfield
>
>
>
> *****************************************************source_analysis**************************************
>
>
>
> subject_rpost_data= {‘A’, ‘B’};
>
>
>
> subj={‘A’, ‘B’ };
>
>
>
> nsubj = numel(subj);
>
>
>
>
>
>    % Loop over subjects
>
>
>
>    for s=1:nsubj
>
>    fprintf(['starting source analysis for: ', subj{s},'\n '])
>
>
>
>
>
>    load(fname_preproc_data);
>
>    load(fname_sourcemodel);
>
>    load(fname_leadfield);
>
>    load(fname_headmodel);
>
>    load(fname_elec);
>
>
>
>    mri = ft_read_mri(fname_seg_mri);
>
>    mri.coordsys = 'ctf';
>
>
>
>    load(fname_smri )
>
>    % transform original mri to segemented mri transformation info
>
>    trns = segmentedmri.transform / mri.transform;
>
>    clear segmentedmri
>
>    % reslice mri
>
>    mri.coordsys = 'ctf';
>
>    mri = ft_volumereslice([], mri);
>
>    % transform mri to coordinates of leadfield
>
>    mri = ft_transform_geometry(trns, mri);
>
>
>
>
>
>    % Bring data as in time domain
>
>    % Cut Trial data in baseline and evoked time segments
>
>    cfg = [];
>
>    cfg.latency = [-1.0 0]; % baseline        % choose baseline as i did with sensor analysis (100ms)
>
>    datbasl = ft_selectdata(cfg, preproc_data.(EEG_name));
>
>    cfg = [];
>
>    cfg.latency = [0 3]; % evoked activity
>
>    datact = ft_selectdata(cfg,preproc_data.(EEG_name));
>
>    cfg = [];
>
>    cfg.latency = [-1 3];
>
>    datall = ft_selectdata(cfg,preproc_data.(EEG_name));
>
>
>
> %%
>
>    % Compute covariance matrix
>
>
>
>    cfg            = [];
>
>    cfg.covariance = 'yes';
>
>    cfg.keeptrials = 'no'; % 'no' creates averaged trial
>
>    cfg.removemean = 'yes';
>
>    cfg.channel = {'all', '-E257'};
>
>
>
>    datbasl_avg = ft_timelockanalysis(cfg, datbasl); %Baseline data (in time domain)
>
>    datact_avg  = ft_timelockanalysis(cfg, datact);  %Activity data
>
>    datall_avg  = ft_timelockanalysis(cfg, datall);  %Data with baseline and activity
>
>
>
>
>
>    %% Source analysis
>
>    %
>
>    % adapt leadfield channels to channel of current eeg data (199 instead
>
>    % of 256)
>
>    [~,b] = match_str(datbasl_avg.label, leadfield.label);
>
>    for k = 1:numel(leadfield.leadfield)
>
>        if ~isempty(leadfield.leadfield{k})
>
>            tmp = leadfield.leadfield{k};
>
>            tmp = tmp(b,:);
>
>            tmp = tmp-repmat(mean(tmp,1),[size(tmp,1) 1]); % average re-ref
>
>            leadfield.leadfield{k} = tmp;
>
>        end
>
>    end
>
>    leadfield.label = leadfield.label(b);
>
>
>
>
>
>    %  Compute common spatial filter
>
>    cfg                  = [];
>
>    cfg.channel          = datall_avg.label;
>
>    cfg.elec              = elec_aligned.elec_aligned;
>
>    cfg.method            = 'lcmv';
>
> %    cfg.grid            = leadfield;
>
>    cfg.headmodel        = headmodel.hdm;
>
>    cfg.sourcemodel.grid.pos  = leadfield.pos; % bei FT wird hier der output von ft_leadfield angegeben
>
>    cfg.grid.resolution  = 5;
>
>    cfg.lcmv.keepfilter  = 'yes';
>
>    cfg.lcmv.fixedori    = 'yes';
>
>    cfg.lcmv.projectnoise = 'yes';
>
>    cfg.lcmv.weightnorm = 'nai';
>
>    cfg.lcmv.lambda      = '5%';
>
>
>
>    eegsrc_all = ft_sourceanalysis(cfg, datall_avg);    %source data in all time window
>
>
>
>    % apply common filters to pre and post stimulus data
>
>    cfg.grid.filter      = eegsrc_all.avg.filter;
>
>
>
>    % Compute source for baseline and activty time window
>
>    eegsrc_basl = ft_sourceanalysis(cfg, datbasl_avg);  %source data for baseline time window
>
>    eegsrc_act  = ft_sourceanalysis(cfg, datact_avg);    %source data for activity time window
>
>
>
>
>
>    % contrast post stimulus onset activity with respect to baseline
>
>    eegsrc_act_basnrm = eegsrc_act;
>
>    eegsrc_act_basnrm.avg.pow = (eegsrc_act.avg.pow - eegsrc_basl.avg.pow)./ eegsrc_basl.avg.pow;
>
>
>
>
>
>    %% Choose time of interest
>
>
>
>    % average across time the dipole moments within the N1 latency range
>
>    ind    = find(eegsrc_act_basnrm.time>=0.1 & eegsrc_act_basnrm.time<=0.5); %at 18ms-24ms
>
>    timecourse = eegsrc_act_basnrm.avg.mom(eegsrc_act_basnrm.inside);
>
>    tc_toi    = zeros(size(eegsrc_act_basnrm.avg.pow(eegsrc_act_basnrm.inside)));
>
>
>
>    for ii = 1:length(timecourse)
>
>        tc_toi(ii) = mean(abs(timecourse{ii}(ind)));
>
>    end
>
>
>
>    source = eegsrc_act_basnrm;
>
>    source.avg.pow(eegsrc_act_basnrm.inside) = tc_toi;
>
> %    source.cfg = rmfield(source.cfg, {'headmodel' 'callinfo'}); % this is removed because it takes up a lot of memory
>
>
>
>    % Save source
>
>
>
>    % interpolate and normalize to individual mri
>
>    %first, interpolate
>
>    cfg          = [];
>
>    cfg.parameter = 'pow';
>
>    eeg_source_interp  = ft_sourceinterpolate(cfg, source, mri);
>
>
>
>
>
>    % second, normalise
>
>    cfg = [];
>
>    cfg.nonlinear    = 'no';
>
>    eeg_source_interp_norm = ft_volumenormalise(cfg, eeg_source_interp);
>
>
>
>    % save the interpolate and normalised data
>
>
>
> %%
>
>      % load source reconstructed data
>
> %    keep subjects path_data nsubj path_ft
>
>
>
>    allsource_rpost = cell(1,nsubj);
>
>    for s = 1:nsubj
>
>        datapath = strcat(fname_eeg_source_interp_norm);
>
> %        datafile = fullfile(datapath, [subj{s}, '_source.mat']);    % take _source data?
>
>        datafile = fullfile(datapath, [subj{s}, '_eeg_source_interp_norm.mat']);
>
>        load(datafile)
>
>
>
>        allsource_rpost{s}    = eeg_source_interp_norm;
>
> %        allsource_rpost{s}    = source;
>
>    end
>
>
>
>
>
>    % grand average
>
>    cfg            = [];
>
>    cfg.parameter  = 'pow';
>
> %    cfg.keepindividual='yes';
>
>    gasource_rpost  = ft_sourcegrandaverage(cfg, allsource_rpost{:});
>
>    %save gasource_rpost
>
>
>
>
>
>
>
>
>
> With best wishes,
>
> Faizal Zulkifly
>
>
>
> --------------------------------------------------------
>
> Mohd Faizal Mohd Zulkifly
>
> University Medical Center Göttingen
>
> University of Göttingen
>
> Clinic for Clinical Neurophysiology
>
> Robert-Koch-Straße 40
>
> 37075 Göttingen
>
> Germany
>
> Tel: +49 551 39-8457
>
>
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/ab68131f/attachment.htm>

From jan.schoffelen at donders.ru.nl  Sat May  2 17:04:40 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sat, 2 May 2020 15:04:40 +0000
Subject: [FieldTrip] Difficulty using "plotfiltresp" --- trying to plot
 frequency response curve on my data
In-Reply-To: <40216434-7AC3-4DCB-9735-50F6DA7AAEC7@gmail.com>
References: <80B32BBD-0307-40A7-AF2E-DEE86E9994D8@stanford.edu>
 <8D02F2B0-C330-4E69-AE45-48FC5AD6C771@donders.ru.nl>
 <40216434-7AC3-4DCB-9735-50F6DA7AAEC7@gmail.com>
Message-ID: <B3466442-CFDC-4167-AC99-C70D72DD7655@donders.ru.nl>

Hi Jonathon,

I don’t know what is going wrong. I have never used this functionality myself, so I would need to dig into it in order to check whether 1) I can reproduce your problem, and 2) to look for a solution.

Have you tried a different type of filter (e.g. ‘firws’) to check whether your issue is filter type dependent? As a background note, the ‘plotfiltresp’-option has been contributed by Andreas Widmann, who also contributed few advanced digital filters (which work much better than the default butterworth IIR filter), one of which being the ‘firws’. It could be that the plotfiltresp functionality has only been correctly implemented for the firws filter. If this happens to be the case, we can think about supporting this option for the other filters as well, provided the lower level code allows for this in principle. We look forward to any code improvement suggestions as PRs on github.

Besides, I’d recommend to use the matlab debugger, to investigate what’s going on. You can place a breakpoint somewhere in the code, and then step through it line by line. This way you can investigate whether cfg options are passed on correctly, and whether they are used to begin with. This is the strategy we would use to look into potential issues


Best wishes,
Jan-Mathijs


On 25 Apr 2020, at 01:18, Jonathon James Parker <parkerjo at stanford.edu<mailto:parkerjo at stanford.edu>> wrote:

Hi Jan:

Not sure of the proper etiquette

here if I should reply all to the thread.

Sincerest apologies, that was a transcription typo in the e-mail. I triple checked my code, and re-ran a couple test cases, and I can still not get the filter response curve to plot.

Any thoughts?

Best,
Jonathon


From: "Schoffelen, J.M. (Jan Mathijs)" <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Date: Wednesday, April 22, 2020 at 11:29 AM
To: FieldTrip discussion list <fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>>
Subject: Re: [FieldTrip] Difficulty using "plotfiltresp" --- trying to plot frequency response curve on my data

Hi Jonathon,
There’s a typo in the cfg specification: cfg.poltfiltresp should read: cfg.plotfiltresp.

Best wishes,
JM



On 22 Apr 2020, at 20:12, Jonathon James Parker <parkerjo at stanford.edu<mailto:parkerjo at stanford.edu>> wrote:

Hi Fieldtrippers:

I am interested in looking at the Frequency response curve after applying different filter types to extract high-gamma band (70-170Hz) in my dataset.

I have used the cfg.plotfiltresp = ‘yes’ flag in running preprocessing on a subset of my data. The call to ft_preprocessing runs without issue, but there is no plot of the filter response curve.

Here is an example of the cfg I am using for the call to ft_preprocessing

 cfgi = [];
    cfgi.bpfilter = 'yes';
    cfgi.bpfreq = [l70 170];
    cfgi.bpfilttype = 'but';
    cfgi.bpinstabilityfix = 'reduce';
    cfgi.bpfiltrord = 8;
    cfgi.poltfiltresp = ‘yes’;



I searched the code of ft_preprocessing and only see the “plotfiltresp” referenced in handling the cfg. flag, thus I am guessing this parameter is simply passed to a lower level pre_proc function depending on the filter type.

Has anyone else had this problem and can offer advice on how to get this functionality to work?

I am running Fieldtrip August 2019 build.

Hope everyone is staying healthy.

Kindest regards and thank you,

Jonathon

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jonathon “JP" Parker MD, PhD
Resident in Neurosurgery | PGY5
Morgridge Endowed Postdoctoral Fellow
Maternal & Child Health Research Institute
Department of Neurosurgery
Stanford University
E: parkerjo at stanford.edu<mailto:parkerjo at stanford.edu>





_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/37bb102b/attachment.htm>

From bkinkini at gmail.com  Sat May  2 22:22:17 2020
From: bkinkini at gmail.com (Kinkini .)
Date: Sat, 2 May 2020 22:22:17 +0200
Subject: [FieldTrip] Problems with ft_Channelrepair / interpolation
In-Reply-To: <72CCE675-2DB9-4BDA-862A-150DD1A41369@donders.ru.nl>
References: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>
 <72CCE675-2DB9-4BDA-862A-150DD1A41369@donders.ru.nl>
Message-ID: <CAM2-uk58f6B-3prHAMCfQVhW+GBxpKpxh63xpXz3hDmbTB6JVA@mail.gmail.com>

Hello  Jan,

Thank you so much for your comments.

I am excluding bad channels while applying CAR.
Also, I tried excluding bad channels from ICA and interpolate them later.
But as I had mentioned before, I am facing problems
applying ft_freqstatistics.

Any suggestion on that?

Thanks again,

*Kinkini*


On Sat, May 2, 2020 at 1:51 PM Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl> wrote:

> Hi Kinkini,
>
> I would recommend not doing a CAR before you have removed bad channels.
> Also, I would recommend not tu ‘repair’ any bad channels prior to running
> ICA.
> Best wishes,
> Jan-Mathijs
>
>
> On 1 May 2020, at 13:33, Kinkini . <bkinkini at gmail.com> wrote:
>
> Dear FieldTripers,
>
> Hope everyone is coping well with the current situation.
>
> I am relatively new in fieldtrip and I have been long stuck with using
> ft_channelrepair for quite sometime now.
>
> Briefly about my analysis pipeline:
> 1- Loading and epoching the data
> 2- ft_preprocessing - filtering, baselining, CAR
> 3- ft_databrowser - marking bad channels
> 4. ft_rejectvisual - rejecting bad channels; keepchannel = 'repair'
> 5. ft_channelrepair
> 6. ICA
> 7. TF Analysis
> 8. TF statististics
>
> I have problems pertaining to step 4 and 5. In step 4 I want to keep the
> bad channels so that I can interpolate them in the next step. When I use
> data browser to look thorough the data, the bad channels look okay. But the
> problem starts when I perform ICA on them. My first observation is that the
> wchange value is very big (looks like this : 257868.69202720), but ICA runs
> completely. However the ICA component topoplots look weird (screenshots
> attached). However, when I look through the icabrowser plots , there are
> peaks at physiological frequencies.
>
> In order to avoid this, I tried getting rid of the bad channels completely
> using ft_rejectvisual, perform ICA and then get back the missing channels
> using neighbourhood average. Doing this, I was able to perform TF analysis,
> but when I wanted to apply statistics on the data, I had errors. Finally, I
> had to avoid the entire step of  interpolation to be able to run everything
> and also perform statistics. But in a long run, I cannot avoid this step.
>
> I am finding no clue as to where is it going wrong.
>
> Hence, any idea, any clue from you all would help me very much. I am happy
> to provide with more details if necessary.
> Thank you so much for your response.
>
> Best regards,
>
> Kinkini Bhadra
> PhD student
> Department of Fundamental Neurosciences
> University of Geneva
>
>
> <Screenshot 2020-05-01 11.57.28.png><Screenshot 2020-05-01 11.57.42.png>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200502/5a2dc967/attachment.htm>

From jan.schoffelen at donders.ru.nl  Sun May  3 20:46:05 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sun, 3 May 2020 18:46:05 +0000
Subject: [FieldTrip] Problems with ft_Channelrepair / interpolation
In-Reply-To: <CAM2-uk58f6B-3prHAMCfQVhW+GBxpKpxh63xpXz3hDmbTB6JVA@mail.gmail.com>
References: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>
 <72CCE675-2DB9-4BDA-862A-150DD1A41369@donders.ru.nl>
 <CAM2-uk58f6B-3prHAMCfQVhW+GBxpKpxh63xpXz3hDmbTB6JVA@mail.gmail.com>
Message-ID: <B651D81B-07F8-4477-AA8B-8848DB2D1929@donders.ru.nl>

Hi Kinkini,

I don’t have any concrete suggestions here. Perhaps you should try and first pinpoint the potential cause of the issue yourself. If you dump an entire pipeline in an e-mail, it is unclear to us where we should focus on. Specifically, it is not clear whether any upstream processing steps are relevant at all for the issue you are facing. You wrote: "but when I wanted to apply statistics on the data, I had errors”.  This is so ill-conditioned that we can just guess as to what is going wrong for you.
Perhaps consult http://www.fieldtriptoolbox.org/faq/how_to_ask_good_questions_to_the_community/ to phrase your question a bit more to-the-point.

Good luck,

Jan-Mathijs


On 2 May 2020, at 22:22, Kinkini . <bkinkini at gmail.com<mailto:bkinkini at gmail.com>> wrote:

Hello  Jan,

Thank you so much for your comments.

I am excluding bad channels while applying CAR.
Also, I tried excluding bad channels from ICA and interpolate them later. But as I had mentioned before, I am facing problems applying ft_freqstatistics.

Any suggestion on that?

Thanks again,

Kinkini


On Sat, May 2, 2020 at 1:51 PM Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>> wrote:
Hi Kinkini,

I would recommend not doing a CAR before you have removed bad channels.
Also, I would recommend not tu ‘repair’ any bad channels prior to running ICA.
Best wishes,
Jan-Mathijs


On 1 May 2020, at 13:33, Kinkini . <bkinkini at gmail.com<mailto:bkinkini at gmail.com>> wrote:

Dear FieldTripers,

Hope everyone is coping well with the current situation.

I am relatively new in fieldtrip and I have been long stuck with using ft_channelrepair for quite sometime now.

Briefly about my analysis pipeline:
1- Loading and epoching the data
2- ft_preprocessing - filtering, baselining, CAR
3- ft_databrowser - marking bad channels
4. ft_rejectvisual - rejecting bad channels; keepchannel = 'repair'
5. ft_channelrepair
6. ICA
7. TF Analysis
8. TF statististics

I have problems pertaining to step 4 and 5. In step 4 I want to keep the bad channels so that I can interpolate them in the next step. When I use data browser to look thorough the data, the bad channels look okay. But the problem starts when I perform ICA on them. My first observation is that the wchange value is very big (looks like this : 257868.69202720), but ICA runs completely. However the ICA component topoplots look weird (screenshots attached). However, when I look through the icabrowser plots , there are peaks at physiological frequencies.

In order to avoid this, I tried getting rid of the bad channels completely using ft_rejectvisual, perform ICA and then get back the missing channels using neighbourhood average. Doing this, I was able to perform TF analysis, but when I wanted to apply statistics on the data, I had errors. Finally, I had to avoid the entire step of  interpolation to be able to run everything and also perform statistics. But in a long run, I cannot avoid this step.

I am finding no clue as to where is it going wrong.

Hence, any idea, any clue from you all would help me very much. I am happy to provide with more details if necessary.
Thank you so much for your response.

Best regards,

Kinkini Bhadra
PhD student
Department of Fundamental Neurosciences
University of Geneva


<Screenshot 2020-05-01 11.57.28.png><Screenshot 2020-05-01 11.57.42.png>_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200503/9f777960/attachment.htm>

From bkinkini at gmail.com  Mon May  4 02:21:34 2020
From: bkinkini at gmail.com (Kinkini .)
Date: Mon, 4 May 2020 02:21:34 +0200
Subject: [FieldTrip] Problems with ft_Channelrepair / interpolation
In-Reply-To: <B651D81B-07F8-4477-AA8B-8848DB2D1929@donders.ru.nl>
References: <CAM2-uk62b3eftMF0HpLTEtRgm7ZQVJRzLfiwgYCOYHJx_t0zbw@mail.gmail.com>
 <72CCE675-2DB9-4BDA-862A-150DD1A41369@donders.ru.nl>
 <CAM2-uk58f6B-3prHAMCfQVhW+GBxpKpxh63xpXz3hDmbTB6JVA@mail.gmail.com>
 <B651D81B-07F8-4477-AA8B-8848DB2D1929@donders.ru.nl>
Message-ID: <CAM2-uk4zho4U0YbH8OEiR2t3merGQ44-+1U4DwS3P0_t1zAf9g@mail.gmail.com>

Hi Jan-Mathijs,

My apologies for providing insufficient information and over generalizing
my question.
But I am happy to let you know that I have just debugged the issue and it
looks like I was having NaN values in some of the trials and
therefore ft_freqstatistics was showing error.

Thanks to you for your previous inputs, it helped me with the problem
related to interpolation and ICA.

Take care,

regards,

*KINKINI BHADRA*


On Sun, May 3, 2020 at 8:46 PM Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl> wrote:

> Hi Kinkini,
>
> I don’t have any concrete suggestions here. Perhaps you should try and
> first pinpoint the potential cause of the issue yourself. If you dump an
> entire pipeline in an e-mail, it is unclear to us where we should focus on.
> Specifically, it is not clear whether any upstream processing steps are
> relevant at all for the issue you are facing. You wrote: "but when I wanted
> to apply statistics on the data, I had errors”.  This is so ill-conditioned
> that we can just guess as to what is going wrong for you.
> Perhaps consult
> http://www.fieldtriptoolbox.org/faq/how_to_ask_good_questions_to_the_community/ to
> phrase your question a bit more to-the-point.
>
> Good luck,
>
> Jan-Mathijs
>
>
> On 2 May 2020, at 22:22, Kinkini . <bkinkini at gmail.com> wrote:
>
> Hello  Jan,
>
> Thank you so much for your comments.
>
> I am excluding bad channels while applying CAR.
> Also, I tried excluding bad channels from ICA and interpolate them later.
> But as I had mentioned before, I am facing problems
> applying ft_freqstatistics.
>
> Any suggestion on that?
>
> Thanks again,
>
> *Kinkini*
>
>
> On Sat, May 2, 2020 at 1:51 PM Schoffelen, J.M. (Jan Mathijs) <
> jan.schoffelen at donders.ru.nl> wrote:
>
>> Hi Kinkini,
>>
>> I would recommend not doing a CAR before you have removed bad channels.
>> Also, I would recommend not tu ‘repair’ any bad channels prior to running
>> ICA.
>> Best wishes,
>> Jan-Mathijs
>>
>>
>> On 1 May 2020, at 13:33, Kinkini . <bkinkini at gmail.com> wrote:
>>
>> Dear FieldTripers,
>>
>> Hope everyone is coping well with the current situation.
>>
>> I am relatively new in fieldtrip and I have been long stuck with using
>> ft_channelrepair for quite sometime now.
>>
>> Briefly about my analysis pipeline:
>> 1- Loading and epoching the data
>> 2- ft_preprocessing - filtering, baselining, CAR
>> 3- ft_databrowser - marking bad channels
>> 4. ft_rejectvisual - rejecting bad channels; keepchannel = 'repair'
>> 5. ft_channelrepair
>> 6. ICA
>> 7. TF Analysis
>> 8. TF statististics
>>
>> I have problems pertaining to step 4 and 5. In step 4 I want to keep the
>> bad channels so that I can interpolate them in the next step. When I use
>> data browser to look thorough the data, the bad channels look okay. But the
>> problem starts when I perform ICA on them. My first observation is that the
>> wchange value is very big (looks like this : 257868.69202720), but ICA runs
>> completely. However the ICA component topoplots look weird (screenshots
>> attached). However, when I look through the icabrowser plots , there are
>> peaks at physiological frequencies.
>>
>> In order to avoid this, I tried getting rid of the bad channels
>> completely using ft_rejectvisual, perform ICA and then get back the missing
>> channels using neighbourhood average. Doing this, I was able to perform TF
>> analysis, but when I wanted to apply statistics on the data, I had errors.
>> Finally, I had to avoid the entire step of  interpolation to be able to run
>> everything and also perform statistics. But in a long run, I cannot avoid
>> this step.
>>
>> I am finding no clue as to where is it going wrong.
>>
>> Hence, any idea, any clue from you all would help me very much. I am
>> happy to provide with more details if necessary.
>> Thank you so much for your response.
>>
>> Best regards,
>>
>> Kinkini Bhadra
>> PhD student
>> Department of Fundamental Neurosciences
>> University of Geneva
>>
>>
>> <Screenshot 2020-05-01 11.57.28.png><Screenshot 2020-05-01 11.57.42.png>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200504/f661f53c/attachment.htm>

From widmann at uni-leipzig.de  Mon May  4 15:32:23 2020
From: widmann at uni-leipzig.de (Andreas Widmann)
Date: Mon, 4 May 2020 15:32:23 +0200
Subject: [FieldTrip] Difficulty using "plotfiltresp" --- trying to plot
 frequency response curve on my data
In-Reply-To: <B3466442-CFDC-4167-AC99-C70D72DD7655@donders.ru.nl>
References: <80B32BBD-0307-40A7-AF2E-DEE86E9994D8@stanford.edu>
 <8D02F2B0-C330-4E69-AE45-48FC5AD6C771@donders.ru.nl>
 <40216434-7AC3-4DCB-9735-50F6DA7AAEC7@gmail.com>
 <B3466442-CFDC-4167-AC99-C70D72DD7655@donders.ru.nl>
Message-ID: <A0D8026A-FE5C-4465-AC18-E8DDD4FDFF8D@uni-leipzig.de>

Hi Jonathon and Jan-Mathijs,

indeed this functionality appears to be missing for the Butterworth filters. To be honest I do not remember why this was omitted as it appears to be fully functional (but without in depth testing for now).

This can, however, be easily fixed. For lowpass filtering the code is already there but commented for unclear reasons, see ft_preproc_lowpassfilter.m, lines 154-156:
https://github.com/fieldtrip/fieldtrip/blob/master/preproc/ft_preproc_lowpassfilter.m

You just need to uncomment and copy these three lines to the corresponding location in ft_preproc_bandpassfilter.m in the preproc directory (and ft_preproc_bandstopfilter.m and ft_preproc_highpassfilter.m in case needed) and it should be working. If you file an issue at the Github fieldtrip page the problem can be fixed quickly, I assume.

Note that plotting is done *before* filter stability is checked. Thus, if you get a stability warning the plot does not reflect the actually applied filter. You have to re-run with order adjusted to what is reported in the stability warning message (as I would recommend anyway). Possibly this limitation was the reason for omission at that time?

Hope this helps! Best,
Andreas

> Am 02.05.2020 um 17:04 schrieb Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>:
> 
> Hi Jonathon,
> 
> I don’t know what is going wrong. I have never used this functionality myself, so I would need to dig into it in order to check whether 1) I can reproduce your problem, and 2) to look for a solution.
> 
> Have you tried a different type of filter (e.g. ‘firws’) to check whether your issue is filter type dependent? As a background note, the ‘plotfiltresp’-option has been contributed by Andreas Widmann, who also contributed few advanced digital filters (which work much better than the default butterworth IIR filter), one of which being the ‘firws’. It could be that the plotfiltresp functionality has only been correctly implemented for the firws filter. If this happens to be the case, we can think about supporting this option for the other filters as well, provided the lower level code allows for this in principle. We look forward to any code improvement suggestions as PRs on github.
> 
> Besides, I’d recommend to use the matlab debugger, to investigate what’s going on. You can place a breakpoint somewhere in the code, and then step through it line by line. This way you can investigate whether cfg options are passed on correctly, and whether they are used to begin with. This is the strategy we would use to look into potential issues
> 
> 
> Best wishes,
> Jan-Mathijs
> 
> 
>> On 25 Apr 2020, at 01:18, Jonathon James Parker <parkerjo at stanford.edu> wrote:
>> 
>> Hi Jan:
>>  
>> Not sure of the proper etiquette
>>  
>> here if I should reply all to the thread. 
>> 
>> Sincerest apologies, that was a transcription typo in the e-mail. I triple checked my code, and re-ran a couple test cases, and I can still not get the filter response curve to plot.
>>  
>> Any thoughts?
>>  
>> Best,
>> Jonathon
>>  
>>  
>> From: "Schoffelen, J.M. (Jan Mathijs)" <jan.schoffelen at donders.ru.nl>
>> Date: Wednesday, April 22, 2020 at 11:29 AM
>> To: FieldTrip discussion list <fieldtrip at science.ru.nl>
>> Subject: Re: [FieldTrip] Difficulty using "plotfiltresp" --- trying to plot frequency response curve on my data
>>  
>> Hi Jonathon,
>> There’s a typo in the cfg specification: cfg.poltfiltresp should read: cfg.plotfiltresp.
>>  
>> Best wishes,
>> JM
>>  
>> 
>> 
>> On 22 Apr 2020, at 20:12, Jonathon James Parker <parkerjo at stanford.edu> wrote:
>>  
>> Hi Fieldtrippers:
>>  
>> I am interested in looking at the Frequency response curve after applying different filter types to extract high-gamma band (70-170Hz) in my dataset.
>>  
>> I have used the cfg.plotfiltresp = ‘yes’ flag in running preprocessing on a subset of my data. The call to ft_preprocessing runs without issue, but there is no plot of the filter response curve.
>>  
>> Here is an example of the cfg I am using for the call to ft_preprocessing
>>  
>>  cfgi = [];
>>     cfgi.bpfilter = 'yes';
>>     cfgi.bpfreq = [l70 170];
>>     cfgi.bpfilttype = 'but';
>>     cfgi.bpinstabilityfix = 'reduce';
>>     cfgi.bpfiltrord = 8;
>>     cfgi.poltfiltresp = ‘yes’;
>>  
>>  
>>  
>> I searched the code of ft_preprocessing and only see the “plotfiltresp” referenced in handling the cfg. flag, thus I am guessing this parameter is simply passed to a lower level pre_proc function depending on the filter type.
>>  
>> Has anyone else had this problem and can offer advice on how to get this functionality to work?
>>  
>> I am running Fieldtrip August 2019 build.
>>  
>> Hope everyone is staying healthy.
>>  
>> Kindest regards and thank you,
>>  
>> Jonathon
>>  
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> Jonathon “JP" Parker MD, PhD
>> Resident in Neurosurgery | PGY5
>> Morgridge Endowed Postdoctoral Fellow 
>> Maternal & Child Health Research Institute
>> Department of Neurosurgery
>> Stanford University 
>> E: parkerjo at stanford.edu
>> 
>> 
>>  
>>  
>>  
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
> 
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202




From sara.hussain at nih.gov  Mon May  4 23:05:02 2020
From: sara.hussain at nih.gov (Hussain, Sara (NIH/NINDS) [F])
Date: Mon, 4 May 2020 21:05:02 +0000
Subject: [FieldTrip] Issue with segmentation and headmodels
Message-ID: <9493763C-1AF4-4AC2-A64B-4FFB624A27E7@nih.gov>

Hello Fieldtrippers-
I am trying to create headmodels for source localization of EEG data. I have been successful using fieldtrips built in spm segmentation approach for several participants, but there are some for whom the segmentation is extremely poor and wildly inaccurate – adjusting the scalpsmooth and threshold parameters does not help at all. I am wondering if anyone has any tips on how to get a good segmentation using the built in fieldtrip approach through ft_volumesegment.

Alternatively, I have tried using other segmentation approaches (i.e., creating masks in AFNI) – but these approaches seem poorer than that implemented via spm. My main issue is that I am having trouble finding an approach that works reasonably well for everyone. Any tips you have would be highly appreciated, as I have been struggling with this for a few weeks now.

Thanks-
Sara
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200504/79710b18/attachment.htm>

From l.drijvers at donders.ru.nl  Wed May  6 09:58:33 2020
From: l.drijvers at donders.ru.nl (Drijvers, L. (Linda))
Date: Wed, 6 May 2020 07:58:33 +0000
Subject: [FieldTrip] missing sample after using ft_componentanalysis with
 method bsscca
Message-ID: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>

Dear all,

I'm analysing an EEG dataset using MATLAB 2016a + FieldTrip version 20200409.

I am trying to use ft_componentanalysis with cfg.method = 'bsscca' (see code):

cfg             = [];
cfg.channel     = 1:length(data_Aclean.label)-2;
cfg.method      = 'bsscca';
cfg.cellmode    = 'yes';
comp_output      = ft_componentanalysis(cfg, data_Aclean);

When I then try to use ft_databrowser with the following code:

    cfg = [];
    cfg.channel = [1:10];
    cfg.viewmode = 'component';
    cfg.layout = 'customlayout.mat';
    ft_databrowser(cfg, comp_output);

I get the following error:

Index exceeds matrix dimensions.

Error in ft_fetch_data (line 199)
    dat(:,ok) = data.trial{utrl}(chanindx,smps);

Error in ft_databrowser>redraw_cb (line 1630)
  dat = ft_fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx,
  'allowoverlap', istrue(cfg.allowoverlap));

Error in ft_databrowser (line 729)
redraw_cb(h);

A closer look at the data shows that while fsample for my data is 500, smps is 499 after running ft_componentanalysis with method bsscca. However, I can solve the error above by running ft_databrowser with comp_output = rmfield(comp_output, 'sampleinfo').

My question is: what causes this discrepancy in smps (why does this one sample go missing)? Any help would be appreciated.

Best wishes,
Linda Drijvers

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/ | https://www.mpi.nl/people/drijvers-linda

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/5aeb6ea0/attachment.htm>

From l.drijvers at donders.ru.nl  Wed May  6 10:23:29 2020
From: l.drijvers at donders.ru.nl (Drijvers, L. (Linda))
Date: Wed, 6 May 2020 08:23:29 +0000
Subject: [FieldTrip] missing sample after using ft_componentanalysis
 with method bsscca
In-Reply-To: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>
References: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>
Message-ID: <2a7445b0fad748b7a8fe8abbbb8fa778@EXPRD06.hosting.ru.nl>

P.S., sorry, mixed things up: data in comp_output.trial have 499 samples, while smps has 500 elements (presumably based on sampleinfo). So key question is: why do the output trials after bsscca have 1 fewer sample than the input trials?

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/ | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl> On Behalf Of Drijvers, L. (Linda)
Sent: woensdag 6 mei 2020 09:59
To: fieldtrip at science.ru.nl
Subject: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Dear all,

I'm analysing an EEG dataset using MATLAB 2016a + FieldTrip version 20200409.

I am trying to use ft_componentanalysis with cfg.method = 'bsscca' (see code):

cfg             = [];
cfg.channel     = 1:length(data_Aclean.label)-2;
cfg.method      = 'bsscca';
cfg.cellmode    = 'yes';
comp_output      = ft_componentanalysis(cfg, data_Aclean);

When I then try to use ft_databrowser with the following code:
    cfg = [];
    cfg.channel = [1:10];
    cfg.viewmode = 'component';
    cfg.layout = 'customlayout.mat';
    ft_databrowser(cfg, comp_output);

I get the following error:

Index exceeds matrix dimensions.

Error in ft_fetch_data (line 199)
    dat(:,ok) = data.trial{utrl}(chanindx,smps);

Error in ft_databrowser>redraw_cb (line 1630)
  dat = ft_fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx,
  'allowoverlap', istrue(cfg.allowoverlap));

Error in ft_databrowser (line 729)
redraw_cb(h);

A closer look at the data shows that while fsample for my data is 500, smps is 499 after running ft_componentanalysis with method bsscca. However, I can solve the error above by running ft_databrowser with comp_output = rmfield(comp_output, 'sampleinfo').

My question is: what causes this discrepancy in smps (why does this one sample go missing)? Any help would be appreciated.

Best wishes,
Linda Drijvers

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/ | https://www.mpi.nl/people/drijvers-linda

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/48e92247/attachment.htm>

From jan.schoffelen at donders.ru.nl  Wed May  6 11:18:01 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Wed, 6 May 2020 09:18:01 +0000
Subject: [FieldTrip] missing sample after using ft_componentanalysis
 with method bsscca
In-Reply-To: <2a7445b0fad748b7a8fe8abbbb8fa778@EXPRD06.hosting.ru.nl>
References: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>
 <2a7445b0fad748b7a8fe8abbbb8fa778@EXPRD06.hosting.ru.nl>
Message-ID: <A4A148A5-D75C-4722-A4F9-59AE11E3A71A@donders.ru.nl>

Hi Linda

Is the data internally consistent after ft_componentanalysis? In other words, does the number of time points per trial (in data.time) match the number of columns in data.trial?

Please note that the bsscca is a poorly maintained corner (and hardly ever used) of the code, so it might need improvement.

Feel free to send us a Pull Request through github for code improvements.

Best,
Jan-Mathijs

PS: bsscca returns ’shorter’ data than the input because of the way the algorithm works, as described in the reference paper.



On 6 May 2020, at 10:23, Drijvers, L. (Linda) <l.drijvers at donders.ru.nl<mailto:l.drijvers at donders.ru.nl>> wrote:

P.S., sorry, mixed things up: data in comp_output.trial have 499 samples, while smps has 500 elements (presumably based on sampleinfo). So key question is: why do the output trials after bsscca have 1 fewer sample than the input trials?

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org<https://cosilab.org/>
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> On Behalf Of Drijvers, L. (Linda)
Sent: woensdag 6 mei 2020 09:59
To: fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>
Subject: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Dear all,

I’m analysing an EEG dataset using MATLAB 2016a + FieldTrip version 20200409.

I am trying to use ft_componentanalysis with cfg.method = ‘bsscca’ (see code):

cfg             = [];
cfg.channel     = 1:length(data_Aclean.label)-2;
cfg.method      = 'bsscca';
cfg.cellmode    = 'yes';
comp_output      = ft_componentanalysis(cfg, data_Aclean);

When I then try to use ft_databrowser with the following code:
    cfg = [];
    cfg.channel = [1:10];
    cfg.viewmode = 'component';
    cfg.layout = 'customlayout.mat';
    ft_databrowser(cfg, comp_output);

I get the following error:

Index exceeds matrix dimensions.

Error in ft_fetch_data (line 199)
    dat(:,ok) = data.trial{utrl}(chanindx,smps);

Error in ft_databrowser>redraw_cb (line 1630)
  dat = ft_fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx,
  'allowoverlap', istrue(cfg.allowoverlap));

Error in ft_databrowser (line 729)
redraw_cb(h);

A closer look at the data shows that while fsample for my data is 500, smps is 499 after running ft_componentanalysis with method bsscca. However, I can solve the error above by running ft_databrowser with comp_output = rmfield(comp_output, 'sampleinfo').

My question is: what causes this discrepancy in smps (why does this one sample go missing)? Any help would be appreciated.

Best wishes,
Linda Drijvers

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/6ef6b748/attachment.htm>

From l.drijvers at donders.ru.nl  Wed May  6 11:34:58 2020
From: l.drijvers at donders.ru.nl (Drijvers, L. (Linda))
Date: Wed, 6 May 2020 09:34:58 +0000
Subject: [FieldTrip] missing sample after using ft_componentanalysis
 with method bsscca
In-Reply-To: <A4A148A5-D75C-4722-A4F9-59AE11E3A71A@donders.ru.nl>
References: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>
 <2a7445b0fad748b7a8fe8abbbb8fa778@EXPRD06.hosting.ru.nl>
 <A4A148A5-D75C-4722-A4F9-59AE11E3A71A@donders.ru.nl>
Message-ID: <cc76ab246f5f41888864bf69986c0b33@EXPRD06.hosting.ru.nl>

Hi Jan-Mathijs,

Thanks for the fast reply. Data is indeed internally consistent.
And I will read that paper in more detail... Thanks!

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/ | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl> On Behalf Of Schoffelen, J.M. (Jan Mathijs)
Sent: woensdag 6 mei 2020 11:18
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: Re: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Hi Linda

Is the data internally consistent after ft_componentanalysis? In other words, does the number of time points per trial (in data.time) match the number of columns in data.trial?

Please note that the bsscca is a poorly maintained corner (and hardly ever used) of the code, so it might need improvement.

Feel free to send us a Pull Request through github for code improvements.

Best,
Jan-Mathijs

PS: bsscca returns ’shorter’ data than the input because of the way the algorithm works, as described in the reference paper.




On 6 May 2020, at 10:23, Drijvers, L. (Linda) <l.drijvers at donders.ru.nl<mailto:l.drijvers at donders.ru.nl>> wrote:

P.S., sorry, mixed things up: data in comp_output.trial have 499 samples, while smps has 500 elements (presumably based on sampleinfo). So key question is: why do the output trials after bsscca have 1 fewer sample than the input trials?

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org<https://cosilab.org/>
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> On Behalf Of Drijvers, L. (Linda)
Sent: woensdag 6 mei 2020 09:59
To: fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>
Subject: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Dear all,

I’m analysing an EEG dataset using MATLAB 2016a + FieldTrip version 20200409.

I am trying to use ft_componentanalysis with cfg.method = ‘bsscca’ (see code):

cfg             = [];
cfg.channel     = 1:length(data_Aclean.label)-2;
cfg.method      = 'bsscca';
cfg.cellmode    = 'yes';
comp_output      = ft_componentanalysis(cfg, data_Aclean);

When I then try to use ft_databrowser with the following code:
    cfg = [];
    cfg.channel = [1:10];
    cfg.viewmode = 'component';
    cfg.layout = 'customlayout.mat';
    ft_databrowser(cfg, comp_output);

I get the following error:

Index exceeds matrix dimensions.

Error in ft_fetch_data (line 199)
    dat(:,ok) = data.trial{utrl}(chanindx,smps);

Error in ft_databrowser>redraw_cb (line 1630)
  dat = ft_fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx,
  'allowoverlap', istrue(cfg.allowoverlap));

Error in ft_databrowser (line 729)
redraw_cb(h);

A closer look at the data shows that while fsample for my data is 500, smps is 499 after running ft_componentanalysis with method bsscca. However, I can solve the error above by running ft_databrowser with comp_output = rmfield(comp_output, 'sampleinfo').

My question is: what causes this discrepancy in smps (why does this one sample go missing)? Any help would be appreciated.

Best wishes,
Linda Drijvers

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/7b3eeea9/attachment.htm>

From Joachim.Lange at med.uni-duesseldorf.de  Wed May  6 12:27:48 2020
From: Joachim.Lange at med.uni-duesseldorf.de (Joachim.Lange at med.uni-duesseldorf.de)
Date: Wed, 6 May 2020 10:27:48 +0000
Subject: [FieldTrip] Problem with FT's nanmean
In-Reply-To: <mailman.17.1588672802.20883.fieldtrip@science.ru.nl>
References: <mailman.17.1588672802.20883.fieldtrip@science.ru.nl>
Message-ID: <c1653f20b9954b81b88e066349099dd7@med.uni-duesseldorf.de>

Dear all,

I have a dataset with 94 trials, 44800 (virtual) channels, and 600 timepoints. I applied ft_timelockanalysis on this dataset and the output was surprisingly "0" for all channel-time pairs, even for those channels that contained only NaNs (because they were outside the brain). If I tried a smaller number of trials, everything was fine, though (i.e., no zeros, but plausible values).

I was able to boil down the problem to the function "nanmean". If I extract a 94x44800x600 matrix from the dataset and use FT's nanmean (apparently fieldtrip-20200423/external/stats/nanmean.mexa64), the result is zeros, again. If I use matlab's nanmean, everythig seems fine.

Any help is appreciated.

Best,

Jo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/efa027e5/attachment.htm>

From jan.schoffelen at donders.ru.nl  Wed May  6 12:43:05 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Wed, 6 May 2020 10:43:05 +0000
Subject: [FieldTrip] missing sample after using ft_componentanalysis
 with method bsscca
In-Reply-To: <cc76ab246f5f41888864bf69986c0b33@EXPRD06.hosting.ru.nl>
References: <6735b9001bf54722a1e78c291f90803c@EXPRD06.hosting.ru.nl>
 <2a7445b0fad748b7a8fe8abbbb8fa778@EXPRD06.hosting.ru.nl>
 <A4A148A5-D75C-4722-A4F9-59AE11E3A71A@donders.ru.nl>
 <cc76ab246f5f41888864bf69986c0b33@EXPRD06.hosting.ru.nl>
Message-ID: <AB3BDE57-EC29-47DD-960E-AFD9E9F08F0B@donders.ru.nl>

Hi Linda,

I have adjusted ft_componentanalysis, to remove the sampleinfo field from the output in case bsscca is used as method.
This change will be available at the DCCN cluster soon, is alreadly available on the master development branch on github, and will in the release version on github soon.

Best wishes,
Jan-Mathijs


On 6 May 2020, at 11:34, Drijvers, L. (Linda) <l.drijvers at donders.ru.nl<mailto:l.drijvers at donders.ru.nl>> wrote:

Hi Jan-Mathijs,

Thanks for the fast reply. Data is indeed internally consistent.
And I will read that paper in more detail... Thanks!

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org<https://cosilab.org/>
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> On Behalf Of Schoffelen, J.M. (Jan Mathijs)
Sent: woensdag 6 mei 2020 11:18
To: FieldTrip discussion list <fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>>
Subject: Re: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Hi Linda

Is the data internally consistent after ft_componentanalysis? In other words, does the number of time points per trial (in data.time) match the number of columns in data.trial?

Please note that the bsscca is a poorly maintained corner (and hardly ever used) of the code, so it might need improvement.

Feel free to send us a Pull Request through github for code improvements.

Best,
Jan-Mathijs

PS: bsscca returns ’shorter’ data than the input because of the way the algorithm works, as described in the reference paper.




On 6 May 2020, at 10:23, Drijvers, L. (Linda) <l.drijvers at donders.ru.nl<mailto:l.drijvers at donders.ru.nl>> wrote:

P.S., sorry, mixed things up: data in comp_output.trial have 499 samples, while smps has 500 elements (presumably based on sampleinfo). So key question is: why do the output trials after bsscca have 1 fewer sample than the input trials?

Best,
Linda

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org<https://cosilab.org/>
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> On Behalf Of Drijvers, L. (Linda)
Sent: woensdag 6 mei 2020 09:59
To: fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>
Subject: [FieldTrip] missing sample after using ft_componentanalysis with method bsscca

Dear all,

I’m analysing an EEG dataset using MATLAB 2016a + FieldTrip version 20200409.

I am trying to use ft_componentanalysis with cfg.method = ‘bsscca’ (see code):

cfg             = [];
cfg.channel     = 1:length(data_Aclean.label)-2;
cfg.method      = 'bsscca';
cfg.cellmode    = 'yes';
comp_output      = ft_componentanalysis(cfg, data_Aclean);

When I then try to use ft_databrowser with the following code:
    cfg = [];
    cfg.channel = [1:10];
    cfg.viewmode = 'component';
    cfg.layout = 'customlayout.mat';
    ft_databrowser(cfg, comp_output);

I get the following error:

Index exceeds matrix dimensions.

Error in ft_fetch_data (line 199)
    dat(:,ok) = data.trial{utrl}(chanindx,smps);

Error in ft_databrowser>redraw_cb (line 1630)
  dat = ft_fetch_data(opt.orgdata, 'header', opt.hdr, 'begsample', begsample, 'endsample', endsample, 'chanindx', chanindx,
  'allowoverlap', istrue(cfg.allowoverlap));

Error in ft_databrowser (line 729)
redraw_cb(h);

A closer look at the data shows that while fsample for my data is 500, smps is 499 after running ft_componentanalysis with method bsscca. However, I can solve the error above by running ft_databrowser with comp_output = rmfield(comp_output, 'sampleinfo').

My question is: what causes this discrepancy in smps (why does this one sample go missing)? Any help would be appreciated.

Best wishes,
Linda Drijvers

dr. Linda Drijvers | postdoctoral researcher | https://cosilab.org<https://cosilab.org/>
Donders Institute for Brain, Cognition and Behaviour, Radboud University, NL
www.ru.nl/english/people/drijvers-l/<http://www.ru.nl/english/people/drijvers-l/> | https://www.mpi.nl/people/drijvers-linda

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/6f76c716/attachment.htm>

From jan.schoffelen at donders.ru.nl  Wed May  6 13:39:40 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Wed, 6 May 2020 11:39:40 +0000
Subject: [FieldTrip] Problem with FT's nanmean
In-Reply-To: <c1653f20b9954b81b88e066349099dd7@med.uni-duesseldorf.de>
References: <mailman.17.1588672802.20883.fieldtrip@science.ru.nl>
 <c1653f20b9954b81b88e066349099dd7@med.uni-duesseldorf.de>
Message-ID: <20F75BCE-5BBA-4FE6-8F89-DB42D3DE2804@donders.ru.nl>

Hi Jo,

The size of the variable that you are using as an input is quite large, probably it takes up 20GB of RAM or so.
Perhaps that the low-level c-code, on which the nanmean mex-files are based, has problems dealing with such large variables? Although I would have expected an error to be thrown or a segmentation fault in that case. Does mr. Google provide any directions here (e.g. when searching for the maximum allowed variable size in mex files)?
As a side note, I am surprised that the code defaults to using the mex-file, while you seem to have the legacy nanmean function available.

Best wishes,
Jan-Mathijs



On 6 May 2020, at 12:27, joachim.lange at med.uni-duesseldorf.de<mailto:joachim.lange at med.uni-duesseldorf.de> wrote:

Dear all,
I have a dataset with 94 trials, 44800 (virtual) channels, and 600 timepoints. I applied ft_timelockanalysis on this dataset and the output was surprisingly "0" for all channel-time pairs, even for those channels that contained only NaNs (because they were outside the brain). If I tried a smaller number of trials, everything was fine, though (i.e., no zeros, but plausible values).
I was able to boil down the problem to the function "nanmean". If I extract a 94x44800x600 matrix from the dataset and use FT's nanmean (apparently fieldtrip-20200423/external/stats/nanmean.mexa64), the result is zeros, again. If I use matlab's nanmean, everythig seems fine.
Any help is appreciated.
Best,
Jo
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/4789ebcb/attachment.htm>

From MGlassen at kesslerfoundation.org  Wed May  6 22:34:23 2020
From: MGlassen at kesslerfoundation.org (Michael Glassen  -  Biomedical Engineer)
Date: Wed, 6 May 2020 20:34:23 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
Message-ID: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200506/52358477/attachment.htm>

From marcel.van.den.velde at gmail.com  Thu May  7 01:50:39 2020
From: marcel.van.den.velde at gmail.com (Marcel van den Velde)
Date: Thu, 7 May 2020 01:50:39 +0200
Subject: [FieldTrip] define response onset as 0 point, looking back
Message-ID: <CAChwwKszJUEzUL==q_F+2o-NYjQJM-MOU8VWm9Fmc=shCN_K7A@mail.gmail.com>

Dear all,

I am doing a MEG analysis on hand movement preparation: subjects are
presented with visual stimuli (coded in the trigger channel) and have to
respond by moving their hand. The study requires that I investigate the
ERFs prior to the movement onset (but not capturing anything pre-stimulus).
How can I best move the 0 point from stimulus onset to movement onset and
look back?

What I have now is the following, but I am not sure whether this is correct:

First a trial definition calling an own function and an own added field to
assign the response time (cfg.trialdef.rt)

        % trial definition
        cfg = [];
        cfg.dataset = subject_meg_data;
        cfg.trialfun = ‘trialfun_move’;                           % <— own
function
        cfg.trialdef.rt = movement_rt_inseconds;       % <— own field, to
pass RTs on
        cfg.trialdef.eventtype  = 'UPPT001';
        cfg.trialdef.eventvalue = [1:32];
        cfg = ft_definetrial(cfg);

With as function:

function [trl, event] = trialfun_move(cfg)

        % read header information and events from dataset
        hdr   = ft_read_header(cfg.dataset);
        event = ft_read_event(cfg.dataset);

        % search for events of interest, get value and sample
        value  = [event(find(strcmp(cfg.trialdef.eventtype,
{event.type}))).value]';
        sample = [event(find(strcmp(cfg.trialdef.eventtype,
{event.type}))).sample]';

        % define trial: starts at picture onset, stops at movement onset
(response)
        trl_begin = sample;
        trl_end   = sample + round(cfg.trialdef.rt * hdr.Fs);
        offset    = repmat(0, numel(value), 1);
        trl       = [trl_begin trl_end offset value cfg.trialdef.rt];

end % end function

The trial definition block is then followed by preprocessing and moving the
0 time point from picture onset to movement onset using ft_redefinetrial:

        % preprocessing
        cfg.channel = {'MEG'};
        cfg.continuous = 'yes';
        cfg.bpfilter = 'yes';
        cfg.bpfreq = [1 30];
        data = ft_preprocessing(cfg);

        % shift 0 time point from picture to movement onset
        cfg = [];
        cfg.offset = - round(movement_rt_inseconds * data.fsample);
        data = ft_redefinetrial(cfg, data);

Is this a correct approach, and am I correct in assuming that with this
last step, the 0 time point is now correctly shifted from picture onset to
movement onset, as the first sample is defined to be minus RT earlier than
the 0 time point? Is there a way to check this in the data structure?
Thanks for any help.

Best regards,
Marcel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/ad7da4d2/attachment.htm>

From jan.schoffelen at donders.ru.nl  Thu May  7 09:17:10 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Thu, 7 May 2020 07:17:10 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
Message-ID: <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs




J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/0f27c5b4/attachment.htm>

From jan.schoffelen at donders.ru.nl  Thu May  7 09:43:26 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Thu, 7 May 2020 07:43:26 +0000
Subject: [FieldTrip] define response onset as 0 point, looking back
In-Reply-To: <CAChwwKszJUEzUL==q_F+2o-NYjQJM-MOU8VWm9Fmc=shCN_K7A@mail.gmail.com>
References: <CAChwwKszJUEzUL==q_F+2o-NYjQJM-MOU8VWm9Fmc=shCN_K7A@mail.gmail.com>
Message-ID: <DA6B4A2D-6C58-4E85-8232-E81E9F087DA0@donders.ru.nl>

Dear Marcel,

This looks good, indeed. To be sure about this, you can check the first elements in each of the trials’ corresponding time vectors. These now should be the negative of the trial specific reaction time: data.time{i}(1) ~= -movement_rt_inseconds(i); (give or take a sample)

Best wishes,
Jan-Mathijs




On 7 May 2020, at 01:50, Marcel van den Velde <marcel.van.den.velde at gmail.com<mailto:marcel.van.den.velde at gmail.com>> wrote:

Dear all,

I am doing a MEG analysis on hand movement preparation: subjects are presented with visual stimuli (coded in the trigger channel) and have to respond by moving their hand. The study requires that I investigate the ERFs prior to the movement onset (but not capturing anything pre-stimulus). How can I best move the 0 point from stimulus onset to movement onset and look back?

What I have now is the following, but I am not sure whether this is correct:

First a trial definition calling an own function and an own added field to assign the response time (cfg.trialdef.rt)

        % trial definition
        cfg = [];
        cfg.dataset = subject_meg_data;
        cfg.trialfun = ‘trialfun_move’;                           % <— own function
        cfg.trialdef.rt = movement_rt_inseconds;       % <— own field, to pass RTs on
        cfg.trialdef.eventtype  = 'UPPT001';
        cfg.trialdef.eventvalue = [1:32];
        cfg = ft_definetrial(cfg);

With as function:

function [trl, event] = trialfun_move(cfg)

        % read header information and events from dataset
        hdr   = ft_read_header(cfg.dataset);
        event = ft_read_event(cfg.dataset);

        % search for events of interest, get value and sample
        value  = [event(find(strcmp(cfg.trialdef.eventtype, {event.type}))).value]';
        sample = [event(find(strcmp(cfg.trialdef.eventtype, {event.type}))).sample]';

        % define trial: starts at picture onset, stops at movement onset (response)
        trl_begin = sample;
        trl_end   = sample + round(cfg.trialdef.rt * hdr.Fs);
        offset    = repmat(0, numel(value), 1);
        trl       = [trl_begin trl_end offset value cfg.trialdef.rt];

end % end function

The trial definition block is then followed by preprocessing and moving the 0 time point from picture onset to movement onset using ft_redefinetrial:

        % preprocessing
        cfg.channel = {'MEG'};
        cfg.continuous = 'yes';
        cfg.bpfilter = 'yes';
        cfg.bpfreq = [1 30];
        data = ft_preprocessing(cfg);

        % shift 0 time point from picture to movement onset
        cfg = [];
        cfg.offset = - round(movement_rt_inseconds * data.fsample);
        data = ft_redefinetrial(cfg, data);

Is this a correct approach, and am I correct in assuming that with this last step, the 0 time point is now correctly shifted from picture onset to movement onset, as the first sample is defined to be minus RT earlier than the 0 time point? Is there a way to check this in the data structure? Thanks for any help.

Best regards,
Marcel
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/a3db8dd4/attachment.htm>

From marcel.van.den.velde at gmail.com  Thu May  7 13:38:37 2020
From: marcel.van.den.velde at gmail.com (Marcel van den Velde)
Date: Thu, 7 May 2020 13:38:37 +0200
Subject: [FieldTrip] define response onset as 0 point, looking back
In-Reply-To: <DA6B4A2D-6C58-4E85-8232-E81E9F087DA0@donders.ru.nl>
References: <CAChwwKszJUEzUL==q_F+2o-NYjQJM-MOU8VWm9Fmc=shCN_K7A@mail.gmail.com>
 <DA6B4A2D-6C58-4E85-8232-E81E9F087DA0@donders.ru.nl>
Message-ID: <CAChwwKsLXPpjE-k53Pm7a8H+LrkQL1oCL7f=DjS29Y9+Khd0hw@mail.gmail.com>

Dear Mathijs,

Thank you for your reply. I will run this check to be sure.

Best regards,
Marcel

On Thu, May 7, 2020 at 10:11 AM Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl> wrote:

> Dear Marcel,
>
> This looks good, indeed. To be sure about this, you can check the first
> elements in each of the trials’ corresponding time vectors. These now
> should be the negative of the trial specific reaction time: data.time{i}(1)
> ~= -movement_rt_inseconds(i); (give or take a sample)
>
> Best wishes,
> Jan-Mathijs
>
>
>
>
> On 7 May 2020, at 01:50, Marcel van den Velde <
> marcel.van.den.velde at gmail.com> wrote:
>
> Dear all,
>
> I am doing a MEG analysis on hand movement preparation: subjects are
> presented with visual stimuli (coded in the trigger channel) and have to
> respond by moving their hand. The study requires that I investigate the
> ERFs prior to the movement onset (but not capturing anything pre-stimulus).
> How can I best move the 0 point from stimulus onset to movement onset and
> look back?
>
> What I have now is the following, but I am not sure whether this is
> correct:
>
> First a trial definition calling an own function and an own added field to
> assign the response time (cfg.trialdef.rt)
>
>         % trial definition
>         cfg = [];
>         cfg.dataset = subject_meg_data;
>         cfg.trialfun = ‘trialfun_move’;                           % <— own
> function
>         cfg.trialdef.rt = movement_rt_inseconds;       % <— own field, to
> pass RTs on
>         cfg.trialdef.eventtype  = 'UPPT001';
>         cfg.trialdef.eventvalue = [1:32];
>         cfg = ft_definetrial(cfg);
>
> With as function:
>
> function [trl, event] = trialfun_move(cfg)
>
>         % read header information and events from dataset
>         hdr   = ft_read_header(cfg.dataset);
>         event = ft_read_event(cfg.dataset);
>
>         % search for events of interest, get value and sample
>         value  = [event(find(strcmp(cfg.trialdef.eventtype,
> {event.type}))).value]';
>         sample = [event(find(strcmp(cfg.trialdef.eventtype,
> {event.type}))).sample]';
>
>         % define trial: starts at picture onset, stops at movement onset
> (response)
>         trl_begin = sample;
>         trl_end   = sample + round(cfg.trialdef.rt * hdr.Fs);
>         offset    = repmat(0, numel(value), 1);
>         trl       = [trl_begin trl_end offset value cfg.trialdef.rt];
>
> end % end function
>
> The trial definition block is then followed by preprocessing and moving
> the 0 time point from picture onset to movement onset using
> ft_redefinetrial:
>
>         % preprocessing
>         cfg.channel = {'MEG'};
>         cfg.continuous = 'yes';
>         cfg.bpfilter = 'yes';
>         cfg.bpfreq = [1 30];
>         data = ft_preprocessing(cfg);
>
>         % shift 0 time point from picture to movement onset
>         cfg = [];
>         cfg.offset = - round(movement_rt_inseconds * data.fsample);
>         data = ft_redefinetrial(cfg, data);
>
> Is this a correct approach, and am I correct in assuming that with this
> last step, the 0 time point is now correctly shifted from picture onset to
> movement onset, as the first sample is defined to be minus RT earlier than
> the 0 time point? Is there a way to check this in the data structure?
> Thanks for any help.
>
> Best regards,
> Marcel
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/fa326487/attachment.htm>

From MGlassen at kesslerfoundation.org  Thu May  7 17:47:18 2020
From: MGlassen at kesslerfoundation.org (Michael Glassen  -  Biomedical Engineer)
Date: Thu, 7 May 2020 15:47:18 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
Message-ID: <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>

Hi Jan,

Thank you so much for your help, I just had a few follow up questions.

-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.

               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Thank you again so much for all your help!

Best,
Michael Glassen





-



From: fieldtrip <fieldtrip-bounces at science.ru.nl> On Behalf Of Schoffelen, J.M. (Jan Mathijs)
Sent: Thursday, May 7, 2020 3:17 AM
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/3cdda01a/attachment.htm>

From x.vrijdag at auckland.ac.nz  Fri May  8 01:34:10 2020
From: x.vrijdag at auckland.ac.nz (Xavier Vrijdag)
Date: Thu, 7 May 2020 23:34:10 +0000
Subject: [FieldTrip] [FORGED] Re: Computing source-level ROI EEG
 connectivity
Message-ID: <F1E73D4A-C462-404B-8A8A-45E012E47A4B@auckland.ac.nz>

Hi Michael,

I think Jan-Matthijs intended to do the following (which I do currently as well):

    %Calculate the channel covariance matrix for all exposures

            cfg = [];

            cfg.covariance = 'yes';

            cfg.covariancewindow = 'all';

            cfg.keeptrials  = 'yes';

            timelock_allexp = ft_timelockanalysis(cfg, data_filt);



            %Calculate the channel covariance matric for each exposure seperate

            timelock=cell(length(exposures),1);

            for j=1:length(exposures)

                cfg = [];

                cfg.covariance = 'yes';

                cfg.covariancewindow = 'all';

                cfg.trials = find(ismember(trialinfo, exposures{j}));

                cfg.keeptrials  = 'yes';

                timelock{j} = ft_timelockanalysis(cfg, data_filt);

            end

            if ~debug; clear data_filt; end



            %General source localisation

            cfg = [];

            cfg.headmodel = vol;

            cfg.elec = elec_aligned;

            cfg.grid = grid;

            cfg.method = 'lcmv';

            %cfg.lcmv.projectnoise='yes'; %needed for neural activity index

            cfg.lcmv.fixedori = 'yes';  %Project onto largest variance orientation

            cfg.lcmv.keepfilter = 'yes'; %Keep the beamformer weights

            cfg.lcmv.lambda = '5%'; %Regularise a little

            %      cfg.rawtrial    = 'yes';      % project each single trial through the filter.

            %      cfg.keeptrials  = 'yes';

            source_allexp = ft_sourceanalysis(cfg, timelock_allexp);

            if ~debug; clear timelock_allexp; end



            % source localisation for each exposure seperate using combined filter

            cfg = [];

            cfg.headmodel = vol;

            cfg.elec = elec_aligned;

            cfg.grid = grid;

            cfg.grid.filter = source_allexp.avg.filter; % use the common filter computed in the previous step!

            cfg.method = 'lcmv';

            %cfg.lcmv.projectnoise='yes'; %needed for neural activity index

            cfg.lcmv.fixedori = 'yes';  %Project onto largest variance orientation

            %cfg.lcmv.keepfilter = 'yes'; %Keep the beamformer weights

            cfg.lcmv.lambda = '5%'; %Regularise a little

            cfg.rawtrial    = 'yes';      % project each single trial through the filter.

            cfg.keeptrials  = 'yes';

            if ~debug; clear source_allexp; end
This calculates the filter for all exposures and then uses this filter to calculate the mom for each trial separate for each exposure (have both rawetrial and keeptrials on).

I had the same problem with running out of memory. I found that Fieldtrip was putting all the trials on 1 very long time axis (based on their previous time axis), with a lot of zeros in front and behind each sample. This created a huge data matrix, which was mostly empty. That why I realigned all time axes before the data goes into the timelockanalysis function:
            %align time axis (all time axis start at 0)
            data_filt.time(:)={0:1/data_filt.fsample:(length(data_filt.time{1})/data_filt.fsample-1/data_filt.fsample)};
This might be the case for you as well?

I trialled granger as well and couldn’t get a difference between exposures to various narcotic agents. I am currently working with mutual information, which seems to work reasonably well. Upside of MI over GC is its non-linear sensitivity.

Regards,

Xavier

From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org>
Reply to: FieldTrip discussion list <fieldtrip at science.ru.nl>
Date: Friday, 8 May 2020 at 3:55 AM
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: [FORGED] Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Jan,

Thank you so much for your help, I just had a few follow up questions.

-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.

               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Thank you again so much for all your help!

Best,
Michael Glassen





-



From: fieldtrip <fieldtrip-bounces at science.ru.nl> On Behalf Of Schoffelen, J.M. (Jan Mathijs)
Sent: Thursday, May 7, 2020 3:17 AM
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands






On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/2a5d9521/attachment.htm>

From xiew1202 at gmail.com  Fri May  8 02:40:38 2020
From: xiew1202 at gmail.com (Wanze Xie)
Date: Thu, 7 May 2020 20:40:38 -0400
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
Message-ID: <CAA6G0Y-Yhor+gHnBa3DCnxCUZ0WVmc089BhbEx=xkGqUcZ7fPg@mail.gmail.com>

Hi Michael,
In a recent paper we published
<https://bmcmedicine.biomedcentral.com/articles/10.1186/s12916-019-1431-5>,
I basically did what Jan-Mathijs recommended in his email. I generated the
eLORETA filter with the lead-field matrix and head models. I then used the
filter only to perform the cortical source reconstruction to get the
moments in 3 orientations for each dipole. The next step was to use the SVD
function (like PCA) to reduce the moments into one dimensional signal.  I
copied and pasted the part of the codes I used for these steps in the end
of this email. You can also find the entire program I used here:
https://github.com/happytudouni/SourceSpaceFunctionalConnectivityAnalysis

The templates we used were children's MRI templates, so I did the
parcellation outside of Fieldtrip. You can find that part of the codes in
the program as well.

I hope this helps and good luck.

Wanze

sourcedata = [];
ntrial = size(EEG_FT.trial,1);
ndipole = find(~cellfun(@isempty,efilter)); %This array equals
find(grid.inside);
%ndipole = find(grid.inside);
ntime = size(EEG_FT.time,2);
sourcedata.trial = NaN(ntrial,length(ndipole),ntime);
tic;
for i=1:ntrial
fprintf('%.0f out of %.0f \n',i,ntrial); %Inform the process (n out of the
total trial number);
for j = 1:length(ndipole)
moments = efilter{ndipole(j)} *squeeze(EEG_FT.trial(i,:,:));
[u, s, v] = svd(moments, 'econ'); %Find the dimension
explaining/representing the most variance;
m = u(:,1)'*moments; %this m equals to or has a linear relationship with
v(:,1)', e.g., all the elements are 3 times bigger than the elements in
v(:,1)';
%Or simply do: %m = v(:,1)';
sourcedata.trial(i,j,:) = m;
end
end
analysistime = toc;
disp(['The Source analysis took ' num2str(analysistime) 's']);

Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org>
于2020年5月7日周四 上午11:48写道：

> Hi Jan,
>
>
>
> Thank you so much for your help, I just had a few follow up questions.
>
>
>
> *-I would check whether the individual trials after source reconstruction
> yield meaningful values in the ‘mom’-field. Particularly, are the different
> trials different? Do the time series look meaningful to begin with (both in
> terms of signal magnitude and ’shape’)? The reason I ask, is that I am not
> fully sure whether the ‘rawtrial’ option is behaving according to your
> expectations.*
>
> *-Another way for getting the mom would be to use cfg.keepfilter in
> ft_sourceanalysis, and left-multiply each dipole location’s ’spatial
> filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.*
>
>
>
>                I went through and plotted a couple different time series
> from the mom field from different trials and the same dipole, they are not
> equal and the shape looks ok to me, the magnitudes range from 10^-7 to
> 10^-4, is that normal? Source was calculated with everything in meters if
> that matters. Can you explain a little more the other method for
> calculating mom? The only option I have to add is keepfilter to
> sourceanalysis? And then I multiply each of these filters against the trial
> data matrix and it will leave me with what rawtrial is giving me but more
> reliably? Can I then still use the parcellate option on the output here? Or
> is this not necessary as rawtrial seems to be working?
>
>
>
> *-In order to get a ‘parcellated’ representation of your source level
> data, I recommend to use ft_sourceparcellate, which should achieve the
> parcellation you performed by hand (with the binary masks).*
>
>
>
>                I tried using the ft_sourceparcellate function but I was
> running into a memory issue when ran on the rawtrial source, and when I
> remove that option and run it on the default trial-averaged sources I get a
> different error, which is pasted below. mri2 is the broddman area atlas
> interpolated onto my source model. Also, is there any way to parcellate
> twice with the function like I am doing by hand? The broddman area atlas I
> have is not divided into left and right hemispheres so I have another atlas
> I am using that is divided into hemispheres.
>
>
>
> *mri2 = *
>
>
>
> *                                             struct with fields:*
>
>
>
> *                                             pos: [8196×3 double]*
>
> *                                              tri: [16384×3 double]*
>
> *                                             unit: 'm'*
>
> *                                              tissue: [8196×1 double]*
>
> *                                             tissuelabel: {1×70 cell}*
>
> *                                             cfg: [1×1 struct]*
>
>
>
> *                              cfg = *
>
>
>
> *                                             struct with fields:*
>
>
>
> *                                              method: 'mean'*
>
> *                                             parcellation: 'tissue'*
>
> *                                               parameter: 'mom'*
>
>
>
> *ft_sourceparcellate(cfg,sourceEEG,mri2)*
>
> *there is no "Dentate" in "tissue"*
>
> *there is no "Hypothalamus" in "tissue"*
>
> *there is no "Substania Nigra" in "tissue"*
>
> *there is no "Caudate Tail" in "tissue"*
>
> *there is no "Putamen" in "tissue"*
>
> *there is no "Medial Geniculum Body" in "tissue"*
>
> *there is no "Lateral Globus Pallidus" in "tissue"*
>
> *there is no "Subthalamic Nucleus" in "tissue"*
>
> *there is no "Medial Globus Pallidus" in "tissue"*
>
> *there is no "Lateral Geniculum Body" in "tissue"*
>
> *there is no "Anterior Commissure" in "tissue"*
>
> *there is no "Ventral Posterior Lateral Nucleus" in "tissue"*
>
> *there is no "Ventral Posterior Medial Nucleus" in "tissue"*
>
> *there is no "Ventral Lateral Nucleus" in "tissue"*
>
> *there is no "Ventral Anterior Nucleus" in "tissue"*
>
> *there is no "Caudate Body" in "tissue"*
>
> *there is no "Lateral Posterior Nucleus" in "tissue"*
>
> *there is no "Lateral Dorsal Nucleus" in "tissue"*
>
> *there is no "Midline Nucleus" in "tissue"*
>
> *there are in total 8196 positions, 8190 positions are inside the brain,
> 2611 positions have a label*
>
> *2609 of the positions inside the brain have a label*
>
> *2609 of the labeled positions are inside the brain*
>
> *5581 of the positions inside the brain do not have a label*
>
> *creating 70 parcels for parameter mom by taking the mean*
>
> *computing parcellation*
>
> *Index exceeds the number of array elements (0).*
>
>
>
> *Error in ft_sourceparcellate>cellmean1 (line 488)*
>
> *y = x{1};*
>
>
>
> *Error in ft_sourceparcellate (line 226)*
>
> *                                             tmp(j,:,:) =
> cellmean1(dat(seg==j));*
>
>
>
>                -If I cannot get source parcellate to work, does my method
> of creating a mask and pulling out the source powers seem sound? I see that
> I should use mom instead of pow, so would I then just take all the voxels
> in an ROI and average the x direction together, the y direction together
> and the z together? Then find the direction with the largest power and use
> that as my 1by x time series power(using svd as described in
> documentation)? This is what I’m assuming sourceparcellate does if I select
> ‘eig’ as the method.
>
>
>
> *ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc),
> in the spectral analysis you should probably use a decent amount of zero
> padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data
> that stands a chance to get a stable factorization.*
>
>
>
>
>
>                -Finally, if I choose to go for granger, what kind of
> cfg.pad and tapsmofrq would you recommend? I am mostly interested in the
> beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)
>
>
>
> Thank you again so much for all your help!
>
>
>
> Best,
>
> Michael Glassen
>
>
>
>
>
>
>
>
>
>
>
> -
>
>
>
>
>
>
>
> *From:* fieldtrip <fieldtrip-bounces at science.ru.nl> *On Behalf Of *Schoffelen,
> J.M. (Jan Mathijs)
> *Sent:* Thursday, May 7, 2020 3:17 AM
> *To:* FieldTrip discussion list <fieldtrip at science.ru.nl>
> *Subject:* Re: [FieldTrip] Computing source-level ROI EEG connectivity
>
>
>
> Dear Michael,
>
>
>
> It looks that you already got quite far! I agree that the DTF values do
> not make much sense.
>
>
>
> a few pointers:
>
>
>
> -I would use some regularisation for  the MNE reconstruction.
>
> -I would check whether the individual trials after source reconstruction
> yield meaningful values in the ‘mom’-field. Particularly, are the different
> trials different? Do the time series look meaningful to begin with (both in
> terms of signal magnitude and ’shape’)? The reason I ask, is that I am not
> fully sure whether the ‘rawtrial’ option is behaving according to your
> expectations.
>
> -Another way for getting the mom would be to use cfg.keepfilter in
> ft_sourceanalysis, and left-multiply each dipole location’s ’spatial
> filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
>
> -IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and
> connectivity estimation. You should work with the mom.
>
> -In order to get a ‘parcellated’ representation of your source level data,
> I recommend to use ft_sourceparcellate, which should achieve the
> parcellation you performed by hand (with the binary masks).
>
> -The parcellation operation can be an average of the mom across the
> dipoles that belong to a parcel, but an alternative might be the the 1st
> principal component. The advantage of the latter would be that the
> per-parcel signal will be reduced to a single time series (rather then 3
> x/y/z orientation time courses), which is convenient (and required) for the
> interpretation of the subsequent computations.
>
> -You may want to think a bit about the depth weighting, since the MNE
> favors superficial locations in terms of amplitude, and this will also
> percolate to the way the parcellated time series are computed.
>
> -IMPORTANT: using ‘dtf’ without any additional specification of parameters
> is probably not what you want here. The reason is that under the hood a
> multivariate factorization of the spectral matrix is performed (at least:
> an attempt is made), which will miserably fail in your case. The reason for
> this failure (thinking a bit more about this, I am quite surprised that it
> worked to begin with) is the fact that you ask for a factorization of a
> size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of
> the matrix is less than the number of channels in your EEG array. Even if
> Nparcel is less than the number of EEG electrodes, this factorization will
> be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as
> a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This
> results in a parcel-pairwise factorization (which is hopefully stable most
> of the time). I am not a fan of dtf/pdc anyway given that the measures are
> claimed to provide estimates unproblematic estimates that are interpretable
> without any caveats.
>
> -ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc),
> in the spectral analysis you should probably use a decent amount of zero
> padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data
> that stands a chance to get a stable factorization.
>
>
>
> So, no definitive answers unfortunately, but perhaps some food for thought
> that might get you closer to a good result.
>
>
>
> Good luck and keep up the good work,
>
>
>
> Jan-Mathijs
>
>
>
>
>
>
>
> J.M.Schoffelen, MD PhD
> Associate PI, VIDI-fellow - PI, language in interaction
> Telephone: +31-24-3614793
>
> Physical location: room 00.028
>
> Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands
>
>
>
>
>
> On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <
> MGlassen at kesslerfoundation.org> wrote:
>
>
>
> Hi all,
>
>
>
> I am having issues using fieldtrip for source reconstruction and
> connectivity analysis with preprocessed EEG data. I believe the issue is
> occurring when I try to project my sources to specific ROIs before getting
> the connectivity. I have outlined my pipeline below:
>
>
>
> -Because I do not have subject MRIs, I am using a template headmodel and
> sourcemodel that come included with fieldtrip
>
>                - headmodel = standard_bem.mat
>
>                -sourcemodel = cortex_8196.surf.gii
>
>
>
> -After importing EEG data, I project the EEG electrodes to the scalp using
> the code below:
>
>                if strcmp(headmodel.type, 'bemcp')
>
>              scalp_index = 3;
>
> elseif strcmp(headmodel.type, 'dipoli')
>
>              scalp_index = 1;
>
> end
>
> cfg = [];
>
> cfg.method = 'project';
>
> cfg.headshape = headmodel.bnd(scalp_index);
>
>
>
> eegData.elec = ft_electroderealign(cfg, eegData.elec);
>
>
>
>
>
> -I then calculate covariance on a trial basis and calculate the leadfield
> matrix:
>
>
>
>                cfg = [];
>
> cfg.covariance = 'yes';
>
> cfg.covariancewindow = [-inf 0];
>
> cfg.keeptrials = 'yes';
>
> tlckEeg = ft_timelockanalysis(cfg, eegData);
>
> cfg         = [];
>
> cfg.elec    = tlckEeg.elec;   % sensor information
>
> cfg.channel = tlckEeg.label;  % the used channels
>
> cfg.grid    = sourcemodel;   % source points
>
> cfg.headmodel = headmodel;   % volume conduction model
>
> cfg.singleshell.batchsize = 5000; % speeds up the computation
>
> leadfield   = ft_prepare_leadfield(cfg);
>
>
>
>
>
> -Now with the leadfield calculated, I calculate sources on a trial basis
> here:
>
>
>
> cfg               = [];
>
> cfg.method        = 'mne';
>
> cfg.sourcemodel   = leadfield;
>
> cfg.headmodel     = headmodel;
>
> cfg.mne.prewhiten = 'yes';
>
> cfg.mne.lambda    = 0;
>
> cfg.mne.scalesourcecov = 'yes';
>
> cfg.rawtrial      = 'yes';
>
> sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
>
>                sourceEEG =
>
>
>
>                               struct with fields:
>
>
>
>                               time: [1×357 double]
>
>                               inside: [8196×1 logical]
>
>                               pos: [8196×3 double]
>
>                                tri: [16384×3 double]
>
>                               method: 'rawtrial'
>
>                               trial: [1×400 struct]
>
>                               df: 400
>
>                               cfg: [1×1 struct]
>
>
>
>
>
>                sourceEEG.trial =
>
>
>
>                               1×400 struct array with fields:
>
>
>
>                               mom
>
>                                pow
>
>                               noisecov
>
>
>
> size(sourceEEG.trial(1).pow)
>
>
>
> ans =
>
>
>
>                                              8196         357
>
>
>
> -So at this point I have 400 trials, and for each of these trials I have a
> time course of source power at 8196 voxels and 357 time points for each of
> those voxels.
>
> -I then import two atlases, one that includes broddman areas and one that
> includes left and right hemispheres. I interpolate these atlases onto my
> source model and get the following:
>
>                broddman =
>
> struct with fields:
>
>
>
>                                       pos: [8196×3 double]
>
>                                        tri: [16384×3 double]
>
>                                         unit: 'm'
>
>                                        tissue: [8196×1 double] (*each of
> these is a value 1-70, corresponding to which atlas entry the voxel is
> located in)*
>
>                                        tissuelabel: {1×70 cell}*(ROI
> labels for the atlas, includes broddman areas not separated by hemisphere)*
>
>                                       cfg: [1×1 struct]
>
> hemis2 =
>
> struct with fields:
>
> pos: [8196×3 double]
>
>                                       tri: [16384×3 double]
>
>                                         unit: 'm'
>
>                                         tissue: [8196×1 double] (*each of
> these is a value 1-7, corresponding to which atlas entry the voxel is
> located in)*
>
>
>
>                                          tissuelabel: {1×7 cell} *(ROI
> Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one
> inter-hemispheric)*
>
>                                       cfg: [1×1 struct]
>
>
>
>
>
> Now I create a binary mask for each left and right broddman area. For each
> ROI in the broddman area atlas(1-70), I find all voxels that are located
> within. This gives me a list of voxels for each broddman area. I then take
> each of these lists and find which are in the left hemisphere and which are
> in the right to get left and right broddman areas.
>
> After these steps I am left with 140 binary masks, (size 1x8196), which
> equal 1 if the voxel is contained in the specific ROI and 0 if it is not.
> Using these masks, I extract the time course power for each ROI by taking
> the mean power of every voxel in the roi at each time point:
>
>                     roiData(i,i3,i2) =
> mean(sourceEEG.trial(i2).pow(Masks{i},i3));
>
>
>
> where i = roi number,
>
>
>
>        i2 = trial number,
>
>
>
>        i3 = time point
>
>
>
> In order to get this data into fieldtrip format, I put ROI data into an
> EEGLAB structure along with 6 emg channels that were recorded at the same
> time and use eeglab2fieldtrip function to have a fieldtrip structure
> containing the broddman area sources as channels. (contained in *header*)
>
>
>
> After this I perform the final step of computing dtf connectivity between
> each of the source rois and the emg channels with the code below:
>
>
>
> cfg           = [];
>
> cfg.method    = 'mtmfft';
>
> cfg.taper     = 'dpss';
>
> cfg.output    = 'fourier';
>
> cfg.tapsmofrq = 2;
>
> freq          = ft_freqanalysis(cfg, header);
>
> cfg           = [];
>
> cfg.method    = 'dtf';
>
> dtf           = ft_connectivityanalysis(cfg, freq);
>
>
>
>
>
> The values I get in DTF are extremely low, 10^-20. I am not sure why but I
> believe it has to do with the way I am projecting source activations onto
> specific ROIs. Any help or advice on how to change my pipeline is
> appreciated.
>
>
>
>
>
> Best,
>
> Michael Glassen
>
>
>
>
>
>
>   ­­   _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
>
>
>
>   ­­
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200507/9da8f273/attachment.htm>

From jan.schoffelen at donders.ru.nl  Fri May  8 09:17:56 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Fri, 8 May 2020 07:17:56 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
Message-ID: <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200508/a68287bf/attachment.htm>

From MGlassen at kesslerfoundation.org  Fri May  8 16:15:42 2020
From: MGlassen at kesslerfoundation.org (Michael Glassen  -  Biomedical Engineer)
Date: Fri, 8 May 2020 14:15:42 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>,
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
Message-ID: <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200508/c20ddbd0/attachment.htm>

From jan.schoffelen at donders.ru.nl  Fri May  8 16:29:38 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Fri, 8 May 2020 14:29:38 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
Message-ID: <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>

Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs





On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200508/cd808629/attachment.htm>

From xiew1202 at gmail.com  Fri May  8 22:24:20 2020
From: xiew1202 at gmail.com (Wanze Xie)
Date: Fri, 8 May 2020 16:24:20 -0400
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
 <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
Message-ID: <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>

Hi Jan-Mathijs,
I have two short questions regarding your suggestions to Michael: 1) any
reason for why doing svd for concatenated trials would work better than
doing svd per trial?
2) If we do svd with concatenated trials do we need to re-segment the data
into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work
way more efficiently if they are applied to data in epochs rather than one
long trial, although I am not 100% assured.

Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>于2020年5月8日
周五上午10:35写道：

> Hi Michael,
>
> The WFU atlas is a volumetrically defined atlas, correct? So, in order for
> the parcellation to work, the atlas needs to be mapped onto the cortically
> constrained sheet of dipoles that you used for source reconstruction.
> This is not entirely trivial, but doable. If you obtained your atlas
> already as represented on a cortically constrained set of locations, then
> you need to ensure that these locations topologically map to the dipole
> locations of your source model.
>
> Best wishes,
> Jan-Mathijs
>
>
>
>
>
> On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <
> MGlassen at kesslerfoundation.org> wrote:
>
> Thank you everyone for the help!
>
> Just one final question, I got the Brodmann area atlas and the hemisphere
> atlas from this toolbox SPM “WFU-PickAtlas”.
>
> Does anyone know if there is a Brodmann area atlas that is known to work
> with fieldtrip?
>
> Best,
> Michael Glassen
> ------------------------------
> *From:* fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of
> Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
> *Sent:* Friday, May 8, 2020 3:17:56 AM
> *To:* FieldTrip discussion list
> *Subject:* Re: [FieldTrip] Computing source-level ROI EEG connectivity
>
> Hi Michael,
>
> Adding to Wanze’s and Xavier’s replies:
>
>
>                I went through and plotted a couple different time series
> from the mom field from different trials and the same dipole, they are not
> equal and the shape looks ok to me, the magnitudes range from 10^-7 to
> 10^-4, is that normal? Source was calculated with everything in meters if
> that matters. Can you explain a little more the other method for
> calculating mom? The only option I have to add is keepfilter to
> sourceanalysis? And then I multiply each of these filters against the trial
> data matrix and it will leave me with what rawtrial is giving me but more
> reliably? Can I then still use the parcellate option on the output here? Or
> is this not necessary as rawtrial seems to be working?
>
>
> If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d
> need to look in the code myself in some more detail) because historically
> the ‘rawtrial’-functionality was implemented for the beamformer algorithms,
> and not for the MNE. As such, it has never been tested thoroughly for MNE,
> so although it seems to produce an output for you, I am not 100% sure that
> it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality
> for the beamformers is shaky in itself, and we still have it on our
> to-do-list to make the code more internally consistent and correct.
>
>
> *-In order to get a ‘parcellated’ representation of your source level
> data, I recommend to use ft_sourceparcellate, which should achieve the
> parcellation you performed by hand (with the binary masks).*
>
>                I tried using the ft_sourceparcellate function but I was
> running into a memory issue when ran on the rawtrial source, and when I
> remove that option and run it on the default trial-averaged sources I get a
> different error, which is pasted below. mri2 is the broddman area atlas
> interpolated onto my source model. Also, is there any way to parcellate
> twice with the function like I am doing by hand? The broddman area atlas I
> have is not divided into left and right hemispheres so I have another atlas
> I am using that is divided into hemispheres.
>
> *mri2 =*
>
> *                                             struct with fields:*
>
> *                                             pos: [8196×3 double]*
> *                                              tri: [16384×3 double]*
> *                                             unit: 'm'*
> *                                              tissue: [8196×1 double]*
> *                                             tissuelabel: {1×70 cell}*
> *                                             cfg: [1×1 struct]*
>
> *                              cfg =*
>
> *                                             struct with fields:*
>
> *                                              method: 'mean'*
> *                                             parcellation: 'tissue'*
> *                                               parameter: 'mom'*
>
> *ft_sourceparcellate(cfg,sourceEEG,mri2)*
> *there is no "Dentate" in "tissue"*
> *there is no "Hypothalamus" in "tissue"*
> *there is no "Substania Nigra" in "tissue"*
> *there is no "Caudate Tail" in "tissue"*
> *there is no "Putamen" in "tissue"*
> *there is no "Medial Geniculum Body" in "tissue"*
> *there is no "Lateral Globus Pallidus" in "tissue"*
> *there is no "Subthalamic Nucleus" in "tissue"*
> *there is no "Medial Globus Pallidus" in "tissue"*
> *there is no "Lateral Geniculum Body" in "tissue"*
> *there is no "Anterior Commissure" in "tissue"*
> *there is no "Ventral Posterior Lateral Nucleus" in "tissue"*
> *there is no "Ventral Posterior Medial Nucleus" in "tissue"*
> *there is no "Ventral Lateral Nucleus" in "tissue"*
> *there is no "Ventral Anterior Nucleus" in "tissue"*
> *there is no "Caudate Body" in "tissue"*
> *there is no "Lateral Posterior Nucleus" in "tissue"*
> *there is no "Lateral Dorsal Nucleus" in "tissue"*
> *there is no "Midline Nucleus" in "tissue"*
> *there are in total 8196 positions, 8190 positions are inside the brain,
> 2611 positions have a label*
> *2609 of the positions inside the brain have a label*
> *2609 of the labeled positions are inside the brain*
> *5581 of the positions inside the brain do not have a label*
> *creating 70 parcels for parameter mom by taking the mean*
> *computing parcellation*
> *Index exceeds the number of array elements (0).*
>
> *Error in ft_sourceparcellate>cellmean1 (line 488)*
> *y = x{1};*
>
> *Error in ft_sourceparcellate (line 226)*
> *                                             tmp(j,:,:) =
> cellmean1(dat(seg==j));*
>
>                -If I cannot get source parcellate to work, does my method
> of creating a mask and pulling out the source powers seem sound? I see that
> I should use mom instead of pow, so would I then just take all the voxels
> in an ROI and average the x direction together, the y direction together
> and the z together? Then find the direction with the largest power and use
> that as my 1by x time series power(using svd as described in
> documentation)? This is what I’m assuming sourceparcellate does if I select
> ‘eig’ as the method.
>
>
> -With regard to thte parcellation: understood if memory limitations
> prevent you from using it. Yet, the error message you get when using the
> trial-averaged data suggests an issue with your atlas. Where did you get it
> from? It looks as if only 2611 out of the 8196 cortical locations have a
> label. Is that according to your expectations?
> -If indeed you are to manually parcellate (with the mask), you can do one
> of the following:
>   * average x/y/z across dipole locations, followed by an svd (I’d
> recommend to do this svd on the trial-concatenated data, rather than on a
> per-trial basis)
>   * (to mimick the ‘eig’ method): concatenate the time series across
> dipole locations (and trials), followed by a single svd on the whole matrix.
>
>
>
>
> *ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc),
> in the spectral analysis you should probably use a decent amount of zero
> padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data
> that stands a chance to get a stable factorization.*
>
>
>                -Finally, if I choose to go for granger, what kind of
> cfg.pad and tapsmofrq would you recommend? I am mostly interested in the
> beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)
>
>
> Irrespective of using granger or the disrecommended dtf/pdc, all
> techniques that require a spectral factorization need padding and
> smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a
> cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of
> ‘wet finger work’, as we sould say in Dutch -> google for ’natte
> vingerwerk’ if you want to learn more).
>
> Best wishes,
> Jan-Mathijs
>
>
> *Subject:* Re: [FieldTrip] Computing source-level ROI EEG connectivity
>
> Dear Michael,
>
> It looks that you already got quite far! I agree that the DTF values do
> not make much sense.
>
> a few pointers:
>
> -I would use some regularisation for  the MNE reconstruction.
> -I would check whether the individual trials after source reconstruction
> yield meaningful values in the ‘mom’-field. Particularly, are the different
> trials different? Do the time series look meaningful to begin with (both in
> terms of signal magnitude and ’shape’)? The reason I ask, is that I am not
> fully sure whether the ‘rawtrial’ option is behaving according to your
> expectations.
> -Another way for getting the mom would be to use cfg.keepfilter in
> ft_sourceanalysis, and left-multiply each dipole location’s ’spatial
> filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
> -IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and
> connectivity estimation. You should work with the mom.
> -In order to get a ‘parcellated’ representation of your source level data,
> I recommend to use ft_sourceparcellate, which should achieve the
> parcellation you performed by hand (with the binary masks).
> -The parcellation operation can be an average of the mom across the
> dipoles that belong to a parcel, but an alternative might be the the 1st
> principal component. The advantage of the latter would be that the
> per-parcel signal will be reduced to a single time series (rather then 3
> x/y/z orientation time courses), which is convenient (and required) for the
> interpretation of the subsequent computations.
> -You may want to think a bit about the depth weighting, since the MNE
> favors superficial locations in terms of amplitude, and this will also
> percolate to the way the parcellated time series are computed.
> -IMPORTANT: using ‘dtf’ without any additional specification of parameters
> is probably not what you want here. The reason is that under the hood a
> multivariate factorization of the spectral matrix is performed (at least:
> an attempt is made), which will miserably fail in your case. The reason for
> this failure (thinking a bit more about this, I am quite surprised that it
> worked to begin with) is the fact that you ask for a factorization of a
> size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of
> the matrix is less than the number of channels in your EEG array. Even if
> Nparcel is less than the number of EEG electrodes, this factorization will
> be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as
> a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This
> results in a parcel-pairwise factorization (which is hopefully stable most
> of the time). I am not a fan of dtf/pdc anyway given that the measures are
> claimed to provide estimates unproblematic estimates that are interpretable
> without any caveats.
> -ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc),
> in the spectral analysis you should probably use a decent amount of zero
> padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data
> that stands a chance to get a stable factorization.
>
> So, no definitive answers unfortunately, but perhaps some food for thought
> that might get you closer to a good result.
>
> Good luck and keep up the good work,
>
> Jan-Mathijs
>
>
>
>
> J.M.Schoffelen, MD PhD
> Associate PI, VIDI-fellow - PI, language in interaction
> Telephone: +31-24-3614793
> Physical location: room 00.028
>
> Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands
>
>
>
>
> On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <
> MGlassen at kesslerfoundation.org> wrote:
>
>
> Hi all,
>
>
>
> I am having issues using fieldtrip for source reconstruction and
> connectivity analysis with preprocessed EEG data. I believe the issue is
> occurring when I try to project my sources to specific ROIs before getting
> the connectivity. I have outlined my pipeline below:
>
>
>
> -Because I do not have subject MRIs, I am using a template headmodel and
> sourcemodel that come included with fieldtrip
>
>                - headmodel = standard_bem.mat
>
>                -sourcemodel = cortex_8196.surf.gii
>
>
>
> -After importing EEG data, I project the EEG electrodes to the scalp using
> the code below:
>                if strcmp(headmodel.type, 'bemcp')
>              scalp_index = 3;
> elseif strcmp(headmodel.type, 'dipoli')
>              scalp_index = 1;
> end
> cfg = [];
> cfg.method = 'project';
> cfg.headshape = headmodel.bnd(scalp_index);
>
> eegData.elec = ft_electroderealign(cfg, eegData.elec);
>
>
> -I then calculate covariance on a trial basis and calculate the leadfield
> matrix:
>
>                cfg = [];
> cfg.covariance = 'yes';
> cfg.covariancewindow = [-inf 0];
> cfg.keeptrials = 'yes';
> tlckEeg = ft_timelockanalysis(cfg, eegData);
> cfg         = [];
> cfg.elec    = tlckEeg.elec;   % sensor information
> cfg.channel = tlckEeg.label;  % the used channels
> cfg.grid    = sourcemodel;   % source points
> cfg.headmodel = headmodel;   % volume conduction model
> cfg.singleshell.batchsize = 5000; % speeds up the computation
> leadfield   = ft_prepare_leadfield(cfg);
>
>
> -Now with the leadfield calculated, I calculate sources on a trial basis
> here:
>
> cfg               = [];
> cfg.method        = 'mne';
> cfg.sourcemodel   = leadfield;
> cfg.headmodel     = headmodel;
> cfg.mne.prewhiten = 'yes';
> cfg.mne.lambda    = 0;
> cfg.mne.scalesourcecov = 'yes';
> cfg.rawtrial      = 'yes';
> sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
>                sourceEEG =
>
>                               struct with fields:
>
>                               time: [1×357 double]
>                               inside: [8196×1 logical]
>                               pos: [8196×3 double]
>                                tri: [16384×3 double]
>                               method: 'rawtrial'
>                               trial: [1×400 struct]
>                               df: 400
>                               cfg: [1×1 struct]
>
>
>                sourceEEG.trial =
>
>                               1×400 struct array with fields:
>
>                               mom
>                                pow
>                               noisecov
>
> size(sourceEEG.trial(1).pow)
>
> ans =
>
>                                              8196         357
>
>
>
> -So at this point I have 400 trials, and for each of these trials I have a
> time course of source power at 8196 voxels and 357 time points for each of
> those voxels.
>
> -I then import two atlases, one that includes broddman areas and one that
> includes left and right hemispheres. I interpolate these atlases onto my
> source model and get the following:
>
>                broddman =
>
> struct with fields:
>
>
>
>                                       pos: [8196×3 double]
>
>                                        tri: [16384×3 double]
>
>                                         unit: 'm'
>
>                                        tissue: [8196×1 double] (*each of
> these is a value 1-70, corresponding to which atlas entry the voxel is
> located in)*
>
>                                        tissuelabel: {1×70 cell}*(ROI
> labels for the atlas, includes broddman areas not separated by hemisphere)*
>
>                                       cfg: [1×1 struct]
>
> hemis2 =
>
> struct with fields:
>
> pos: [8196×3 double]
>
>                                       tri: [16384×3 double]
>
>                                         unit: 'm'
>
>                                         tissue: [8196×1 double] (*each of
> these is a value 1-7, corresponding to which atlas entry the voxel is
> located in)*
>
>
>
>                                          tissuelabel: {1×7 cell} *(ROI
> Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one
> inter-hemispheric)*
>
>                                       cfg: [1×1 struct]
>
>
>
>
>
> Now I create a binary mask for each left and right broddman area. For each
> ROI in the broddman area atlas(1-70), I find all voxels that are located
> within. This gives me a list of voxels for each broddman area. I then take
> each of these lists and find which are in the left hemisphere and which are
> in the right to get left and right broddman areas.
>
> After these steps I am left with 140 binary masks, (size 1x8196), which
> equal 1 if the voxel is contained in the specific ROI and 0 if it is not.
> Using these masks, I extract the time course power for each ROI by taking
> the mean power of every voxel in the roi at each time point:
>                     roiData(i,i3,i2) =
> mean(sourceEEG.trial(i2).pow(Masks{i},i3));
>
> where i = roi number,
>
>        i2 = trial number,
>
>        i3 = time point
>
> In order to get this data into fieldtrip format, I put ROI data into an
> EEGLAB structure along with 6 emg channels that were recorded at the same
> time and use eeglab2fieldtrip function to have a fieldtrip structure
> containing the broddman area sources as channels. (contained in *header*)
>
> After this I perform the final step of computing dtf connectivity between
> each of the source rois and the emg channels with the code below:
>
> cfg           = [];
> cfg.method    = 'mtmfft';
> cfg.taper     = 'dpss';
> cfg.output    = 'fourier';
> cfg.tapsmofrq = 2;
> freq          = ft_freqanalysis(cfg, header);
> cfg           = [];
> cfg.method    = 'dtf';
> dtf           = ft_connectivityanalysis(cfg, freq);
>
>
> The values I get in DTF are extremely low, 10^-20. I am not sure why but I
> believe it has to do with the way I am projecting source activations onto
> specific ROIs. Any help or advice on how to change my pipeline is
> appreciated.
>
>
> Best,
> Michael Glassen
>
>
>
>
>
>   ­­   _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
>
>
>   ­­   _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
>
>   ­­
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200508/4767a65b/attachment.htm>

From jan.schoffelen at donders.ru.nl  Sat May  9 10:11:51 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Sat, 9 May 2020 08:11:51 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
 <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
 <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>
Message-ID: <1C0AF287-1DF7-4B7C-8E5F-F6B435D09BD6@donders.ru.nl>

Hi Wanze,

I have two short questions regarding your suggestions to Michael: 1) any reason for why doing svd for concatenated trials would work better than doing svd per trial?

Well, it’s not that ‘it works better’, but using a per trial svd will result in a different orientation estimate per trial, which then inherently assumes a source model that fixes the location of the dipole, but not its orientation.

2) If we do svd with concatenated trials do we need to re-segment the data into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work way more efficiently if they are applied to data in epochs rather than one long trial, although I am not 100% assured.

Indeed, in most situations (particularly if the experimental protocol is epoch based) it is mandatory to maintain the epoch-structure in the spectral decomposition and connectivity estimation step. To this end the concatenation step is an intermediate one, used only to compute the principal orientation, and this orientation can then be applied to the data structure that still contains the epochs, either using a for-loop across the individual epochs, or exploiting the external/cellfunction code, by a direct multiplication.

Best wishes,
Jan-Mathijs



Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>于2020年5月8日 周五上午10:35写道：
Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs





On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200509/5636fc31/attachment.htm>

From sarah.kirchler at gmail.com  Mon May 11 16:43:59 2020
From: sarah.kirchler at gmail.com (sarah.kirchler at gmail.com)
Date: Mon, 11 May 2020 16:43:59 +0200
Subject: [FieldTrip] Grand mean
Message-ID: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>

An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200511/87825190/attachment.htm>

From camille.maumet at inria.fr  Mon May 11 21:32:08 2020
From: camille.maumet at inria.fr (Camille Maumet)
Date: Mon, 11 May 2020 21:32:08 +0200 (CEST)
Subject: [FieldTrip] Call for talks for OHBM Open Science Room
Message-ID: <761420309.2592044.1589225528478.JavaMail.zimbra@inria.fr>



Dear members of the FieldTrip community, 


The [ https://zimbra.inria.fr/ossig.netlify.com/ | OHBM Open Science Special Interest Group (OS-SIG) ] would like to share two exciting announcements! 

    1. 

The call is now open for talks, demos, and discussions in this year's virtual Open Science Room (OSR). [ https://ohbm.github.io/osr2020/submit/ | Submit your idea now! ] 
    2. 

We are providing 20 mini-grants worth 100 USD each to help OSR speakers set up for online conferencing. Apply via the link above. 



The first deadline for submission is 15 May 2020 , after which initial talk recordings will start. The second and last deadline is on 15 June. For more information, please visit the [ https://ohbm.github.io/osr2020/ | OSR website ] and our [ https://ohbm.github.io/osr2020/faq/ | FAQ ] . 


What happens in the OSR? 


The OSR is the place for OHBM meeting attendees to discuss open research practices, learn from each other, collaborate, and to foster and grow an open and inclusive community. This year, presentations and discussions will focus on [ https://ohbm.github.io/osr2020/themes/ | three main themes ] : 

    1. 

Open Workflows 
    2. 

Open Data 2.0 
    3. 

The Past, Present and Future of Open Neuroimaging 



We will have [ https://ohbm.github.io/osr2020/formats/ | keynotes, lightning talks and demos ] , all related to the OSR themes, while emergent sessions can be scheduled for impromptu discussions. 


Can you contribute? 


We would also love for the community to be involved in building an unforgettable OSR experience. [ https://ohbm.github.io/osr2020/contribute/ | Please find more information about contributor roles and sign up here ] ! 


If you have any questions, please reach out to us at [ mailto:ohbm.osr at gmail.com | ohbm.osr at gmail.com ] and follow [ https://twitter.com/ohbmopen | @OHBMopen ] on Twitter or visit the [ https://ohbm.github.io/osr2020/ | OSR website ] for updates. 


Kind regards, 


Camille Maumet, Cassandra Gould van Praag and Stephan Heunis, on behalf of the OS-SIG 

-- 

[ https://ohbm.github.io/osr2020/ | OSR 2020 website ] 


[ https://ossig.netlify.com/ | OS-SIG website ] 

-- 
Camille Maumet, PhD 

Researcher 
Inria, Univ Rennes, CNRS, Inserm 
Campus de Beaulieu 
35042 Rennes Cedex, France 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200511/aa854736/attachment.htm>

From jan.schoffelen at donders.ru.nl  Tue May 12 14:17:02 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Tue, 12 May 2020 12:17:02 +0000
Subject: [FieldTrip] update to default spmversion
Message-ID: <2F27891C-2406-4174-86BB-1B4A2E96D340@donders.ru.nl>

Dear Fieldtrippers,

I hope you are all well in these strange times. I am reaching out to you all to notify you of a (small) change in default behaviour of FieldTrip functionality.

During the recent toolkit, which took place online, the participants worked on their own computers, causing a larger than usual variability on used MATLAB versions and Operating Systems. One issue we encountered was a compatibility problem with SPM-related mex-files. Specfically, when using the default version, which up until now has been spm8, certain functions did not work. We are typically reluctant to change default behavior of functions, but now we decided to upgrade the default SPM version to spm12, for a more stable user experience overall. We expect this change to be inconsequential for most of you, but would like to note that, when needed, you can always go back to using spm8, by specifying cfg.spmversion=’spm8’, wherever appropriate.

Stay safe and take care,

Jan-Mathijs


J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: kitchen table
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200512/606c7798/attachment.htm>

From jan.schoffelen at donders.ru.nl  Wed May 13 14:53:01 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Wed, 13 May 2020 12:53:01 +0000
Subject: [FieldTrip] Grand mean
In-Reply-To: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
References: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
Message-ID: <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>

Dear Sarah,

It is not clear what error message you get, nor why you think you should ft_timelockanalysis/ft_timelockgrandaverage/ft_topoplotER.

Some pointers:
-For a mathematical operation to be applied to numeric data that resides within a fieldtrip-style data structure you’d use ft_math.
-What you want to do (i.e. adding or subtracting estimates of frequency specific power estimated for different frequency bins) probably requires some manual intervention with the data, because FT will likely prevent you to do so, since it checks whether the frequency bins for the to-be-combined data structures match. I could type some recipe now, but since you are not too clear on the details so I’d rather not spend time on that now. Also, I’d like to give other people the opportunity to chime in here :).

Best wishes,
Jan-Mathijs

On 11 May 2020, at 16:43, sarah.kirchler at gmail.com<mailto:sarah.kirchler at gmail.com> wrote:

Dear Fieldtrip Users,

thank you for all the help you’ve given me already.
Now I am trying to make the sum and the difference of the Grand mean from/between two frequencies I measured with an EEG.
I read that it is possible to make a datastructure using {} within ft_timelockbaseline and then use the option cfg.operation(x1-x2 and so on) as a operation of function ft_topoplotER to make this sum/these differences.
Now my Problem is that I don’t need to make the baselinecorrection via ft_timelockbaseline because I don’t have the baseline in the datasegment I’m interested in. So I tried to build the datastructure for cfg.operation within ft_timelockanalysis but Fieldtrip doesn’t allow this and I get an error message.

My questions are now:
1. Can I make the difference also within the ft_timelockgrandavverage function or do I have to make the difference lawer in ft_topoplotER?
2. If so, how can I or form a datastructure I can use in cfg.operation or make the difference differently with some other function?

I hope you understand me,
to all you extraordinary brains: thank you in advance,

Sarah

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200513/6fa3f89e/attachment.htm>

From manuela.ruzzoli at gmail.com  Wed May 13 15:23:06 2020
From: manuela.ruzzoli at gmail.com (Manuela Ruzzoli)
Date: Wed, 13 May 2020 14:23:06 +0100
Subject: [FieldTrip] missing argument or incorrect argument data type
 function 'offset2time'
Message-ID: <CAKWrAn1+1a-_82C-8OAhnzcmCt3ap4wM_dAEozPdhj+uRKSZzg@mail.gmail.com>

Hi,
I need help solving an error that happens with Mac (Matlab2020a) but not
with Win (Matlab2017a), both using Fieldtrip 20191127.

The error occurs launching the ft_preprocessing and it's:
Check for missing argument or incorrect argument data type in call to
function 'offset2time'.
Error in ft_preprocessing (line 594)
        tim = offset2time(offset, hdr.Fs, size(dat,2));

Here the code (I call this after ft_definetrial, using a customized
cfg.trialfun,
which is working fine):
%%%%%%%%% Parameters for pre-processing%%%%%%
cfg.channel = {'A*', 'B*', 'EXG1', 'EXG2', 'EXG3', 'EXG4','Status'};
cfg.reref = 'yes';
cfg.refchannel = {'EXG3','EXG4'}; % mastoids
cfg.dftfilter  = 'yes';
cfg.dftfreq    = [50 100 150];
cfg.detrend   = 'yes';
cfg.demean = 'no';

    data = ft_preprocessing(cfg);
%%%%%%%%% %%%%%%%%%%%%%%%%%%%%

Thanks
Manu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200513/e5360246/attachment.htm>

From MGlassen at kesslerfoundation.org  Thu May 14 03:14:21 2020
From: MGlassen at kesslerfoundation.org (Michael Glassen  -  Biomedical Engineer)
Date: Thu, 14 May 2020 01:14:21 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <1C0AF287-1DF7-4B7C-8E5F-F6B435D09BD6@donders.ru.nl>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
 <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
 <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>,
 <1C0AF287-1DF7-4B7C-8E5F-F6B435D09BD6@donders.ru.nl>
Message-ID: <f7ac81d918194885a989ff0ebd4478ef@kesslerfoundation.org>

Hi Jan-Mathijs,


I implemented all of your suggestions but I had a quick question on the organization of the bivariate granger connectivity structure. From what I can understand, this should compute connectivity from each channel to every other channel. This is my connectivity structure:

struct with fields:

         labelcmb: {14762×2 cell}
           dimord: 'chancmb_freq'
    grangerspctrm: [14762×201 double]
             freq: [1×201 double]
              cfg: [1×1 struct]


And looking at an entry of labelcmb(14762,:) gives:

1×2 cell array

    {'RGAST[RGAST,LGAST]'}    {'LGAST[RGAST,LGAST]'}

So does this mean that grangerspctrm(14762,:) is the granger connectivity from RGAST to LGAST, or is it from LGAST to RGAST?


Best,
Michael Glassen



________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
Sent: Saturday, May 9, 2020 4:11:51 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Wanze,

I have two short questions regarding your suggestions to Michael: 1) any reason for why doing svd for concatenated trials would work better than doing svd per trial?

Well, it’s not that ‘it works better’, but using a per trial svd will result in a different orientation estimate per trial, which then inherently assumes a source model that fixes the location of the dipole, but not its orientation.

2) If we do svd with concatenated trials do we need to re-segment the data into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work way more efficiently if they are applied to data in epochs rather than one long trial, although I am not 100% assured.

Indeed, in most situations (particularly if the experimental protocol is epoch based) it is mandatory to maintain the epoch-structure in the spectral decomposition and connectivity estimation step. To this end the concatenation step is an intermediate one, used only to compute the principal orientation, and this orientation can then be applied to the data structure that still contains the epochs, either using a for-loop across the individual epochs, or exploiting the external/cellfunction code, by a direct multiplication.

Best wishes,
Jan-Mathijs



Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>于2020年5月8日 周五上午10:35写道：
Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs





On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/067ec885/attachment.htm>

From jan.schoffelen at donders.ru.nl  Thu May 14 08:02:38 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Thu, 14 May 2020 06:02:38 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <f7ac81d918194885a989ff0ebd4478ef@kesslerfoundation.org>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
 <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
 <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>
 <1C0AF287-1DF7-4B7C-8E5F-F6B435D09BD6@donders.ru.nl>
 <f7ac81d918194885a989ff0ebd4478ef@kesslerfoundation.org>
Message-ID: <845599A5-04B0-4FA6-9413-2817791727E3@donders.ru.nl>

Dear Michael,

The convention is left column to right column, so in this case RGAST to LGAST. the stuff between the ‘[‘ is to indicate that the pairwise metric has been obtained with a bivariate model that included LGAST and RGAST.

Best wishes,
Jan-Mathijs


On 14 May 2020, at 03:14, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi Jan-Mathijs,

I implemented all of your suggestions but I had a quick question on the organization of the bivariate granger connectivity structure. From what I can understand, this should compute connectivity from each channel to every other channel. This is my connectivity structure:

struct with fields:

         labelcmb: {14762×2 cell}
           dimord: 'chancmb_freq'
    grangerspctrm: [14762×201 double]
             freq: [1×201 double]
              cfg: [1×1 struct]

And looking at an entry of labelcmb(14762,:) gives:

1×2 cell array

    {'RGAST[RGAST,LGAST]'}    {'LGAST[RGAST,LGAST]'}

So does this mean that grangerspctrm(14762,:) is the granger connectivity from RGAST to LGAST, or is it from LGAST to RGAST?


Best,
Michael Glassen


________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Saturday, May 9, 2020 4:11:51 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Wanze,

I have two short questions regarding your suggestions to Michael: 1) any reason for why doing svd for concatenated trials would work better than doing svd per trial?

Well, it’s not that ‘it works better’, but using a per trial svd will result in a different orientation estimate per trial, which then inherently assumes a source model that fixes the location of the dipole, but not its orientation.

2) If we do svd with concatenated trials do we need to re-segment the data into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work way more efficiently if they are applied to data in epochs rather than one long trial, although I am not 100% assured.

Indeed, in most situations (particularly if the experimental protocol is epoch based) it is mandatory to maintain the epoch-structure in the spectral decomposition and connectivity estimation step. To this end the concatenation step is an intermediate one, used only to compute the principal orientation, and this orientation can then be applied to the data structure that still contains the epochs, either using a for-loop across the individual epochs, or exploiting the external/cellfunction code, by a direct multiplication.

Best wishes,
Jan-Mathijs



Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>于2020年5月8日 周五上午10:35写道：
Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs





On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/21c82f34/attachment.htm>

From sarah.kirchler at gmail.com  Thu May 14 09:32:33 2020
From: sarah.kirchler at gmail.com (Sarah Kirchler)
Date: Thu, 14 May 2020 09:32:33 +0200
Subject: [FieldTrip] Grand mean
In-Reply-To: <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>
References: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
 <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>
Message-ID: <CAKLTn3c0VQXxEUVAnPgda27Dp-om10_jxKEY6LdQQda_3g=SAg@mail.gmail.com>

Dear Jan-Mathijs,

thank you for your answer. I see, i expressed myself not very clear.
I'd like to make the Grand mean for the difference and the sum between two
specific frequencies I measured visually wih a SSVEP.
I'd like to do this because I'm interested in how the frequencies are
processed in the brain regarding each other and a control measurement.
I'm not sure if I can make the difference already when I make the GM or
later, when I plot the topography.
I tried to make this by building a datastructure that contains the GM of
the one and the other frequency and then usw ft_math to compare them. But
this doesn't work for me.
Maybe thats enough information for you to understand the problem better,
I'm a beginner so I often explain my problems a little bit confusing, sorry
for that.

Best,

Sarah

Am Mi., 13. Mai 2020 um 15:30 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl>:

> Dear Sarah,
>
> It is not clear what error message you get, nor why you think you should
> ft_timelockanalysis/ft_timelockgrandaverage/ft_topoplotER.
>
> Some pointers:
> -For a mathematical operation to be applied to numeric data that resides
> within a fieldtrip-style data structure you’d use ft_math.
> -What you want to do (i.e. adding or subtracting estimates of frequency
> specific power estimated for different frequency bins) probably requires
> some manual intervention with the data, because FT will likely prevent you
> to do so, since it checks whether the frequency bins for the to-be-combined
> data structures match. I could type some recipe now, but since you are not
> too clear on the details so I’d rather not spend time on that now. Also,
> I’d like to give other people the opportunity to chime in here :).
>
> Best wishes,
> Jan-Mathijs
>
> On 11 May 2020, at 16:43, sarah.kirchler at gmail.com wrote:
>
> Dear Fieldtrip Users,
>
> thank you for all the help you’ve given me already.
> Now I am trying to make the sum and the difference of the Grand mean
> from/between two frequencies I measured with an EEG.
> I read that it is possible to make a datastructure using {} within
> ft_timelockbaseline and then use the option cfg.operation(x1-x2 and so on)
> as a operation of function ft_topoplotER to make this sum/these differences.
>
> Now my Problem is that I don’t need to make the baselinecorrection via
> ft_timelockbaseline because I don’t have the baseline in the datasegment
> I’m interested in. So I tried to build the datastructure for cfg.operation
> within ft_timelockanalysis but Fieldtrip doesn’t allow this and I get an
> error message.
>
> My questions are now:
> 1. Can I make the difference also within the ft_timelockgrandavverage
> function or do I have to make the difference lawer in ft_topoplotER?
> 2. If so, how can I or form a datastructure I can use in cfg.operation or
> make the difference differently with some other function?
>
> I hope you understand me,
> to all you extraordinary brains: thank you in advance,
>
> Sarah
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/99b56464/attachment.htm>

From adikilim1 at gmail.com  Thu May 14 14:51:22 2020
From: adikilim1 at gmail.com (Adi Kilim)
Date: Thu, 14 May 2020 15:51:22 +0300
Subject: [FieldTrip] Source localization statistics for specific ROI using
 atlas
Message-ID: <CAGxgQhUCmfx+twvKJ5Gy31TMzcrHucsHiqk_3u2ad24G_HN9qQ@mail.gmail.com>

Dear community,

I am doing a source analysis on MEG data; I used the LCMV beamformer
to localize on time-locked data, and want to contrast two conditions: faces
and vehicles in tempo-occipital regions. I used AAL atlas to do that. The
code is running however when I'm looking at the stat struct all the voxel
are include inside the analysis and thus the clusters are across different
brain regions. I've searched around the tutorial web pages and the mailing
list archive,
and didn't find explanation for this or similar problem in fieldtrip
similar versions (I'm using fieldtrip-20200409). This is my code: ------- aal
= ft_read_atlas('ROI_MNI_V4.nii');

cfgStat = [];

%
cfgStat.atlas        =  aal;
cfgStat.roi          = {'Temporal_Mid_L'}; %Example ROI
cfgStat.avgoverroi   = 'yes'; cfgStat.hemisphere   = 'left';
cfgStat.inputcoord   = 'mni' ;

cfgStat.avgovertime     = 'yes'; %'no'
cfgStat.parameter        ='avg.pow';
cfgStat.method           = 'montecarlo';
cfgStat.statistic        = 'depsamplesT'; cfgStat.correctm         =
'cluster';
cfgStat.clusteralpha     = 0.05;
cfgStat.clusterstatistic = 'maxsum';
cfgStat.minnbchan        = 2;
cfgStat.tail             = 0;
cfgStat.clustertail      = 0;
cfgStat.alpha            = 0.05;
cfgStat.numrandomization = 1000;
cfgStat.neighbours       = neighbours;
cfgStat.design           = designMat;


[stat_mainCond_spcTime] = ft_sourcestatistics(cfgStat,
cond1_allSub{:},cond2_allSub{:});
-------
Any ideas on how to solve this atlas source statistics problem (performing
statistics on specific ROI and identify the cluster) would be greatly
appreciated!
Thanks, Adi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/964f372c/attachment.htm>

From tobias.stdgl at gmail.com  Thu May 14 16:32:58 2020
From: tobias.stdgl at gmail.com (Tobias Staudigl)
Date: Thu, 14 May 2020 16:32:58 +0200
Subject: [FieldTrip] Open PhD positions at LMU Munich: Neuronal basis of
 human memory
Message-ID: <CADSs8yRenHLeP=4oUq-b+i1bUE_uA5g6TOEkH_m-Z-BroZZnwQ@mail.gmail.com>

Dear Fieldtrip community,

We are looking to fill *two fully funded PhD positions* investigating
the *neuronal
basis of memory processes*, with a strong focus on human electrophysiology
(iEEG and EEG). The successful candidates will join our team at the *LMU in
Munich, Germany *(http://www.psy.lmu.de/knp).

Apply for a PhD position with us!
Applications are invited for two PhD positions in the group of Prof. Dr.
Tobias Staudigl (Cognitive Neuropsychology, LMU Munich, Germany) to
investigate the neuronal basis of memory in humans.
One position will have a strong focus on memory processes acting during
sleep, the other position will focus on navigation and memory.
The successful applicant will work in a multi-disciplinary environment on a
project that aims at understanding the electrophysiological basis of memory
processes. The project comprises research with epilepsy patients as well as
healthy populations, including invasive as well as non-invasive techniques.
The research is funded by the ERC Starting Grant project “How the human
thalamus guides navigation and memory: a common coding framework built on
direct thalamic recordings” (DirectThalamus).

*How to apply:*
Please visit our website
http://www.psy.lmu.de/knp/research/open-positions/index.html
for more info.

Thanks!
Tobias Staudigl
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/29d1687b/attachment.htm>

From gopalar.ccf at gmail.com  Thu May 14 17:50:06 2020
From: gopalar.ccf at gmail.com (Raghavan Gopalakrishnan)
Date: Thu, 14 May 2020 11:50:06 -0400
Subject: [FieldTrip] Between-condition permutation analysis
Message-ID: <052901d62a07$57759670$0660c350$@gmail.com>

Dear Fieldtrippers,

 

I have a scenario as depicted below with a oversimplified example.

Condition-1 has subjects-A (n=30),B (n=45),C(n=100)and D(n=50)

Condition-2 has subjects-X (n=90), Y(n=75) and Z(n=60)

 

Basically there are two conditions with 

1. totally different subjects (ABCD in condition-1, XYZ in condition-2)

2. different number of subjects (4 in condition-1, 3 in condition-2)

3. different number of trials per subject (as indicated by n next to each
subject)

 

I would like to perform cluster based time frequency comparisons between the
two conditions.

I have come across studies where same subjects are studied over two
conditions and have differing trial numbers. But, here I have different
subjects in each condition, different number of subjects percondition and
different number of trials per subject. 

Does group comparison of condition-1 vs condition-2 using cluster based
permutation analysis based on differing t-statistic hold valid in the above
mentioned experimental design? Any input would be of great help.

 

I was following some advice from a previous thread and paper from Groppe et
al. that permutation statistics are insensitive to population variance.

http://www.cogsci.ucsd.edu/~dgroppe/PUBLICATIONS/mass_uni_preprint2.pdf

https://mailman.science.ru.nl/pipermail/fieldtrip/2015-March/021934.html

 

Thank you.

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/416610b1/attachment.htm>

From jan.schoffelen at donders.ru.nl  Thu May 14 18:00:34 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Thu, 14 May 2020 16:00:34 +0000
Subject: [FieldTrip] Source localization statistics for specific ROI
 using atlas
In-Reply-To: <CAGxgQhUCmfx+twvKJ5Gy31TMzcrHucsHiqk_3u2ad24G_HN9qQ@mail.gmail.com>
References: <CAGxgQhUCmfx+twvKJ5Gy31TMzcrHucsHiqk_3u2ad24G_HN9qQ@mail.gmail.com>
Message-ID: <19C19F4E-993A-46C1-AE9C-2A0044D358C7@donders.ru.nl>

Dear Adi,

As discussed outside the scope of the other readers: could you please provide some additional information with respect to possible diagnostics you performed yourself so far? Also, perhaps you could point to some documentation on the website, or earlier e-mail threads to provide some context?

One thing you could do, is to read through the code of ft_sourcestatistics, and check whether the cfg.roi/cfg.atlas/cfg.inputcoord arguments are used to begin with. If you use the MATLAB debugger and the ‘dbstep’ and ‘dbstep in’ buttons you can recurse into lower level functions, such as ft_checkdata and ft_selectdata, which could be the place where the magic might be supposed to take place.

Best wishes,
Jan-Mathijs

On 14 May 2020, at 14:51, Adi Kilim <adikilim1 at gmail.com<mailto:adikilim1 at gmail.com>> wrote:

Dear community,

I am doing a source analysis on MEG data; I used the LCMV beamformer
to localize on time-locked data, and want to contrast two conditions: faces and vehicles in tempo-occipital regions. I used AAL atlas to do that. The code is running however when I'm looking at the stat struct all the voxel are include inside the analysis and thus the clusters are across different brain regions. I've searched around the tutorial web pages and the mailing list archive,
and didn't find explanation for this or similar problem in fieldtrip similar versions (I'm using fieldtrip-20200409). This is my code: ------- aal = ft_read_atlas('ROI_MNI_V4.nii');

cfgStat = [];

%
cfgStat.atlas        =  aal;
cfgStat.roi          = {'Temporal_Mid_L'}; %Example ROI
cfgStat.avgoverroi   = 'yes'; cfgStat.hemisphere   = 'left';
cfgStat.inputcoord   = 'mni' ;

cfgStat.avgovertime     = 'yes'; %'no'
cfgStat.parameter        ='avg.pow';
cfgStat.method           = 'montecarlo';
cfgStat.statistic        = 'depsamplesT'; cfgStat.correctm         = 'cluster';
cfgStat.clusteralpha     = 0.05;
cfgStat.clusterstatistic = 'maxsum';
cfgStat.minnbchan        = 2;
cfgStat.tail             = 0;
cfgStat.clustertail      = 0;
cfgStat.alpha            = 0.05;
cfgStat.numrandomization = 1000;
cfgStat.neighbours       = neighbours;
cfgStat.design           = designMat;


[stat_mainCond_spcTime] = ft_sourcestatistics(cfgStat, cond1_allSub{:},cond2_allSub{:});
-------
Any ideas on how to solve this atlas source statistics problem (performing statistics on specific ROI and identify the cluster) would be greatly appreciated!
Thanks, Adi

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/5ad4ede6/attachment.htm>

From jan.schoffelen at donders.ru.nl  Thu May 14 18:03:24 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Thu, 14 May 2020 16:03:24 +0000
Subject: [FieldTrip] Grand mean
In-Reply-To: <CAKLTn3c0VQXxEUVAnPgda27Dp-om10_jxKEY6LdQQda_3g=SAg@mail.gmail.com>
References: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
 <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>
 <CAKLTn3c0VQXxEUVAnPgda27Dp-om10_jxKEY6LdQQda_3g=SAg@mail.gmail.com>
Message-ID: <C0988689-BF6D-47F2-BBE5-0E466438AD50@donders.ru.nl>

Dear Sarah,

Thanks for clarifying your question. Now, could you provide the readership with some additional information about how you constructed these data structures, and how you tried to combine them, otherwise we (i.e. the people who’d want to think along with you to fix your problem) don’t know where to start.

Jan-Mathijs


On 14 May 2020, at 09:32, Sarah Kirchler <sarah.kirchler at gmail.com<mailto:sarah.kirchler at gmail.com>> wrote:

Dear Jan-Mathijs,

thank you for your answer. I see, i expressed myself not very clear.
I'd like to make the Grand mean for the difference and the sum between two specific frequencies I measured visually wih a SSVEP.
I'd like to do this because I'm interested in how the frequencies are processed in the brain regarding each other and a control measurement.
I'm not sure if I can make the difference already when I make the GM or later, when I plot the topography.
I tried to make this by building a datastructure that contains the GM of the one and the other frequency and then usw ft_math to compare them. But this doesn't work for me.
Maybe thats enough information for you to understand the problem better, I'm a beginner so I often explain my problems a little bit confusing, sorry for that.

Best,

Sarah

Am Mi., 13. Mai 2020 um 15:30 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>:
Dear Sarah,

It is not clear what error message you get, nor why you think you should ft_timelockanalysis/ft_timelockgrandaverage/ft_topoplotER.

Some pointers:
-For a mathematical operation to be applied to numeric data that resides within a fieldtrip-style data structure you’d use ft_math.
-What you want to do (i.e. adding or subtracting estimates of frequency specific power estimated for different frequency bins) probably requires some manual intervention with the data, because FT will likely prevent you to do so, since it checks whether the frequency bins for the to-be-combined data structures match. I could type some recipe now, but since you are not too clear on the details so I’d rather not spend time on that now. Also, I’d like to give other people the opportunity to chime in here :).

Best wishes,
Jan-Mathijs

On 11 May 2020, at 16:43, sarah.kirchler at gmail.com<mailto:sarah.kirchler at gmail.com> wrote:

Dear Fieldtrip Users,

thank you for all the help you’ve given me already.
Now I am trying to make the sum and the difference of the Grand mean from/between two frequencies I measured with an EEG.
I read that it is possible to make a datastructure using {} within ft_timelockbaseline and then use the option cfg.operation(x1-x2 and so on) as a operation of function ft_topoplotER to make this sum/these differences.
Now my Problem is that I don’t need to make the baselinecorrection via ft_timelockbaseline because I don’t have the baseline in the datasegment I’m interested in. So I tried to build the datastructure for cfg.operation within ft_timelockanalysis but Fieldtrip doesn’t allow this and I get an error message.

My questions are now:
1. Can I make the difference also within the ft_timelockgrandavverage function or do I have to make the difference lawer in ft_topoplotER?
2. If so, how can I or form a datastructure I can use in cfg.operation or make the difference differently with some other function?

I hope you understand me,
to all you extraordinary brains: thank you in advance,

Sarah

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200514/141ceafe/attachment.htm>

From sarah.kirchler at gmail.com  Fri May 15 09:51:38 2020
From: sarah.kirchler at gmail.com (Sarah Kirchler)
Date: Fri, 15 May 2020 09:51:38 +0200
Subject: [FieldTrip] Grand mean
In-Reply-To: <C0988689-BF6D-47F2-BBE5-0E466438AD50@donders.ru.nl>
References: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
 <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>
 <CAKLTn3c0VQXxEUVAnPgda27Dp-om10_jxKEY6LdQQda_3g=SAg@mail.gmail.com>
 <C0988689-BF6D-47F2-BBE5-0E466438AD50@donders.ru.nl>
Message-ID: <CAKLTn3f78BTn7qDHggqjZKzPRcD0FdE63Yk3+tkr=xQS+ibMTQ@mail.gmail.com>

Hi Jan-Mathijs,

thank you for your answer, I do my best to explain your questions.
The Problem is, that I don't have datastructures that I can combine (but I
would like to have them). So that's the primary question.

These are the steps I already did:
I measured, as mentioned before, with an EEG the visual stimulation via two
frequencies (SSVEP).
I preprocessed my data with ft_preprocessing (cuttet it in segments, did
filtering, concenated the cfg-Matrix with the trialinfo of my clean
preprocessed data and then, with a loop, I made the SSVEP-analysis for all
my subjects (ft_timelockanalysis and ft_frequencyanalysis).
I made the timelockanalysis for the two frequencies separately and for the
control-target (which in this case is something like a baseline-condition
for measuring the average activation of the subject-brains, so I can differ
the target-activation from it. Now  I added the Grand Mean:

gm_1 = ft_timelockgrandaverage(cfggm, tl1); gm_2 =
ft_timelockgrandaverage(cfggm, tl2);)

separately for the two frequencies.
I am now failing when trying to make the grand mean for the difference and
the sum of the two frequencies. I tried to make something like this for the
sum:

gm_3 =ft_timelockgrandaverage(cfggm, tl1, tl2)

but I don't think it's correct.
So I tried to make the difference like that:

cfg = [];
cfg.parameter = 'avg';
cfg.operation = 'x1-x2';
difftopo12 = ft_math(cfg, gm_1, gm_2);
figure
cfg=[];
cfg.xlim = [0.1:0.05:0.5];
cfg.zlim = [-2 2];
cfg.layout = '63equidistant_lay.mat';
ft_topoplotER(cfg, difftopo12);

But for this procedure I need datastructures for x1 and x2, which I don't
have.
(Fieldtrip: In the specification of the mathematical operation, x1 is the
parameter obtained

from the first input data structure, x2 from the second, etc.)

So I have a way that would work but not the datastructures.

I tried to make the datastructures like this:

tl1{vpn} = ft_timelockanalysis(cfg,data)       (vpn is the name I gave the
subjects when looping them for the timelock- and frequencyanalysis. --> for
for vpn = 1:length(cleannames)...)

and then to make the grand mean like this:

gm_1 = ft_timelockgrandaverage(cfg, tl1{:});

but it doesn't work.


I would be really thankfull if you yould give me some help to find the
error,

Sarah



Am Do., 14. Mai 2020 um 19:12 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl>:

> Dear Sarah,
>
> Thanks for clarifying your question. Now, could you provide the readership
> with some additional information about how you constructed these data
> structures, and how you tried to combine them, otherwise we (i.e. the
> people who’d want to think along with you to fix your problem) don’t know
> where to start.
>
> Jan-Mathijs
>
>
> On 14 May 2020, at 09:32, Sarah Kirchler <sarah.kirchler at gmail.com> wrote:
>
> Dear Jan-Mathijs,
>
> thank you for your answer. I see, i expressed myself not very clear.
> I'd like to make the Grand mean for the difference and the sum between two
> specific frequencies I measured visually wih a SSVEP.
> I'd like to do this because I'm interested in how the frequencies are
> processed in the brain regarding each other and a control measurement.
> I'm not sure if I can make the difference already when I make the GM or
> later, when I plot the topography.
> I tried to make this by building a datastructure that contains the GM of
> the one and the other frequency and then usw ft_math to compare them. But
> this doesn't work for me.
> Maybe thats enough information for you to understand the problem better,
> I'm a beginner so I often explain my problems a little bit confusing, sorry
> for that.
>
> Best,
>
> Sarah
>
> Am Mi., 13. Mai 2020 um 15:30 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <
> jan.schoffelen at donders.ru.nl>:
>
>> Dear Sarah,
>>
>> It is not clear what error message you get, nor why you think you should
>> ft_timelockanalysis/ft_timelockgrandaverage/ft_topoplotER.
>>
>> Some pointers:
>> -For a mathematical operation to be applied to numeric data that resides
>> within a fieldtrip-style data structure you’d use ft_math.
>> -What you want to do (i.e. adding or subtracting estimates of frequency
>> specific power estimated for different frequency bins) probably requires
>> some manual intervention with the data, because FT will likely prevent you
>> to do so, since it checks whether the frequency bins for the to-be-combined
>> data structures match. I could type some recipe now, but since you are not
>> too clear on the details so I’d rather not spend time on that now. Also,
>> I’d like to give other people the opportunity to chime in here :).
>>
>> Best wishes,
>> Jan-Mathijs
>>
>> On 11 May 2020, at 16:43, sarah.kirchler at gmail.com wrote:
>>
>> Dear Fieldtrip Users,
>>
>> thank you for all the help you’ve given me already.
>> Now I am trying to make the sum and the difference of the Grand mean
>> from/between two frequencies I measured with an EEG.
>> I read that it is possible to make a datastructure using {} within
>> ft_timelockbaseline and then use the option cfg.operation(x1-x2 and so on)
>> as a operation of function ft_topoplotER to make this sum/these differences.
>>
>> Now my Problem is that I don’t need to make the baselinecorrection via
>> ft_timelockbaseline because I don’t have the baseline in the datasegment
>> I’m interested in. So I tried to build the datastructure for cfg.operation
>> within ft_timelockanalysis but Fieldtrip doesn’t allow this and I get an
>> error message.
>>
>> My questions are now:
>> 1. Can I make the difference also within the ft_timelockgrandavverage
>> function or do I have to make the difference lawer in ft_topoplotER?
>> 2. If so, how can I or form a datastructure I can use in cfg.operation or
>> make the difference differently with some other function?
>>
>> I hope you understand me,
>> to all you extraordinary brains: thank you in advance,
>>
>> Sarah
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/0d976dff/attachment.htm>

From stephen.whitmarsh at gmail.com  Fri May 15 11:50:59 2020
From: stephen.whitmarsh at gmail.com (Stephen Whitmarsh)
Date: Fri, 15 May 2020 11:50:59 +0200
Subject: [FieldTrip] Grand mean
In-Reply-To: <CAKLTn3f78BTn7qDHggqjZKzPRcD0FdE63Yk3+tkr=xQS+ibMTQ@mail.gmail.com>
References: <5eb964b2.1c69fb81.f1032.cbd9@mx.google.com>
 <F2AED1EF-E47E-467E-8A40-5CCEDAFBC2AC@donders.ru.nl>
 <CAKLTn3c0VQXxEUVAnPgda27Dp-om10_jxKEY6LdQQda_3g=SAg@mail.gmail.com>
 <C0988689-BF6D-47F2-BBE5-0E466438AD50@donders.ru.nl>
 <CAKLTn3f78BTn7qDHggqjZKzPRcD0FdE63Yk3+tkr=xQS+ibMTQ@mail.gmail.com>
Message-ID: <CAFrxm=yvCx3XdFvgAiRHM4K71OcA6DgqfMTZVOm9nw181qrNjA@mail.gmail.com>

Dear Sarah,

Let me add my 2 cents here. Since a simple subtraction should not pose a
problem, its perhaps more a matter of clarifying the pipeline and
datastructures.  I would therefor suggest to simply add or subtract time
courses using MATLAB (first). This will make debugging much more
straightforward, and will also force you to look a bit more into the data
structures, which might clarify things already.

>From the top of my head;
After data = ft_preprocessing, your timecourse data (the voltages over
time) will be in data.trial{:}. In data.time you will find the
corresponding time axes.
After data = ft_timelockanalysis (single subject), you will probably end up
with your timecourse data in data.avg. In data.time you will find the
corresponding time axis of the average.
After data = ft_timelockgrandaverage (over subjects), your timecourse data
will probably be in data.avg.avg.  In data.time you will find the
corresponding time axis of the average.
For all, check data.dimord to see how the dimensions of the data.avg /
data.avg. avg are organized, probably "chan_time_rpt" (channels x time x
trials), or "chan_time" (channels x time).

Now, assuming the length of your data, the number of channels, etc. (i.e.
everything *but* the values in the timecourses), are the same between
conditions, you should be able to simply copy one averaged datastructure,
and replace the averaged time course data with the difference / sum you
calculate 'by hand'. E.g.

data_diff = data_cond1;
data_diff.avg.avg = data_cond2.avg.avg - data_cond1.avg.avg;
or
data_diff = data_cond1;
data_diff.avg.avg = data_cond2.avg.avg ./ data_cond1.avg.avg; % use ./
instead of / to tell MATLAB to just divide datapoint-by-datapoint instead
of dividing the matrices.

Note that you will lose the fieldtrip bookkeeping of the analysis pipeline
etc., but this will do the trick and demystify it a bit, and afterward you
can always replace it with ft_maths.

Hope this helps,
Stephen





Op vr 15 mei 2020 om 10:12 schreef Sarah Kirchler <sarah.kirchler at gmail.com
>:

> Hi Jan-Mathijs,
>
> thank you for your answer, I do my best to explain your questions.
> The Problem is, that I don't have datastructures that I can combine (but I
> would like to have them). So that's the primary question.
>
> These are the steps I already did:
> I measured, as mentioned before, with an EEG the visual stimulation via
> two frequencies (SSVEP).
> I preprocessed my data with ft_preprocessing (cuttet it in segments, did
> filtering, concenated the cfg-Matrix with the trialinfo of my clean
> preprocessed data and then, with a loop, I made the SSVEP-analysis for all
> my subjects (ft_timelockanalysis and ft_frequencyanalysis).
> I made the timelockanalysis for the two frequencies separately and for the
> control-target (which in this case is something like a baseline-condition
> for measuring the average activation of the subject-brains, so I can differ
> the target-activation from it. Now  I added the Grand Mean:
>
> gm_1 = ft_timelockgrandaverage(cfggm, tl1); gm_2 =
> ft_timelockgrandaverage(cfggm, tl2);)
>
> separately for the two frequencies.
> I am now failing when trying to make the grand mean for the difference and
> the sum of the two frequencies. I tried to make something like this for the
> sum:
>
> gm_3 =ft_timelockgrandaverage(cfggm, tl1, tl2)
>
> but I don't think it's correct.
> So I tried to make the difference like that:
>
> cfg = [];
> cfg.parameter = 'avg';
> cfg.operation = 'x1-x2';
> difftopo12 = ft_math(cfg, gm_1, gm_2);
> figure
> cfg=[];
> cfg.xlim = [0.1:0.05:0.5];
> cfg.zlim = [-2 2];
> cfg.layout = '63equidistant_lay.mat';
> ft_topoplotER(cfg, difftopo12);
>
> But for this procedure I need datastructures for x1 and x2, which I don't
> have.
> (Fieldtrip: In the specification of the mathematical operation, x1 is the
> parameter obtained
>
> from the first input data structure, x2 from the second, etc.)
>
> So I have a way that would work but not the datastructures.
>
> I tried to make the datastructures like this:
>
> tl1{vpn} = ft_timelockanalysis(cfg,data)       (vpn is the name I gave the
> subjects when looping them for the timelock- and frequencyanalysis. --> for
> for vpn = 1:length(cleannames)...)
>
> and then to make the grand mean like this:
>
> gm_1 = ft_timelockgrandaverage(cfg, tl1{:});
>
> but it doesn't work.
>
>
> I would be really thankfull if you yould give me some help to find the
> error,
>
> Sarah
>
>
>
> Am Do., 14. Mai 2020 um 19:12 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <
> jan.schoffelen at donders.ru.nl>:
>
>> Dear Sarah,
>>
>> Thanks for clarifying your question. Now, could you provide the
>> readership with some additional information about how you constructed these
>> data structures, and how you tried to combine them, otherwise we (i.e. the
>> people who’d want to think along with you to fix your problem) don’t know
>> where to start.
>>
>> Jan-Mathijs
>>
>>
>> On 14 May 2020, at 09:32, Sarah Kirchler <sarah.kirchler at gmail.com>
>> wrote:
>>
>> Dear Jan-Mathijs,
>>
>> thank you for your answer. I see, i expressed myself not very clear.
>> I'd like to make the Grand mean for the difference and the sum between
>> two specific frequencies I measured visually wih a SSVEP.
>> I'd like to do this because I'm interested in how the frequencies are
>> processed in the brain regarding each other and a control measurement.
>> I'm not sure if I can make the difference already when I make the GM or
>> later, when I plot the topography.
>> I tried to make this by building a datastructure that contains the GM of
>> the one and the other frequency and then usw ft_math to compare them. But
>> this doesn't work for me.
>> Maybe thats enough information for you to understand the problem better,
>> I'm a beginner so I often explain my problems a little bit confusing, sorry
>> for that.
>>
>> Best,
>>
>> Sarah
>>
>> Am Mi., 13. Mai 2020 um 15:30 Uhr schrieb Schoffelen, J.M. (Jan Mathijs) <
>> jan.schoffelen at donders.ru.nl>:
>>
>>> Dear Sarah,
>>>
>>> It is not clear what error message you get, nor why you think you should
>>> ft_timelockanalysis/ft_timelockgrandaverage/ft_topoplotER.
>>>
>>> Some pointers:
>>> -For a mathematical operation to be applied to numeric data that resides
>>> within a fieldtrip-style data structure you’d use ft_math.
>>> -What you want to do (i.e. adding or subtracting estimates of frequency
>>> specific power estimated for different frequency bins) probably requires
>>> some manual intervention with the data, because FT will likely prevent you
>>> to do so, since it checks whether the frequency bins for the to-be-combined
>>> data structures match. I could type some recipe now, but since you are not
>>> too clear on the details so I’d rather not spend time on that now. Also,
>>> I’d like to give other people the opportunity to chime in here :).
>>>
>>> Best wishes,
>>> Jan-Mathijs
>>>
>>> On 11 May 2020, at 16:43, sarah.kirchler at gmail.com wrote:
>>>
>>> Dear Fieldtrip Users,
>>>
>>> thank you for all the help you’ve given me already.
>>> Now I am trying to make the sum and the difference of the Grand mean
>>> from/between two frequencies I measured with an EEG.
>>> I read that it is possible to make a datastructure using {} within
>>> ft_timelockbaseline and then use the option cfg.operation(x1-x2 and so on)
>>> as a operation of function ft_topoplotER to make this sum/these differences.
>>>
>>> Now my Problem is that I don’t need to make the baselinecorrection via
>>> ft_timelockbaseline because I don’t have the baseline in the datasegment
>>> I’m interested in. So I tried to build the datastructure for cfg.operation
>>> within ft_timelockanalysis but Fieldtrip doesn’t allow this and I get an
>>> error message.
>>>
>>> My questions are now:
>>> 1. Can I make the difference also within the ft_timelockgrandavverage
>>> function or do I have to make the difference lawer in ft_topoplotER?
>>> 2. If so, how can I or form a datastructure I can use in cfg.operation
>>> or make the difference differently with some other function?
>>>
>>> I hope you understand me,
>>> to all you extraordinary brains: thank you in advance,
>>>
>>> Sarah
>>>
>>> _______________________________________________
>>> fieldtrip mailing list
>>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>>> https://doi.org/10.1371/journal.pcbi.1002202
>>>
>>>
>>> _______________________________________________
>>> fieldtrip mailing list
>>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>>> https://doi.org/10.1371/journal.pcbi.1002202
>>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/fd7660ce/attachment.htm>

From jonas at obleser.de  Fri May 15 14:48:08 2020
From: jonas at obleser.de (Jonas Obleser)
Date: Fri, 15 May 2020 14:48:08 +0200
Subject: [FieldTrip] =?utf-8?q?up-to-4-y_postdoctoral_position_=40=C2=A0O?=
 =?utf-8?q?bleserlab=2C_University_of_L=C3=BCbeck=2C_Germany?=
Message-ID: <AD2D408A-2E59-4FBD-A749-32AC3376068B@obleser.de>


Dear all, thanks for sharing:
The following call for applications is live (Deadline JUNE 7).

We are looking for a new face,
bringing with them enthusiasm and research ideas in any of:
neural and behavioural dynamics; ageing; sensory decline
https://auditorycognition.com/2020/05/13/we-are-hiring-4-y-postdoctoral-position/ <https://auditorycognition.com/2020/05/13/we-are-hiring-4-y-postdoctoral-position/> 
Best wishes, Jonas 



Jonas Obleser
Prof. Dr. rer. nat. habil., Dipl.-Psych.
Chair in Physiological Psychology and Research Methods




 
University of Lübeck
Department of Psychology
MFC 8, Maria-Goeppert-Straße 9a
23562 Lübeck, Germany

Phone +49 (0)451 3101 3620
Mobile +49 (0)171 6993337
jonas.obleser at uni-luebeck.de <mailto:jonas.obleser at uni-luebeck.de>
http://jonasobleser.com


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/b5a9725d/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.png
Type: image/png
Size: 8108 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/b5a9725d/attachment.png>

From christoph.kayser at uni-bielefeld.de  Fri May 15 15:15:28 2020
From: christoph.kayser at uni-bielefeld.de (Kayser, Christoph)
Date: Fri, 15 May 2020 13:15:28 +0000
Subject: [FieldTrip] 
 =?iso-8859-1?q?up-to-4-y_postdoctoral_position_=40?=
 =?iso-8859-1?q?=A0Obleserlab=2C_University_of_L=FCbeck=2C_Germany?=
In-Reply-To: <AD2D408A-2E59-4FBD-A749-32AC3376068B@obleser.de>
References: <AD2D408A-2E59-4FBD-A749-32AC3376068B@obleser.de>
Message-ID: <bd82a07c391f469c9fe7e34a7900aea0@uni-bielefeld.de>

Hallo Jonas,


alles gut bei euch? Hier alles Chaos. In der Theorie kann man wohl bald wieder Versuche machen, in der Praxis sehen ich vor Okt nicht viel; die meisten hängen eh mit Kindern zu Hause...


Cool, das mit der 4 Jahre Stelle; im Lotto gewonnen? Mir hat jemand einen DFG Grant über pre-stimulus effects zerschossen, quasi mit dem Kommentar alle (unsere) vorherringen Studien wären quasi statistischer noise... Noch nie so einen üblen review gesehen. Das Thema scheint wohl sehr zu polarisieren.


LG

Christoph





________________________________
Von: fieldtrip <fieldtrip-bounces at science.ru.nl> im Auftrag von Jonas Obleser <jonas at obleser.de>
Gesendet: Freitag, 15. Mai 2020 14:48
An: fieldtrip at science.ru.nl
Betreff: [FieldTrip] up-to-4-y postdoctoral position @ Obleserlab, University of Lübeck, Germany


Dear all, thanks for sharing:
The following call for applications is live (Deadline JUNE 7).

We are looking for a new face,
bringing with them enthusiasm and research ideas in any of:
neural and behavioural dynamics; ageing; sensory decline
https://auditorycognition.com/2020/05/13/we-are-hiring-4-y-postdoctoral-position/
Best wishes, Jonas



Jonas Obleser
Prof. Dr. rer. nat. habil., Dipl.-Psych.
Chair in Physiological Psychology and Research Methods


[cid:image001.png at 01D5EFAC.74C1D0D0]


University of Lübeck
Department of Psychology
MFC 8, Maria-Goeppert-Straße 9a
23562 Lübeck, Germany

Phone +49 (0)451 3101 3620
Mobile +49 (0)171 6993337
jonas.obleser at uni-luebeck.de<mailto:jonas.obleser at uni-luebeck.de>
http://jonasobleser.com


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/e7173243/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.png
Type: image/png
Size: 8108 bytes
Desc: image001.png
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/e7173243/attachment.png>

From MGlassen at kesslerfoundation.org  Fri May 15 22:33:39 2020
From: MGlassen at kesslerfoundation.org (Michael Glassen  -  Biomedical Engineer)
Date: Fri, 15 May 2020 20:33:39 +0000
Subject: [FieldTrip] Computing source-level ROI EEG connectivity
In-Reply-To: <845599A5-04B0-4FA6-9413-2817791727E3@donders.ru.nl>
References: <2fb6d71f4f5b428d81eaf57d5bc4d3bc@kesslerfoundation.org>
 <1D465686-EF2F-46D8-8E99-398685CC7396@donders.ru.nl>
 <351c278003e24d15a41cc01b4e1d75ce@kesslerfoundation.org>
 <10CEEB52-34D2-472F-AF9B-1D65B79F6039@donders.ru.nl>
 <1352eb475f704cb2b8a8ddbd94f79ac4@kesslerfoundation.org>
 <95993020-065B-48C1-B7A6-9B8E04F787E7@donders.ru.nl>
 <CAA6G0Y8HNpz9YBkCyKvRCS4Ow6u-=+=P-WuFwJp6K5efffDOqQ@mail.gmail.com>
 <1C0AF287-1DF7-4B7C-8E5F-F6B435D09BD6@donders.ru.nl>
 <f7ac81d918194885a989ff0ebd4478ef@kesslerfoundation.org>,
 <845599A5-04B0-4FA6-9413-2817791727E3@donders.ru.nl>
Message-ID: <42a8ae40e02e452485b32fd655e1aab5@kesslerfoundation.org>

Dear Fieldtrip Community,


I implemented most of the changes you all suggested and some that you didn't, and I am still getting some odd results, but in a different way. At the end of my pipeline I am computing bivariate granger causality over all ROIs in the volumetric AAL atlas provided with fieldtrip. ft_sourceparcellate gives me errors when trying to use, so to project sources onto ROIs I interpolate the AAL atlas onto my sourcemodel using ft_sourceinterpolate. I then go through each ROI and create a binary mask of voxels, which I then use to average the moms together to get ROI source activity. Before this step I use the svd method to pick a principal component of each voxel. When I plot a heatmap of these results averaged over the beta band(12-30 Hz), most roi pairs have a granger value between 0.1-0.3, but there are certain rois that have a very high granger across a ton of regions(>1).  This happened with multiple datasets from different studies. I suspect that the issue(if these is one) in my pipeline is coming from how I am using the atlas to group together voxels into ROIs, but I am not sure. I have listed my process below with as much detail as possible, if you need any other information let me know:


Link to a matlab figure of granger results:

https://drive.google.com/open?id=1CCaTsw8VO0829GJsggBiB0LMquVRx4Ao


Step 1: Importing headmodel and EEG Data


My first step is loading in the default bem headmodel that comes shipped with fieldtrip, shown below:



headmodel =

  struct with fields:

     bnd: [1×3 struct]
    cond: [0.3300 0.0041 0.3300]
     mat: [3000×3000 double]
    type: 'dipoli'
    unit: 'mm'


I then import the EEG data(63 channels, 10-20 electrode layout) and convert the units to mm.


eegData = eeglab2fieldtrip(EEG,'preprocessing','none');

eegData.elec  = ft_convert_units(header.elec, 'mm');

eegData =

  struct with fields:

         elec: [1×1 struct]
      fsample: 1000
        trial: {1×113 cell}
         time: {1×113 cell}
        label: {1×63 cell}
    trialinfo: [113×7 table]
          cfg: [1×1 struct]

I then project the electrodes to the scalp using the code below. Plotting afterwards confirms the electrodes are properly aligned with the headmodel.

if strcmp(headmodel.type, 'bemcp')
    scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
    scalp_index = 1;
end

cfg = [];
cfg.method = 'project'; % onto scalp surface
cfg.headshape = headmodel.bnd(scalp_index); % scalp surface

eegData.elec = ft_electroderealign(cfg, eegData.elec);



Step 2: Calculate the foward solution:

In this step, I calculate the covariance for my data, and create the source model and calculate the leadfield.

cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);

cfg             = [];
cfg.headmodel   = headmodel;
cfg.resolution  = 10;
cfg.inwardshift = 5;

sourcemodel = ft_prepare_sourcemodel(cfg);

cfg = [];
cfg.sourcemodel = sourcemodel;
cfg.headmodel   = headmodel;
cfg.elec        = tlckEeg.elec;

leadfield = ft_prepare_leadfield(cfg);

sourcemodel =

  struct with fields:

       dim: [13 18 14]
       pos: [3276×3 double]
      unit: 'mm'
    inside: [3276×1 logical]
       cfg: [1×1 struct]

leadfield =

  struct with fields:

                dim: [13 18 14]
                pos: [3276×3 double]
               unit: 'mm'
             inside: [3276×1 logical]
                cfg: [1×1 struct]
          leadfield: {1×3276 cell}
              label: {63×1 cell}
    leadfielddimord: '{pos}_chan_ori'




Step 3: Calculate the inverse solution

In this step, I calculate the sources using eloretta twice, once with the keepfilter option enabled and once with rawtrial enabled(this second run is used to obtain the correct structure format, the moms calculated from rawtrial are replaced with filter calculated moms). I then take the filters from the first run and multiply them with the original dataset to get the trial by trial mom data, which I use to replace the trial moms that were obtained with the rawtrial option. Then, for each voxel, I concanate all trial moms and calculate the principal component using svd. Once I have these I recalculate the moms for each trial using only the principal component.

cfg               = [];
cfg.method        = 'eloreta';
cfg.grid   = leadfield;
cfg.headmodel     = headmodel;
cfg.eloreta.lambda = 0.05;
cfg.keepmom = 'yes';
cfg.mne.keepmom = 'yes';
cfg.eloreta.keepfilter = 'yes';

sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);

sourceEEG =

  struct with fields:

      time: [1×4000 double]
       dim: [13 18 14]
    inside: [3276×1 logical]
       pos: [3276×3 double]
    method: 'average'
       avg: [1×1 struct]
       cfg: [1×1 struct]


cfg               = [];
cfg.method        = 'eloreta';
cfg.grid   = leadfield;
cfg.headmodel     = headmodel;
cfg.eloreta.lambda = 0.05;
cfg.mne.projectnoise = 'yes';
cfg.keepmom = 'yes';
cfg.rawtrial = 'yes';

trialSource          = ft_sourceanalysis(cfg,tlckEeg);


trialSource =

  struct with fields:

      time: [1×4000 double]
       dim: [13 18 14]
    inside: [3276×1 logical]
       pos: [3276×3 double]
    method: 'rawtrial'
     trial: [1×113 struct]
        df: 113
       cfg: [1×1 struct]


%% Calculating 3 dimensional trial moms
for i = 1:length(sourceEEG.avg.filter)
    for i2 = 1:length(eegData.trial)

        if isempty(sourceEEG.avg.filter{i})

            x = [];

        else

            x = sourceEEG.avg.filter{i} * eegData.trial{i2}(:,:);

        end

        trialSource.trial(i2).mom{i} = x;

    end

end

%% Calculating the principal component for each voxel
for i2 = 1:length(trialSource.trial(1).mom)
    timeseries = [];

    for i = 1:length(trialSource.trial)
        timeseries = cat(2,timeseries,trialSource.trial(i).mom{i2});
    end

    [u{i2}, s{i2}, v{i2}] = svd(timeseries, 'econ');

end

%% Calculating 1dimensional trial moms
for i = 1:length(sourceEEG.avg.filter)
    for i2 = 1:length(eegData.trial)

        if isempty(sourceEEG.avg.filter{i})

            x = [];

        else

           x = u{i}(:,1)' *sourceEEG.avg.filter{i} * eegData.trial{i2}(:,:);

        end

        trialSource.trial(i2).mom{i} = x;

    end

end

Step 4: Create ROI masks from AAL atlas

In this step I load in the default AAL atlas included with fieldtrip. I then interpolate this atlas onto my sourcemodel. At this point I have tried to use ft_sourceparcellate to divide up my source data into ROIs, but I receive an error. Both the atlas and my head/source models are volumetric, and because I am using the template headmodel both objects are in MNI space, so I'm not sure how else to troubleshoot this part. Because of this error, I am using the interpolated atlas to create binary masks and averaging all moms for voxels in each ROI.

Code when I try to use ft_sourceparcellate:

atlas = ft_read_atlas(broddmanLoc);

atlas =

  struct with fields:

            dim: [91 109 91]
            hdr: [1×1 struct]
      transform: [4×4 double]
           unit: 'mm'
         tissue: [91×109×91 double]
    tissuelabel: {1×116 cell}
       coordsys: 'mni'

cfg = [];
cfg.method        = 'nearest';
cfg.parameter = 'tissue';
atlas2 = ft_sourceinterpolate(cfg,atlas,sourcemodel);

atlas2 =

  struct with fields:

          dim: [13 18 14]
    transform: [4×4 double]
         unit: 'mm'
       inside: [13×18×14 logical]
       tissue: [13×18×14 double]
          cfg: [1×1 struct]

% Here I try to use the original atlas with ft_sourceparcellate and receive an error
cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas)
Error using ft_sourceparcellate (line 109)
the source positions are not consistent with the parcellation, please use FT_SOURCEINTERPOLATE

% As you can see above, when I interpolate the atlas onto the source model, tissuelabel is missing in atlas2, so it is not recognized as a parcellation. When I add tissuelabel from atlas to atlas2, another error appears.

cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas2)
Error using ft_sourceparcellate (line 97)
This function requires parcellation data as input, see ft_datatype_parcellation.

atlas2.tissuelabel = atlas.tissuelabel;
cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas2)
Error using ft_sourceparcellate (line 97)
each index value should have a corresponding entry in "tissuelabel"

% Because of these errors, I instead create my own binary masks for each ROI, using methods from this tutorial:
http://www.fieldtriptoolbox.org/faq/how_can_i_map_source_locations_between_two_different_representations/

<http://www.fieldtriptoolbox.org/faq/how_can_i_map_source_locations_between_two_different_representations/> atlas = ft_read_atlas(broddmanLoc);

cfg = [];
cfg.method        = 'nearest';
cfg.parameter = 'tissue';
atlas2 = ft_sourceinterpolate(cfg,atlas,sourcemodel);

roiData.time = eegData.time;
roiData.label = atlas.tissuelabel';
roiData.trial = {};

missingLabels = [];
for i = 1:length(atlas.tissuelabel)

    indx = find(atlas2.tissue==i);
    if isempty(indx)
        missingLabels = [missingLabels i];
    end

    for i3 = 1:length(trialSource.trial)
        timeseries = [];
        for i2 = 1:length(indx)
            try
                timeseries = cat(1,timeseries,trialSource.trial(i).mom{indx(i2)});
            end
        end

        if ~isempty(timeseries)
            for i4 = 1:size(timeseries,2)

                roiData.trial{i3}(i,i4) = mean(timeseries(:,i4));

            end
        else
            roiData.trial{i3}(i,:) = ones(1,length(roiData.time{1}))*10^-10;
        end
    end

end


Using this method, some ROIs from the atlas have zero indices found in the source model, which is confusing to me. I tried replace the source data for missing ROIs with a very small non-zero #(10^-10) so that the rest of the script runs. Looking at the indices now I realize that these are the indices with extrememly high granger values, so adding in small non-zero values is not a valid solution it seems. Is there any reason for these ROIs to not be showing up in my model? The missing indices are listed below. I assume that the issue is coming from the interpolation of the atlas.


missingLabels = [21 70 79 80 95 101 107 108 109]



Step 5: Calculate Connectivity


In this step I calculate granger causality. I don't think anything is going wrong here, after having gone through all of my code for this email I realize that the missing ROIs are the most likely culprit.


cfg            = [];
cfg.output     = 'fourier';
cfg.method     = 'mtmfft';
cfg.foilim     = [0 50];
cfg.tapsmofrq  = 4;
cfg.keeptrials = 'yes';
cfg.pad = 4;
freq    = ft_freqanalysis(cfg, roiData);

cfg = [];
cfg.method = 'granger';
cfg.granger.sfmethod = 'bivariate';
granger = ft_connectivityanalysis(cfg, freq);

Conclusions

After going through all of my code, I realize the main issue is that some of the atlas ROIs have no indices in my sourcemodel after interpolating. Is there any fix/advice that you can suggest to either fix this problem, or to make ft_sourceparcellate work so that I can avoid this issue altogether? I realize there is a lot of code and steps to go through here, and I appreciate any help that you can provide. This mailing list has been a great resource for me so far, and I hope I can return the favor to some fellow fieldtrippers soon!

Best,
Michael Glassen






________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
Sent: Thursday, May 14, 2020 2:02:38 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

The convention is left column to right column, so in this case RGAST to LGAST. the stuff between the ‘[‘ is to indicate that the pairwise metric has been obtained with a bivariate model that included LGAST and RGAST.

Best wishes,
Jan-Mathijs


On 14 May 2020, at 03:14, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi Jan-Mathijs,

I implemented all of your suggestions but I had a quick question on the organization of the bivariate granger connectivity structure. From what I can understand, this should compute connectivity from each channel to every other channel. This is my connectivity structure:

struct with fields:

         labelcmb: {14762×2 cell}
           dimord: 'chancmb_freq'
    grangerspctrm: [14762×201 double]
             freq: [1×201 double]
              cfg: [1×1 struct]

And looking at an entry of labelcmb(14762,:) gives:

1×2 cell array

    {'RGAST[RGAST,LGAST]'}    {'LGAST[RGAST,LGAST]'}

So does this mean that grangerspctrm(14762,:) is the granger connectivity from RGAST to LGAST, or is it from LGAST to RGAST?


Best,
Michael Glassen


________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Saturday, May 9, 2020 4:11:51 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Wanze,

I have two short questions regarding your suggestions to Michael: 1) any reason for why doing svd for concatenated trials would work better than doing svd per trial?

Well, it’s not that ‘it works better’, but using a per trial svd will result in a different orientation estimate per trial, which then inherently assumes a source model that fixes the location of the dipole, but not its orientation.

2) If we do svd with concatenated trials do we need to re-segment the data into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work way more efficiently if they are applied to data in epochs rather than one long trial, although I am not 100% assured.

Indeed, in most situations (particularly if the experimental protocol is epoch based) it is mandatory to maintain the epoch-structure in the spectral decomposition and connectivity estimation step. To this end the concatenation step is an intermediate one, used only to compute the principal orientation, and this orientation can then be applied to the data structure that still contains the epochs, either using a for-loop across the individual epochs, or exploiting the external/cellfunction code, by a direct multiplication.

Best wishes,
Jan-Mathijs



Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>于2020年5月8日 周五上午10:35写道：
Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs





On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.


-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.




ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs


Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands




On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



     _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



     _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


     _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/9ff626f5/attachment.htm>

From pdhami06 at gmail.com  Fri May 15 23:58:50 2020
From: pdhami06 at gmail.com (Paul Dhami)
Date: Fri, 15 May 2020 17:58:50 -0400
Subject: [FieldTrip] Imaginary Coherence and Averaging Over Time - to do or
 not to do?
Message-ID: <CABqnCmCYwB6FzDF+1ZXecNfyQH=X1YuQMjJzgux5QKAPp0DqGw@mail.gmail.com>

Dear FieldTrip community,

please forgive my ignorance, but I have a question in relation to the
calculation of imaginary coherence, and certain plots I have been seeing in
the literature.

I've seen papers present what appears to be imaginary coherence values
averaged across time (where as the plot is a line plot of coherence values
against frequency for a pair of electrodes), as well as 'coherograms',
where for a pair of electrodes, a 3D plot is presented with time-frequency
and the colour being coherence values.

My question is then for the option of averaging over time, is there one
recommendation over the other (yes versus no). Or is it more of a
hypothesis driven choice?

Any insight into this topic would be greatly appreciated.

Best wishes,
Paul
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200515/0dffb8a5/attachment.htm>

From x.vrijdag at auckland.ac.nz  Sun May 17 01:01:10 2020
From: x.vrijdag at auckland.ac.nz (Xavier Vrijdag)
Date: Sat, 16 May 2020 23:01:10 +0000
Subject: [FieldTrip] [FORGED] Re: Computing source-level ROI EEG
 connectivity
Message-ID: <19610131-DBB9-4990-B1BA-286847BB3277@auckland.ac.nz>

Hello Michael,

I currently following a very similar path for analysing my EEG data with the following steps:

%Load the template brain, MRI and EEG electrodes
load ('biosemi32elec_aligned.mat') % electrodes have been manually aligned using the interface
load ('leadfield6mm.mat')
load([FIELDTRIPDIR '/template/headmodel/standard_bem.mat']); %template boundary element model
load([FIELDTRIPDIR  '/template/headmodel/standard_mri.mat']); %template mri
atlas = ft_read_atlas([FIELDTRIPDIR '/template/atlas/aal/ROI_MNI_V4.nii']);

%Generate sourcemodel and leadfields (common for all data)

    cfg = [];

    cfg.headmodel = vol;

    cfg.elec = elec_aligned;

    cfg.grid.resolution = 6;   % use a 3-D grid with a 6mm resolution

    cfg.grid.unit       = 'mm';

    cfg.channel = 1:32;

    grid = ft_prepare_leadfield(cfg);
Load the data

%Calculate the channel covariance matrix for all exposures
        cfg = [];
        cfg.covariance = 'yes';
        cfg.covariancewindow = 'all';
        cfg.keeptrials  = 'yes';
        timelock_allexp = ft_timelockanalysis(cfg, data_filt);

%Calculate the channel covariance matric for each exposure separate
        timelock=cell(length(exposures));
        for j=1:length(exposures)
            cfg = [];
            cfg.covariance = 'yes';
            cfg.covariancewindow = 'all';
            cfg.trials = find(ismember(trialinfo, exposures{j}));
            cfg.keeptrials  = 'yes';
            timelock{j} = ft_timelockanalysis(cfg, data_filt);
        end

%General source localisation
        cfg = [];
        cfg.headmodel = vol;
        cfg.elec = elec_aligned;
        cfg.grid = grid;
        cfg.method = 'lcmv';
        cfg.lcmv.fixedori = 'yes';  %Project onto largest variance orientation
        cfg.lcmv.keepfilter = 'yes'; %Keep the beamformer weights
        cfg.lcmv.lambda = '5%'; %Regularise a little
        source_allexp = ft_sourceanalysis(cfg, timelock_allexp);

% source localisation for each exposure separate using combined filter
        cfg = [];
        cfg.headmodel = vol;
        cfg.elec = elec_aligned;
        cfg.grid = grid;
        cfg.grid.filter = source_allexp.avg.filter; % use the common filter computed in the previous step!
        cfg.method = 'lcmv';
        cfg.lcmv.fixedori = 'yes';  %Project onto largest variance orientation
        cfg.lcmv.lambda = '5%'; %Regularise a little
        cfg.rawtrial    = 'yes';      % project each single trial through the filter.
        cfg.keeptrials  = 'yes';

        parc_sources=cell(length(exposures),1);
        for j=1:length(exposures)
            source = ft_sourceanalysis(cfg, timelock{j});
            source = ft_datatype_source(source);

            cfg = [];
            cfg.parameter = 'all';
            source_int = ft_sourceinterpolate(cfg, source, atlas);

            cfg = [];
            cfg.method       = 'max';
            parc_sources{j}=ft_sourceparcellate(cfg, source_int, atlas);
        end

I hope my code for source parcellation helps to solve your problem.

Regards,

Xavier


From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org>
Reply to: FieldTrip discussion list <fieldtrip at science.ru.nl>
Date: Saturday, 16 May 2020 at 8:42 AM
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: [FORGED] Re: [FieldTrip] Computing source-level ROI EEG connectivity


Dear Fieldtrip Community,



I implemented most of the changes you all suggested and some that you didn't, and I am still getting some odd results, but in a different way. At the end of my pipeline I am computing bivariate granger causality over all ROIs in the volumetric AAL atlas provided with fieldtrip. ft_sourceparcellate gives me errors when trying to use, so to project sources onto ROIs I interpolate the AAL atlas onto my sourcemodel using ft_sourceinterpolate. I then go through each ROI and create a binary mask of voxels, which I then use to average the moms together to get ROI source activity. Before this step I use the svd method to pick a principal component of each voxel. When I plot a heatmap of these results averaged over the beta band(12-30 Hz), most roi pairs have a granger value between 0.1-0.3, but there are certain rois that have a very high granger across a ton of regions(>1).  This happened with multiple datasets from different studies. I suspect that the issue(if these is one) in my pipeline is coming from how I am using the atlas to group together voxels into ROIs, but I am not sure. I have listed my process below with as much detail as possible, if you need any other information let me know:



Link to a matlab figure of granger results:

https://drive.google.com/open?id=1CCaTsw8VO0829GJsggBiB0LMquVRx4Ao



Step 1: Importing headmodel and EEG Data



My first step is loading in the default bem headmodel that comes shipped with fieldtrip, shown below:



headmodel =

  struct with fields:

     bnd: [1×3 struct]
    cond: [0.3300 0.0041 0.3300]
     mat: [3000×3000 double]
    type: 'dipoli'
    unit: 'mm'


I then import the EEG data(63 channels, 10-20 electrode layout) and convert the units to mm.


eegData = eeglab2fieldtrip(EEG,'preprocessing','none');

eegData.elec  = ft_convert_units(header.elec, 'mm');

eegData =

  struct with fields:

         elec: [1×1 struct]
      fsample: 1000
        trial: {1×113 cell}
         time: {1×113 cell}
        label: {1×63 cell}
    trialinfo: [113×7 table]
          cfg: [1×1 struct]

I then project the electrodes to the scalp using the code below. Plotting afterwards confirms the electrodes are properly aligned with the headmodel.

if strcmp(headmodel.type, 'bemcp')
    scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
    scalp_index = 1;
end

cfg = [];
cfg.method = 'project'; % onto scalp surface
cfg.headshape = headmodel.bnd(scalp_index); % scalp surface

eegData.elec = ft_electroderealign(cfg, eegData.elec);



Step 2: Calculate the foward solution:

In this step, I calculate the covariance for my data, and create the source model and calculate the leadfield.

cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);

cfg             = [];
cfg.headmodel   = headmodel;
cfg.resolution  = 10;
cfg.inwardshift = 5;

sourcemodel = ft_prepare_sourcemodel(cfg);

cfg = [];
cfg.sourcemodel = sourcemodel;
cfg.headmodel   = headmodel;
cfg.elec        = tlckEeg.elec;

leadfield = ft_prepare_leadfield(cfg);

sourcemodel =

  struct with fields:

       dim: [13 18 14]
       pos: [3276×3 double]
      unit: 'mm'
    inside: [3276×1 logical]
       cfg: [1×1 struct]

leadfield =

  struct with fields:

                dim: [13 18 14]
                pos: [3276×3 double]
               unit: 'mm'
             inside: [3276×1 logical]
                cfg: [1×1 struct]
          leadfield: {1×3276 cell}
              label: {63×1 cell}
    leadfielddimord: '{pos}_chan_ori'




Step 3: Calculate the inverse solution

In this step, I calculate the sources using eloretta twice, once with the keepfilter option enabled and once with rawtrial enabled(this second run is used to obtain the correct structure format, the moms calculated from rawtrial are replaced with filter calculated moms). I then take the filters from the first run and multiply them with the original dataset to get the trial by trial mom data, which I use to replace the trial moms that were obtained with the rawtrial option. Then, for each voxel, I concanate all trial moms and calculate the principal component using svd. Once I have these I recalculate the moms for each trial using only the principal component.

cfg               = [];
cfg.method        = 'eloreta';
cfg.grid   = leadfield;
cfg.headmodel     = headmodel;
cfg.eloreta.lambda = 0.05;
cfg.keepmom = 'yes';
cfg.mne.keepmom = 'yes';
cfg.eloreta.keepfilter = 'yes';

sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);

sourceEEG =

  struct with fields:

      time: [1×4000 double]
       dim: [13 18 14]
    inside: [3276×1 logical]
       pos: [3276×3 double]
    method: 'average'
       avg: [1×1 struct]
       cfg: [1×1 struct]


cfg               = [];
cfg.method        = 'eloreta';
cfg.grid   = leadfield;
cfg.headmodel     = headmodel;
cfg.eloreta.lambda = 0.05;
cfg.mne.projectnoise = 'yes';
cfg.keepmom = 'yes';
cfg.rawtrial = 'yes';
trialSource          = ft_sourceanalysis(cfg,tlckEeg);


trialSource =

  struct with fields:

      time: [1×4000 double]
       dim: [13 18 14]
    inside: [3276×1 logical]
       pos: [3276×3 double]
    method: 'rawtrial'
     trial: [1×113 struct]
        df: 113
       cfg: [1×1 struct]


%% Calculating 3 dimensional trial moms
for i = 1:length(sourceEEG.avg.filter)
    for i2 = 1:length(eegData.trial)

        if isempty(sourceEEG.avg.filter{i})

            x = [];

        else

            x = sourceEEG.avg.filter{i} * eegData.trial{i2}(:,:);

        end

        trialSource.trial(i2).mom{i} = x;

    end

end

%% Calculating the principal component for each voxel
for i2 = 1:length(trialSource.trial(1).mom)
    timeseries = [];

    for i = 1:length(trialSource.trial)
        timeseries = cat(2,timeseries,trialSource.trial(i).mom{i2});
    end

    [u{i2}, s{i2}, v{i2}] = svd(timeseries, 'econ');

end
%% Calculating 1dimensional trial moms
for i = 1:length(sourceEEG.avg.filter)
    for i2 = 1:length(eegData.trial)

        if isempty(sourceEEG.avg.filter{i})

            x = [];

        else

           x = u{i}(:,1)' *sourceEEG.avg.filter{i} * eegData.trial{i2}(:,:);

        end

        trialSource.trial(i2).mom{i} = x;

    end

end

Step 4: Create ROI masks from AAL atlas

In this step I load in the default AAL atlas included with fieldtrip. I then interpolate this atlas onto my sourcemodel. At this point I have tried to use ft_sourceparcellate to divide up my source data into ROIs, but I receive an error. Both the atlas and my head/source models are volumetric, and because I am using the template headmodel both objects are in MNI space, so I'm not sure how else to troubleshoot this part. Because of this error, I am using the interpolated atlas to create binary masks and averaging all moms for voxels in each ROI.
Code when I try to use ft_sourceparcellate:

atlas = ft_read_atlas(broddmanLoc);

atlas =

  struct with fields:

            dim: [91 109 91]
            hdr: [1×1 struct]
      transform: [4×4 double]
           unit: 'mm'
         tissue: [91×109×91 double]
    tissuelabel: {1×116 cell}
       coordsys: 'mni'

cfg = [];
cfg.method        = 'nearest';
cfg.parameter = 'tissue';
atlas2 = ft_sourceinterpolate(cfg,atlas,sourcemodel);

atlas2 =

  struct with fields:

          dim: [13 18 14]
    transform: [4×4 double]
         unit: 'mm'
       inside: [13×18×14 logical]
       tissue: [13×18×14 double]
          cfg: [1×1 struct]

% Here I try to use the original atlas with ft_sourceparcellate and receive an error
cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas)
Error using ft_sourceparcellate (line 109)
the source positions are not consistent with the parcellation, please use FT_SOURCEINTERPOLATE

% As you can see above, when I interpolate the atlas onto the source model, tissuelabel is missing in atlas2, so it is not recognized as a parcellation. When I add tissuelabel from atlas to atlas2, another error appears.

cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas2)
Error using ft_sourceparcellate (line 97)
This function requires parcellation data as input, see ft_datatype_parcellation.

atlas2.tissuelabel = atlas.tissuelabel;
cfg = [];
cfg.method       = 'eig';
cfg.parcellation = 'tissue';
ft_sourceparcellate(cfg,trialSource,atlas2)
Error using ft_sourceparcellate (line 97)
each index value should have a corresponding entry in "tissuelabel"

% Because of these errors, I instead create my own binary masks for each ROI, using methods from this tutorial:
http://www.fieldtriptoolbox.org/faq/how_can_i_map_source_locations_between_two_different_representations/

 atlas = ft_read_atlas(broddmanLoc);

cfg = [];
cfg.method        = 'nearest';
cfg.parameter = 'tissue';
atlas2 = ft_sourceinterpolate(cfg,atlas,sourcemodel);

roiData.time = eegData.time;
roiData.label = atlas.tissuelabel';
roiData.trial = {};

missingLabels = [];
for i = 1:length(atlas.tissuelabel)

    indx = find(atlas2.tissue==i);
    if isempty(indx)
        missingLabels = [missingLabels i];
    end

    for i3 = 1:length(trialSource.trial)
        timeseries = [];
        for i2 = 1:length(indx)
            try
                timeseries = cat(1,timeseries,trialSource.trial(i).mom{indx(i2)});
            end
        end

        if ~isempty(timeseries)
            for i4 = 1:size(timeseries,2)

                roiData.trial{i3}(i,i4) = mean(timeseries(:,i4));

            end
        else
            roiData.trial{i3}(i,:) = ones(1,length(roiData.time{1}))*10^-10;
        end
    end

end


Using this method, some ROIs from the atlas have zero indices found in the source model, which is confusing to me. I tried replace the source data for missing ROIs with a very small non-zero #(10^-10) so that the rest of the script runs. Looking at the indices now I realize that these are the indices with extrememly high granger values, so adding in small non-zero values is not a valid solution it seems. Is there any reason for these ROIs to not be showing up in my model? The missing indices are listed below. I assume that the issue is coming from the interpolation of the atlas.



missingLabels = [21 70 79 80 95 101 107 108 109]





Step 5: Calculate Connectivity



In this step I calculate granger causality. I don't think anything is going wrong here, after having gone through all of my code for this email I realize that the missing ROIs are the most likely culprit.


cfg            = [];
cfg.output     = 'fourier';
cfg.method     = 'mtmfft';
cfg.foilim     = [0 50];
cfg.tapsmofrq  = 4;
cfg.keeptrials = 'yes';
cfg.pad = 4;
freq    = ft_freqanalysis(cfg, roiData);

cfg = [];
cfg.method = 'granger';
cfg.granger.sfmethod = 'bivariate';
granger = ft_connectivityanalysis(cfg, freq);

Conclusions

After going through all of my code, I realize the main issue is that some of the atlas ROIs have no indices in my sourcemodel after interpolating. Is there any fix/advice that you can suggest to either fix this problem, or to make ft_sourceparcellate work so that I can avoid this issue altogether? I realize there is a lot of code and steps to go through here, and I appreciate any help that you can provide. This mailing list has been a great resource for me so far, and I hope I can return the favor to some fellow fieldtrippers soon!

Best,
Michael Glassen








________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
Sent: Thursday, May 14, 2020 2:02:38 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

The convention is left column to right column, so in this case RGAST to LGAST. the stuff between the ‘[‘ is to indicate that the pairwise metric has been obtained with a bivariate model that included LGAST and RGAST.

Best wishes,
Jan-Mathijs



On 14 May 2020, at 03:14, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi Jan-Mathijs,

I implemented all of your suggestions but I had a quick question on the organization of the bivariate granger connectivity structure. From what I can understand, this should compute connectivity from each channel to every other channel. This is my connectivity structure:
struct with fields:

         labelcmb: {14762×2 cell}
           dimord: 'chancmb_freq'
    grangerspctrm: [14762×201 double]
             freq: [1×201 double]
              cfg: [1×1 struct]

And looking at an entry of labelcmb(14762,:) gives:
1×2 cell array

    {'RGAST[RGAST,LGAST]'}    {'LGAST[RGAST,LGAST]'}

So does this mean that grangerspctrm(14762,:) is the granger connectivity from RGAST to LGAST, or is it from LGAST to RGAST?


Best,
Michael Glassen


________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Saturday, May 9, 2020 4:11:51 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Wanze,

I have two short questions regarding your suggestions to Michael: 1) any reason for why doing svd for concatenated trials would work better than doing svd per trial?

Well, it’s not that ‘it works better’, but using a per trial svd will result in a different orientation estimate per trial, which then inherently assumes a source model that fixes the location of the dipole, but not its orientation.


2) If we do svd with concatenated trials do we need to re-segment the data into epochs/trials?  I think ft_freqanalysis and ft_connectivity would work way more efficiently if they are applied to data in epochs rather than one long trial, although I am not 100% assured.

Indeed, in most situations (particularly if the experimental protocol is epoch based) it is mandatory to maintain the epoch-structure in the spectral decomposition and connectivity estimation step. To this end the concatenation step is an intermediate one, used only to compute the principal orientation, and this orientation can then be applied to the data structure that still contains the epochs, either using a for-loop across the individual epochs, or exploiting the external/cellfunction code, by a direct multiplication.

Best wishes,
Jan-Mathijs




Look forward to hearing from you.

Best,
Wanze



Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>于2020年5月8日 周五上午10:35写道：
Hi Michael,

The WFU atlas is a volumetrically defined atlas, correct? So, in order for the parcellation to work, the atlas needs to be mapped onto the cortically constrained sheet of dipoles that you used for source reconstruction.
This is not entirely trivial, but doable. If you obtained your atlas already as represented on a cortically constrained set of locations, then you need to ensure that these locations topologically map to the dipole locations of your source model.

Best wishes,
Jan-Mathijs






On 8 May 2020, at 16:15, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Thank you everyone for the help!

Just one final question, I got the Brodmann area atlas and the hemisphere atlas from this toolbox SPM “WFU-PickAtlas”.

Does anyone know if there is a Brodmann area atlas that is known to work with fieldtrip?

Best,
Michael Glassen
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl<mailto:jan.schoffelen at donders.ru.nl>>
Sent: Friday, May 8, 2020 3:17:56 AM
To: FieldTrip discussion list
Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Hi Michael,

Adding to Wanze’s and Xavier’s replies:


               I went through and plotted a couple different time series from the mom field from different trials and the same dipole, they are not equal and the shape looks ok to me, the magnitudes range from 10^-7 to 10^-4, is that normal? Source was calculated with everything in meters if that matters. Can you explain a little more the other method for calculating mom? The only option I have to add is keepfilter to sourceanalysis? And then I multiply each of these filters against the trial data matrix and it will leave me with what rawtrial is giving me but more reliably? Can I then still use the parcellate option on the output here? Or is this not necessary as rawtrial seems to be working?

If ‘rawtrial’ works, than this would be fine. I was a bit worried (and I’d need to look in the code myself in some more detail) because historically the ‘rawtrial’-functionality was implemented for the beamformer algorithms, and not for the MNE. As such, it has never been tested thoroughly for MNE, so although it seems to produce an output for you, I am not 100% sure that it’s correct. Also, anecdotally, the ‘rawtrial’/’singletrial’ functionality for the beamformers is shaky in itself, and we still have it on our to-do-list to make the code more internally consistent and correct.



-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).

               I tried using the ft_sourceparcellate function but I was running into a memory issue when ran on the rawtrial source, and when I remove that option and run it on the default trial-averaged sources I get a different error, which is pasted below. mri2 is the broddman area atlas interpolated onto my source model. Also, is there any way to parcellate twice with the function like I am doing by hand? The broddman area atlas I have is not divided into left and right hemispheres so I have another atlas I am using that is divided into hemispheres.

mri2 =

                                             struct with fields:

                                             pos: [8196×3 double]
                                              tri: [16384×3 double]
                                             unit: 'm'
                                              tissue: [8196×1 double]
                                             tissuelabel: {1×70 cell}
                                             cfg: [1×1 struct]

                              cfg =

                                             struct with fields:

                                              method: 'mean'
                                             parcellation: 'tissue'
                                               parameter: 'mom'

ft_sourceparcellate(cfg,sourceEEG,mri2)
there is no "Dentate" in "tissue"
there is no "Hypothalamus" in "tissue"
there is no "Substania Nigra" in "tissue"
there is no "Caudate Tail" in "tissue"
there is no "Putamen" in "tissue"
there is no "Medial Geniculum Body" in "tissue"
there is no "Lateral Globus Pallidus" in "tissue"
there is no "Subthalamic Nucleus" in "tissue"
there is no "Medial Globus Pallidus" in "tissue"
there is no "Lateral Geniculum Body" in "tissue"
there is no "Anterior Commissure" in "tissue"
there is no "Ventral Posterior Lateral Nucleus" in "tissue"
there is no "Ventral Posterior Medial Nucleus" in "tissue"
there is no "Ventral Lateral Nucleus" in "tissue"
there is no "Ventral Anterior Nucleus" in "tissue"
there is no "Caudate Body" in "tissue"
there is no "Lateral Posterior Nucleus" in "tissue"
there is no "Lateral Dorsal Nucleus" in "tissue"
there is no "Midline Nucleus" in "tissue"
there are in total 8196 positions, 8190 positions are inside the brain, 2611 positions have a label
2609 of the positions inside the brain have a label
2609 of the labeled positions are inside the brain
5581 of the positions inside the brain do not have a label
creating 70 parcels for parameter mom by taking the mean
computing parcellation
Index exceeds the number of array elements (0).

Error in ft_sourceparcellate>cellmean1 (line 488)
y = x{1};

Error in ft_sourceparcellate (line 226)
                                             tmp(j,:,:) = cellmean1(dat(seg==j));

               -If I cannot get source parcellate to work, does my method of creating a mask and pulling out the source powers seem sound? I see that I should use mom instead of pow, so would I then just take all the voxels in an ROI and average the x direction together, the y direction together and the z together? Then find the direction with the largest power and use that as my 1by x time series power(using svd as described in documentation)? This is what I’m assuming sourceparcellate does if I select ‘eig’ as the method.

-With regard to thte parcellation: understood if memory limitations prevent you from using it. Yet, the error message you get when using the trial-averaged data suggests an issue with your atlas. Where did you get it from? It looks as if only 2611 out of the 8196 cortical locations have a label. Is that according to your expectations?
-If indeed you are to manually parcellate (with the mask), you can do one of the following:
  * average x/y/z across dipole locations, followed by an svd (I’d recommend to do this svd on the trial-concatenated data, rather than on a per-trial basis)
  * (to mimick the ‘eig’ method): concatenate the time series across dipole locations (and trials), followed by a single svd on the whole matrix.





ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.


               -Finally, if I choose to go for granger, what kind of cfg.pad and tapsmofrq would you recommend? I am mostly interested in the beta band(12-30Hz) and my trial lengths are 357 samples(1.3 seconds)

Irrespective of using granger or the disrecommended dtf/pdc, all techniques that require a spectral factorization need padding and smoothing. In your case I’d recommend a padding of 4 (cfg.pad = 4), and a cfg.tapsmofrq somewhere in the range of 3 and 6 (but the latter is a bit of ‘wet finger work’, as we sould say in Dutch -> google for ’natte vingerwerk’ if you want to learn more).

Best wishes,
Jan-Mathijs



Subject: Re: [FieldTrip] Computing source-level ROI EEG connectivity

Dear Michael,

It looks that you already got quite far! I agree that the DTF values do not make much sense.

a few pointers:

-I would use some regularisation for  the MNE reconstruction.
-I would check whether the individual trials after source reconstruction yield meaningful values in the ‘mom’-field. Particularly, are the different trials different? Do the time series look meaningful to begin with (both in terms of signal magnitude and ’shape’)? The reason I ask, is that I am not fully sure whether the ‘rawtrial’ option is behaving according to your expectations.
-Another way for getting the mom would be to use cfg.keepfilter in ft_sourceanalysis, and left-multiply each dipole location’s ’spatial filter’ (in sourceEEG.avg.filter) with a dataEEG.trial matrix.
-IMPORTANT: don’t use the ‘pow’ for the subsequent spectral analysis and connectivity estimation. You should work with the mom.
-In order to get a ‘parcellated’ representation of your source level data, I recommend to use ft_sourceparcellate, which should achieve the parcellation you performed by hand (with the binary masks).
-The parcellation operation can be an average of the mom across the dipoles that belong to a parcel, but an alternative might be the the 1st principal component. The advantage of the latter would be that the per-parcel signal will be reduced to a single time series (rather then 3 x/y/z orientation time courses), which is convenient (and required) for the interpretation of the subsequent computations.
-You may want to think a bit about the depth weighting, since the MNE favors superficial locations in terms of amplitude, and this will also percolate to the way the parcellated time series are computed.
-IMPORTANT: using ‘dtf’ without any additional specification of parameters is probably not what you want here. The reason is that under the hood a multivariate factorization of the spectral matrix is performed (at least: an attempt is made), which will miserably fail in your case. The reason for this failure (thinking a bit more about this, I am quite surprised that it worked to begin with) is the fact that you ask for a factorization of a size NparcelxNparcel(xfrequency bins) matrix, where the effective rank of the matrix is less than the number of channels in your EEG array. Even if Nparcel is less than the number of EEG electrodes, this factorization will be very poorly estimated and nonsensical. I’d recommend using ‘granger’ as a method, in combination with cfg.granger.sfmethod = ‘bivariate’. This results in a parcel-pairwise factorization (which is hopefully stable most of the time). I am not a fan of dtf/pdc anyway given that the measures are claimed to provide estimates unproblematic estimates that are interpretable without any caveats.
-ALSO IMPORTANT: if you go for a granger-like measure (granger/dtf/pdc), in the spectral analysis you should probably use a decent amount of zero padding (cfg.pad) and sufficient tapsmofrq in order to get spectral data that stands a chance to get a stable factorization.

So, no definitive answers unfortunately, but perhaps some food for thought that might get you closer to a good result.

Good luck and keep up the good work,

Jan-Mathijs



J.M.Schoffelen, MD PhD
Associate PI, VIDI-fellow - PI, language in interaction
Telephone: +31-24-3614793
Physical location: room 00.028
Donders Centre for Cognitive Neuroimaging, Nijmegen, The Netherlands


On 6 May 2020, at 22:34, Michael Glassen - Biomedical Engineer <MGlassen at kesslerfoundation.org<mailto:MGlassen at kesslerfoundation.org>> wrote:

Hi all,

I am having issues using fieldtrip for source reconstruction and connectivity analysis with preprocessed EEG data. I believe the issue is occurring when I try to project my sources to specific ROIs before getting the connectivity. I have outlined my pipeline below:

-Because I do not have subject MRIs, I am using a template headmodel and sourcemodel that come included with fieldtrip
               - headmodel = standard_bem.mat
               -sourcemodel = cortex_8196.surf.gii

-After importing EEG data, I project the EEG electrodes to the scalp using the code below:
               if strcmp(headmodel.type, 'bemcp')
             scalp_index = 3;
elseif strcmp(headmodel.type, 'dipoli')
             scalp_index = 1;
end
cfg = [];
cfg.method = 'project';
cfg.headshape = headmodel.bnd(scalp_index);

eegData.elec = ft_electroderealign(cfg, eegData.elec);


-I then calculate covariance on a trial basis and calculate the leadfield matrix:

               cfg = [];
cfg.covariance = 'yes';
cfg.covariancewindow = [-inf 0];
cfg.keeptrials = 'yes';
tlckEeg = ft_timelockanalysis(cfg, eegData);
cfg         = [];
cfg.elec    = tlckEeg.elec;   % sensor information
cfg.channel = tlckEeg.label;  % the used channels
cfg.grid    = sourcemodel;   % source points
cfg.headmodel = headmodel;   % volume conduction model
cfg.singleshell.batchsize = 5000; % speeds up the computation
leadfield   = ft_prepare_leadfield(cfg);


-Now with the leadfield calculated, I calculate sources on a trial basis here:

cfg               = [];
cfg.method        = 'mne';
cfg.sourcemodel   = leadfield;
cfg.headmodel     = headmodel;
cfg.mne.prewhiten = 'yes';
cfg.mne.lambda    = 0;
cfg.mne.scalesourcecov = 'yes';
cfg.rawtrial      = 'yes';
sourceEEG          = ft_sourceanalysis(cfg,tlckEeg);
               sourceEEG =

                              struct with fields:

                              time: [1×357 double]
                              inside: [8196×1 logical]
                              pos: [8196×3 double]
                               tri: [16384×3 double]
                              method: 'rawtrial'
                              trial: [1×400 struct]
                              df: 400
                              cfg: [1×1 struct]


               sourceEEG.trial =

                              1×400 struct array with fields:

                              mom
                               pow
                              noisecov

size(sourceEEG.trial(1).pow)

ans =

                                             8196         357

-So at this point I have 400 trials, and for each of these trials I have a time course of source power at 8196 voxels and 357 time points for each of those voxels.
-I then import two atlases, one that includes broddman areas and one that includes left and right hemispheres. I interpolate these atlases onto my source model and get the following:
               broddman =
struct with fields:

                                      pos: [8196×3 double]
                                       tri: [16384×3 double]
                                        unit: 'm'
                                       tissue: [8196×1 double] (each of these is a value 1-70, corresponding to which atlas entry the voxel is located in)
                                       tissuelabel: {1×70 cell}(ROI labels for the atlas, includes broddman areas not separated by hemisphere)
                                      cfg: [1×1 struct]
hemis2 =
struct with fields:
pos: [8196×3 double]
                                      tri: [16384×3 double]
                                        unit: 'm'
                                        tissue: [8196×1 double] (each of these is a value 1-7, corresponding to which atlas entry the voxel is located in)

                                         tissuelabel: {1×7 cell} (ROI Labels for hemisphere atlas, contains 3 Left areas, 3 Right Areas and one inter-hemispheric)
                                      cfg: [1×1 struct]


Now I create a binary mask for each left and right broddman area. For each ROI in the broddman area atlas(1-70), I find all voxels that are located within. This gives me a list of voxels for each broddman area. I then take each of these lists and find which are in the left hemisphere and which are in the right to get left and right broddman areas.
After these steps I am left with 140 binary masks, (size 1x8196), which equal 1 if the voxel is contained in the specific ROI and 0 if it is not. Using these masks, I extract the time course power for each ROI by taking the mean power of every voxel in the roi at each time point:
                    roiData(i,i3,i2) = mean(sourceEEG.trial(i2).pow(Masks{i},i3));

where i = roi number,

       i2 = trial number,

       i3 = time point

In order to get this data into fieldtrip format, I put ROI data into an EEGLAB structure along with 6 emg channels that were recorded at the same time and use eeglab2fieldtrip function to have a fieldtrip structure containing the broddman area sources as channels. (contained in header)

After this I perform the final step of computing dtf connectivity between each of the source rois and the emg channels with the code below:

cfg           = [];
cfg.method    = 'mtmfft';
cfg.taper     = 'dpss';
cfg.output    = 'fourier';
cfg.tapsmofrq = 2;
freq          = ft_freqanalysis(cfg, header);
cfg           = [];
cfg.method    = 'dtf';
dtf           = ft_connectivityanalysis(cfg, freq);


The values I get in DTF are extremely low, 10^-20. I am not sure why but I believe it has to do with the way I am projecting source activations onto specific ROIs. Any help or advice on how to change my pipeline is appreciated.


Best,
Michael Glassen



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202



  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


  ­­   _______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200516/9e9947a7/attachment.htm>

From camille.maumet at inria.fr  Fri May 22 11:02:41 2020
From: camille.maumet at inria.fr (Camille Maumet)
Date: Fri, 22 May 2020 11:02:41 +0200 (CEST)
Subject: [FieldTrip] Call for emergent sessions in the Open Science Room at
 OHBM 2020
Message-ID: <1533605515.6419890.1590138161623.JavaMail.zimbra@inria.fr>



Dear members of the FieldTrip community, 




With the [ https://zimbra.inria.fr/ossig.netlify.com/ | OHBM Open Science Special Interest Group (OS-SIG) ] we have a few important updates about the Open Science Room (that will be held virtually during OHBM 2020): 




    1. 

The call for OSR talks is now CLOSED. Submission is now CLOSED for talks in this year's virtual OSR, except for emergent and invited talks . We will be notifying successful applicants soon to start recordings. We communicated previously that there would be a second call for talks, but due to the happy situation of being flooded with submissions, we have decided to close the call and allow time to focus on delivering the best content we can in the time available. If you missed the opportunity to submit a talk and you feel it would be of great benefit to the community, you can [ https://ohbm.github.io/osr2020/contact/ | reach out to us directly ] to consider your proposal. 
    2. 

Emergent session submissions are OPEN . Emergent sessions can still be submitted, leading up to and during the meeting. Which important or controversial topics would you like to see in the OSR? Do you want to lead an informal panel discussion? [ https://ohbm.github.io/osr2020/submit/ | Send us your ideas ] ! 
    3. 

Join the open community review process! We’d love to hear your feedback on the [ https://github.com/ohbm/osr2020/issues?q=is%3Aissue+is%3Aopen+Emergent+session | emergent session submissions ] . Feel free to add an emoji to the abstracts you like, or start a conversation with the authors by commenting! 





We'd also like to thank our volunteers! Our call for volunteers to help build a great Open Science Room was met with enthusiasm! We now have multiple teams up and running and we’re very excited about what’s next. We are so grateful to be part of such an engaging and helpful community. Thank you all! 




For more information, please visit our [ https://ohbm.github.io/osr2020/faq/ | FAQ ] . You are also welcome to reach out to us at [ mailto:ohbm.osr at gmail.com | ohbm.osr at gmail.com ] and follow [ https://twitter.com/ohbmopen | @OHBMopen ] on Twitter or visit the [ https://ohbm.github.io/osr2020/ | OSR website ] for updates. 




Kind regards, 




Camille Maumet, Cassandra Gould van Praag and Stephan Heunis, on behalf of the OS-SIG 
-- 
Camille Maumet, PhD 

Researcher 
Inria, Univ Rennes, CNRS, Inserm 
Campus de Beaulieu 
35042 Rennes Cedex, France 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200522/01327bad/attachment.htm>

From ffein at stanford.edu  Mon May 25 18:55:59 2020
From: ffein at stanford.edu (Franklin Feingold)
Date: Mon, 25 May 2020 16:55:59 +0000
Subject: [FieldTrip] BIDS Derivatives final request for comments
Message-ID: <2EA6137A-0589-49E0-964F-159B91F8033A@stanford.edu>

The BIDS community is preparing to merge the Common Derivatives extension. The updated draft is available for review at https://bids-specification.readthedocs.io/en/common-derivatives/, and comments and suggestions may be submitted on GitHub at https://github.com/bids-standard/bids-specification/pull/265.


The scope of this extension is establishing a set of common principles for organizing derivative datasets, dataset-level metadata, and naming conventions for minimally preprocessed files. Additionally, some common imaging derivatives (e.g., brain masks) have been specified. More detailed modality-specific derivatives are scheduled for inclusion in the next few months.


The final review process entails a minimum of one week for public comment, with a possibility of extension for unresolved discussion. Once public comments are concluded, there will be a one week freeze, during which only critical issues will be considered. (For more details on the release protocol, see https://github.com/bids-standard/bids-specification/blob/master/Release_Protocol.md.)


We look forward to hearing your feedback!

Franklin


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200525/2b87b226/attachment.htm>

From lsmith at cortechsolutions.com  Tue May 26 19:42:29 2020
From: lsmith at cortechsolutions.com (Lloyd Smith)
Date: Tue, 26 May 2020 13:42:29 -0400
Subject: [FieldTrip] support for Biosemi firmware 4.0?
Message-ID: <CAJr_e2uBbVXLr0WQV2s_ws-G_=oaoSw4P5bbj+0YCmHXHwsZFA@mail.gmail.com>

Hi, all. First time posting here, so please pardon any lack of default
knowledge. My company handles US/Canada sales and support for the Biosemi
ActiveTwo EEG system, and I know a lot of our customers use Fieldtrip.
Until now I have never had a pre-sales question from a customer about
Fieldtrip. I was unable to find an answer in your archives, so I am posting
it here.

In mid-2015, Biosemi released firmware 4.0 for the optical receiver / USB
interface. This eliminates the need to install a driver, instead utilizing
a driver that ships with Windows 10. Most older ActiveTwo systems can be
field-upgraded by end-users according to instructions at
https://www.biosemi.com/faq/install_USB.htm.

Thie page at your site -
http://www.fieldtriptoolbox.org/development/realtime/biosemi/ - does not
mention which optical receiver / USB interface firmware versions are
compatible, which leaves open the question of whether firmware 4.0 is
supported. Firmware 3.0 shipped from sometime before Spring 2011 until
Spring of 2015, but all systems shipped from about June 2015 forward have
firmware 4.0, and many older systems have been field-upgraded.

Thanks in advance for any insight!

Best regards,

Lloyd Smith
President
Cortech Solutions, Inc.

E-mail: LSmith at cortechsolutions.com
Tel: 910-362-1143 x202
Cell: 910-431-2811

-- 
Cortech Solutions, Inc.1409 Audubon Blvd, Suite B1
Wilmington, NC 28403 USA



Tel: 910-362-1143
Fax: 910-378-3443



Sales: sales at cortechsolutions.com 
<mailto:sales at cortechsolutions.com>
Support / repairs: 
support at cortechsolutions.com <mailto:support at cortechsolutions.com>
Billing 
/ administration: admin at cortechsolutions.com 
<mailto:admin at cortechsolutions.com>


Web: www.cortechsolutions.com 
<http://www.cortechsolutions.com>



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200526/705b9709/attachment.htm>

From 534843 at umons.ac.be  Wed May 27 09:33:58 2020
From: 534843 at umons.ac.be (Luca La Fisca)
Date: Wed, 27 May 2020 09:33:58 +0200
Subject: [FieldTrip] Frequency shift after source reconstruction
Message-ID: <CAL34+YdK96Qb56xiw2jpYkmq6CRAhwCdi8bR2B+jm9fOU8CH0Q@mail.gmail.com>

Dear community,

I'm Luca La Fisca, PhD student in Belgium and I'm validating the source
reconstruction algorithm using "ft_dipolesimulation".

After having performed a frequency analysis, I noticed the reconstructed
sources have twice the initial frequencies as shown in the following
figures (initial dipole frequencies = 10 and 85 Hz) :

Timelock:
[image: image.png]

Reconstructed sources:
[image: image.png]

Here is the code used to get the timelock signal:
fs = 2048;
fs_down = 512;

% generate EEG pseudo-signal
cfg      = [];
cfg.headmodel = vol;
cfg.elec = elec_aligned;
cfg.channel = elec_aligned.label(1:64);

cfg.dip.pos = [
   -1 65 36           % dipole left
   1 -62 43          % dipole right
   ];

unif_dip = 3^(1/2)/3;
cfg.dip.mom = ...
  [ unif_dip unif_dip unif_dip 0 0 0 ]' + ...
  [ 0 0 0 unif_dip unif_dip unif_dip ]';

event = ft_read_event(EEG_FILE);
event = event(3:end);
signal1 = zeros(length(eeg_data.trial));
signal2 = zeros(length(eeg_data.trial));
val = [event.value];
for s = drange([event(val==10).sample, event(val==11).sample,
event(val==12).sample])
    time = (0:ceil(fs*0.5))/fs;
    signal1(s:s+ceil(fs*0.5)) = 10*sin(10*time*2*pi);
    signal2(s:s+ceil(fs*0.5)) = 30*cos(85*time*2*pi);
end

cfg.dip.signal = {[signal1; signal2]};
cfg.fsample = fs;
raw1 = ft_dipolesimulation(cfg);

% Timelock analysis
% define trials
cfg = [];
cfg.dataset = EEG_FILE;
cfg.trialdef.eventtype  = 'STATUS';
cfg.trialdef.eventvalue = [10 11 12];
cfg.trialdef.prestim    = 0.5;
cfg.trialdef.poststim   = 1;
cfg = ft_definetrial(cfg);
data_trial = ft_redefinetrial(cfg, raw1);

% downsample
cfg = [];
cfg.resamplefs = fs_down;
data_trial = ft_resampledata(cfg,data_trial);

cfg = [];
timelock = ft_timelockanalysis(cfg, data_trial);


Here the code related to the source reconstruction:
% Estimating the leadfield
cfg = [];
cfg.sourcemodel = sourcemodel;    %% where are the sources?
cfg.headmodel   = vol;      %% how do currents spread?
cfg.elec        = elec_aligned; %% where are the sensors?
cfg.channel = elec_aligned.label(1:64);
sourcemodel_and_leadfield = ft_prepare_leadfield(cfg, timelock);

% Source reconstruction
cfg                     = [];
cfg.method              = 'mne';
cfg.sourcemodel         = sourcemodel_and_leadfield;        %the
precomputed leadfield
cfg.headmodel           = vol;                      %the head model
cfg.elec                = elec_aligned;             %the electrodes
cfg.channel             = elec_aligned.label(1:64); %the useful channels
cfg.mne.prewhiten       = 'yes';                    %prewhiten data
cfg.mne.lambda          = 0.01;                     %regularisation
parameter
cfg.mne.scalesourcecov  = 'yes';                %scaling the source
covariance matrix
minimum_norm_eeg        = ft_sourceanalysis(cfg,timelock);

Here the code to perform the frequency analysis:
tmp_pow = minimum_norm_eeg.avg.pow;
pow_fft = fft(tmp_pow'); %freq analysis of reconstructed sources
% pow_fft = fft(timelock.avg'); %freq analysis of timelock signal
% (un)comment depending on the desired one

L = length(timelock.avg);
f = fs_down*(0:(L/2))/L;

P2 = abs(pow_fft/L);
P1 = P2(1:L/2+1,:);
P1 = P1.*f';

figure()
plot(f,P1)
title('Single-Sided Amplitude Spectrum of Reconstructed Sources')
xlabel('f (Hz)')
ylabel('|P1(f)|')

Do you have any idea of what is responsible to this double frequency?
Do you think it is a general issue?
Is it a major issue leading to wrong analysis of the reconstructed signal
(e.g. connectivity analysis)?

I thank you in advance.

Best regards,

*Luca La Fisca*
*PhD Student*
Service d'Information, Signal et Intelligence Artificielle

Boulevard Dolez, 31

7000 Mons

+32 (0)65/37.40.83

*Luca.LAFISCA at umons.ac.be <Luca.LAFISCA at umons.ac.be>*




<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Garanti
sans virus. www.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/c1d6bdbc/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 99182 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/c1d6bdbc/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 99627 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/c1d6bdbc/attachment-0001.png>

From jan.schoffelen at donders.ru.nl  Wed May 27 09:47:30 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Wed, 27 May 2020 07:47:30 +0000
Subject: [FieldTrip] Frequency shift after source reconstruction
In-Reply-To: <CAL34+YdK96Qb56xiw2jpYkmq6CRAhwCdi8bR2B+jm9fOU8CH0Q@mail.gmail.com>
References: <CAL34+YdK96Qb56xiw2jpYkmq6CRAhwCdi8bR2B+jm9fOU8CH0Q@mail.gmail.com>
Message-ID: <56E17F24-C4E2-46A4-B690-6F4F3F678D3D@donders.ru.nl>

Caro Luca,

I haven’t read your code in detail, but I suspect that you perform a spectral analysis on the source.avg.pow, which is the magnitude(-squared) version of the signal’s time course.
As a consequence of this, your frequency ‘doubles’. Consider a sine wave with a given frequency (i.e. a period of 1/f), say 1 Hz. If you take that absolute(-squared) of that sine wave, you get a signal with ’two bumps’ per second, which reflects a periodicity of 2 Hz.

You should work with the ‘mom’ field at the source level.

Best wishes,

Jan-Mathijs


On 27 May 2020, at 09:33, Luca La Fisca <534843 at umons.ac.be<mailto:534843 at umons.ac.be>> wrote:

Dear community,

I'm Luca La Fisca, PhD student in Belgium and I'm validating the source reconstruction algorithm using "ft_dipolesimulation".

After having performed a frequency analysis, I noticed the reconstructed sources have twice the initial frequencies as shown in the following figures (initial dipole frequencies = 10 and 85 Hz) :

Timelock:
<image.png>

Reconstructed sources:
<image.png>

Here is the code used to get the timelock signal:
fs = 2048;
fs_down = 512;

% generate EEG pseudo-signal
cfg      = [];
cfg.headmodel = vol;
cfg.elec = elec_aligned;
cfg.channel = elec_aligned.label(1:64);

cfg.dip.pos = [
   -1 65 36           % dipole left
   1 -62 43          % dipole right
   ];

unif_dip = 3^(1/2)/3;
cfg.dip.mom = ...
  [ unif_dip unif_dip unif_dip 0 0 0 ]' + ...
  [ 0 0 0 unif_dip unif_dip unif_dip ]';

event = ft_read_event(EEG_FILE);
event = event(3:end);
signal1 = zeros(length(eeg_data.trial));
signal2 = zeros(length(eeg_data.trial));
val = [event.value];
for s = drange([event(val==10).sample, event(val==11).sample, event(val==12).sample])
    time = (0:ceil(fs*0.5))/fs;
    signal1(s:s+ceil(fs*0.5)) = 10*sin(10*time*2*pi);
    signal2(s:s+ceil(fs*0.5)) = 30*cos(85*time*2*pi);
end

cfg.dip.signal = {[signal1; signal2]};
cfg.fsample = fs;
raw1 = ft_dipolesimulation(cfg);

% Timelock analysis
% define trials
cfg = [];
cfg.dataset = EEG_FILE;
cfg.trialdef.eventtype  = 'STATUS';
cfg.trialdef.eventvalue = [10 11 12];
cfg.trialdef.prestim    = 0.5;
cfg.trialdef.poststim   = 1;
cfg = ft_definetrial(cfg);
data_trial = ft_redefinetrial(cfg, raw1);

% downsample
cfg = [];
cfg.resamplefs = fs_down;
data_trial = ft_resampledata(cfg,data_trial);

cfg = [];
timelock = ft_timelockanalysis(cfg, data_trial);


Here the code related to the source reconstruction:
% Estimating the leadfield
cfg = [];
cfg.sourcemodel = sourcemodel;    %% where are the sources?
cfg.headmodel   = vol;      %% how do currents spread?
cfg.elec        = elec_aligned; %% where are the sensors?
cfg.channel = elec_aligned.label(1:64);
sourcemodel_and_leadfield = ft_prepare_leadfield(cfg, timelock);

% Source reconstruction
cfg                     = [];
cfg.method              = 'mne';
cfg.sourcemodel         = sourcemodel_and_leadfield;        %the precomputed leadfield
cfg.headmodel           = vol;                      %the head model
cfg.elec                = elec_aligned;             %the electrodes
cfg.channel             = elec_aligned.label(1:64); %the useful channels
cfg.mne.prewhiten       = 'yes';                    %prewhiten data
cfg.mne.lambda          = 0.01;                     %regularisation parameter
cfg.mne.scalesourcecov  = 'yes';                %scaling the source covariance matrix
minimum_norm_eeg        = ft_sourceanalysis(cfg,timelock);

Here the code to perform the frequency analysis:
tmp_pow = minimum_norm_eeg.avg.pow;
pow_fft = fft(tmp_pow'); %freq analysis of reconstructed sources
% pow_fft = fft(timelock.avg'); %freq analysis of timelock signal
% (un)comment depending on the desired one

L = length(timelock.avg);
f = fs_down*(0:(L/2))/L;

P2 = abs(pow_fft/L);
P1 = P2(1:L/2+1,:);
P1 = P1.*f';

figure()
plot(f,P1)
title('Single-Sided Amplitude Spectrum of Reconstructed Sources')
xlabel('f (Hz)')
ylabel('|P1(f)|')

Do you have any idea of what is responsible to this double frequency?
Do you think it is a general issue?
Is it a major issue leading to wrong analysis of the reconstructed signal (e.g. connectivity analysis)?

I thank you in advance.

Best regards,

[https://docs.google.com/uc?export=download&id=1kIixsLbG6VMY0eKRmD_V2qGfWdocai3Y&revid=0B-dw3epKQGxwWWNSYThqWVJCZjZYOGJtNnljTHg1OGR5WFNJPQ]
Luca La Fisca
PhD Student
Service d'Information, Signal et Intelligence Artificielle
Boulevard Dolez, 31
7000 Mons
+32 (0)65/37.40.83
Luca.LAFISCA at umons.ac.be<mailto:Luca.LAFISCA at umons.ac.be>

[https://docs.google.com/uc?export=download&id=1Os8PgOWiHRZwQs_oiXqKDg2gkH2mcJDb&revid=0B-dw3epKQGxweUxueTZMZzRNd2pYR1docldnQzJzWExCWGpFPQ]

[https://ipmcdn.avast.com/images/icons/icon-envelope-tick-round-orange-animated-no-repeat-v1.gif]<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>  Garanti sans virus. www.avast.com<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<x-msg://5/#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/e82236f7/attachment.htm>

From 534843 at umons.ac.be  Wed May 27 10:44:42 2020
From: 534843 at umons.ac.be (Luca La Fisca)
Date: Wed, 27 May 2020 10:44:42 +0200
Subject: [FieldTrip] Frequency shift after source reconstruction
In-Reply-To: <56E17F24-C4E2-46A4-B690-6F4F3F678D3D@donders.ru.nl>
References: <CAL34+YdK96Qb56xiw2jpYkmq6CRAhwCdi8bR2B+jm9fOU8CH0Q@mail.gmail.com>
 <56E17F24-C4E2-46A4-B690-6F4F3F678D3D@donders.ru.nl>
Message-ID: <CAL34+YftczmGFvd63oK5-G2X74KhQOevzaQXLcq0Mf-ZrV1YSw@mail.gmail.com>

Dear Jan-Mathijs,

It is exactly the problem!

Thank you very much :)

Have a nice day,

*Luca La Fisca*
*PhD Student*
Service d'Information, Signal et Intelligence Artificielle

Boulevard Dolez, 31

7000 Mons

+32 (0)65/37.40.83

*Luca.LAFISCA at umons.ac.be <Luca.LAFISCA at umons.ac.be>*





<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Garanti
sans virus. www.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Wed, May 27, 2020 at 10:15 AM Schoffelen, J.M. (Jan Mathijs) <
jan.schoffelen at donders.ru.nl> wrote:

> Caro Luca,
>
> I haven’t read your code in detail, but I suspect that you perform a
> spectral analysis on the source.avg.pow, which is the magnitude(-squared)
> version of the signal’s time course.
> As a consequence of this, your frequency ‘doubles’. Consider a sine wave
> with a given frequency (i.e. a period of 1/f), say 1 Hz. If you take that
> absolute(-squared) of that sine wave, you get a signal with ’two bumps’ per
> second, which reflects a periodicity of 2 Hz.
>
> You should work with the ‘mom’ field at the source level.
>
> Best wishes,
>
> Jan-Mathijs
>
>
> On 27 May 2020, at 09:33, Luca La Fisca <534843 at umons.ac.be> wrote:
>
> Dear community,
>
> I'm Luca La Fisca, PhD student in Belgium and I'm validating the source
> reconstruction algorithm using "ft_dipolesimulation".
>
> After having performed a frequency analysis, I noticed the reconstructed
> sources have twice the initial frequencies as shown in the following
> figures (initial dipole frequencies = 10 and 85 Hz) :
>
> Timelock:
> <image.png>
>
> Reconstructed sources:
> <image.png>
>
> Here is the code used to get the timelock signal:
> fs = 2048;
> fs_down = 512;
>
> % generate EEG pseudo-signal
> cfg      = [];
> cfg.headmodel = vol;
> cfg.elec = elec_aligned;
> cfg.channel = elec_aligned.label(1:64);
>
> cfg.dip.pos = [
>    -1 65 36           % dipole left
>    1 -62 43          % dipole right
>    ];
>
> unif_dip = 3^(1/2)/3;
> cfg.dip.mom = ...
>   [ unif_dip unif_dip unif_dip 0 0 0 ]' + ...
>   [ 0 0 0 unif_dip unif_dip unif_dip ]';
>
> event = ft_read_event(EEG_FILE);
> event = event(3:end);
> signal1 = zeros(length(eeg_data.trial));
> signal2 = zeros(length(eeg_data.trial));
> val = [event.value];
> for s = drange([event(val==10).sample, event(val==11).sample,
> event(val==12).sample])
>     time = (0:ceil(fs*0.5))/fs;
>     signal1(s:s+ceil(fs*0.5)) = 10*sin(10*time*2*pi);
>     signal2(s:s+ceil(fs*0.5)) = 30*cos(85*time*2*pi);
> end
>
> cfg.dip.signal = {[signal1; signal2]};
> cfg.fsample = fs;
> raw1 = ft_dipolesimulation(cfg);
>
> % Timelock analysis
> % define trials
> cfg = [];
> cfg.dataset = EEG_FILE;
> cfg.trialdef.eventtype  = 'STATUS';
> cfg.trialdef.eventvalue = [10 11 12];
> cfg.trialdef.prestim    = 0.5;
> cfg.trialdef.poststim   = 1;
> cfg = ft_definetrial(cfg);
> data_trial = ft_redefinetrial(cfg, raw1);
>
> % downsample
> cfg = [];
> cfg.resamplefs = fs_down;
> data_trial = ft_resampledata(cfg,data_trial);
>
> cfg = [];
> timelock = ft_timelockanalysis(cfg, data_trial);
>
>
> Here the code related to the source reconstruction:
> % Estimating the leadfield
> cfg = [];
> cfg.sourcemodel = sourcemodel;    %% where are the sources?
> cfg.headmodel   = vol;      %% how do currents spread?
> cfg.elec        = elec_aligned; %% where are the sensors?
> cfg.channel = elec_aligned.label(1:64);
> sourcemodel_and_leadfield = ft_prepare_leadfield(cfg, timelock);
>
> % Source reconstruction
> cfg                     = [];
> cfg.method              = 'mne';
> cfg.sourcemodel         = sourcemodel_and_leadfield;        %the
> precomputed leadfield
> cfg.headmodel           = vol;                      %the head model
> cfg.elec                = elec_aligned;             %the electrodes
> cfg.channel             = elec_aligned.label(1:64); %the useful channels
> cfg.mne.prewhiten       = 'yes';                    %prewhiten data
> cfg.mne.lambda          = 0.01;                     %regularisation
> parameter
> cfg.mne.scalesourcecov  = 'yes';                %scaling the source
> covariance matrix
> minimum_norm_eeg        = ft_sourceanalysis(cfg,timelock);
>
> Here the code to perform the frequency analysis:
> tmp_pow = minimum_norm_eeg.avg.pow;
> pow_fft = fft(tmp_pow'); %freq analysis of reconstructed sources
> % pow_fft = fft(timelock.avg'); %freq analysis of timelock signal
> % (un)comment depending on the desired one
>
> L = length(timelock.avg);
> f = fs_down*(0:(L/2))/L;
>
> P2 = abs(pow_fft/L);
> P1 = P2(1:L/2+1,:);
> P1 = P1.*f';
>
> figure()
> plot(f,P1)
> title('Single-Sided Amplitude Spectrum of Reconstructed Sources')
> xlabel('f (Hz)')
> ylabel('|P1(f)|')
>
> Do you have any idea of what is responsible to this double frequency?
> Do you think it is a general issue?
> Is it a major issue leading to wrong analysis of the reconstructed signal
> (e.g. connectivity analysis)?
>
> I thank you in advance.
>
> Best regards,
>
> *Luca La Fisca*
> *PhD Student*
> Service d'Information, Signal et Intelligence Artificielle
>
> Boulevard Dolez, 31
>
> 7000 Mons
>
> +32 (0)65/37.40.83
>
> *Luca.LAFISCA at umons.ac.be <Luca.LAFISCA at umons.ac.be>*
>
>
>
>
>
> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail> Garanti
> sans virus. www.avast.com
> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/96972713/attachment.htm>

From roberto.garza at artorg.unibe.ch  Wed May 27 10:48:33 2020
From: roberto.garza at artorg.unibe.ch (roberto.garza at artorg.unibe.ch)
Date: Wed, 27 May 2020 08:48:33 +0000
Subject: [FieldTrip] tetrahedral to hexahedral mesh
Message-ID: <2fd108830fb249eab06332279dcddce2@artorg.unibe.ch>

Good morning,

I'm working in the DBS field and I'm using your library to obtain the headmodel. My aim is to include conductivity anisotropy in the computation of the electric field (by using the FieldTrip-SimBio pipeline). I have one conductivity matrix for each voxel in the image, so I built a hexahedral mesh to get a straightforward correspondence between an element and its conductivity. Now I need to integrate in the model the electrode as well: I have it in the form of a tetrahedral mesh. Is there a way to convert tetrahedral mesh to hexahedral? Or is there another way to integrate the two models that I'm not seeing?


Thank you for your time


Roberto Garza
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/ad26e496/attachment.htm>

From j.vorw01 at gmail.com  Wed May 27 10:58:19 2020
From: j.vorw01 at gmail.com (Johannes Vorwerk)
Date: Wed, 27 May 2020 10:58:19 +0200
Subject: [FieldTrip] tetrahedral to hexahedral mesh
In-Reply-To: <2fd108830fb249eab06332279dcddce2@artorg.unibe.ch>
References: <2fd108830fb249eab06332279dcddce2@artorg.unibe.ch>
Message-ID: <0C1496AA-EE8F-4D9B-8CF8-DC69C4068D32@gmail.com>

Hi Roberto,

having implemented the FieldTrip-Simbio pipeline and having worked on DBS myself, I would recommend you not to use a hexahedral mesh for this kind of simulations, since it is very hard to properly resolve the geometry of a DBS lead in a hexahedral mesh. Furthermore, the mesh should be especially refined around the DBS lead to achieve high numerical accuracies, which is only (easily) possible using tetrahedral meshes.

To achieve anisotropic conductivities in a tetrahedral mesh, I would recommend you to assign the anisotropy tensor of the voxel closest to the center of the tetrahedral element for each element. Additional interpolation of the tensors is quite tricky.

For DBS computations, I would also recommend you to take a look at LeadDBS (Horn, Andreas, et al. "Lead-DBS v2: Towards a comprehensive pipeline for deep brain stimulation imaging." Neuroimage 184 (2019): 293-316., lead-dbs.org <http://lead-dbs.org/>), which relies on the same numerical background as FieldTrip-SimBio.

Best,
	Johannes

> On 27. May 2020, at 10:48, <roberto.garza at artorg.unibe.ch> <roberto.garza at artorg.unibe.ch> wrote:
> 
> Good morning,
> I'm working in the DBS field and I'm using your library to obtain the headmodel. My aim is to include conductivity anisotropy in the computation of the electric field (by using the FieldTrip-SimBio pipeline). I have one conductivity matrix for each voxel in the image, so I built a hexahedral mesh to get a straightforward correspondence between an element and its conductivity. Now I need to integrate in the model the electrode as well: I have it in the form of a tetrahedral mesh. Is there a way to convert tetrahedral mesh to hexahedral? Or is there another way to integrate the two models that I'm not seeing?
> 
> Thank you for your time
> 
> Roberto Garza
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip <https://mailman.science.ru.nl/mailman/listinfo/fieldtrip>
> https://doi.org/10.1371/journal.pcbi.1002202 <https://doi.org/10.1371/journal.pcbi.1002202>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200527/23b3f206/attachment.htm>

From r.oostenveld at donders.ru.nl  Thu May 28 09:01:25 2020
From: r.oostenveld at donders.ru.nl (Robert Oostenveld)
Date: Thu, 28 May 2020 09:01:25 +0200
Subject: [FieldTrip] support for Biosemi firmware 4.0?
In-Reply-To: <CAJr_e2uBbVXLr0WQV2s_ws-G_=oaoSw4P5bbj+0YCmHXHwsZFA@mail.gmail.com>
References: <CAJr_e2uBbVXLr0WQV2s_ws-G_=oaoSw4P5bbj+0YCmHXHwsZFA@mail.gmail.com>
Message-ID: <EB988ECD-23DB-4539-B308-13C60F7CE7DD@donders.ru.nl>

Hi Loyd,

Welcome on the mailing list! 

The realtime interface to the Biosemi amplifiers was implemented and contributed by FieldTrip users, not by the core team. I recall that it had contributions from two separate groups. Also, we don’t have a Biosemi amplifier, so we don’t use it ourselves and cannot test ourselves.

If I look at the commit history at 
https://github.com/fieldtrip/fieldtrip/commits/master/realtime/src/acquisition/biosemi <https://github.com/fieldtrip/fieldtrip/commits/master/realtime/src/acquisition/biosemi>
and
https://github.com/fieldtrip/fieldtrip/commits/master/realtime/src/acquisition/biosemi/biosemi2ft.cc <https://github.com/fieldtrip/fieldtrip/commits/master/realtime/src/acquisition/biosemi/biosemi2ft.cc>

I see it dates back to 2012 and that later changes mainly relate to streamlining the build process and Makefile. Part of the history details appears to be missing, since it predates the moment when we switched over from an internal Subversion server to GitHub. But most of it seems to be pre-2015, which suggests that it was written for firmware 3.0. I also assume that at the time firmware 4.0 was introduced on new devices, it was still slow to get updated on existing devices, which means that the code changes in 2015 (done by people that were not likely to have a brand-new device) were not related to the new firmware. 

It would be good if the documentation on http://www.fieldtriptoolbox.org/development/realtime/biosemi/ <http://www.fieldtriptoolbox.org/development/realtime/biosemi/> (which is maintained here <https://github.com/fieldtrip/website/blob/master/development/realtime/biosemi.md>) would be updated to reflect this. E.g. add a section about the different firmware versions, how to determine yourself which one is installed on your amplifier, etc. Possibly also test it both with a 3.0 and a 4.0 version of the amplifier and report on the results. Editing that page on the website is as simple as clicking on the pencil button on the upper right. 



All contributions are reviewed and stylistically corrected by me or another team member, so don’t worry if the markdown formatting is not totally correct yet.

It would even be better if the source code of the Biosemi real-time interface was reviewed and would be updated to reflect the 4.0 firmware. Changes should be compatible with the 3.0 version, or a a copy of the exiting code should be kept to ensure that researchers with 3.0 version amplifiers can continue to use it.

I am looking forward to the contribution of Biosemi or Cortech Solutions to improve the researchers’ experience with this hardware.

best regards,
Robert






> On 26 May 2020, at 19:42, Lloyd Smith <lsmith at cortechsolutions.com> wrote:
> 
> Hi, all. First time posting here, so please pardon any lack of default knowledge. My company handles US/Canada sales and support for the Biosemi ActiveTwo EEG system, and I know a lot of our customers use Fieldtrip. Until now I have never had a pre-sales question from a customer about Fieldtrip. I was unable to find an answer in your archives, so I am posting it here. 
> 
> In mid-2015, Biosemi released firmware 4.0 for the optical receiver / USB interface. This eliminates the need to install a driver, instead utilizing a driver that ships with Windows 10. Most older ActiveTwo systems can be field-upgraded by end-users according to instructions at  https://www.biosemi.com/faq/install_USB.htm <https://www.biosemi.com/faq/install_USB.htm>. 
> 
> Thie page at your site - http://www.fieldtriptoolbox.org/development/realtime/biosemi/ <http://www.fieldtriptoolbox.org/development/realtime/biosemi/> - does not mention which optical receiver / USB interface firmware versions are compatible, which leaves open the question of whether firmware 4.0 is supported. Firmware 3.0 shipped from sometime before Spring 2011 until Spring of 2015, but all systems shipped from about June 2015 forward have firmware 4.0, and many older systems have been field-upgraded. 
> 
> Thanks in advance for any insight!
> 
> Best regards, 
> 
> Lloyd Smith 
> President 
> Cortech Solutions, Inc. 
> 
> E-mail: LSmith at cortechsolutions.com <mailto:LSmith at cortechsolutions.com> 
> Tel: 910-362-1143 x202 
> Cell: 910-431-2811
> 
> 
> 
> Cortech Solutions, Inc.
> 1409 Audubon Blvd, Suite B1
> Wilmington, NC 28403 USA
> 
> Tel: 910-362-1143
> Fax: 910-378-3443
> 
> Sales: sales at cortechsolutions.com <mailto:sales at cortechsolutions.com>
> Support / repairs: support at cortechsolutions.com <mailto:support at cortechsolutions.com>
> Billing / administration: admin at cortechsolutions.com <mailto:admin at cortechsolutions.com>
> 
> Web: www.cortechsolutions.com <http://www.cortechsolutions.com/>
> 
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200528/cee91e21/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PastedGraphic-1.png
Type: image/png
Size: 21038 bytes
Desc: not available
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200528/cee91e21/attachment.png>

From C.vandenBoomen at uu.nl  Thu May 28 11:43:24 2020
From: C.vandenBoomen at uu.nl (Boomen, C. van den (Carlijn))
Date: Thu, 28 May 2020 09:43:24 +0000
Subject: [FieldTrip] Fwd:  mexmaci64 cannot be opened
In-Reply-To: <0A5D04E4-C4C1-4ADA-96A1-92D88AE931CC@donders.ru.nl>
References: <73CBB6C8-73C4-40CF-B285-B8BB7FB8E05F@gmail.com>,
 <0A5D04E4-C4C1-4ADA-96A1-92D88AE931CC@donders.ru.nl>
Message-ID: <AM0PR05MB5268698C060191AC4F8915F9898E0@AM0PR05MB5268.eurprd05.prod.outlook.com>

Hi,

Thank you for the suggestion! Unfortunately, while running ft_compile_mex I get the error that several of the source files cannot be found (see below). I also tried the alternative way (using mex) but then the files can't be found either.

Does anyone recognise this problem, and know a solution?

Best,
Carlijn

Report when using ft_compile_mex:

Skipping up-to-date MEX file compat/matlablt2010b/@uint64/abs
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/min
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/max
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/plus
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/minus
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/times
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/rdivide
Skipping up-to-date MEX file @config/private/deepcopy
Skipping up-to-date MEX file @config/private/increment
Skipping up-to-date MEX file @config/private/setzero
Error: source file for ft_omri_smooth_volume cannot be found.
Error: source file for sap2matlab cannot be found.
Error: source file for ft_getopt cannot be found.
Error: source file for read_16bit cannot be found.
Error: source file for read_24bit cannot be found.
Error: source file for lmoutr cannot be found.
Error: source file for ltrisect cannot be found.
Error: source file for plinproj cannot be found.
Error: source file for ptriproj cannot be found.
Error: source file for routlm cannot be found.
Error: source file for solid_angle cannot be found.
Error: source file for rfbevent cannot be found.
Error: source file for meg_leadfield1 cannot be found.
Error: source file for splint_gh cannot be found.
Error: source file for plgndr cannot be found.
Error: source file for ft_spike_sub_crossx cannot be found.
Error: source file for rename cannot be found.
Error: source file for getpid cannot be found.
Error: source file for nanmean cannot be found.
Error: source file for nanstd cannot be found.
Error: source file for nanvar cannot be found.
Error: source file for nansum cannot be found.
Error: source file for nanstd cannot be found.
Error: source file for det2x2 cannot be found.
Error: source file for inv2x2 cannot be found.
Error: source file for mtimes2x2 cannot be found.
Error: source file for sandwich2x2 cannot be found.
Error: source file for combineClusters cannot be found.
Skipping up-to-date MEX file external/fileexchange/CalcMD5
Error: source file for mxSerialize_cpp cannot be found.
Error: source file for mxDeserialize_cpp cannot be found.


________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
Sent: 02 May 2020 13:54
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: [FieldTrip] Fwd: mexmaci64 cannot be opened


Hi Carlijn

You may want to try and compile the mex files from scratch for your OS and Matlab version. There is some more documentation on the website about the compilation of mex-files (e.g. search for ft_compile_mex, or more generally for mex).

Best wishes,
Jan-Mathijs


On 24 Apr 2020, at 14:39, Boomen, C. van den (Carlijn) <C.vandenBoomen at uu.nl<mailto:C.vandenBoomen at uu.nl>> wrote:

Hi all,

I've a new version of MacOS and fieldtrip functions don't seem to work anymore. I get the error that mexmaci64 files cannot be opened. I've looked at the link below, and followed the instructions. However, this only seems to work for running ft_default, but I keep receiving the error for other functions (e.g. ft_preprocessing). Does anyone know what the problem might be, or have an idea for a solution?

http://www.fieldtriptoolbox.org/faq/mexmaci64_cannot_be_opened_because_the_developer_cannot_be_verified/

Thank you!
Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200528/23db6414/attachment.htm>

From lucas.struber at univ-grenoble-alpes.fr  Fri May 29 08:35:00 2020
From: lucas.struber at univ-grenoble-alpes.fr (Lucas Struber)
Date: Fri, 29 May 2020 08:35:00 +0200
Subject: [FieldTrip] FIR filter default order
Message-ID: <fbafb994-7340-851e-8588-45744fe4154a@univ-grenoble-alpes.fr>

Hello,

When performing a spectral estimation of EEG data by applying a FIR 
bandpass filter and then doing a Hilbert transform 
(/ft_specest_hilbert/), the default filter order proposed by 
/ft_preproc_bandpassfilter /is :
/N = 3*fix(Fs / Fbp(1));/ (l.236).
where Fs is the sampling frequency and Fbp(1) the lower boundary of the 
frequency band.

I was simply wondering, where does this value comes from ? Any 
explication, litterature references or even advice on how to choose N 
(different from default value) when performing hilbert spectral 
estimation is welcome.

For information, i'm working on EEG data acquired in human subjects in a 
visuo-motor adpatation task.

Kind regards,

-- 
Lucas Struber
Ingénieur de recherche
+33 (0)6.33.91.93.52

Laboratoire TIMC-IMAG, équipe SPM
UGA Site Santé
38700 La Tronche

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/3f64047d/attachment.htm>

From camille.maumet at inria.fr  Fri May 29 09:13:27 2020
From: camille.maumet at inria.fr (Camille Maumet)
Date: Fri, 29 May 2020 09:13:27 +0200 (CEST)
Subject: [FieldTrip] OHBM Brainhack 2020 registration is open!
Message-ID: <1658503355.9006956.1590736407771.JavaMail.zimbra@inria.fr>



Dear members of fieldtrip, 


The OHBM Open Science Special Interest Group (OS-SIG) is very happy to announce: 


    * 

Registration is now open for the 2020 OHBM Brainhack (the hackathon organized by the OS-SIG) that will be held online, June 16-18 . [ http://www.humanbrainmapping.org/HackathonReg | Register here! ] 



    * 

We are providing 50 mini-grants worth 100 USD each to help hackathon attendees set up for online conferencing. Apply via the link above . 




Who is the OHBM Brainhack for? 


Watch our [ https://www.youtube.com/watch?v=BaClh_LBli4&feature=youtu.be | short video ] ! 


Is my time zone included in the program of the 2020 OHBM hackathon? 


Wherever you are in the world, the OHBM Brainhack will happen at a time that is within reasonable working hours. For the first time, the OHBM Brainhack will be a global online event organized around 3 hubs: ‘Asia and Pacific’, ‘Europe, Middle East and Africa’ and ‘The Americas’. Each hub will run at a different time, with a [ https://ohbm.github.io/hackathon2020/schedule/ | common program ] shared across the 3 hubs. 



We thank [ https://openneuro.org/ | Openneuro ] , [ https://www.incf.org/ | INCF ] , [ https://www.cneuromod.ca/ | CNeuroMod ] , [ http://ludmercentre.ca/ | The Ludmer, ] [ https://conp.ca/ |  CONP ] and [ https://www.win.ox.ac.uk/ |  WIN ] for their generous contributions in support of the OS-SIG. 



For updates, please visit the [ https://ohbm.github.io/hackathon2020/ | OHBM Brainhack website ] , the [ http://ossig.netlify.com/ | OS-SIG website ] , follow [ https://twitter.com/ohbmopen | @OHBMopen ] on Twitter or follow OHBM wechat official account. If you have any questions, please reach out to us at [ mailto:ossig2019 at inria.fr | ossig2019 at inria.fr ] . 


Kind regards, 


Camille Maumet, Liza Levitis and Rémi Gau, on behalf of the Open Science SIG 




-- 
Camille Maumet, PhD 

Researcher 
Inria, Univ Rennes, CNRS, Inserm 
Campus de Beaulieu 
35042 Rennes Cedex, France 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/826a1d6e/attachment.htm>

From floss at apjanke.net  Fri May 29 09:30:48 2020
From: floss at apjanke.net (Andrew Janke)
Date: Fri, 29 May 2020 03:30:48 -0400
Subject: [FieldTrip] MEX compilation failure under R2020a on macOS 10.14
Message-ID: <7c69418a-08ec-5b8d-2416-14b23a7d2ef4@apjanke.net>

Hi, FieldTrip folks,

I'm running FieldTrip under Matlab R2020a on macOS 10.14.6 with Xcode
11.3.1.

When I try to recompile all the MEX files, I got some warnings and a
compilation error.

Any ideas? Maybe this MATRIX_DLL_EXPORT_SYM hack is no longer working
under R2020a and recent versions? From src/mxSerialize_cpp.cpp:

// MX_API_VER has unfortunately not changed between R2013b and R2014a,
// so we use the new MATRIX_DLL_EXPORT_SYM as an ugly hack instead
#ifdefined(__cplusplus) &&defined(MATRIX_DLL_EXPORT_SYM)
#defineEXTERN_Cextern
namespacematrix{ namespacedetail{ namespacenoninlined{
namespacemx_array_api{
#endif


This is not urgent – I'm not actually using FieldTrip for work; just
playing around with it after I saw Carlijn Boomen's compilation problems.

Perhaps this is related to the new C++ and interleaved-complex MEX APIs
that Matlab introduced recently?

Details:

>> addpath ~/local/repos/fieldtrip/
>> cd ~/local/repos/fieldtrip/utilities
>> !git log --oneline | head -10
36193a97a updated test scripts, the cfg.sourcemodel should also have a
label if it contains a filter. Select only MEG channels for source
analysis with pre-computed leadfield.
0e3a52de5 fixed bug in selection of optode channels that was intrpduced
with the recent #1377
6325434a6 automatically synchronized identical files to
0fe5399736d832b3206e778603e6427f7bd829fa
0fe539973 fixed multiple regression errors due to PR #1377, mostly
related to sloppy data bookkeeping
6dac9ac18 automatically synchronized identical files to
b79f65a9e7284c0f244f3c52875ba9f7479932fd
b79f65a9e improve ft_sourceanalysis flexbility to work with pre-computed
leadfields (#1377)
b4d569823 Update feature_request.md
49b433569 Update bug_report.md
606c7d67e Update feature_request.md
a48f337db Update bug_report.md
>> ft_compile_mex(true)
Compiling MEX file compat/matlablt2010b/@uint64/abs ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/min ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/max ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/plus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/minus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/times ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/rdivide ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/deepcopy ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/increment ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/setzero ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/online_mri/ft_omri_smooth_volume ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/src/acquisition/siemens/src/sap2matlab ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10:
warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
                switch(item->type) {
                       ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10:
note: add missing switch cases
                switch(item->type) {
                       ^
1 warning generated.

/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12:
warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12:
note: add missing switch cases
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20:
warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
            switch(item->type) {
                   ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20:
note: add missing switch cases
            switch(item->type) {
                   ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ft_getopt ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_16bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_24bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/lmoutr ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ltrisect ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/plinproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ptriproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/routlm ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/solid_angle ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning:
implicit declaration of function 'mxGetNaN' is invalid in C99
[-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/rfbevent ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/meg_leadfield1 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/splint_gh ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/plgndr ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/ft_spike_sub_crossx ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/rename ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/getpid ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanmean ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanvar ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nansum ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/det2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/inv2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mtimes2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/sandwich2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/combineClusters ...
Building with 'Xcode Clang++'.
MEX completed successfully.
Compiling MEX file external/fileexchange/CalcMD5 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mxSerialize_cpp ...
Building with 'Xcode Clang++'.
Error using mex
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:1: error:
unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxSerialize(mxArray const *);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:17: error:
expected ';' after top level declarator
EXTERN_C mxArray* mxSerialize(mxArray const *);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:1: error:
unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:17: error:
expected ';' after top level declarator
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:22:31: error:
use of undeclared identifier 'mxSerialize'
        plhs[0] = (mxArray *) mxSerialize(prhs[0]);
                              ^
5 errors generated.

Error in ft_compile_mex>compile_mex_list (line 217)
  eval(cmd);
Error in ft_compile_mex (line 114)
  compile_mex_list(L, ftpath, force);
>> ver
-----------------------------------------------------------------------------------------------------
MATLAB Version: 9.8.0.1323502 (R2020a)
MATLAB License Number: 973906
Operating System: Mac OS X  Version: 10.14.6 Build: 18G4032
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java
HotSpot(TM) 64-Bit Server VM mixed mode
-----------------------------------------------------------------------------------------------------
MATLAB                                                Version
9.8         (R2020a)               
Database Toolbox                                      Version
9.2.1       (R2020a)               
FieldTrip                                             Version
unknown     www.fieldtriptoolbox.org
Financial Toolbox                                     Version
5.15        (R2020a)               
Optimization Toolbox                                  Version
8.5         (R2020a)               
Statistics and Machine Learning Toolbox               Version
11.7        (R2020a)               
>>

Cheers,
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/cbb23ebd/attachment.htm>

From floss at apjanke.net  Fri May 29 09:32:07 2020
From: floss at apjanke.net (Andrew Janke)
Date: Fri, 29 May 2020 03:32:07 -0400
Subject: [FieldTrip] Fwd: mexmaci64 cannot be opened
In-Reply-To: <AM0PR05MB5268698C060191AC4F8915F9898E0@AM0PR05MB5268.eurprd05.prod.outlook.com>
References: <73CBB6C8-73C4-40CF-B285-B8BB7FB8E05F@gmail.com>
 <0A5D04E4-C4C1-4ADA-96A1-92D88AE931CC@donders.ru.nl>
 <AM0PR05MB5268698C060191AC4F8915F9898E0@AM0PR05MB5268.eurprd05.prod.outlook.com>
Message-ID: <e3f910fa-99ca-d3fe-8d17-ab7e39c9447a@apjanke.net>

Carlijn,

Can you share the exact error message you got originally when Matlab
said the MEX files couldn't be opened? And what versions of Matlab and
macOS are you running?

Cheers,
Andrew

On 5/28/20 5:43 AM, Boomen, C. van den (Carlijn) wrote:
> Hi,
>
> Thank you for the suggestion! Unfortunately, while running
> ft_compile_mex I get the error that several of the source files cannot
> be found (see below). I also tried the alternative way (using mex) but
> then the files can't be found either.
>
> Does anyone recognise this problem, and know a solution?
>
> Best,
> Carlijn
>
> Report when using ft_compile_mex:
>
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/abs
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/min
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/max
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/plus
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/minus
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/times
> Skipping up-to-date MEX file compat/matlablt2010b/@uint64/rdivide
> Skipping up-to-date MEX file @config/private/deepcopy
> Skipping up-to-date MEX file @config/private/increment
> Skipping up-to-date MEX file @config/private/setzero
> Error: source file for ft_omri_smooth_volume cannot be found.
> Error: source file for sap2matlab cannot be found.
> Error: source file for ft_getopt cannot be found.
> Error: source file for read_16bit cannot be found.
> Error: source file for read_24bit cannot be found.
> Error: source file for lmoutr cannot be found.
> Error: source file for ltrisect cannot be found.
> Error: source file for plinproj cannot be found.
> Error: source file for ptriproj cannot be found.
> Error: source file for routlm cannot be found.
> Error: source file for solid_angle cannot be found.
> Error: source file for rfbevent cannot be found.
> Error: source file for meg_leadfield1 cannot be found.
> Error: source file for splint_gh cannot be found.
> Error: source file for plgndr cannot be found.
> Error: source file for ft_spike_sub_crossx cannot be found.
> Error: source file for rename cannot be found.
> Error: source file for getpid cannot be found.
> Error: source file for nanmean cannot be found.
> Error: source file for nanstd cannot be found.
> Error: source file for nanvar cannot be found.
> Error: source file for nansum cannot be found.
> Error: source file for nanstd cannot be found.
> Error: source file for det2x2 cannot be found.
> Error: source file for inv2x2 cannot be found.
> Error: source file for mtimes2x2 cannot be found.
> Error: source file for sandwich2x2 cannot be found.
> Error: source file for combineClusters cannot be found.
> Skipping up-to-date MEX file external/fileexchange/CalcMD5
> Error: source file for mxSerialize_cpp cannot be found.
> Error: source file for mxDeserialize_cpp cannot be found.
>
>
> ------------------------------------------------------------------------
> *From:* fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of
> Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl>
> *Sent:* 02 May 2020 13:54
> *To:* FieldTrip discussion list <fieldtrip at science.ru.nl>
> *Subject:* [FieldTrip] Fwd: mexmaci64 cannot be opened
>  
>
> Hi Carlijn
>
> You may want to try and compile the mex files from scratch for your OS
> and Matlab version. There is some more documentation on the website
> about the compilation of mex-files (e.g. search for ft_compile_mex, or
> more generally for mex).
>
> Best wishes,
> Jan-Mathijs
>
>
>> On 24 Apr 2020, at 14:39, Boomen, C. van den (Carlijn)
>> <C.vandenBoomen at uu.nl <mailto:C.vandenBoomen at uu.nl>> wrote:
>>
>> Hi all,
>>
>> I've a new version of MacOS and fieldtrip functions don't seem to
>> work anymore. I get the error that mexmaci64 files cannot be opened.
>> I've looked at the link below, and followed the instructions.
>> However, this only seems to work for running ft_default, but I keep
>> receiving the error for other functions (e.g. ft_preprocessing). Does
>> anyone know what the problem might be, or have an idea for a solution?
>>
>> http://www.fieldtriptoolbox.org/faq/mexmaci64_cannot_be_opened_because_the_developer_cannot_be_verified/
>>
>> Thank you!
>> Best,
>> Carlijn
>>
>> Dr. Carlijn van den Boomen | Departments of Developmental and
>> Experimental Psychology | Utrecht University | Langeveld Building -
>> room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands |
>> phone: +31(30) 253 1266 | fax: +31(30) 253 4511
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>
>
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/ddb70c59/attachment.htm>

From C.vandenBoomen at uu.nl  Fri May 29 09:36:08 2020
From: C.vandenBoomen at uu.nl (Boomen, C. van den (Carlijn))
Date: Fri, 29 May 2020 07:36:08 +0000
Subject: [FieldTrip] Fwd: mexmaci64 cannot be opened
In-Reply-To: <d36b94a3-c89c-4c6b-706a-fa4b03121bb8@gmail.com>
References: <73CBB6C8-73C4-40CF-B285-B8BB7FB8E05F@gmail.com>
 <0A5D04E4-C4C1-4ADA-96A1-92D88AE931CC@donders.ru.nl>
 <AM0PR05MB5268698C060191AC4F8915F9898E0@AM0PR05MB5268.eurprd05.prod.outlook.com>,
 <d36b94a3-c89c-4c6b-706a-fa4b03121bb8@gmail.com>
Message-ID: <AM0PR05MB52682AA58B93711270FDB737898F0@AM0PR05MB5268.eurprd05.prod.outlook.com>

Hi,

Robert Oostenveld helped me solve the error, and adapted the website. If anyone has a similar problem, feel free to email me.

I'm using MacOS Catalina and Matlab 2020a (but the same error occures with Matlab 2019a).

Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
________________________________
From: Andrew Janke <apjanke.floss at gmail.com>
Sent: 29 May 2020 09:31
To: FieldTrip discussion list <fieldtrip at science.ru.nl>; Boomen, C. van den (Carlijn) <C.vandenBoomen at uu.nl>
Subject: Re: [FieldTrip] Fwd: mexmaci64 cannot be opened

Carlijn,

Can you share the exact error message you got originally when Matlab said the MEX files couldn't be opened? And what versions of Matlab and macOS are you running?

Cheers,
Andrew

On 5/28/20 5:43 AM, Boomen, C. van den (Carlijn) wrote:
Hi,

Thank you for the suggestion! Unfortunately, while running ft_compile_mex I get the error that several of the source files cannot be found (see below). I also tried the alternative way (using mex) but then the files can't be found either.

Does anyone recognise this problem, and know a solution?

Best,
Carlijn

Report when using ft_compile_mex:

Skipping up-to-date MEX file compat/matlablt2010b/@uint64/abs
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/min
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/max
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/plus
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/minus
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/times
Skipping up-to-date MEX file compat/matlablt2010b/@uint64/rdivide
Skipping up-to-date MEX file @config/private/deepcopy
Skipping up-to-date MEX file @config/private/increment
Skipping up-to-date MEX file @config/private/setzero
Error: source file for ft_omri_smooth_volume cannot be found.
Error: source file for sap2matlab cannot be found.
Error: source file for ft_getopt cannot be found.
Error: source file for read_16bit cannot be found.
Error: source file for read_24bit cannot be found.
Error: source file for lmoutr cannot be found.
Error: source file for ltrisect cannot be found.
Error: source file for plinproj cannot be found.
Error: source file for ptriproj cannot be found.
Error: source file for routlm cannot be found.
Error: source file for solid_angle cannot be found.
Error: source file for rfbevent cannot be found.
Error: source file for meg_leadfield1 cannot be found.
Error: source file for splint_gh cannot be found.
Error: source file for plgndr cannot be found.
Error: source file for ft_spike_sub_crossx cannot be found.
Error: source file for rename cannot be found.
Error: source file for getpid cannot be found.
Error: source file for nanmean cannot be found.
Error: source file for nanstd cannot be found.
Error: source file for nanvar cannot be found.
Error: source file for nansum cannot be found.
Error: source file for nanstd cannot be found.
Error: source file for det2x2 cannot be found.
Error: source file for inv2x2 cannot be found.
Error: source file for mtimes2x2 cannot be found.
Error: source file for sandwich2x2 cannot be found.
Error: source file for combineClusters cannot be found.
Skipping up-to-date MEX file external/fileexchange/CalcMD5
Error: source file for mxSerialize_cpp cannot be found.
Error: source file for mxDeserialize_cpp cannot be found.


________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl><mailto:fieldtrip-bounces at science.ru.nl> on behalf of Schoffelen, J.M. (Jan Mathijs) <jan.schoffelen at donders.ru.nl><mailto:jan.schoffelen at donders.ru.nl>
Sent: 02 May 2020 13:54
To: FieldTrip discussion list <fieldtrip at science.ru.nl><mailto:fieldtrip at science.ru.nl>
Subject: [FieldTrip] Fwd: mexmaci64 cannot be opened


Hi Carlijn

You may want to try and compile the mex files from scratch for your OS and Matlab version. There is some more documentation on the website about the compilation of mex-files (e.g. search for ft_compile_mex, or more generally for mex).

Best wishes,
Jan-Mathijs


On 24 Apr 2020, at 14:39, Boomen, C. van den (Carlijn) <C.vandenBoomen at uu.nl<mailto:C.vandenBoomen at uu.nl>> wrote:

Hi all,

I've a new version of MacOS and fieldtrip functions don't seem to work anymore. I get the error that mexmaci64 files cannot be opened. I've looked at the link below, and followed the instructions. However, this only seems to work for running ft_default, but I keep receiving the error for other functions (e.g. ft_preprocessing). Does anyone know what the problem might be, or have an idea for a solution?

http://www.fieldtriptoolbox.org/faq/mexmaci64_cannot_be_opened_because_the_developer_cannot_be_verified/

Thank you!
Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202





_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/b9626d3d/attachment.htm>

From C.vandenBoomen at uu.nl  Fri May 29 09:39:07 2020
From: C.vandenBoomen at uu.nl (Boomen, C. van den (Carlijn))
Date: Fri, 29 May 2020 07:39:07 +0000
Subject: [FieldTrip] MEX compilation failure under R2020a on macOS 10.14
In-Reply-To: <7c69418a-08ec-5b8d-2416-14b23a7d2ef4@apjanke.net>
References: <7c69418a-08ec-5b8d-2416-14b23a7d2ef4@apjanke.net>
Message-ID: <AM0PR05MB5268F365DE906001D1B367EA898F0@AM0PR05MB5268.eurprd05.prod.outlook.com>

Hi Andrew,

To add to the information on the website, this is what in total solved the problem. I think step 1 and possibly step two aren't necessary, but this total process did the trick for me.


1.     Download the program Xcode from the Applestore (free of charge)

2.     Copy in the Matlab command window the following code: ft_compile_mex

3.     Open a terminal and copy the following code (where LOCATION_OF_FIELDTRIP is the direction to FieldTrip), and type your computer password when a password is asked for in the terminal

sudo xattr -r -d com.apple.quarantine LOCATION_OF_FIELDTRIP

4.     Copy the following code in the terminal

sudo find LOCATION_OF_FIELDTRIP -name \*.mex\* -exec spctl --add {} \;


Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl> on behalf of Andrew Janke <floss at apjanke.net>
Sent: 29 May 2020 09:30
To: FieldTrip discussion list <fieldtrip at science.ru.nl>
Subject: [FieldTrip] MEX compilation failure under R2020a on macOS 10.14

Hi, FieldTrip folks,

I'm running FieldTrip under Matlab R2020a on macOS 10.14.6 with Xcode 11.3.1.

When I try to recompile all the MEX files, I got some warnings and a compilation error.

Any ideas? Maybe this MATRIX_DLL_EXPORT_SYM hack is no longer working under R2020a and recent versions? From src/mxSerialize_cpp.cpp:

// MX_API_VER has unfortunately not changed between R2013b and R2014a,
// so we use the new MATRIX_DLL_EXPORT_SYM as an ugly hack instead
#if defined(__cplusplus) && defined(MATRIX_DLL_EXPORT_SYM)
#define EXTERN_C extern
namespace matrix{ namespace detail{ namespace noninlined{ namespace mx_array_api{
#endif


This is not urgent – I'm not actually using FieldTrip for work; just playing around with it after I saw Carlijn Boomen's compilation problems.

Perhaps this is related to the new C++ and interleaved-complex MEX APIs that Matlab introduced recently?

Details:

>> addpath ~/local/repos/fieldtrip/
>> cd ~/local/repos/fieldtrip/utilities
>> !git log --oneline | head -10
36193a97a updated test scripts, the cfg.sourcemodel should also have a label if it contains a filter. Select only MEG channels for source analysis with pre-computed leadfield.
0e3a52de5 fixed bug in selection of optode channels that was intrpduced with the recent #1377
6325434a6 automatically synchronized identical files to 0fe5399736d832b3206e778603e6427f7bd829fa
0fe539973 fixed multiple regression errors due to PR #1377, mostly related to sloppy data bookkeeping
6dac9ac18 automatically synchronized identical files to b79f65a9e7284c0f244f3c52875ba9f7479932fd
b79f65a9e improve ft_sourceanalysis flexbility to work with pre-computed leadfields (#1377)
b4d569823 Update feature_request.md
49b433569 Update bug_report.md
606c7d67e Update feature_request.md
a48f337db Update bug_report.md
>> ft_compile_mex(true)
Compiling MEX file compat/matlablt2010b/@uint64/abs ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/min ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/max ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/plus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/minus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/times ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/rdivide ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/deepcopy ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/increment ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/setzero ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/online_mri/ft_omri_smooth_volume ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/src/acquisition/siemens/src/sap2matlab ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
                switch(item->type) {
                       ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10: note: add missing switch cases
                switch(item->type) {
                       ^
1 warning generated.

/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12: note: add missing switch cases
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
            switch(item->type) {
                   ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20: note: add missing switch cases
            switch(item->type) {
                   ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ft_getopt ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_16bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_24bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/lmoutr ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ltrisect ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/plinproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ptriproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/routlm ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/solid_angle ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/rfbevent ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/meg_leadfield1 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/splint_gh ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/plgndr ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/ft_spike_sub_crossx ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/rename ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/getpid ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanmean ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanvar ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nansum ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/det2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/inv2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mtimes2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/sandwich2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/combineClusters ...
Building with 'Xcode Clang++'.
MEX completed successfully.
Compiling MEX file external/fileexchange/CalcMD5 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mxSerialize_cpp ...
Building with 'Xcode Clang++'.
Error using mex
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:1: error: unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxSerialize(mxArray const *);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:17: error: expected ';' after top level declarator
EXTERN_C mxArray* mxSerialize(mxArray const *);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:1: error: unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:17: error: expected ';' after top level declarator
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:22:31: error: use of undeclared identifier 'mxSerialize'
        plhs[0] = (mxArray *) mxSerialize(prhs[0]);
                              ^
5 errors generated.

Error in ft_compile_mex>compile_mex_list (line 217)
  eval(cmd);
Error in ft_compile_mex (line 114)
  compile_mex_list(L, ftpath, force);
>> ver
-----------------------------------------------------------------------------------------------------
MATLAB Version: 9.8.0.1323502 (R2020a)
MATLAB License Number: 973906
Operating System: Mac OS X  Version: 10.14.6 Build: 18G4032
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
-----------------------------------------------------------------------------------------------------
MATLAB                                                Version 9.8         (R2020a)
Database Toolbox                                      Version 9.2.1       (R2020a)
FieldTrip                                             Version unknown     www.fieldtriptoolbox.org<http://www.fieldtriptoolbox.org>
Financial Toolbox                                     Version 5.15        (R2020a)
Optimization Toolbox                                  Version 8.5         (R2020a)
Statistics and Machine Learning Toolbox               Version 11.7        (R2020a)
>>

Cheers,
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/a323ebc4/attachment.htm>

From jan.schoffelen at donders.ru.nl  Fri May 29 09:53:04 2020
From: jan.schoffelen at donders.ru.nl (Schoffelen, J.M. (Jan Mathijs))
Date: Fri, 29 May 2020 07:53:04 +0000
Subject: [FieldTrip] MEX compilation failure under R2020a on macOS 10.14
In-Reply-To: <AM0PR05MB5268F365DE906001D1B367EA898F0@AM0PR05MB5268.eurprd05.prod.outlook.com>
References: <7c69418a-08ec-5b8d-2416-14b23a7d2ef4@apjanke.net>
 <AM0PR05MB5268F365DE906001D1B367EA898F0@AM0PR05MB5268.eurprd05.prod.outlook.com>
Message-ID: <89D9FAD3-49CC-4FF9-B66C-134A0768CAA6@donders.ru.nl>

Dear Carlijn,

Thanks for getting back at us. I understand that the information on the website can be further improved, please feel free to adjust this. That should not be too difficult.

Best wishes,
Jan-Mathijs



On 29 May 2020, at 09:39, Boomen, C. van den (Carlijn) <C.vandenBoomen at uu.nl<mailto:C.vandenBoomen at uu.nl>> wrote:

Hi Andrew,

To add to the information on the website, this is what in total solved the problem. I think step 1 and possibly step two aren't necessary, but this total process did the trick for me.

1.     Download the program Xcode from the Applestore (free of charge)
2.     Copy in the Matlab command window the following code: ft_compile_mex
3.     Open a terminal and copy the following code (where LOCATION_OF_FIELDTRIP is the direction to FieldTrip), and type your computer password when a password is asked for in the terminal
sudo xattr -r -d com.apple.quarantine LOCATION_OF_FIELDTRIP
4.     Copy the following code in the terminal
sudo find LOCATION_OF_FIELDTRIP -name \*.mex\* -exec spctl --add {} \;

Best,
Carlijn

Dr. Carlijn van den Boomen | Departments of Developmental and Experimental Psychology | Utrecht University | Langeveld Building - room H066 | Heidelberglaan 1 | 3584 CS Utrecht | the Netherlands | phone: +31(30) 253 1266 | fax: +31(30) 253 4511
________________________________
From: fieldtrip <fieldtrip-bounces at science.ru.nl<mailto:fieldtrip-bounces at science.ru.nl>> on behalf of Andrew Janke <floss at apjanke.net<mailto:floss at apjanke.net>>
Sent: 29 May 2020 09:30
To: FieldTrip discussion list <fieldtrip at science.ru.nl<mailto:fieldtrip at science.ru.nl>>
Subject: [FieldTrip] MEX compilation failure under R2020a on macOS 10.14

Hi, FieldTrip folks,

I'm running FieldTrip under Matlab R2020a on macOS 10.14.6 with Xcode 11.3.1.

When I try to recompile all the MEX files, I got some warnings and a compilation error.

Any ideas? Maybe this MATRIX_DLL_EXPORT_SYM hack is no longer working under R2020a and recent versions? From src/mxSerialize_cpp.cpp:

// MX_API_VER has unfortunately not changed between R2013b and R2014a,
// so we use the new MATRIX_DLL_EXPORT_SYM as an ugly hack instead
#if defined(__cplusplus) && defined(MATRIX_DLL_EXPORT_SYM)
#define EXTERN_C extern
namespace matrix{ namespace detail{ namespace noninlined{ namespace mx_array_api{
#endif


This is not urgent – I'm not actually using FieldTrip for work; just playing around with it after I saw Carlijn Boomen's compilation problems.

Perhaps this is related to the new C++ and interleaved-complex MEX APIs that Matlab introduced recently?

Details:

>> addpath ~/local/repos/fieldtrip/
>> cd ~/local/repos/fieldtrip/utilities
>> !git log --oneline | head -10
36193a97a updated test scripts, the cfg.sourcemodel should also have a label if it contains a filter. Select only MEG channels for source analysis with pre-computed leadfield.
0e3a52de5 fixed bug in selection of optode channels that was intrpduced with the recent #1377
6325434a6 automatically synchronized identical files to 0fe5399736d832b3206e778603e6427f7bd829fa
0fe539973 fixed multiple regression errors due to PR #1377, mostly related to sloppy data bookkeeping
6dac9ac18 automatically synchronized identical files to b79f65a9e7284c0f244f3c52875ba9f7479932fd
b79f65a9e improve ft_sourceanalysis flexbility to work with pre-computed leadfields (#1377)
b4d569823 Update feature_request.md
49b433569 Update bug_report.md
606c7d67e Update feature_request.md
a48f337db Update bug_report.md
>> ft_compile_mex(true)
Compiling MEX file compat/matlablt2010b/@uint64/abs ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/min ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/max ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/plus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/minus ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/times ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file compat/matlablt2010b/@uint64/rdivide ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/deepcopy ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/increment ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file @config/private/setzero ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/online_mri/ft_omri_smooth_volume ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file realtime/src/acquisition/siemens/src/sap2matlab ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
                switch(item->type) {
                       ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/sap2matlab.c:33:10: note: add missing switch cases
                switch(item->type) {
                       ^
1 warning generated.

/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:323:12: note: add missing switch cases
    switch(typ) {
           ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20: warning: enumeration value 'SAP_ARRAY_SIZE' not handled in switch [-Wswitch]
            switch(item->type) {
                   ^
/Users/janke/local/repos/fieldtrip/realtime/src/acquisition/siemens/src/siemensap.c:436:20: note: add missing switch cases
            switch(item->type) {
                   ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ft_getopt ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_16bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/read_24bit ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/lmoutr ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ltrisect ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/plinproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/ptriproj ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/routlm ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/solid_angle ...
Building with 'Xcode with Clang'.
/Users/janke/local/repos/fieldtrip/src/geometry.c:176:15: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    proj[0] = mxGetNaN();
              ^
/Users/janke/local/repos/fieldtrip/src/geometry.c:219:11: warning: implicit declaration of function 'mxGetNaN' is invalid in C99 [-Wimplicit-function-declaration]
    *la = mxGetNaN();
          ^
2 warnings generated.

MEX completed successfully.
Compiling MEX file src/rfbevent ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/meg_leadfield1 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/splint_gh ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/plgndr ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/ft_spike_sub_crossx ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/rename ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/getpid ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanmean ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanvar ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nansum ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/nanstd ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/det2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/inv2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mtimes2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/sandwich2x2 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/combineClusters ...
Building with 'Xcode Clang++'.
MEX completed successfully.
Compiling MEX file external/fileexchange/CalcMD5 ...
Building with 'Xcode with Clang'.
MEX completed successfully.
Compiling MEX file src/mxSerialize_cpp ...
Building with 'Xcode Clang++'.
Error using mex
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:1: error: unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxSerialize(mxArray const *);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:10:17: error: expected ';' after top level declarator
EXTERN_C mxArray* mxSerialize(mxArray const *);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:1: error: unknown type name 'EXTERN_C'
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
^
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:11:17: error: expected ';' after top level declarator
EXTERN_C mxArray* mxDeserialize(const void *, size_t);
                ^
                ;
/Users/janke/local/repos/fieldtrip/src/mxSerialize_cpp.cpp:22:31: error: use of undeclared identifier 'mxSerialize'
        plhs[0] = (mxArray *) mxSerialize(prhs[0]);
                              ^
5 errors generated.

Error in ft_compile_mex>compile_mex_list (line 217)
  eval(cmd);
Error in ft_compile_mex (line 114)
  compile_mex_list(L, ftpath, force);
>> ver
-----------------------------------------------------------------------------------------------------
MATLAB Version: 9.8.0.1323502 (R2020a)
MATLAB License Number: 973906
Operating System: Mac OS X  Version: 10.14.6 Build: 18G4032
Java Version: Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
-----------------------------------------------------------------------------------------------------
MATLAB                                                Version 9.8         (R2020a)
Database Toolbox                                      Version 9.2.1       (R2020a)
FieldTrip                                             Version unknown     www.fieldtriptoolbox.org<http://www.fieldtriptoolbox.org/>
Financial Toolbox                                     Version 5.15        (R2020a)
Optimization Toolbox                                  Version 8.5         (R2020a)
Statistics and Machine Learning Toolbox               Version 11.7        (R2020a)
>>

Cheers,
Andrew
_______________________________________________
fieldtrip mailing list
https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
https://doi.org/10.1371/journal.pcbi.1002202

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20200529/2504d808/attachment.htm>

From widmann at uni-leipzig.de  Fri May 29 13:11:00 2020
From: widmann at uni-leipzig.de (Andreas Widmann)
Date: Fri, 29 May 2020 13:11:00 +0200
Subject: [FieldTrip] FIR filter default order
In-Reply-To: <fbafb994-7340-851e-8588-45744fe4154a@univ-grenoble-alpes.fr>
References: <fbafb994-7340-851e-8588-45744fe4154a@univ-grenoble-alpes.fr>
Message-ID: <5DEF600F-F7E8-4D1D-B7BC-EF086FAE8C60@uni-leipzig.de>

Hi Lucas,

> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>     N = 3*fix(Fs / Fbp(1)); (l.236).
> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
> 
> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.

This equation is explicitly wrong for almost any application in electrophysiology, including yours (as I understand it). To my understanding this is long known. We discussed this issue some years ago in the context of a bug report. As far as I remember it was decided to keep it as it is for backward compatibility. Possibly, a warning notice that 'fir'-type should not be used without order parameter could be added?

All concepts underlying FIR filter order are explained here:
https://home.uni-leipzig.de/biocog/eprints/widmann_a2015jneuroscimeth250_34.pdf

In a nutshell:
For FIR filters we need a so called transition band between passband (no attenuation) and stopband (full attenuation) in which attenuation gradually changes from no to full attenuation. The width of this transition band is a function of filter order (and window type but this doesn’t matter for now). The higher the filter order the sharper the transition from passband to stopband, the lower the filter order the shallower the transition from passband to stopband.

The cutoff frequency is in the center of the transition band at half amplitude (-6 dB). In the first step you define your requested band edges, for example a passband from 9 to 11 Hz and stopbands below 7 and above 13 Hz. The cutoff frequencies (to be given as parameters in 'Fbp' as [Fhp Flp]) would be 8 and 12 Hz. Required  transition band width is 2 Hz (note that with the current implementation all transition bands must have equal width; different widths are in principle possible but complex to implement; it is simpler to successively apply lowpass and highpass filters with different orders; this approach has no relevant drawbacks besides computation time).

The 'fir‘ type filter by default uses a hamming window. The equation to compute filter order from requested transition bandwidth is (see Table 1 incl. caption of the above paper):

m = 3.3 / (df / fs)

3.3 is a window type specific parameter. df is transition bandwidth and fs is sampling frequency. For fs = 500 Hz this would result in a required filter order of m = 825. Filter order must be even, thus m = 826.

The equation used in 'fir' would give you an order of m = 186 in this example. But, order m = 186 would give you a transition bandwidth of df = 8.8 Hz (just solve the equation for df). That is, the passband of the highpass part would start at 8 Hz plus half the transition bandwidth df / 2 = 4.4, thus at 12.4 Hz and the passband of the lowpass part at 7.6 Hz (12 Hz - 4.4 Hz). As the higher passband edge is below the lower passband edge this obviously cannot work out; this filter does not have a passband.

I would advise against using the Fieldtrip 'fir‘ type filter for two more reasons: (1) It is based on the MATLAB fir1 function. This function is again based on firls *fitting* a filter to a rectangular response function. This is numerically considerably less accurate than computing the correct sinc function (by orders of magnitude at particular points as for example DC attenuation). (2) It defaults to twopass filtering. Twopass filtering is unnecessary for linear-phase FIR filters (as here), doubles filter order (but without actually much improving transition bandwidth) and doubles computation time.

In general I would recommend to use 'firws‘ filter type not showing these problems. The default for order is different from the above equation used in 'fir‘-type and more appropriate for typical ERP and related applications (wide passbands). In your case (narrow passbands; as I understood it) you will still need to give transition bandwidth as separate parameter 'df‘ (or compute order and give it as parameter ’N’).

Hope this help! Best,
Andreas

> Am 29.05.2020 um 08:35 schrieb Lucas Struber <lucas.struber at univ-grenoble-alpes.fr>:
> 
> Hello,
> 
> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>     N = 3*fix(Fs / Fbp(1)); (l.236).
> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
> 
> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.
> 
> For information, i'm working on EEG data acquired in human subjects in a visuo-motor adpatation task.
> 
> Kind regards,
> 
> -- 
> Lucas Struber
> Ingénieur de recherche
> +33 (0)6.33.91.93.52
> 
> Laboratoire TIMC-IMAG, équipe SPM
> UGA Site Santé
> 38700 La Tronche
> 
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202




From lucas.struber at univ-grenoble-alpes.fr  Fri May 29 13:57:17 2020
From: lucas.struber at univ-grenoble-alpes.fr (Lucas Struber)
Date: Fri, 29 May 2020 13:57:17 +0200
Subject: [FieldTrip] FIR filter default order
In-Reply-To: <5DEF600F-F7E8-4D1D-B7BC-EF086FAE8C60@uni-leipzig.de>
References: <fbafb994-7340-851e-8588-45744fe4154a@univ-grenoble-alpes.fr>
 <5DEF600F-F7E8-4D1D-B7BC-EF086FAE8C60@uni-leipzig.de>
Message-ID: <7d5ee616-2cf7-b83b-761f-c4664f30501d@univ-grenoble-alpes.fr>

Hi Andreas,

Thank you for your answer, which confirm what I understood about FIR 
filters (I read your paper before you mentionned it).

However I still can't explain myself why this *wrong* default parameters 
gives me spectral amplitudes very similar to spectral amplitudes 
estimated with a Morlet wavelet transform (with n cycles equal to 7). 
While using FIR and setting m = 3.3/(df/fs) (m is then the same for all 
frequencies), gives me a very different result...

Any insights or suggestions on this ?

In any case i'll try with firws.

Best regards,

Lucas

Le 29/05/2020 à 13:11, Andreas Widmann a écrit :
> Hi Lucas,
>
>> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>>      N = 3*fix(Fs / Fbp(1)); (l.236).
>> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
>>
>> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.
> This equation is explicitly wrong for almost any application in electrophysiology, including yours (as I understand it). To my understanding this is long known. We discussed this issue some years ago in the context of a bug report. As far as I remember it was decided to keep it as it is for backward compatibility. Possibly, a warning notice that 'fir'-type should not be used without order parameter could be added?
>
> All concepts underlying FIR filter order are explained here:
> https://home.uni-leipzig.de/biocog/eprints/widmann_a2015jneuroscimeth250_34.pdf
>
> In a nutshell:
> For FIR filters we need a so called transition band between passband (no attenuation) and stopband (full attenuation) in which attenuation gradually changes from no to full attenuation. The width of this transition band is a function of filter order (and window type but this doesn’t matter for now). The higher the filter order the sharper the transition from passband to stopband, the lower the filter order the shallower the transition from passband to stopband.
>
> The cutoff frequency is in the center of the transition band at half amplitude (-6 dB). In the first step you define your requested band edges, for example a passband from 9 to 11 Hz and stopbands below 7 and above 13 Hz. The cutoff frequencies (to be given as parameters in 'Fbp' as [Fhp Flp]) would be 8 and 12 Hz. Required  transition band width is 2 Hz (note that with the current implementation all transition bands must have equal width; different widths are in principle possible but complex to implement; it is simpler to successively apply lowpass and highpass filters with different orders; this approach has no relevant drawbacks besides computation time).
>
> The 'fir‘ type filter by default uses a hamming window. The equation to compute filter order from requested transition bandwidth is (see Table 1 incl. caption of the above paper):
>
> m = 3.3 / (df / fs)
>
> 3.3 is a window type specific parameter. df is transition bandwidth and fs is sampling frequency. For fs = 500 Hz this would result in a required filter order of m = 825. Filter order must be even, thus m = 826.
>
> The equation used in 'fir' would give you an order of m = 186 in this example. But, order m = 186 would give you a transition bandwidth of df = 8.8 Hz (just solve the equation for df). That is, the passband of the highpass part would start at 8 Hz plus half the transition bandwidth df / 2 = 4.4, thus at 12.4 Hz and the passband of the lowpass part at 7.6 Hz (12 Hz - 4.4 Hz). As the higher passband edge is below the lower passband edge this obviously cannot work out; this filter does not have a passband.
>
> I would advise against using the Fieldtrip 'fir‘ type filter for two more reasons: (1) It is based on the MATLAB fir1 function. This function is again based on firls *fitting* a filter to a rectangular response function. This is numerically considerably less accurate than computing the correct sinc function (by orders of magnitude at particular points as for example DC attenuation). (2) It defaults to twopass filtering. Twopass filtering is unnecessary for linear-phase FIR filters (as here), doubles filter order (but without actually much improving transition bandwidth) and doubles computation time.
>
> In general I would recommend to use 'firws‘ filter type not showing these problems. The default for order is different from the above equation used in 'fir‘-type and more appropriate for typical ERP and related applications (wide passbands). In your case (narrow passbands; as I understood it) you will still need to give transition bandwidth as separate parameter 'df‘ (or compute order and give it as parameter ’N’).
>
> Hope this help! Best,
> Andreas
>
>> Am 29.05.2020 um 08:35 schrieb Lucas Struber <lucas.struber at univ-grenoble-alpes.fr>:
>>
>> Hello,
>>
>> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>>      N = 3*fix(Fs / Fbp(1)); (l.236).
>> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
>>
>> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.
>>
>> For information, i'm working on EEG data acquired in human subjects in a visuo-motor adpatation task.
>>
>> Kind regards,
>>
>> -- 
>> Lucas Struber
>> Ingénieur de recherche
>> +33 (0)6.33.91.93.52
>>
>> Laboratoire TIMC-IMAG, équipe SPM
>> UGA Site Santé
>> 38700 La Tronche
>>
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
>
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202

-- 
Lucas Struber
Ingénieur de recherche
+33 (0)6.33.91.93.52

Laboratoire TIMC-IMAG, équipe SPM
UGA Site Santé
38700 La Tronche



From widmann at uni-leipzig.de  Fri May 29 16:01:32 2020
From: widmann at uni-leipzig.de (Andreas Widmann)
Date: Fri, 29 May 2020 16:01:32 +0200
Subject: [FieldTrip] FIR filter default order
In-Reply-To: <7d5ee616-2cf7-b83b-761f-c4664f30501d@univ-grenoble-alpes.fr>
References: <fbafb994-7340-851e-8588-45744fe4154a@univ-grenoble-alpes.fr>
 <5DEF600F-F7E8-4D1D-B7BC-EF086FAE8C60@uni-leipzig.de>
 <7d5ee616-2cf7-b83b-761f-c4664f30501d@univ-grenoble-alpes.fr>
Message-ID: <AE8F54F3-86A0-4BEC-A8C9-37C764FDFD97@uni-leipzig.de>

Hi Lucas,

> Thank you for your answer, which confirm what I understood about FIR filters (I read your paper before you mentionned it).
> 
> However I still can't explain myself why this *wrong* default parameters gives me spectral amplitudes very similar to spectral amplitudes estimated with a Morlet wavelet transform (with n cycles equal to 7). While using FIR and setting m = 3.3/(df/fs) (m is then the same for all frequencies), gives me a very different result...
> 
> Any insights or suggestions on this ?
There are various intricacies and versions of amplitude scaling in wavelet analysis (e.g. normalized frequency as in textbook equations vs. sampling frequency in the application etc.). My suggestion would be to start debugging with synthetic test signals where you know the ground truth, for example impulses, sine waves and white noise. 

Morlet wavelet analysis can be implemented using convolution, that is, Morlet wavelets can in principle be (ab-)used as FIR filters (as STFT can be implemented via convolution; the only major difference between Gabor STFT transform and Morlet wavelet transform is the definition of time zero).

And you can compare your FIR filter coefficients (returned by ft_preproc_*passfilter.m in B) and your Morlet wavelets (real+imag) in the frequency domain (the example code in the supplementary materials of the paper should contain all necessary parts if I remember correctly).

Best,
Andreas

> In any case i'll try with firws.
> 
> Best regards,
> 
> Lucas
> 
> Le 29/05/2020 à 13:11, Andreas Widmann a écrit :
>> Hi Lucas,
>> 
>>> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>>>     N = 3*fix(Fs / Fbp(1)); (l.236).
>>> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
>>> 
>>> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.
>> This equation is explicitly wrong for almost any application in electrophysiology, including yours (as I understand it). To my understanding this is long known. We discussed this issue some years ago in the context of a bug report. As far as I remember it was decided to keep it as it is for backward compatibility. Possibly, a warning notice that 'fir'-type should not be used without order parameter could be added?
>> 
>> All concepts underlying FIR filter order are explained here:
>> https://home.uni-leipzig.de/biocog/eprints/widmann_a2015jneuroscimeth250_34.pdf
>> 
>> In a nutshell:
>> For FIR filters we need a so called transition band between passband (no attenuation) and stopband (full attenuation) in which attenuation gradually changes from no to full attenuation. The width of this transition band is a function of filter order (and window type but this doesn’t matter for now). The higher the filter order the sharper the transition from passband to stopband, the lower the filter order the shallower the transition from passband to stopband.
>> 
>> The cutoff frequency is in the center of the transition band at half amplitude (-6 dB). In the first step you define your requested band edges, for example a passband from 9 to 11 Hz and stopbands below 7 and above 13 Hz. The cutoff frequencies (to be given as parameters in 'Fbp' as [Fhp Flp]) would be 8 and 12 Hz. Required  transition band width is 2 Hz (note that with the current implementation all transition bands must have equal width; different widths are in principle possible but complex to implement; it is simpler to successively apply lowpass and highpass filters with different orders; this approach has no relevant drawbacks besides computation time).
>> 
>> The 'fir‘ type filter by default uses a hamming window. The equation to compute filter order from requested transition bandwidth is (see Table 1 incl. caption of the above paper):
>> 
>> m = 3.3 / (df / fs)
>> 
>> 3.3 is a window type specific parameter. df is transition bandwidth and fs is sampling frequency. For fs = 500 Hz this would result in a required filter order of m = 825. Filter order must be even, thus m = 826.
>> 
>> The equation used in 'fir' would give you an order of m = 186 in this example. But, order m = 186 would give you a transition bandwidth of df = 8.8 Hz (just solve the equation for df). That is, the passband of the highpass part would start at 8 Hz plus half the transition bandwidth df / 2 = 4.4, thus at 12.4 Hz and the passband of the lowpass part at 7.6 Hz (12 Hz - 4.4 Hz). As the higher passband edge is below the lower passband edge this obviously cannot work out; this filter does not have a passband.
>> 
>> I would advise against using the Fieldtrip 'fir‘ type filter for two more reasons: (1) It is based on the MATLAB fir1 function. This function is again based on firls *fitting* a filter to a rectangular response function. This is numerically considerably less accurate than computing the correct sinc function (by orders of magnitude at particular points as for example DC attenuation). (2) It defaults to twopass filtering. Twopass filtering is unnecessary for linear-phase FIR filters (as here), doubles filter order (but without actually much improving transition bandwidth) and doubles computation time.
>> 
>> In general I would recommend to use 'firws‘ filter type not showing these problems. The default for order is different from the above equation used in 'fir‘-type and more appropriate for typical ERP and related applications (wide passbands). In your case (narrow passbands; as I understood it) you will still need to give transition bandwidth as separate parameter 'df‘ (or compute order and give it as parameter ’N’).
>> 
>> Hope this help! Best,
>> Andreas
>> 
>>> Am 29.05.2020 um 08:35 schrieb Lucas Struber <lucas.struber at univ-grenoble-alpes.fr>:
>>> 
>>> Hello,
>>> 
>>> When performing a spectral estimation of EEG data by applying a FIR bandpass filter and then doing a Hilbert transform (ft_specest_hilbert), the default filter order proposed by ft_preproc_bandpassfilter is :
>>>     N = 3*fix(Fs / Fbp(1)); (l.236).
>>> where Fs is the sampling frequency and Fbp(1) the lower boundary of the frequency band.
>>> 
>>> I was simply wondering, where does this value comes from ? Any explication, litterature references or even advice on how to choose N (different from default value) when performing hilbert spectral estimation is welcome.
>>> 
>>> For information, i'm working on EEG data acquired in human subjects in a visuo-motor adpatation task.
>>> 
>>> Kind regards,
>>> 
>>> -- 
>>> Lucas Struber
>>> Ingénieur de recherche
>>> +33 (0)6.33.91.93.52
>>> 
>>> Laboratoire TIMC-IMAG, équipe SPM
>>> UGA Site Santé
>>> 38700 La Tronche
>>> 
>>> _______________________________________________
>>> fieldtrip mailing list
>>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>>> https://doi.org/10.1371/journal.pcbi.1002202
>> 
>> _______________________________________________
>> fieldtrip mailing list
>> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>> https://doi.org/10.1371/journal.pcbi.1002202
> 
> -- 
> Lucas Struber
> Ingénieur de recherche
> +33 (0)6.33.91.93.52
> 
> Laboratoire TIMC-IMAG, équipe SPM
> UGA Site Santé
> 38700 La Tronche
> 
> _______________________________________________
> fieldtrip mailing list
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> https://doi.org/10.1371/journal.pcbi.1002202




