I like pysurfer, but at this point in time mayavi is still painful to install and unreliable. So for a while now I have been in need of a fairly basic, but still reasonably pretty matplotlib-based brain surface plotting function. I've been using a few basic snippets for this for a while, but following some inspiration from MMW, I've written a more complete one and added it to tvb-library.
The following are some extended usage notes and examples:
Notebook setup¶
Enable matlab in the notebook
Define some variables
# define system-specific filepaths etc
%run ~/set_localenv_vars.py
nb_name = 'mpl_surface_viz'
# this is where I look for things
outdir = '%s/notebooks/%s' %(le['data_dir'],nb_name)
# this is where things actually live
outdir_loc = '%s/%s' %('/mnt/titania-hecuba/mcintosh_lab/john/Data/notebooks', nb_name)
import os;
if not os.path.isdir(outdir_loc): os.makedirs(outdir_loc)
if not os.path.isdir(outdir): os.system('ln -s %s %s' %(outdir_loc,outdir))
# stuff for workdocs-cloudfiles
aws_key = 'drowssaperucesyreva'
aws_secret = '?teytidettopsuoyevah'
# Analysis stuff
em_dir = le['code_dir'] + '/libraries_of_mine/github/eigenmodes'
tvb_lib_dir = le['code_dir'] + '/libraries_of_mine/github/tvb-library'
tvb_dat_dir = le['code_dir'] + '/libraries_of_mine/github/tvb-data'
Importage
# Generic stuff
import os,sys,inspect
from scipy.io import loadmat,savemat
# Visualization stuff
%matplotlib inline
from matplotlib import cm,pyplot as plt
from IPython.display import Image,display as d
# Neuroimaging stuff
import nibabel as nib
# TVB stuff
nbso,nbse = sys.stdout,sys.stderr # hack part 1/2 to keep output printing properly
sys.path.append(tvb_lib_dir)
sys.path.append(tvb_dat_dir)
from tvb.simulator.lab import *
sys.stdout,sys.stderr = nbso,nbse # ...hack part 2/2
from tvb.datatypes.surfaces import Surface
from tvb.simulator.plot.tools import (plot_surface_mpl,plot_surface_mpl_mv,
get_rotation_matrix,get_combined_rotation_matrix)
# Workdocs-cloudfiles stuff
sys.path.append(le['ipynb_workdocs_dir'])
from new_utils import nb_fig,cloudfiles_nb
Initialize aws api and workdocs-cloudfiles folder
cnb = cloudfiles_nb('aws', [aws_key,aws_secret])
cnb.initialize_folder(nb_name)
Calico document tools
%%javascript
IPython.load_extensions('calico-spell-check', 'calico-document-tools',
'calico-cell-tools');
Go to output folder
os.chdir(outdir)
Ok, let's get cracking!
Plotting Function¶
First for completeness, let's show the full code of the main plotting functions:
print inspect.getsource(plot_surface_mpl)
print inspect.getsource(plot_surface_mpl_mv)
print inspect.getsource(get_rotation_matrix)
print inspect.getsource(get_combined_rotation_matrix)
Plotting generic brain surfaces¶
The functions work pretty well for generic surfaces such as those produced by freesurfer.
Load data
lho_file = '/software/freesurfer/subjects/fsaverage/surf/lh.orig'
lho_vtx,lho_tri = nib.freesurfer.read_geometry(lho_file)
rho_file = '/software/freesurfer/subjects/fsaverage/surf/rh.orig'
rho_vtx,rho_tri = nib.freesurfer.read_geometry(rho_file)
Simple example
# <!-- collapse=False-->
f = '%s/simple_fs_example.png' %outdir
# make figure
fig, ax = plt.subplots(nrows=2,ncols=2,figsize=(8,6))
plot_surface_mpl(lho_vtx,lho_tri,view='lh_lat',reorient='fs',title='lh lat',ax=ax[0,0])
plot_surface_mpl(lho_vtx,lho_tri,view='lh_med',reorient='fs',title='lh med',ax=ax[1,0])
plot_surface_mpl(rho_vtx,rho_tri,view='rh_lat',reorient='fs',title='rh lat',ax=ax[0,1])
plot_surface_mpl(rho_vtx,rho_tri,view='rh_med',reorient='fs',title='rh med',ax=ax[1,1])
plt.tight_layout()
plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'Simple freesurfer surface plotting example'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)
A few notes on plotting freesurfer:
- In general these are denser than the surface used in tvb, so the renders take a little longer to produce, and if the vertex lines are shown on the figures, they will look somewhat darker because denser surfaces have more vertex lines to plot.
TVB Surfaces¶
Load data
Most of the tvb default connectivities can generally be loaded without having to specify full file paths.
Going to load some of these by specifying the filenames anyway demonstrate the process:
ctx_file = tvb_dat_dir + '/tvb_data/surfaceData/cortex_16384.zip'
rm_file = tvb_dat_dir + '/tvb_data/regionMapping/regionMapping_16k_76.bz2'
conn_file = tvb_dat_dir + '/tvb_data/connectivity/connectivity_76.zip'
ctx = cortex.Cortex.from_file(source_file = ctx_file,
region_mapping_file =rm_file)
vtx,tri,rm = ctx.vertices,ctx.triangles,ctx.region_mapping
conn = connectivity.Connectivity.from_file(conn_file); conn.configure()
isrh_reg = conn.is_right_hemisphere(range(conn.number_of_regions))
isrh_vtx = np.array([isrh_reg[r] for r in rm])
dat = conn.tract_lengths[:,0] # 'dat' is one column of the region-based tract lengths
# connectivity matrix. The corresponding region is
# right auditory cortex ('rA1')
# <!-- collapse=False-->
f = '%s/tvb_rA1_tract_lengths_multiview_1.png' %outdir
# make figure
plot_surface_mpl_mv(vtx=vtx,tri=tri,rm=rm,data=dat,
hemi=isrh_vtx,title=u'rA1 \ntract length')
plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'TVB default data rA1 tract lengths multiview example 1'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)
# <!-- collapse=False-->
f = '%s/tvb_rA1_tract_lengths_multiview_2.png' %outdir
# make figure
plot_surface_mpl_mv(vtx=vtx,tri=tri,rm=rm,data=dat,
hemi=isrh_vtx,title=u'rA1 \ntract length',
shade_kwargs = {'edgecolors': 'white',
'linewidth': 0.1},
figsize=(20,20))
plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'TVB default data rA1 tract lengths multiview example 2'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)
# <!-- collapse=False-->
f = '%s/tvb_rA1_tract_lengths_multiview_3.png' %outdir
# make figure
plot_surface_mpl_mv(vtx=vtx,tri=tri,rm=rm,data=dat,
hemi=isrh_vtx,title=u'rA1 \ntract length',
shade_kwargs = {'shading': 'gouraud',
'cmap': 'rainbow'})
plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'TVB default data rA1 tract lengths multiview example 3'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)
# <!-- collapse=False-->
f = '%s/tvb_rA1_tract_lengths_multiview_4.png' %outdir
# make figure
plot_surface_mpl_mv(vtx=vtx,tri=tri,rm=rm,data=dat,
hemi=isrh_vtx,title=u'ghostly!',
shade_kwargs = {'shading': 'flat',
'cmap': 'rainbow',
'edgecolors': 'white',
'linewidth': 0.3})
plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'TVB default data rA1 tract lengths multiview example 4'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)
Some other rotations
# <!-- collapse=False-->
f = '%s/tvb_rA1_tract_lengths_other_rotations.png' %outdir
# make figure
fig, ax= plt.subplots(ncols=3,nrows=2, figsize=(12,6))
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,view='inferior',ax=ax[0][0],title='inferior')
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,view='posterior',ax=ax[0][1], title='posterior')
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,view='anterior',ax=ax[0][2], title='anterior')
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,
view=[(0,-90),(1,55)],ax=ax[1][0],title='lh angle')
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,
view=[(0,-90),(1,-25)],ax=ax[1][1],title='rh angle')
plot_surface_mpl(vtx=vtx,tri=tri,rm=rm,data=dat,
view=[(0,-110),(1,-90)],ax=ax[1][2], title='oops')
plt.tight_layout(); plt.savefig(f, bbox_inches='tight')
plt.close()
# upload to cloud and embed link in notebook
cap = ''; label = 'TVB default data rA1 tract lengths - other rotations'
im = nb_fig(f,label,cap,cnb,show_fignum=False,size=(800,500))
d(im)