[FieldTrip] ft_sourceanalysis single trial reconstruction
CHATEAUX Manon
manon.CHATEAUX at univ-amu.fr
Mon Oct 25 19:02:10 CEST 2021
Dear FieldTrip community,
I want to compute coherence between brain sources and an EMG channel that I selected. Here is the pipeline I am using :
* Preprocess MEG and EMG data
* Process single subject MRI data to get (a) the head model, (b) the source model with leadfields
* Reconstruct MEG data using beamformer techniques in the time domain.
* Compute coherence between source data and EMG data
To be able to compute coherence, I need to reconstruct data for all trials and not as an average of trials. But I encountered a problem at this level.
Here is the code I used first :
% Compute noise-covariance matrix
cfg = [];
cfg.covariance = 'yes'; %default takes the whole time window to estimate the noise covariance matrix
cfg.keeptrials = 'yes';
tlcontr_MEG = ft_timelockanalysis(cfg, MEG_contr);
% Compute inverse modelling with mne : source data averaged over
% trails
cfg = [];
cfg.method = 'mne';
cfg.sourcemodel = leadfield;
cfg.headmodel = headmodel;
cfg.mne.lambda = 3; %%????
cfg.mne.keepfilter = 'yes';
cfg.rawtrial = 'no';
source_MEG_contr = ft_sourceanalysis(cfg,tlcontr_MEG);
% Get source data for all trials : project trials by hand
FILTER = source_MEG_contr.avg.filter(cellfun(@(a) ~isempty(a),source_MEG_contr.avg.filter));
for triali = 1 : length(MEG_contr.trial)
source_MEG_contr_trials.pow{triali} = cell2mat(cellfun(@(a) sum((a*MEG_contr.trial{triali}).^2,1),FILTER,'UniformOutput',false)');
disp(['Trial n° ' num2str(triali) ' out of ' num2str(length(MEG_contr.trial))])
end
source_MEG_contr_trials is to be the structure that contains source data for all trials. As you can see I computed it by hand, following a thread that I found on the website.
Then I found it was possible to use ft_sourceanalysis again, to project all trials through the filter computed at the first use of the function. So I replaced the last paragraph of code with the following :
% project all trials through common spatial filter to get source data
% for separate trials
cfg=[];
cfg.method = 'mne';
cfg.sourcemodel = leadfield; % previously computed grid
cfg.headmodel = headmodel; % previously computed volume conduction model
cfg.rawtrial = 'yes'; % project each single trial through the filter to reconstruct single trial data
cfg.sourcemodel.filter = source_MEG_contr.avg.filter; % use the common filter computed in the previous step!
source_MEG_contr_trials = ft_sourceanalysis(cfg, tlcontr_MEG); % contains the source estimates for all trials/both conditions
I preferred this "automatic" way rather than the manual one because it allows me to keep the FieldTrip shape of structures more easily and display results using FieldTrip functions.
However, I realized that it returned completely different results. After trying to understand the steps performed in the second use of ft_sourceanalysis, I realized that filters used to compute trial source data from trial channel data (l. 295 in ft_inverse_mne of fieldtrip-20210921 : estimate.mom{i} = sourcemodel.filter{i}*dat) were different from filters in cfg.sourcemodel.filter.
In fact, channel labels are taken from the leadfield structure. Lines (channel dimension) in filter matrices (in cfg.sourcemodel.filter) are reorganized so that it matches channel order from data.label (= tlcontr_MEG.label).
See l.404-410 in ft_sourceanalysis of fieldtrip-20210921 :
[dum, chansel] = match_str(data.label, sourcemodel.label);
sourcemodel.label = sourcemodel.label(chansel);
for i=1:numel(sourcemodel.filter)
if ~isempty(sourcemodel.filter{i})
sourcemodel.filter{i} = sourcemodel.filter{i}(:, chansel);
end
end
Thus, if I understand it correctly, this step assumes that lines in filter matrices (which come from source_MEG_contr structure) are organized in the same way as channels in leadfields. However, this is not actually the case here because
1. source_MEG_contr.avg.label and data.label (= tlcontr_MEG.label) are equal.
2. I don't understand why but leadfields.label is different from the original alphanumerical channel organization - A1 A2 A3 etc...- found in raw data (as well as in source_MEG_contr, and in tlcontr_MEG).
So I think that in my case, lines in filter matrices should not be reorganized (when they are not, I get the same results as by hand) but as leadfield structure is also used when I compute source_MEG_contr from tlcontr_MEG, I am not sure I can trust source_MEG_contr either.
I would truly appreciate if someone could proofread and pinpoint some problems in this reasoning to help me solve this annoying problem. In the meantime I will try to recompute the leadfield structure so that channel order is the same everywhere.
Thank you in advance for your help and the time you will spend reading through this message!
Manon Châteaux
phD Student at Aix-Marseille University
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.science.ru.nl/pipermail/fieldtrip/attachments/20211025/7e931bbe/attachment.htm>
More information about the fieldtrip
mailing list