Presenting results in an academic paper is probably the most important part of writing up. Clear and visually appealing figures can turn a mediocre paper into a fantastic one. Brain mapping is no exception to this rule.
Most analyse of MRI data is done in volume space (as opposed to doing it on the surface) and results are often presented as two dimensional slices, such as this example:
In [1]:
import nibabel as nb
from nipy.labs.viz_tools.activation_maps import plot_map
dmn_file = "/SCR/PowerFolder/Dropbox/papers/neural_correlates_of_mind_wandering/vol0006.nii.gz"
dmn_nii = nb.load(dmn_file)
plot_map(dmn_nii.get_data(), dmn_nii.get_affine(), threshold=3.,
draw_cross=False, vmin=3., vmax=6., cmap="autumn")
Out[1]:
In the example above I have used the "plot_map: function from nipy to show three orthogonal slices of the Default Mode Network (data taken from http://fsl.fmrib.ox.ac.uk/analysis/brainmap+rsns/).
However, some people find a three dimensional renders of the cortex visually more appealing and easier to understand. I also wanted to include such figures in the paper I have been working on recently. Initially we used SUMA (and when I say we I mean my dear friend Judy) to generate them, but this process required many manual steps that had to be done in the GUI (and therefore they were not scriptable). It was ok if I would do the figures only once, but a heated dicussion with my coauthors resulted with minor changes to the processing and the figures would have be regenerated. What I really wanted was a method that would allow me to do this in python in a fully automated manner.
Luckily there is pysyrfer - a python based piece of software that uses Mayavi and FreeSurfer to render 3D brain (with layers and the whole shebang).
From the surfer package we will need two things:
In [2]:
from surfer import Brain, io
Since our data is in volume space (but in MNI) the first thing we need to do is to convert it to surface. This can be done by the project_volume_data function from surfer.io. The only catch is that this function needs a transformation matrix. This should more or less be na identity matrix (with some flipping), but FreeSurfer provides optimized MNI152 to fsaverage transformation:
In [3]:
!cat /afs/cbs.mpg.de/software/freesurfer/currentversion/amd64/2.15/average/mni152.register.dat
Having found the transformation matrix we can convert our volume:
In [4]:
reg_file = "/afs/cbs.mpg.de/software/freesurfer/currentversion/amd64/2.15/average/mni152.register.dat"
surf_data = io.project_volume_data(dmn_file, "lh", reg_file)
The second parameter indicates that we are interested in the left hemisphere. Now that we have the data we can show it on the surface. First step involves showing just the surface without any overlays:
In [5]:
from IPython.core.display import Image
brain = Brain("fsaverage", "lh", "pial")
brain.save_image("/tmp/my3dbrain.png")
Image("/tmp/my3dbrain.png")
Out[5]:
Beautiful isn't it? Lets add the overlay:
In [21]:
brain.add_overlay(surf_data, min=3., max=6.)
brain.save_image("/tmp/my3dbrain.png")
Image("/tmp/my3dbrain.png")
Out[21]:
I find the grey curvature shading distracting so I will turn it off. I also prefer white background and slightly darker brain.
In [25]:
brain = Brain("fsaverage", "lh", "pial", curv=None,
config_opts={"cortex": "bone",
"background": "white"})
brain.add_overlay(surf_data, min=3., max=6.)
brain.save_image("/tmp/my3dbrain.png")
Image("/tmp/my3dbrain.png")
Out[25]:
We can also show the inflated version of the brain:
In [27]:
brain = Brain("fsaverage", "lh", "inflated", curv=None,
config_opts={"cortex": "bone",
"background": "white"})
brain.add_overlay(surf_data, min=3., max=6.)
brain.save_image("/tmp/my3dbrain.png")
Image("/tmp/my3dbrain.png")
Out[27]:
Of course it is also worth looking at the medial wall
In [29]:
brain = Brain("fsaverage", "lh", "pial", curv=None,
config_opts={"cortex": "bone",
"background": "white"})
brain.add_overlay(surf_data, min=3., max=6.)
brain.show_view("medial")
brain.save_image("/tmp/my3dbrain.png")
Image("/tmp/my3dbrain.png")
Out[29]:
We can also show both at the same time
In [32]:
brain.save_montage("/tmp/my3dbrain.png",['l', 'm'], orientation='v')
Image("/tmp/my3dbrain.png")
Out[32]:
Doing the same thing for the other hemisphere will require applying the transformation matrix again:
In [41]:
brain = Brain("fsaverage", "rh", "pial", curv=None,
config_opts={"cortex": "bone",
"background": "white"})
surf_data = io.project_volume_data(dmn_file, "rh", reg_file)
brain.add_overlay(surf_data, min=3., max=6.)
brain.save_montage("/tmp/my3dbrain.png",['l', 'm'], orientation='v')
Image("/tmp/my3dbrain.png")
Out[41]:
So here you go. Using pysurfer you can easily generate beautiful 3D figures and thanks to python all of it can be automated saving time and energy.