Plotting
Choose a plot class for the data you want to display. Each class keeps a scene open while you add data; the methods below provide static figures and 3D views.
SurfacePlot
SurfacePlot(
*,
left: PolyData | str | Path | None = None,
right: PolyData | str | Path | None = None,
projection_surface: tuple[
PolyData | str | Path | None,
PolyData | str | Path | None,
]
| None = None,
views: str | Sequence[str] = "lateral",
layout: Literal["grid", "row", "column"] = "grid",
zoom: float = 1.0,
color: str = "#979797",
opacity: float = 1.0,
window_size: tuple[int, int] = (1000, 600),
background: str = "white",
)
Bases: _BasePlot
Display cortical hemispheres in named anatomical views.
Initialize hemisphere panels and their shared camera scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
PolyData | str | Path | None
|
Hemisphere meshes or surface files accepted by |
None
|
right
|
PolyData | str | Path | None
|
Hemisphere meshes or surface files accepted by |
None
|
projection_surface
|
tuple | None
|
Anatomical localization surfaces in (left, right) order, each a PolyData or local surface path; use None for an absent hemisphere. Supplied and displayed hemispheres must match and have identical ordered triangles and corresponding vertices. Meshes are copied. Use original pial or midthickness geometry when displaying inflated surfaces. None localizes on the display meshes themselves; it cannot recover anatomical distances from a deformed mesh. This pair is shared by every projected add_contacts call. It is unused when project=False. Supplied meshes are still loaded and validated at construction. Face winding must point outward; names and vertex counts alone cannot verify alignment. |
None
|
views
|
str | Sequence[str]
|
Anatomical views in display order: lateral, medial, dorsal, ventral, anterior, posterior. Lateral/medial directions depend on hemisphere. All views use RAS axes. Dorsal/ventral views put anterior at the top; other views put superior at the top. |
"lateral"
|
layout
|
str
|
"grid": rows are views and columns are hemispheres (left then right). "row" or "column": flatten panels in hemisphere-first order, retaining the requested view order within each hemisphere. One hemisphere is supported with the same rules. |
"grid"
|
zoom
|
float
|
Positive magnification relative to the common fitted parallel scale. Values above one enlarge the surfaces and may crop them. |
1.0
|
color
|
str
|
Uniform surface color understood by PyVista. The neutral gray matches the midpoint of surfplot's default Greys_r backdrop. |
"#979797"
|
opacity
|
float
|
Surface opacity from 0 (transparent) to 1 (opaque). |
1.0
|
window_size
|
tuple[int, int]
|
Total window width and height in pixels, including all panels. |
(1000, 600)
|
background
|
str
|
PyVista background color. |
"white"
|
Returns:
| Type | Description |
|---|---|
None
|
Initializes this plot instance and its persistent PyVista scene. |
Attributes:
| Name | Type | Description |
|---|---|---|
plotter |
Plotter
|
Persistent renderer. Use |
Notes
Starts with the requested cameras and a shared parallel scale. Camera changes
affect display only. Use add_layer for vertex data. Contacts default to
nearest-surface projection followed by display mapping. Localization uses
projection_surface when supplied, otherwise the display meshes themselves.
Surface materials follow surfplot/BrainSpace: ambient 0.05, diffuse 1.0,
specular 0.1, and specular power 1.0, with smooth shading and one white
camera headlight per panel. These defaults do not depend on PyVista's
theme. Materials and lights remain adjustable through plotter.
add_layer
add_layer(
data: ArrayLike | dict[str, ArrayLike],
*,
cmap: str | Colormap = "viridis",
color_range: tuple[float, float] | None = None,
cbar: bool = False,
cbar_label: str = "",
cbar_kws: dict[str, Any] | None = None,
) -> None
Color surface vertices, covering earlier layers where data are present.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ArrayLike | dict[str, ArrayLike]
|
One-dimensional vertex values, in surface vertex order. An array contains all displayed hemispheres, left then right. A dictionary with "left" and/or "right" keys can update individual hemispheres. NaN and masked values retain the previous color. Zero is a normal value; infinity is rejected. Inputs are copied, never resampled. |
required |
cmap
|
str | Colormap
|
A PyVista-supported colormap name or Matplotlib colormap. Without color_range, finite values across both supplied hemispheres set the range and constant data use the middle color. Color alpha blends with the previous layer; overall surface opacity is unchanged. |
"viridis"
|
color_range
|
tuple[float, float] | None
|
Finite increasing (minimum, maximum) for continuous colors. Values outside this range use endpoint colors. None uses finite values across both supplied hemispheres; constant data use the middle color. Reuse a range to compare separate plots. |
None
|
cbar
|
bool
|
Include this layer's own colorbar in subsequent Figures. Each call adds a separate bar; False leaves earlier requests intact. Bars do not appear in view() or HTML. Masked and NaN values are excluded from automatic ranges. |
False
|
cbar_label
|
str
|
Colorbar title, such as the statistic name or units. |
""
|
cbar_kws
|
dict | None
|
Matplotlib Figure.colorbar options for this layer only, such as ticks, format, location, orientation, fraction, pad, or shrink. Requires cbar=True. Options are copied when the layer is added. Default bar length uses shrink=0.5; override it in this dictionary. Bars default to horizontal; location can select another side and its native orientation. The last layer's bar is outermost when bars share a side. Reuse a dictionary for a common style. Mapping, target axes, and label are controlled by anatplot: use cmap, color_range, and cbar_label rather than the colorbar keys mappable, cmap, norm, ax, cax, or label. |
None
|
Returns:
| Type | Description |
|---|---|
None
|
Updates surface colors in place and records this layer's optional colorbar. Geometry, cameras, and existing Figures are unchanged. |
Notes
Colors update every view without changing cameras or adding overlapping meshes. Repeated calls composite colors in order; layers cannot yet be removed or edited independently. The colorbar shows the colormap before alpha blending with earlier layers or shading by scene lights. Use add_parcellation for discrete labels and label-to-color dictionaries. Vertex colors can blend across triangle interiors. Vertex counts alone cannot establish correspondence: templates and vertex ordering must match. File loading and atlas lookup tables remain upstream operations.
add_parcellation
add_parcellation(
data: ArrayLike | dict[str, ArrayLike],
*,
cmap: str | Colormap | dict[int, str] = "tab20",
) -> None
Assign discrete colors to atlas labels, independent of label spacing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ArrayLike | dict[str, ArrayLike]
|
One integer label per surface vertex, in the same ordering as
|
required |
cmap
|
str | Colormap | dict[int, str]
|
Assign successive palette entries to sorted unique labels across both supplied hemispheres. Colors repeat when the palette is exhausted; the same ID has the same color in both hemispheres. A dictionary specifies exact colors for every unmasked label. |
"tab20"
|
Returns:
| Type | Description |
|---|---|
None
|
Updates the existing vertex colors without adding meshes or a colorbar. Geometry, cameras, and source labels are unchanged. |
Notes
Palette assignments depend on the labels supplied in this call. Use a
fixed dictionary to preserve colors across different label subsets.
Colors composite like add_layer and can blend within triangles;
exact parcel outlines and colorbars are not provided.
add_contacts
add_contacts(
xyz: ArrayLike,
*,
hemisphere: Literal["left", "right"] | None = None,
project: bool = True,
max_distance: float | None = 6.0,
radius: float = 1.0,
color: str | Sequence[str] = "crimson",
lighting: bool = True,
) -> list[Actor]
Add projected or original-coordinate contacts to hemisphere views.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xyz
|
ArrayLike
|
Finite coordinates of shape (n_contacts, 3), with at least one row. Columns are R, A, S in millimetres, aligned with the localization mesh (or display mesh when project=False). Input coordinates are copied; row order is preserved. |
required |
hemisphere
|
str | None
|
None assigns each contact to the closest available localization surface, or display surface when project=False. Exact distance ties select left. A single displayed hemisphere receives all contacts. "left" or "right" overrides assignment for every row. No assignment is inferred from the sign of X. |
None
|
project
|
bool
|
Project to the nearest point on the selected localization mesh, using the constructor's projection_surface when supplied, otherwise the display mesh. Map its triangle and barycentric position to the display mesh. Move the sphere center outward along the display face normal by radius + 0.05 mm. False retains supplied positions without offset. |
True
|
max_distance
|
float | None
|
Maximum distance in millimetres from an input contact to its selected localization surface. Contacts farther away are excluded with one summary warning; equality is included. None disables the limit. Ignored when project=False. Distance is measured before display mapping and sphere offset. |
6.0
|
radius
|
float
|
Positive sphere radius in millimetres, shared by this call's contacts. |
1.0
|
color
|
str | Sequence[str]
|
One named or hex color, or one color string per contact in row order. Spheres are opaque and participate in normal depth ordering. |
"crimson"
|
lighting
|
bool
|
Shade sphere colors using scene lights and highlights. False uses unlit colors. Geometry, radius, projection, and depth ordering are identical for both settings. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
actors |
list[Actor]
|
Actors ordered by hemisphere (left then right), then requested view. Only hemispheres receiving contacts create actors. Row and color order are preserved within each group. Repeated calls retain actors. An empty list is returned when every contact exceeds the distance limit. |
Notes
Cameras and zoom are preserved. Automatic assignment chooses a display hemisphere, not verified anatomical membership. Projection loses depth and does not establish cortical membership, including for deep contacts. Contacts within the projection distance limit are added, but overlap, far-side occlusion and view clipping can still hide them. The limit is a display selection, not a measure of localization accuracy. Changing radius also changes the outward display offset. No registration or ROI filtering is performed. Use project=False for original or externally prepared display coordinates.
ROIPlot
ROIPlot(
image: Nifti1Image | Nifti2Image | str | Path,
*,
window_size: tuple[int, int] = (900, 650),
background: str = "white",
)
Bases: _ContactPlot
Display selected region boundaries from a discrete NIfTI image.
Initialize an empty region scene with an anterior-superior camera.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
Nifti1Image | Nifti2Image | str | Path
|
Binary mask or discrete label image accepted by |
required |
window_size
|
tuple[int, int]
|
Window width and height in pixels. |
(900, 650)
|
background
|
str
|
PyVista background color. |
"white"
|
Returns:
| Type | Description |
|---|---|
None
|
Initializes this plot instance and its persistent PyVista scene. |
Attributes:
| Name | Type | Description |
|---|---|---|
plotter |
Plotter
|
Persistent scene. Region actors and camera controls are native PyVista. |
Notes
The initial parallel view looks from anterior and superior toward the regions, with superior as view-up. In RAS this uses camera offset (0, 1, 1) and view-up (0, 0, 1); anatomical left appears on the viewer's right. The first region or contact batch fits the camera. Later additions preserve framing; use plotter.reset_camera() to include all actors again. For reproducible figures, set PyVista camera parameters in Python before to_figure(). Use view() to explore the anatomy.
add_roi
add_roi(
labels: ArrayLike,
*,
color: str = "#D98C70",
opacity: float = 0.1,
smoothing: bool = True,
) -> Actor
Add the outer boundary of selected labels, preserving existing framing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
labels
|
Sequence[int]
|
Positive IDs present in the image, merged into one display region. For a binary mask, use [1]. Separate calls retain separate actors. |
required |
color
|
str
|
Uniform PyVista surface color. |
"#D98C70"
|
opacity
|
float
|
Surface opacity from 0 to 1. The default is a translucent anatomical background for displaying internal structures. |
0.1
|
smoothing
|
bool
|
Enable SurfaceNets smoothing; see |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
actor |
Actor
|
Added surface actor. Its properties can be adjusted with PyVista. |
Notes
Original voxel labels and the image affine are never modified. The first addition to an empty scene fits the camera. Later additions preserve camera position, direction, projection, and zoom; only the depth clipping range is updated. New regions outside the current frame may remain offscreen. Use plotter.reset_camera() to fit all actors when needed.
add_contacts
add_contacts(
xyz: ArrayLike,
*,
radius: float = 1.0,
color: str | Sequence[str] = "crimson",
lighting: bool = True,
) -> Actor
Add opaque contact spheres at their supplied coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xyz
|
ArrayLike
|
Finite coordinates with shape (n_contacts, 3), with at least one contact. Columns are R, A, S in millimetres, in the same coordinate frame as the displayed anatomy. Input order is preserved. |
required |
radius
|
float
|
Positive finite sphere radius in millimetres, shared by all contacts. This is a display size, not an estimate of electrode dimensions. |
1.0
|
color
|
str | Sequence[str]
|
One named or hex color for all contacts, or exactly one color string per contact in xyz order. Examples: "crimson" or ["red", "#3366CC"]. Colors are interpreted by PyVista; spheres are opaque. |
"crimson"
|
lighting
|
bool
|
Shade sphere colors using scene lights and highlights. False uses unlit colors. Geometry, radius, coordinates, and depth ordering are identical for both settings. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
actor |
Actor
|
One actor containing all contact spheres added by this call. Subsequent calls add separate actors without replacing earlier ones. |
Notes
Coordinates are copied and never projected, registered, filtered by ROI membership, or moved to avoid occlusion. Contacts outside an ROI remain visible at their supplied locations. Spheres use real mesh geometry so their physical size and colors are retained in PNG and HTML exports. The first contact batch in an empty scene fits the camera. Later additions preserve camera position, direction, projection, and zoom; only the depth clipping range is updated. Contacts outside the current frame may remain offscreen. Use plotter.reset_camera() to fit all actors when needed. Surface transparency affects visibility; contacts obey normal depth order.
VolumePlot
VolumePlot(
*,
left: PolyData | str | Path | None = None,
right: PolyData | str | Path | None = None,
color: str = "#D8D8D8",
opacity: float = 0.1,
window_size: tuple[int, int] = (900, 650),
background: str = "white",
)
Bases: _ContactPlot
Display a translucent whole-brain surface background in one scene.
Initialize the whole-brain background and its dorsal camera.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
PolyData | str | Path | None
|
Anatomical hemisphere surfaces accepted by |
None
|
right
|
PolyData | str | Path | None
|
Anatomical hemisphere surfaces accepted by |
None
|
color
|
str
|
Uniform PyVista surface color. |
"#D8D8D8"
|
opacity
|
float
|
Brain background opacity from 0 to 1. |
0.1
|
window_size
|
tuple[int, int]
|
Window width and height in pixels. |
(900, 650)
|
background
|
str
|
PyVista background color. |
"white"
|
Returns:
| Type | Description |
|---|---|
None
|
Initializes this plot instance and its persistent PyVista scene. |
Attributes:
| Name | Type | Description |
|---|---|---|
plotter |
Plotter
|
Persistent renderer, including the shared scene camera. |
Notes
Uses surface meshes, not voxel volume rendering or slices. The initial top (dorsal) view puts anterior at the top and anatomical left on the left. The translucent background provides whole-brain context. Inflated meshes do not represent physical anatomy. Contact coordinates must already match the anatomical surfaces; no projection or registration is performed. Adding contacts preserves the initial or manually adjusted camera framing.
add_contacts
add_contacts(
xyz: ArrayLike,
*,
radius: float = 1.0,
color: str | Sequence[str] = "crimson",
lighting: bool = True,
) -> Actor
Add opaque contact spheres at their supplied coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xyz
|
ArrayLike
|
Finite coordinates with shape (n_contacts, 3), with at least one contact. Columns are R, A, S in millimetres, in the same coordinate frame as the displayed anatomy. Input order is preserved. |
required |
radius
|
float
|
Positive finite sphere radius in millimetres, shared by all contacts. This is a display size, not an estimate of electrode dimensions. |
1.0
|
color
|
str | Sequence[str]
|
One named or hex color for all contacts, or exactly one color string per contact in xyz order. Examples: "crimson" or ["red", "#3366CC"]. Colors are interpreted by PyVista; spheres are opaque. |
"crimson"
|
lighting
|
bool
|
Shade sphere colors using scene lights and highlights. False uses unlit colors. Geometry, radius, coordinates, and depth ordering are identical for both settings. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
actor |
Actor
|
One actor containing all contact spheres added by this call. Subsequent calls add separate actors without replacing earlier ones. |
Notes
Coordinates are copied and never projected, registered, filtered by ROI membership, or moved to avoid occlusion. Contacts outside an ROI remain visible at their supplied locations. Spheres use real mesh geometry so their physical size and colors are retained in PNG and HTML exports. The first contact batch in an empty scene fits the camera. Later additions preserve camera position, direction, projection, and zoom; only the depth clipping range is updated. Contacts outside the current frame may remain offscreen. Use plotter.reset_camera() to fit all actors when needed. Surface transparency affects visibility; contacts obey normal depth order.
Display and export
These methods apply to SurfacePlot, ROIPlot, and VolumePlot.
to_figure
to_figure(
*,
ax: Axes | None = None,
figsize: tuple[float, float] | None = None,
dpi: float | None = None,
render_dpi: float = 600,
) -> Figure
Create an independent Matplotlib snapshot of the current scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ax
|
Axes | None
|
Target 2D Axes. None creates a Figure; supplied axes retain existing artists and siblings. Each call adds a snapshot and the requested colorbars. |
None
|
figsize
|
tuple[float, float] | None
|
New Figure width and height in inches, default window_size / 100. Only valid when ax is None. |
None
|
dpi
|
float | None
|
New Figure canvas DPI, default 150. Only valid when ax is None; supplied figures retain their size and DPI. |
None
|
render_dpi
|
float
|
Finite positive brain-image pixels per inch, measured after layout and rounded up to whole pixels. Lower values provide lighter previews. |
600
|
Returns:
| Name | Type | Description |
|---|---|---|
figure |
Figure
|
New or supplied Figure, without displaying or saving. Use pyplot.show() or figure.savefig(). The brain occupies one Axes with its aspect preserved. |
Notes
The snapshot keeps scene cameras and window state unchanged and survives close(). Later scene edits, Figure resizing, or export at higher DPI do not rerender it; create another snapshot at the intended size and render_dpi. PNG dimensions follow Figure size and export DPI. PDF/SVG embed the original brain pixels with vector titles and colorbars. Rendering requires a working VTK graphics context.
view
view(
*,
jupyter_backend: Literal["trame", "server", "client"]
| None = None,
) -> None
Open the current scene for three-dimensional exploration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
jupyter_backend
|
(trame, server, client)
|
Notebook viewer backend. None selects Trame in Notebooks, allowing server/client switching. Server streams VTK images; client renders geometry in the browser. Explicit backends require Notebook mode. |
"trame"
|
Returns:
| Type | Description |
|---|---|
None
|
Displays the viewer while retaining this scene for later additions or export. The viewer return value is not exposed. |
Notes
Displays geometry without Matplotlib titles or colorbars. Desktop use opens a native window; on macOS it requires the main thread. Press Q to return to Python while retaining the scene. Closing via OS controls may destroy its graphics context. Notebook viewers require an open scene. Browser rendering may differ from VTK. Use to_figure() for a publication snapshot and export_html() for an independent browser scene.
export_html
Export a self-contained interactive browser scene.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path | None
|
Destination HTML file; its parent directory must exist. PyVista changes the suffix to .html. If omitted, return an in-memory buffer. |
None
|
Returns:
| Type | Description |
|---|---|
StringIO | None
|
HTML buffer when path is None, otherwise None after writing the file. |
Notes
Uses Trame scene export and its offline viewer, preserving camera projection and zoom. The exported file embeds geometry and a VTK.js viewer: readers need WebGL, but no Python server or installation. Browser lighting and transparency can differ from native VTK screenshots. Browser camera changes do not update the original Python scene.
close
close() -> None
Release the scene's graphics resources.
Returns:
| Type | Description |
|---|---|
None
|
Closes the underlying PyVista plotter. Existing Matplotlib snapshots and independent HTML exports remain usable; this scene cannot be rendered again. |