Note
Go to the end to download the full example code. or to run this example in your browser via Binder
Working with Surface images¶
Here we explain how surface images are represented within Nilearn and how you can plot, save and load them.
What is a surface image?¶
Within the context of neuroimaging, a surface image is an alternative way of representing MRI data as opposed to a volumetric image.
While volumetric images are 3D grids of voxels, surface images consist of points (vertices) in 3D space connected to represent the surface of the brain.
Practically, this means that the main difference between the two is the basic unit that holds the data. For volumetric images, that basic unit is a voxel, while for surface images it is a vertex.
The goal of this tutorial is to show you how to work with surface images in Nilearn. For more existential questions like why surface images are useful, how they are created etc., Andy Jahn’s blog is a good starting point.
Surface images have two main components:
The mesh, which is the geometry of the surface.
The data, which is the information stored at each vertex of the mesh.
Mesh¶
A mesh can be defined by two arrays:
The coordinates of the vertices.
Which vertices need to be connected to form faces.
Note
This representation of a mesh is known as Face-Vertex representation.
For brain surfaces we typically have two meshes: one for the left hemisphere
and one for the right hemisphere.
Nilearn represents this as a
PolyMesh
object with two parts
:
left
and right
.
So you can define your own mesh, say, for the left part a tetrahedron
and for the right part a pyramid, using numpy arrays and create a
PolyMesh
object as follows:
import numpy as np
from nilearn.surface import InMemoryMesh, PolyMesh
# for the tetrahedron
left_coords = np.asarray(
[
[0, 0, 0], # vertex 0
[1, 0, 0], # vertex 1
[0, 1, 0], # vertex 2
[0, 0, 1], # vertex 3
]
)
left_faces = np.asarray(
[
[1, 0, 2], # face created by connecting vertices 1, 0, 2
[0, 1, 3], # face created by connecting vertices 0, 1, 3
[0, 3, 2], # face created by connecting vertices 0, 3, 2
[1, 2, 3], # face created by connecting vertices 1, 2, 3
]
)
# for the pyramid
right_coords = (
np.asarray(
[
[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0],
[0, 0, 1],
]
)
+ 2
)
right_faces = np.asarray(
[
[0, 1, 4],
[0, 3, 1],
[1, 3, 2],
[1, 2, 4],
[2, 3, 4],
[0, 4, 3],
]
)
# put the two parts together
mesh = PolyMesh(
left=InMemoryMesh(left_coords, left_faces),
right=InMemoryMesh(right_coords, right_faces),
)
Data¶
The data is the information stored at each vertex of the mesh. This can be anything from the thickness of the cortex to the activation level at that vertex.
For this example, let’s create some random data for the vertices of the mesh:
rng = np.random.default_rng(0)
left_data = rng.random(mesh.parts["left"].n_vertices)
right_data = rng.random(mesh.parts["right"].n_vertices)
# put them together in a dictionary
data = {
"left": left_data,
"right": right_data,
}
Creating a surface image¶
Now we can create a surface image by combining the mesh and the data
using the SurfaceImage
class:
from nilearn.surface import SurfaceImage
surface_image = SurfaceImage(mesh=mesh, data=data)
Plotting the surface image¶
The surface image can be plotted using the different functions
from the nilearn.plotting
module.
Here we will show how to use the
view_surf
function:
from nilearn.plotting import view_surf
Plot the left part
view_surf(
surf_map=surface_image,
hemi="left",
)