Plotting atlas with statistical map overlay on cortical surface

Hi all,
I’m having difficulty trying to plot an atlas as well as a statistical map onto the same cortical surface with nilearn.
I want to plot the Yeo functional atlas onto the cortical surface, and then overlay it with my cluster results. I can plot them separately, but I want to overlay them on 1 brain.
Does anyone have ideas about how to do this?
My code:
from nilearn import plotting, datasets, surface,

Load cortical surface mesh

fsaverage = datasets.fetch_surf_fsaverage()
#load yeo atlas
atlas_yeo_2011 = datasets.fetch_atlas_yeo_2011()
atlas_yeo = atlas_yeo_2011.thick_7
#project yeo atlas onto fsaverage
texture = surface.vol_to_surf(atlas_yeo, fsaverage[‘pial_right’],
inner_mesh=fsaverage[‘white_right’],
interpolation=‘nearest’,
n_samples=1,radius=0.0
)
#plot yeo atlas
fig=plotting.plot_surf_roi(fsaverage.pial_right, roi_map=texture, hemi=‘right’,
darkness=0.5,cmap=‘Set3’,
bg_on_data=True,
bg_map=fsaverage.sulc_right
)

#load my own data
map1 = ‘my_clusters.nii.gz’
mask1 = surface.vol_to_surf(map1, fsaverage[‘pial_right’],
inner_mesh=fsaverage[‘white_right’])
#plot my own data - using figure=fig to plot over the atlas
#plot maps
plotting.plot_surf_stat_map(fsaverage.pial_right, stat_map=mask1, hemi=‘right’,
threshold=0.5,
alpha=0.1,
figure=fig,
)
plotting.show()
The output only shows my cluster:
clust

1 Like

Do you have to stick to nilearn? If not I think HCP workbench can do this overlay quite easily: Connectome - Using Connectome Workbench

I’m not sure if it supports fsaverage space, if not, you might need to re-run your analysis with Yeo’s atlas under HCP fsLR surface space (which is available in yeo’s lab github repo). If your data is of small amount it can be one way to try

you could use plotting.plot_surf_contours as shown in this example

Thanks neo! Unfortunately yes. I can create this plot no worries in R (my preferred plotting tool!). All of my other figures are using nilearn.

Thanks jeromedockes. I’ve just managed to do this but I was hoping to have the contours ‘filled in’ as it were. But this is a good compromise.

You might also consider Surfice. The image below is from Scripting/Templates/Outline, but you can remove the outline effect if you wish. The Surfice Python script is

import gl
gl.resetdefaults()
gl.meshload('lh.pial')
gl.overlayload('boggle.lh.annot')
#make contour at border of atlas
gl.contour(0)
#reduce atlas salience:
gl.atlassaturationalpha(0.2, 0.5)
gl.overlayload('motor_4t95vol.nii.gz')
gl.overlayminmax(gl.overlaycount(),-2,-3)
#hide statistical map:
gl.overlayopacity(gl.overlaycount(),0)
#draw outline of statistical threshold
gl.contour(gl.overlaycount())

When calling the “plot_surf_stat_map” function a new figure is created by default see plot_surf_stat_map documentation .
You can override this by specifying the same figure in plot_surf_roi and in plot_surf_stat_map (adding figure = f or something similar).

Thanks Haya! That’s why I specified 'figure = ’ for plot_surf_roi and ‘figure = fig’ in the plot_surf_stat_map command. Even when I include ‘figure = fig’ within the plot_surf_roi command it doesn’t work.

Thanks neurolabusc but I’m really interested in using nilearn if I can. Thanks for the tip!

Sorry did not see it in the last call line… Have you tried specifying the same “axes” instead of figure? (maybe defining a figure before calling both functions something like fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10,10), dpi=400) then using the same axes in both plotting functions).

Success! Thanks so much @haya for your suggestions. Looking at the issue here, I needed to define the axis and then specify the surface subplot kwarg:
fig, axes = plt.subplots(nrows=1, ncols=1, subplot_kw={“projection”: “3d”})
My code:
from nilearn import datasets, plotting, surface
import matplotlib.pyplot as plt

#Load cortical surface mesh
fsaverage = datasets.fetch_surf_fsaverage()
#load yeo atlas
atlas_yeo_2011 = datasets.fetch_atlas_yeo_2011()
atlas_yeo = atlas_yeo_2011.thick_7
#project yeo atlas onto fsaverage
texture = surface.vol_to_surf(atlas_yeo, fsaverage[‘pial_right’],
inner_mesh=fsaverage[‘white_right’],
interpolation=‘nearest’,
n_samples=1, radius=0.0)
fig, axes = plt.subplots(nrows=1, ncols=1, subplot_kw={“projection”: “3d”})
#plot yeo atlas
plotting.plot_surf_roi(fsaverage.pial_right, roi_map=texture, hemi=‘right’,
darkness=0.3, cmap=‘Set3’,
bg_on_data=True, bg_map=fsaverage.sulc_right, axes=axes)

#load my own data
map1 = ‘my_cluster.nii.gz’
mask1 = surface.vol_to_surf(map1, fsaverage[‘pial_right’],
inner_mesh=fsaverage[‘white_right’])
#plot maps
plotting.plot_surf_stat_map(fsaverage.pial_right, stat_map=mask1, hemi=‘right’,
darkness=0.1, alpha=0.001, axes=axes)
clust2