[FieldTrip] Source fitting with template MRI/Headmodel
Matt Craddock
m.p.craddock at leeds.ac.uk
Wed Jan 25 18:11:41 CET 2017
Sorry Tommy, I misread the sign of my results - they're the same as
yours :) I get the NaNs plotting thing sometimes too, never totally sure
why as it seems intermittent.
Cheers,
Matt
On 25/01/2017 16:13, Tommy Wilson wrote:
> Hi Matt,
>
> Thanks so much for your reply here!
>
> I believe I've correctly implemented your comments: I computed a common
> filter by source analyzing the combined (read: averaged) data/covariance
> matrix. In a second step, I used this filter to source localize each
> condition separately. I subsequently contrasted the two conditions, but
> I'm seeing that sourceU.avg.pow > sourceA.avg.pow at about 99% of the
> voxels. I attached an image of the ft_sourceplot to this email. (I don't
> know why the NaNs aren't masking appropriately, but I can figure that
> out on my own time).
>
> I also attempted your quick and dirty solution to see if I could
> reproduce that, and I'm seeing the same thing as above (sourceU.avg.pow
>> sourceA.avg.pow in 99% of voxels), which is exactly the opposite of
> what you said you came up with. (The ft_sourceplot for this scenario
> looks identical to the first, which is unsurprising--in both cases, we
> used the average covariance matrix to construct the filters, so they
> ought to be identical). I must be doing something wrong here, but alas,
> I can't seem to put the pieces together.
>
> Any help/guidance you could provide would be deeply appreciated. I've
> attached the updated script to this email (and printed it below for
> posterity), and as before, the data can be found here
> <https://www.dropbox.com/s/8w99ejwrzmwc5pt/Source_fitting_dump.mat?dl=0>.
>
> Again, thank you for taking the time to respond.
>
> Best,
>
> Tommy
>
> --- CODE ---
>
> %% Source fitting protocol
> % Fieldtrip path (to find template MRI)
> ftdir = 'your\path\here\fieldtrip-20160309';
>
> % Average both conditions to generate common filter
> M = ft_timelockgrandaverage(struct(),A,U);
> M.cov = mean(cat(3,A.cov,U.cov),3);
>
> % Equate covariance matrices for now to rule out any differences in the
> % source fit due to differences in covariances
> % A.cov = U.cov;
>
> %%% Do the LCMV sourcefitting
> cfg = [];
> cfg.method = 'lcmv';
> cfg.grid = leadfield;
> cfg.vol = vol;
> cfg.elec = elec;
> cfg.lcmv.lambda = '15%';
> cfg.lcmv.keepfilter = 'yes';
> cfg.lcmv.fixedori = 'yes';
> cfg.lcmv.projectnoise = 'yes';
>
> % Generate common filter
> sourceM = ft_sourceanalysis(cfg,M);
>
> % Add the common filter to the cfg
> cfg.grid.filter = sourceM.avg.filter;
>
> % Source fit the originals
> sourceA = ft_sourceanalysis(cfg,A);
> sourceU = ft_sourceanalysis(cfg,U);
>
> %%% Matt's quick and dirty version
> % Replace A's cov matrix with an average of A.cov and U.cov
> tmp = A.cov;
> A.cov = mean(cat(3,tmp,U.cov),3);
>
> cfg = [];
> cfg.method = 'lcmv';
> cfg.grid = leadfield;
> cfg.vol = vol;
> cfg.elec = elec;
> cfg.lcmv.lambda = '15%';
> cfg.lcmv.keepfilter = 'yes';
> cfg.lcmv.fixedori = 'yes';
> cfg.lcmv.projectnoise = 'yes';
>
> % Generate common test filter
> sourceA_common_test = ft_sourceanalysis(cfg,A);
>
> % Add common filter to configuration
> cfg.grid.filter = sourceA_common_test.avg.filter;
>
> % Replace original covariance matrix
> A.cov = tmp;
>
> % Now fit both A and U with the common test filter
> sourceA_test = ft_sourceanalysis(cfg,A);
> sourceU_test = ft_sourceanalysis(cfg,U);
>
>
> %%% Attempt a contrast
> % Create the contrasts
> sourceContrast = sourceA;
> sourceContrast.avg.pow = sourceA.avg.pow - sourceU.avg.pow;
> sourceContrast_test = sourceA_test;
> sourceContrast_test.avg.pow = sourceA_test.avg.pow - sourceU_test.avg.pow;
>
> % Gauge what percent of the contrast is negative (i.e. sourceU power >
> % sourceA power)
> perc_neg =
> sum(sourceContrast.avg.pow(sourceContrast.inside(:))<0)./numel(sourceContrast.avg.pow(sourceContrast.inside(:)));
> perc_neg_test =
> sum(sourceContrast_test.avg.pow(sourceContrast_test.inside(:))<0)./numel(sourceContrast_test.avg.pow(sourceContrast_test.inside(:)));
>
> %%% Visualize the output
> % Load template MRI
> mri = ft_read_mri([ftdir '\template\anatomy\single_subj_T1.nii']);
>
> % Interpolate source onto MRI
> cfg = [];
> cfg.parameter = 'avg.pow';
> sourceContrast_interp = ft_sourceinterpolate(cfg, sourceContrast, mri);
> sourceContrast_test_interp = ft_sourceinterpolate(cfg,
> sourceContrast_test, mri);
>
> % Visualize with ft_sourceplot
> cfg = [];
> cfg.method = 'ortho';
> cfg.funparameter = 'avg.pow';
> cfg.funcolorlim = [-100 5];
> cfg.maskparameter = cfg.funparameter;
> ft_sourceplot(cfg, sourceContrast_interp);
>
> cfg = [];
> cfg.method = 'ortho';
> cfg.funparameter = 'avg.pow';
> cfg.funcolorlim = [-100 5];
> cfg.maskparameter = cfg.funparameter;
> ft_sourceplot(cfg, sourceContrast_test_interp);
>
> On Tue, Jan 24, 2017 at 4:12 PM Matt Craddock <m.p.craddock at leeds.ac.uk
> <mailto:m.p.craddock at leeds.ac.uk>> wrote:
>
> Hi Tommy,
>
> > % Equate covariance matrices for now to rule out any differences
> in the
> > % source fit due to differences in covariances
> > U.cov = A.cov;
> >
>
> This is the problem. ft_sourceanalysis is using the covariance matrix
> and leadfield to construct a spatial filter for each grid point; if the
> covariance matrices are equivalent, the source solutions will be too.
>
> What you need to do is something like run the source analysis on data
> averaged over both conditions first, then take the filter from the
> combined analysis and run source analysis on each condition seperately.
>
> so say sourceAll is the result of
> ft_sourceanalysis(cfg,bothConditions)
>
> You'd do
>
> cfg.grid.filter = sourceAll.avg.filter
>
> then
>
> ft_sourceanalysis(cfg,A)
> ft_sourceanalysis(cfg,U)
>
> As a quick and dirty version I just replaced the covariance matrix in A
> with the average of the two A.cov and U.cov, ran sourceanalysis on that,
> then put A.cov back to its original value and ran sourceanalysis on each
> condition seperately. Spoiler: the unattended condition has lower
> activity everywhere :)
>
> There's some weirdness around the boundaries of the headmodel, not sure
> what's causing that exactly. Maybe try using a different source grid
> instead of the standard one...
>
> Cheers,
> Matt
>
> On 24/01/2017 16:36, Tommy Wilson wrote:
> > Hi Julian,
> >
> > Thank you so much for your reply.
> >
> > I've pasted the commented code below (I apologize for the code dump).
> > I've also attached an m-file to this email if you'd prefer to download
> > it that way. If relevant, you can download the leadfield,
> headmodel and
> > electrode locations here
> >
> <https://www.dropbox.com/s/8w99ejwrzmwc5pt/Source_fitting_dump.mat?dl=0
> <https://www.dropbox.com/s/8w99ejwrzmwc5pt/Source_fitting_dump.mat?dl=0>>
> > (that file also includes the raw data stored in variables A and U
> that I
> > am attempting to source-fit).
> >
> > As per your questions: I do indeed have a contrast between
> attended (A)
> > and unattended (U) conditions. I've written the code below to
> source-fit
> > both conditions and create the contrast. However, despite that the raw
> > topographies (see attached images) are different, the source-fits are
> > the same (...?). As a consequence, the contrast has no non-zero
> values.
> > If instead, I normalize to noise (i.e. generate the Neural Activity
> > Index
> >
> <http://www.fieldtriptoolbox.org/tutorial/beamformer#neural_activity_index
> <http://www.fieldtriptoolbox.org/tutorial/beamformer#neural_activity_index>>)
> > and look at a contrast there, we again see no non-zero values.
> >
> > Outside of the contrast, I've implemented your other suggestions. I've
> > rescaled the original ft_sourceplot such that you can see the
> extent of
> > it (see attached image). To my mind, it shouldn't look like this, but
> > having never done this before, I'm not quite sure what to expect. I've
> > also included an image of the ft_sourceplot for the Neural Activity
> > Index of sourceA which also appears to me to be artefactual. More
> to the
> > point, I'd expect that since the topographies for A and U are
> different,
> > the NAIs should be different, which is not the case.
> >
> > I'm sort of at a loss about how to proceed here. So, thank you
> very much
> > for taking the time to look into this. If I can supply anything
> else to
> > help, please don't hesitate to let me know.
> >
> > Best,
> >
> > Tommy Wilson
> >
> > --- CODE ---
> >
> > %% Source fitting protocol
> > % Fieldtrip path (to find template MRI)
> > ftdir = 'your\path\here\';
> >
> > % Equate covariance matrices for now to rule out any differences
> in the
> > % source fit due to differences in covariances
> > U.cov = A.cov;
> >
> > %%% Do the LCMV sourcefitting
> > cfg = [];
> > cfg.method = 'lcmv';
> > cfg.grid = leadfield;
> > cfg.vol = vol;
> > cfg.elec = elec;
> > cfg.lcmv.lambda = '15%';
> > cfg.lcmv.keepfilter = 'yes';
> > cfg.lcmv.fixedori = 'yes';
> > cfg.lcmv.projectnoise = 'yes';
> >
> > sourceA = ft_sourceanalysis(cfg,A);
> > sourceU = ft_sourceanalysis(cfg,U);
> >
> >
> > %%% Attempt a contrast
> > % Create the contrast
> > sourceContrast = sourceA;
> > sourceContrast.avg.pow = sourceA.avg.pow - sourceU.avg.pow;
> >
> > % Check to see if any non-zero values exist in the contrast
> > if all(sourceContrast.avg.pow(sourceContrast.inside(:)) == 0)
> > warning('No non-zero contast values exist. ft_sourceplot will give
> > an error. Do not plot.');
> > end
> >
> >
> > %%% Instead of a contrast, look at the Neural Activity Index (NAI)
> > % See:
> >
> http://www.fieldtriptoolbox.org/tutorial/beamformer#neural_activity_index
> <http://www.fieldtriptoolbox.org/tutorial/beamformer#neural_activity_index>
> > sourceA_NAI = sourceA;
> > sourceA_NAI.avg.pow = sourceA.avg.pow./sourceA.avg.noise;
> > sourceU_NAI = sourceU;
> > sourceU_NAI.avg.pow = sourceU.avg.pow./sourceU.avg.noise;
> >
> > if all(sourceA_NAI.avg.pow(sourceA_NAI.inside(:)) -
> > sourceU_NAI.avg.pow(sourceU_NAI.inside(:))==0)
> > warning('No non-zero contast values exist. ft_sourceplot will give
> > an error. Do not plot.')
> > end
> >
> >
> > %%% Visualize the output
> > % Load template MRI
> > mri = ft_read_mri([ftdir
> > '\fieldtrip-20160309\template\anatomy\single_subj_T1.nii']);
> >
> > % Interpolate source onto MRI
> > cfg = [];
> > cfg.parameter = 'avg.pow';
> > sourceA_interp = ft_sourceinterpolate(cfg, sourceA, mri);
> > sourceA_NAI_interp = ft_sourceinterpolate(cfg, sourceA_NAI, mri);
> >
> > % Visualize with ft_sourceplot
> > cfg = [];
> > cfg.method = 'ortho';
> > cfg.funparameter = 'avg.pow';
> > cfg.funcolorlim = [0 3e3];
> > cfg.maskparameter = cfg.funparameter;
> > ft_sourceplot(cfg, sourceA_interp);
> >
> > cfg = [];
> > cfg.method = 'ortho';
> > cfg.funparameter = 'avg.pow';
> > cfg.maskparameter = cfg.funparameter;
> > ft_sourceplot(cfg, sourceA_NAI_interp);
> >
> > On Tue, Jan 24, 2017 at 3:42 AM Julian Keil <julian.keil at gmail.com
> <mailto:julian.keil at gmail.com>
> > <mailto:julian.keil at gmail.com <mailto:julian.keil at gmail.com>>> wrote:
> >
> > Hi Tommy,
> >
> > did you do some sort of contrast (e.g. with the noise estimate
> or a
> > baseline) after your source analysis?
> > Right now, it's not clear what you are looking at. Could you paste
> > your code not only of the sourceanalysis, but the rest after which
> > got you to the plot?
> > It might also be the case that the automatic scaling in the source
> > plot throws you off - maybe try setting it by hand.
> >
> > Good luck,
> >
> > Julian
> >
> > Am 23.01.2017 um 22:00 schrieb Tommy Wilson:
> >
> > > Hi all,
> > >
> > > I'm working with EEG data and I'm trying to get some basic
> source
> > fitting up and running. Unfortunately, I don't have individual
> > subject MRIs, so I'm using the templates provided by
> fieldtrip. I've
> > co-registered my 160 Biosemi electrodes to the standard_bem
> template
> > (see attached picture). For the sourcemodel, I'm using the
> > standard_sourcemodel3d5mm grid (picture attached, overlaid on
> > standard_bem). I can prepare the leadfield from there with
> > ft_prepare_leadfield (cfg.normalize = 'yes'), as per the LCMV
> tutorial.
> > >
> > > To test this configuration, I've selected a time window in
> my data
> > and averaged across it (the covariance matrix was also
> calculated);
> > the topography of this averaged data is attached. I then
> attempted a
> > source fit with the LCMV beamformer:
> > >
> > > cfg = [];
> > > cfg.method = 'lcmv';
> > > cfg.grid = leadfield;
> > > cfg.vol = vol;
> > > cfg.elec = elec;
> > > cfg.lcmv.lambda = '15%';
> > > cfg.lcmv.keepfilter = 'yes';
> > > cfg.lcmv.fixedori = 'yes';
> > > cfg.lcmv.projectnoise = 'yes';
> > >
> > > sourceA = ft_sourceanalysis(cfg,A);
> > >
> > > After interpolating to the single_subj_T1.nii provided with
> > ft_sourceinterpolate and plotting with ft_sourceplot, I am given a
> > sourceplot that is highly focal in nature (see attached picture).
> > >
> > > I'd find it very surprising if this topography were generated
> > primarily by a source that isn't even inside the brain (as the
> > sourceplot indicates). So, I'm not sure exactly where/how I'm
> going
> > wrong with this one, nor am I sure how to trouble shoot it. Any
> > guidance you might provide would be greatly appreciated.
> > >
> > > Thanks so much,
> > >
> > > Tommy
> > >
> > > <Grid.PNG><Electrode
> >
> localization.PNG><Topo.PNG><Source.PNG>_______________________________________________
> > > fieldtrip mailing list
> > > fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>
> <mailto:fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>>
> > > https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> <https://mailman.science.ru.nl/mailman/listinfo/fieldtrip>
> >
> > _______________________________________________
> > fieldtrip mailing list
> > fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>
> <mailto:fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>>
> > https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> <https://mailman.science.ru.nl/mailman/listinfo/fieldtrip>
> >
> >
> >
> > _______________________________________________
> > fieldtrip mailing list
> > fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>
> > https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> <https://mailman.science.ru.nl/mailman/listinfo/fieldtrip>
> >
> _______________________________________________
> fieldtrip mailing list
> fieldtrip at donders.ru.nl <mailto:fieldtrip at donders.ru.nl>
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
> <https://mailman.science.ru.nl/mailman/listinfo/fieldtrip>
>
>
>
> _______________________________________________
> fieldtrip mailing list
> fieldtrip at donders.ru.nl
> https://mailman.science.ru.nl/mailman/listinfo/fieldtrip
>
More information about the fieldtrip
mailing list