Skip to content

Commit 886e212

Browse files
ENH - added example script to construct MNI-aligned template source model for FEM
thanks to @NataschaRoos and @vitpia
1 parent 0699a00 commit 886e212

File tree

6 files changed

+126
-7
lines changed

6 files changed

+126
-7
lines changed

example.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ See also the [tutorials](/tutorial) and [frequently asked questions](/faq).
5555
- [Compute EEG leadfields using a concentric spheres headmodel](/example/source/concentricspheres)
5656
- [Compute EEG leadfields using a BEM headmodel](/example/source/bem)
5757
- [Compute EEG leadfields using a FEM headmodel](/example/source/fem)
58+
- [Create a template source model aligned to MNI space](/example/source/sourcemodel_mnitemplate)
5859
- [Compute forward simulated data and apply a beamformer scan](/example/compute_forward_simulated_data_and_apply_a_beamformer_scan)
5960
- [Compute forward simulated data and apply a dipole fit](/example/compute_forward_simulated_data_and_apply_a_dipole_fit)
6061
- [Compute forward simulated data using ft_dipolesimulation](/example/compute_forward_simulated_data)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
title: Create a template source model aligned to MNI space
3+
category: example
4+
tags: [meg, mri, headmodel, source]
5+
---
6+
7+
# Create template source models aligned to MNI space
8+
9+
On the [template sourcemodel](/template/sourcemodel) page we describe that we have a number of 3D grid
10+
source models defined in MNI space. These models can be used as templates for individual subject data,
11+
allowing for more accurate and consistent source reconstruction across subjects. The procedure for this
12+
is described in the [source model tutorial](/tutorial/sourcemodel).
13+
14+
These source models are only available at a few resolutions, and have dipoles throughout the whole brain
15+
compartment, including CSF, white matter and gray matter. That is convenient for beamformer source
16+
reconstruction of MEG and EEG data with a BEM or single shell head model, but not so for minimum
17+
norm source reconstruction or for source estimates using a FEM model.
18+
19+
The following script describes how to create your own template source model in MNI space, at 3mm
20+
resolution, and only with dipoles in gray matter.
21+
22+
{% include markup/yellow %}
23+
Note that "gray" is the American English spelling, while "grey" is the British English spelling.
24+
Both are correct, but **[ft_volumesegment](/reference/ft_volumesegment)** uses the American
25+
spelling, whereas SPM uses the British spelling.
26+
{% include markup/end %}
27+
28+
% read the 1 mm resolution canonical MNI template MRI
29+
[ftver, ftpath] = ft_version
30+
mri = ft_read_mri(fullfile(ftpath, 'template/anatomy/single_subj_T1_1mm.nii'));
31+
mri.coordsys = 'mni';
32+
33+
% make a tissue probability map segmentation of CSF, white and gray matter
34+
cfg = [];
35+
cfg.output = 'tpm';
36+
cfg.spmmethod = 'old';
37+
seg = ft_volumesegment(cfg,mri);
38+
39+
% there are also voxels that are neither CSF, white or gray matter
40+
seg.otherwise = ones(seg.dim)-seg.gray-seg.white-seg.csf;
41+
42+
% make a matrix with 4 columns, each row is a voxel
43+
% the probabilistic sum of all tissue types adds up to 1, or 100%
44+
prob = [seg.gray(:) seg.white(:) seg.csf(:) seg.otherwise(:)];
45+
46+
% identify which voxels have the highest probability of being gray matter
47+
% these are considered to be inside the (binary) grey matter compartment
48+
inside = zeros(seg.dim);
49+
for voxel = 1:prod(seg.dim)
50+
[m,tissue] = max(prob(voxel,:)); % tissue = column, m = number
51+
inside(voxel) = tissue == 1;
52+
end
53+
54+
% these are not needed any more
55+
seg = rmfield(seg,'gray');
56+
seg = rmfield(seg,'white');
57+
seg = rmfield(seg,'csf');
58+
seg = rmfield(seg,'otherwise');
59+
60+
% add the inside-gray-matter mask
61+
seg.inside = inside;
62+
63+
%% prepare a source model for gray matter
64+
65+
cfg = [];
66+
cfg.method = 'basedongrid';
67+
cfg.xgrid = -90:3:90;
68+
cfg.ygrid = -120:3:90;
69+
cfg.zgrid = -90:3:90;
70+
cfg.unit = 'mm';
71+
72+
% you want the xgrid/ygrid/zgrid numbers to be such, that they cover the entire brain
73+
% and that they are nicely symmetric around the origin. In this case they are chosen
74+
% such that there is also a dipole exactly at [0, 0, 0].
75+
76+
sourcemodel_template = ft_prepare_sourcemodel(cfg);
77+
78+
% the resulting source model consists of a 3D grid of dipoles that spans the brain,
79+
% but does not specify which ones are inside the grey matter (or the brain) or outside
80+
81+
figure
82+
ft_plot_mesh(sourcemodel_template.pos)
83+
84+
% you should rotate the figure, you will see that it is a square block with many dipoles
85+
86+
% we now determine for each dipole what tissue type it is in
87+
sourcemodel_template.inside = zeros(prod(sourcemodel_template.dim),1);
88+
89+
% the following uses the inverse homogenous transformation to go from head to voxel coordinates
90+
91+
for dipole = 1:prod(sourcemodel_template.dim) % loop over all dipoles
92+
thispos = sourcemodel_template.pos(dipole,:); % the position of this dipole in head coordinates
93+
thispos = [thispos 1]';
94+
thisvox = round(inv(seg.transform)*thispos); % the indices of the nearest voxel in the segmented MRI
95+
if thisvox(1) < 1 || thisvox(1) > seg.dim(1)
96+
% it falls outside the segmented volume
97+
sourcemodel_template.inside(dipole) = 0;
98+
elseif thisvox(2) < 1 || thisvox(2) > seg.dim(2)
99+
% it falls outside the segmented volume
100+
sourcemodel_template.inside(dipole) = 0;
101+
elseif thisvox(3) < 1 || thisvox(3) > seg.dim(3)
102+
% it falls outside the segmented volume
103+
sourcemodel_template.inside(dipole) = 0;
104+
else
105+
% look up in the segmented volume whether the nearest voxel is gray matter
106+
sourcemodel_template.inside(dipole) = seg.inside(thisvox(1), thisvox(2), thisvox(3));
107+
end
108+
end
109+
110+
% convert it into a logical array with true/false values
111+
sourcemodel_template.inside = logical(sourcemodel_template.inside);
112+
113+
% make a plot of the dipoles that are inside the gray matter
114+
figure
115+
ft_plot_mesh(sourcemodel_template.pos(sourcemodel_template.inside,:))
116+
117+
% you should rotate the figure, you will see that it is a brain-shaped cloud of dipoles, only in gray matter
118+

