forked from mne-tools/mne-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot_morph_stc.py
More file actions
266 lines (200 loc) · 11.5 KB
/
Copy pathplot_morph_stc.py
File metadata and controls
266 lines (200 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# -*- coding: utf-8 -*-
r"""
===========================================
Morphing source estimates using SourceMorph
===========================================
In this tutorial we will morph different kinds of source estimation results
between individual subject spaces using :class:`mne.SourceMorph`.
For group level statistical analyses, subject specific results have to be
mapped to a common space.
We will use precomputed data and morph surface and volume source estimates to a
common space. The common space of choice will be FreeSurfer's 'fsaverage' See
:ref:`sphx_glr_auto_tutorials_plot_background_freesurfer.py` for more
information.
Furthermore we will convert our volume source estimate into a NIfTI image using
:meth:`morph.as_volume <mne.SourceMorph.as_volume>`.
.. contents::
:local:
Why morphing?
=============
Modern neuroimaging techniques, such as source reconstruction or fMRI analyses,
make use of advanced mathematical models and hardware to map brain activity
patterns into a subject specific anatomical brain space.
This enables the study of spatio-temporal brain activity. The representation of
spatio-temporal brain data is often mapped onto the anatomical brain structure
to relate functional and anatomical maps. Thereby activity patterns are
overlaid with anatomical locations that supposedly produced the activity.
Anatomical MR images are often used as such or are transformed into an inflated
surface representations to serve as "canvas" for the functional projection.
This projection must hence be in the same space.
In order to compute group level statistics, data representations across
subjects must be morphed to a common frame, such that anatomically and
functional similar structures are represented at the same spatial location for
*all subjects equally*.
Since brains vary, morphing comes into play to tell us how the data
produced by subject A, would be represented on the brain of subject B.
See also this :ref:`tutorial on surface source estimation
<sphx_glr_auto_tutorials_plot_mne_solutions.py>`
or this :ref:`example on volumetric source estimation
<sphx_glr_auto_examples_inverse_plot_compute_mne_inverse_volume.py>`.
Morphing **volume** source estimates
====================================
A volumetric source estimate represents functional data in a volumetric 3D
space. The difference between a volumetric representation and a "mesh" (
commonly referred to as "3D-model"), is that the volume is "filled" while the
mesh is "empty". Thus it is not only necessary to morph the points of the
outer hull, but also the "content" of the volume.
In MNE-Python, volumetric source estimates are represented as
:class:`mne.VolSourceEstimate`. The morph was successful if functional data of
Subject A overlaps with anatomical data of Subject B, in the same way it does
for Subject A.
See :ref:`sphx_glr_auto_examples_inverse_plot_morph_volume_stc.py` for an
example of such a morph.
Volumetric morphing is performed using dipy_.
Setting up SourceMorph for VolSourceEstimate
--------------------------------------------
See also: :ref:`sphx_glr_auto_examples_inverse_plot_morph_volume_stc.py`.
We know that the morph from Subject A to subject B employs a precomputation
of a morph volume. The respective morphing operation will be non-linear and
this is why a single transformation matrix would not be sufficient.
:class:`mne.SourceMorph` will use segmented anatomical MR images computed
using :ref:`FreeSurfer <sphx_glr_auto_tutorials_plot_background_freesurfer.py>`
to compute the morph map. In order tell SourceMorph which MRIs to use,
``subject_from`` and ``subject_to`` need to be defined as the name of the
respective folder in FreeSurfer's home directory.
``subject_from`` can also be inferred from :class:`src <mne.SourceSpaces>`,
subject_to set is to 'fsaverage' by default and ``subjects_dir`` can be None
when set in the environment. In that case SourceMorph can be initialized taking
src as only argument (for better understanding more keyword arguments are
defined here).
The default parameter setting for *spacing* will cause the reference volumes
to be resliced before computing the transform. A value of '5' would cause
the function to reslice to an isotropic voxel size of 5 mm. The higher this
value the less accurate but faster the computation will be.
>>> morph = SourceMorph(subject_from='sample', # Default: None
>>> subject_to='fsaverage', # Default
>>> subjects_dir=subjects_dir, # Default: None
>>> src=src, # Default: None
>>> spacing=5) # Default
Apply morph to VolSourceEstimate
--------------------------------
The morph will be applied to the source estimate data, by giving it as the
first argument to the morph we computed above. Note that
:meth:`morph() <mne.SourceMorph.__call__>` can take the same input arguments
as :meth:`morph.as_volume() <mne.SourceMorph.as_volume>` to return a NIfTI
image instead of a MNE-Python representation of the source estimate.
>>> stc_fsaverage = morph(stc)
Convert morphed VolSourceEstimate into NIfTI
--------------------------------------------
We can convert our morphed source estimate into a NIfTI volume using
:meth:`morph.as_volume() <mne.SourceMorph.as_volume>`. We provided our
morphed source estimate as first argument. All following keyword arguments can
be used to modify the output image.
Note that ``apply_morph=False``, that is the morph will not be applied because
the data has already been morphed. Set ``apply_morph=True`` to output
un-morphed data as a morphed volume. Further
:meth:`morph() <mne.SourceMorph.__call__>` can be used to output a volume as
well, taking the same input arguments. Provide ``as_volume=True`` when calling
the :class:`mne.SourceMorph` instance. In that case however apply_morph will of
course be True by default.
>>> img = morph.as_volume(stc_fsaverage, # morphed VolSourceEstimate
>>> mri_resolution=True, # Default: False
>>> mri_space=True, # Default: mri_resolution
>>> apply_morph=False, # Default
>>> format='nifti1') # Default
Example result for morphing **volume** source estimates
--------------------------------------------------------
:ref:`sphx_glr_auto_examples_inverse_plot_morph_volume_stc.py`
.. image:: ../../_images/sphx_glr_plot_morph_volume_stc_001.png
Morphing **surface** source estimates
=====================================
See: also :ref:`sphx_glr_auto_examples_inverse_plot_morph_surface_stc.py`.
A surface source estimate represents data relative to a 3-dimensional mesh of
the inflated brain surface computed using FreeSurfer. This mesh is defined by
its vertices. If we want to morph our data from one brain to another, then
this translates to finding the correct transformation to transform each
vertex from Subject A into a corresponding vertex of Subject B. Under the hood
:ref:`FreeSurfer <sphx_glr_auto_tutorials_plot_background_freesurfer.py>`
uses spherical representations to compute the morph.
In MNE-Python, surface source estimates are represented as
:class:`mne.SourceEstimate` or :class:`mne.VectorSourceEstimate`. Those can
be used together with :class:`mne.SourceSpaces` or without.
The morph was successful if functional data of Subject A overlaps with
anatomical surface data of Subject B, in the same way it does for Subject A.
See :ref:`sphx_glr_auto_examples_inverse_plot_morph_surface_stc.py` for an
example of such a morph.
Please see also Gramfort *et al.* (2013) [1]_.
Setting up SourceMorph for SourceEstimate
-----------------------------------------
In MNE surface source estimates are represented as lists of vertices. If
that is not entirely clear, we ask ourselves
:ref:`sphx_glr_auto_tutorials_plot_object_source_estimate.py`
The respective list of our data can either be obtained from
:class:`mne.SourceSpaces` (src) or from the data we want to morph itself. If
src is not provided, the morph will not be precomputed but instead will be
prepared for morphing when calling.
This works only with (Vector) :class:`SourceEstimate <mne.SourceEstimate>`.
See :class:`mne.SourceMorph` for additional parameter settings. We keep the
default parameters for *src* and *spacing*.
Since the default of spacing (resolution of surface mesh) is 5 and subject_to
was set to 'fsaverage', SourceMorph will use default vertices to morph
(``[np.arange(10242)] * 2``).
If src was not defined, the morph will actually not be precomputed, because
we lack the vertices *from* that we want to compute. Instead the morph will
be set up and when applying it, the actual transformation will be computed on
the fly.
>>> morph = SourceMorph(subject_from='sample',
>>> subject_to='fsaverage',
>>> subjects_dir=subjects_dir,
>>> src=None,
>>> spacing=5)
Apply morph to (Vector) SourceEstimate
--------------------------------------
The morph will be applied to the source estimate data, by giving it as the
first argument to the morph we computed above.
>>> stc_fsaverage = morph(stc)
Example result for morphing **surface** source estimates
--------------------------------------------------------
:ref:`sphx_glr_auto_examples_inverse_plot_morph_surface_stc.py`
.. image:: ../../_images/sphx_glr_plot_morph_surface_stc_001.png
Reading and writing SourceMorph from and to disk
================================================
An instance of SourceMorph can be saved, by calling
:meth:`morph.save <mne.SourceMorph.save>`.
>>> morph.save('my-file-name')
This methods allows for specification of a filename under which the ``morph``
will be save in ".h5" format. If no file extension is provided, "-morph.h5"
will be appended to the respective defined filename.
In turn, reading a saved source morph can be achieved by using
:func:`mne.read_source_morph`:
>>> from mne import read_source_morph
>>> morph = read_source_morph('my-file-name-morph.h5')
Additional Info
===============
In addition to the functionality, demonstrated above, :class:`mne.SourceMorph`
can be used slightly different as well, in order to enhance user comfort.
For instance, it is possible to directly obtain a NIfTI image when calling
the SourceMorph instance, but setting ``as_volume=True``. If so, the
:meth:`morph() <mne.SourceMorph.__call__>` function takes the same input
arguments as :meth:`morph.as_volume <mne.SourceMorph.as_volume>`.
Moreover it can be decided whether to actually apply the morph or not. This way
SourceMorph can be used to output un-morphed data as a volume as well. By
setting ``apply_morph`` and ``as_volume`` to True, the source estimate will be
morphed and convert it into a volume in one go:
>>> img = morph(stc, as_volume=True, apply_morph=True)
Once the environment is set up correctly, no information such as
``subject_from`` or ``subjects_dir`` must be provided, since it can be inferred
from the data and use morph to 'fsaverage' by default. SourceMorph can further
be used without creating an instance and assigning it to a variable. Instead
the :class:`__init__ <mne.SourceMorph>` and
:meth:`__call__ <mne.SourceMorph.__call__>` methods of SourceMorph can be daisy
chained into a handy one-liner. Taking this together the shortest possible way
to morph data directly would be:
>>> stc_fsaverage = mne.SourceMorph(src=src)(stc)
References
==========
.. [1] Gramfort, A., Luessi, M., Larson, E., Engemann, D. A., Strohmeier, D.,
Brodbeck, C., ... & Hämäläinen, M. (2013). MEG and EEG data analysis
with MNE-Python. Frontiers in neuroscience, 7, 267.
.. _dipy: http://nipy.org/dipy/
"""