Skip to content

SurfacePlot: Basics

This tutorial builds a cortical map with electrode contacts, then shows how to display atlas labels on the same surfaces.

1. Fetch matching surfaces and shading

Fetch public fsLR 32k inflated surfaces for the visible brain and sulcal depth from the same template and density for its shading. More built-in templates and atlases are listed in Datasets.

import numpy as np

from anatplot import SurfacePlot, datasets

surfaces = datasets.fetch_surfaces("fsLR", surface="inflated", density="32k")
sulc = datasets.fetch_sulcal_depth("fsLR", density="32k")

2. Add the map

Start with the Neurosynth association map for the “default mode” term, using sulcal shading to make the cortical folds visible.

left_map, right_map = datasets.fetch_dmn_map_fslr32k()
# Mask this map's zero background to leave the shading underneath visible.
association = {
    "left": np.ma.masked_equal(left_map, 0),
    "right": np.ma.masked_equal(right_map, 0),
}
plot = SurfacePlot(
    **surfaces,
    views=["lateral", "medial"],
    window_size=(1000, 600),
    zoom=1.5,
)
plot.add_layer(sulc, cmap="gray")  # Sulcal shading beneath the map.
# Give the map its own labelled colorbar.
plot.add_layer(association, cmap="YlOrRd", cbar=True, cbar_label="Association Z")
fig = plot.to_figure(figsize=(10, 7))
Association map with sulcal shading on lateral and medial fsLR surfaces

3. Add contacts to this map

Next, add four contacts to the map, using color to distinguish the two pairs.

# Coordinates in the template's RAS millimetre frame.
xyz = [
    [-64, -13, 23],
    [-60, -42, 37],
    [66, -14, 22],
    [64, -37, 32],
]
plot.add_contacts(
    xyz,
    radius=4.0,
    color=["royalblue", "gold", "royalblue", "gold"],
)
fig = plot.to_figure(figsize=(10, 7))
Association map and four contacts on lateral and medial fsLR surfaces

Contacts on inflated surfaces

Contacts must share the original pial or midthickness surface's RAS millimetre frame. The projection_surface pair returned by fetch_surfaces() lets SurfacePlot locate contacts on that anatomy and transfer them to the inflated display. Projection removes depth and skips contacts farther than 6 mm by default; see contact projection.

4. Save the completed figure

Save the completed figure, then close the scene to release graphics resources.

fig.savefig("cortex.png", dpi=300)
plot.close()

For 3D viewing and HTML export, see Save and display. To substitute your own maps or contacts, see Use your own data.

Alternative: show atlas labels

To show regions instead of a continuous map, use the Schaefer 100-region, seven-network atlas on the same fsLR 32k surfaces. add_parcellation() assigns colors to labels without creating a colorbar.

parcellation = datasets.fetch_parcellation("schaefer")
# Hide the atlas background while preserving the original parcel IDs.
labels = {
    "left": np.ma.masked_equal(parcellation["left"], 0),
    "right": np.ma.masked_equal(parcellation["right"], 0),
}
# A with block releases the scene's graphics resources when it ends.
with SurfacePlot(
    **surfaces,
    views=["lateral", "medial"],
    window_size=(1000, 600),
    zoom=1.5,
) as atlas_plot:
    atlas_plot.add_layer(sulc, cmap="gray")
    atlas_plot.add_parcellation(labels)
    atlas_fig = atlas_plot.to_figure(figsize=(10, 7))
Schaefer atlas labels on both fsLR hemispheres

Highlight left-hemisphere parcels 17 and 18 while leaving the rest of the cortex visible.

parcellation = datasets.fetch_parcellation("schaefer")
left_labels = parcellation["left"]
# Keep the selected IDs and hide all other parcels with NaN.
selected = np.where(np.isin(left_labels, [17, 18]), left_labels, np.nan)
with SurfacePlot(
    **surfaces,
    views=["lateral", "medial"],
    window_size=(1000, 600),
    zoom=1.5,
) as atlas_plot:
    atlas_plot.add_layer(sulc, cmap="gray")
    atlas_plot.add_parcellation(
        {"left": selected},
        cmap={17: "crimson", 18: "gold"},
    )
    atlas_fig = atlas_plot.to_figure(figsize=(10, 7))
Two left-hemisphere Schaefer parcels

Parcel names are available from the atlas label table, for example parcellation["labels"]["left"][17]["name"].

Brain size and spacing

If the brains in either recipe need more or less room, adjust zoom. Within one SurfacePlot, layout arranges the views; there is no separate gap setting.

Change Effect
Increase zoom Larger brains, smaller visible gaps
Decrease zoom Smaller brains, larger visible gaps

Panel positions stay fixed. Excessive zoom can crop a brain, and the window_size width-to-height ratio also affects space available per view.