faq/development/datatype.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ An example of a source structure obtained after performing a frequency domain so
4747
inside: [1x3415 double] indices to the positions at which the source activity is actually estimated
4848
outside: [1x3317 double] indices to the positions at which the source activity has not been estimated
4949

50-
dim: [xdim ydim zdim] if the positions are described as a 3D regular grid, this contains the
50+
dim: [xdim ydim zdim] if the positions are described as a regularly spaced 3D grid, this contains the
5151
dimensionality of the 3D volume
5252
vol: [1x1 struct] volume conductor model
5353
cumtapcnt: [10x1 double] information about the number of tapers per original trial
@@ -69,7 +69,7 @@ This is the new definition of a data structure that represents data correspondin
6969
pos: [6732x3 double] positions at which the source activity could have been estimated
7070
inside: [6732x1 logical] logical vector of positions at which the source activity is actually estimated
7171

72-
dim: [xdim ydim zdim] if the positions can be described as a 3D regular grid, this contains the
72+
dim: [xdim ydim zdim] if the positions can be described as a regularly spaced 3D grid, this contains the
7373
dimensionality of the 3D volume
7474
vol: [1x1 struct] volume conductor model
7575
cumtapcnt: [120x1 double] information about the number of tapers per original trial

faq/source/sticking_out.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ For the singleshell, singlesphere or localspheres models for MEG it is not a pro
2626

2727
## Solution
2828

