Source code for neuromaps.plotting

# -*- coding: utf-8 -*-
"""Functionality for plotting."""

import matplotlib
from matplotlib import colors as mcolors, pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # noqa
from nilearn.plotting import plot_surf
import numpy as np

from neuromaps.datasets import ALIAS, fetch_atlas
from neuromaps.images import load_gifti
from neuromaps.transforms import _check_hemi

HEMI = dict(L='left', R='right')

matplotlib.colormaps.register(
    mcolors.LinearSegmentedColormap.from_list(
        'caret_blueorange', [
            '#00d2ff', '#009eff', '#006cfe', '#0043fe',
            '#fd4604', '#fe6b01', '#ffd100', '#ffff04'
            ]),
    name="caret_blueorange"
)


[docs]def plot_surf_template(data, template, density, surf='inflated', hemi=None, data_dir=None, mask_medial=True, **kwargs): """ Plot `data` on `template` surface. Parameters ---------- data : str or os.PathLike or tuple-of-str Path to data file(s) to be plotted. If tuple, assumes (left, right) hemisphere. template : {'civet', 'fsaverage', 'fsLR'} Template on which `data` is defined density : str Resolution of template surf : str, optional Surface on which `data` should be plotted. Must be valid for specified `space`. Default: 'inflated' hemi : {'L', 'R'}, optional If `data` is not a tuple, which hemisphere it should be plotted on. Default: None mask_medial : bool, optional Whether to mask vertices along the medial wall. Default: True kwargs : key-value pairs Passed directly to `nilearn.plotting.plot_surf` Returns ------- fig : matplotlib.Figure instance Plotted figure """ atlas = fetch_atlas(template, density, data_dir=data_dir, verbose=0) template = ALIAS.get(template, template) if template == 'MNI152': raise ValueError('Cannot plot MNI152 on the surface. Try performing ' 'registration fusion to project data to the surface ' 'and plotting the projection instead.') surf, medial = atlas[surf], atlas['medial'] opts = dict(alpha=1.0, threshold=np.spacing(1)) opts.update(**kwargs) if kwargs.get('bg_map') is not None and kwargs.get('alpha') is None: opts['alpha'] = 'auto' data, hemispheres = zip(*_check_hemi(data, hemi)) n_surf = len(data) fig, axes = plt.subplots(n_surf, 2, subplot_kw={'projection': '3d'}) axes = (axes,) if n_surf == 1 else axes.T for row, hemi, img in zip(axes, hemispheres, data): geom = load_gifti(getattr(surf, hemi)).agg_data() img = load_gifti(img).agg_data().astype('float32') # set medial wall to NaN; this will avoid it being plotted if mask_medial: med = load_gifti(getattr(medial, hemi)).agg_data().astype(bool) img[np.logical_not(med)] = np.nan for ax, view in zip(row, ['lateral', 'medial']): ax.disable_mouse_rotation() plot_surf(geom, img, hemi=HEMI[hemi], axes=ax, view=view, **opts) poly = ax.collections[0] try: poly.set_facecolors( _fix_facecolors(ax, poly._original_facecolor, *geom, view, hemi) ) except AttributeError: pass if not opts.get('colorbar', False): fig.tight_layout() if n_surf == 1: fig.subplots_adjust(wspace=-0.1) else: fig.subplots_adjust(wspace=-0.4, hspace=-0.15) return fig
def _fix_facecolors(ax, facecolors, vertices, faces, view, hemi): """ Update `facecolors` to reflect shading of mesh geometry. Parameters ---------- ax : plt.Axes3dSubplot Axis instance facecolors : (F,) array_like Original facecolors of plot vertices : (V, 3) Vertices of surface mesh faces : (F, 3) Triangles of surface mesh view : {'lateral', 'medial'} Plotted view of brain Returns ------- colors : (F,) array_like Updated facecolors with appropriate shading """ hemi_view = {'R': {'lateral': 'medial', 'medial': 'lateral'}} views = { 'lateral': plt.cm.colors.LightSource(azdeg=225, altdeg=19.4712), 'medial': plt.cm.colors.LightSource(azdeg=45, altdeg=19.4712) } # reverse medial / lateral views if plotting right hemisphere view = hemi_view.get(hemi, {}).get(view, view) # re-shade colors normals = ax._generate_normals(vertices[faces]) colors = ax._shade_colors(np.asarray(facecolors), normals, views[view]) return colors