Cifti Surface Plots
Nilearn Surface Plot
The NiLearn library has some very nice plotting functions. One of my favorite features of the library is the ability to create stand-alone surface plots like the one below!
Example of surface plot
While I often create ad-hoc surface plots, I thought I thought I might actually document the process both for my future reference, and to help others.
First, I’ll go through the general case: suppose we have some cifti file on the standard hcp 32k mesh (like a .dscalar.nii
file). It might be nice to create an interactive visualization of this file for a presentation/website. I’ll outline the steps to doing this below, but first two quick notes:
-
To keep stand-alone files small and have the demo work on most machines, it’s best to downsample the 64k cifti file to the 10k free-surfer mesh. This also saves bandwith and helps the visualization to load faster.
-
The Nilearn surface plotting function is designed to deal with hemispheres separately.
Converting to Gifti
The first step is to separate the input file into two hemispheres for separate processing. To do this we will use -cifti-separate
. The command will look like:
wb_command -cifti-separate $inputF COLUMN \
-metric CORTEX_LEFT inputLeft.dscalar.nii \
-metric CORTEX_RIGHT inputRight.dscalar.nii
We are now ready to downsample! Fortunately there is a nice HCP document (here) that covers how to convert from a cifti file to a gifti file. I summarize the key part here. We can downsample using the following workbench command wb_command -metric-resample
. The documentation for this functions recommends using using the ADAPT_BARY_AREA
option which will give us a command that looks like the following:
wb_command -metric-resample <metric-in> <current-sphere> <new-sphere> \
ADAP_BARY_AREA <metric-out> -area-metrics <current-area> <new-area>
This command will have to be run separately for the two hemispheres. If we assign the input file to the variable $inputF
and the needed files for the left hemisphere are:
Argument | File | Description |
---|---|---|
<metric in> |
$inputF |
Metric file to resample |
<current-sphere> |
fs_LR-deformed_to-fsaverage.L.sphere.32k_fs_LR.surf.gii | A sphere surface with the mesh that the metric is currently on |
<new-sphere> |
fsaverage5_std_sphere.L.10k_fsavg_L.surf.gii | A sphere surface that is in register with <current-sphere> and has the desired output mesh |
<current-area> |
fs_LR.L.midthickness_va_avg.32k_fs_LR.shape.gii | A metric file with vertex areas for <current-sphere> mesh |
<new-area> |
fsaverage5.L.midthickness_va_avg.10k_fsavg_L.shape.gii | A metric file with vertex areas for <new-sphere> mesh |
The relevant files can be found in a zip file realeased by WashU (here) Assuming that all these files are placed in a directory called refDir
, the final command looks like:
wb_command -metric-resample \
inputLeft.func.gii \
${refDir}/fs_LR-deformed_to-fsaverage.L.sphere.32k_fs_LR.surf.gii \
${refDir}/fsaverage5_std_sphere.L.10k_fsavg_L.surf.gii \
ADAP_BARY_AREA left.func.gii -area-metrics \
${refDir}/fs_LR.L.midthickness_va_avg.32k_fs_LR.shape.gii \
${refDir}/fsaverage5.L.midthickness_va_avg.10k_fsavg_L.shape.gii
Creating Visualization
We are now in the fun part. One of the reasons for converting to the freesurfer5 10k mesh is because the Nilearn library has a buit-in helper function for retrieving the surface mesh and sulcal depth for this surface. The following python code can then be used to save a stand-alone view of a hemisphere!
import numpy as np
import nilearn as nil
from nilearn import plotting
left = nil.surface.load_surf_data('left.func.gii')
right = nil.surface.load_surf_data('right.func.gii')
bg = nil.datasets.fetch_surf_fsaverage5(mesh='fsaverage5')
img = plotting.view_surf(bg['pial_left'],left,bg_map=bg['sulc_left'])
img.save_as_html('leftHem.html')
Finally, the last step in this process we will clean up all the files generated in this process
rm inputLeft.dscalar.nii inputRight.dscalar.nii left.func.gii right.func.gii
For convience, we can combine all of these steps into one single python script. This script will take in a .dscalar.nii
file and output two html files in the directory where it was called.
I recommend reading the options
The main one being choosing whether the input file is a mask or not
If you have the RCC mounted, just use the following
echo "alias nilPlot='python /group/jbinder/work/smazurchuk/nil_surfPlot.py'" >> ~/.bashrc
Notes:
- You cannot set alpha values on the surface plot. I tried many times.