29-
If you are working with regular 3D grids as source model, you don't have to do anything. FieldTrip will check for every source whether it is inside or outside the innermost compartment of the volume conductor, and all sources outside will be flagged and not used in the source reconstruction. FieldTrip will actually do the same check for source models based on a triangulated cortical sheets. You can use the `cfg.inwardshift` option to ensure that sources that are on the inside - but too close to the surface for BEM - are also flagged as outside.
29+
If you are working with regularly spaced 3D grids as source model, you don't have to do anything. FieldTrip will check for every source whether it is inside or outside the innermost compartment of the volume conductor, and all sources outside will be flagged and not used in the source reconstruction. FieldTrip will actually do the same check for source models based on a triangulated cortical sheets. You can use the `cfg.inwardshift` option to ensure that sources that are on the inside - but too close to the surface for BEM - are also flagged as outside.
3030

3131
If you do not want to flag any of your dipoles as outside and exclude them from the source estimation, you have to modify your source model. First of all, you should ensure that your cortical sheet is properly aligned with your volume conduction model of the head. The `cfg.moveinward` option in **[ft_prepare_sourcemodel](/reference/ft_prepare_sourcemodel)** takes all dipoles that are outside, and projects then on an inward-shifted surface of the inside-skull. I.e. it deforms the cortical sheet by pushing some vertices inward. This should work both for spherical models (i.e. concentric spheres) and BEM models. In the case of spherical models, it will result in a cortical mesh that is squeezed in to a sphere shape.
3232

template/sourcemodel.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ When you do source reconstruction with dipole fit methods (as implemented in **[
2020
When doing source reconstruction with beamformers, people typically scan the brain volume where dipoles are defined on a regular 3D grid, with a regular spacing between the dipole locations. These grids are usually optimized to the individual anatomy of the participant. To facilitate group analysis, however, a clever strategy is to use a template grid (based on a template anatomical volume) that will be (linearly or non-linearly) warped to the individual participant's anatomy. Although this may lead to irregular spacing between the dipole locations (both across and potentially within participants), the dipole locations are directly comparable across participants, because they coincide in standard space.
2121
The FieldTrip template directory provides a set of sourcemodels defined on regular 3D-grids that are constructed from the MNI-template anatomy from SPM. These template sourcemodels can subsequently be used to be inverse normalized to the individual participant's anatomy. See this [example](/example/sourcemodel_aligned2mni) for more information.
2222

23-
Template source models with the varying dipole spacing (4, 5, 6, 7.5, 8 and 10 mm) on a regular 3-D grid are available in fieldtrip/template/sourcemodel director
23+
Template source models with the varying dipole spacing (4, 5, 6, 7.5, 8 and 10 mm) on a regular 3-D grid are released along with the FieldTrip toolbox and available in the `fieldtrip/template/sourcemodel` directory:
2424

2525
- standard_sourcemodel3d10mm.mat
2626
- standard_sourcemodel3d4mm.mat
@@ -29,7 +29,7 @@ Template source models with the varying dipole spacing (4, 5, 6, 7.5, 8 and 10 m
2929
- standard_sourcemodel3d7point5mm.mat
3030
- standard_sourcemodel3d8mm.mat
3131

32-
To load and visualize the 3D regular grids, you can do for example
32+
To load and visualize the regularly spaced 3D grids, you can do
3333

3434
load standard_sourcemodel3d5mm.mat
3535

@@ -44,7 +44,7 @@ or you can use
4444
figure
4545
ft_plot_mesh(sourcemodel)
4646

47-
You will notice that the 3D regular grids are not that interesting to look at; since there are no connecting elements (triangles), **[ft_plot_mesh](/reference/plotting/ft_plot_mesh)** will only show the vertices.
47+
You will notice that the regularly spaced 3D grids are not that interesting to look at; since there are no connecting elements (triangles), **[ft_plot_mesh](/reference/plotting/ft_plot_mesh)** will only show the vertices.
4848

4949
### Distributed source models with MNE
5050

workshop/neuroimaging2-2425/sr4.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ row in the 'avg’ field belongs to which channel).
354354
Next we will make a source reconstruction using the 'mne’ method of FieldTrip’s
355355
ft_sourceanalysis function. Before we can do this, we need to define our source
356356
model, i.e., the set of locations that we assume to be active. For now we assume
357-
that the active dipoles are distributed on a 3D regular grid, with a spacing
357+
that the active dipoles are distributed on a regular 3D grid, with a spacing
358358
of 1 cm between the dipoles:
359359

360360
sourcemodel = ni2_sourcemodel('type', 'grid', 'resolution', 1);

0 commit comments

Comments
 (0)