cedalion.plots

Plotting functions for visualization of montages, meshes, etc.

Functions

image_recon(X, head[, cmap, clim, ...])

Render a single frame of brain or scalp activity on a specified view.

image_recon_multi_view(X_ts, head[, cmap, ...])

Generate a multi-view (2×3 grid) visualization of head activity across different views.

image_recon_view(X_ts, head[, cmap, clim, ...])

Generate a single-view visualization of head activity.

plot3d(brain_mesh, scalp_mesh, geo3d, timeseries)

Plots a 3D visualization of brain and scalp meshes.

plot_labeled_points(plotter, points[, ...])

Plots a labeled point cloud with optional interaction for picking points.

plot_montage3D(amp, geo3d)

Plots a 3D visualization of a montage.

plot_stim_markers(ax, stim[, fmt, y])

Add stimulus indicators to an Axes.

plot_surface(plotter, surface[, color, ...])

Plots a surface mesh with optional landmark picking in a PyVista plotter.

plot_vector_field(plotter, points, vectors)

Plots a vector field on a PyVista plotter.

scalp_plot(ts, geo3d, metric, ax[, title, ...])

Creates a 2D plot of the head with channels coloured according to a given metric.

scalp_plot_gif(data_ts, geo3d, filename[, ...])

Generate a GIF of scalp topographies over time from time-series data.

Classes

OptodeSelector(surface, points[, normals, ...])

A class for visualizing point clouds with interactive features in PyVista.

cedalion.plots.plot_montage3D(
amp: DataArray,
geo3d: DataArray,
)[source]

Plots a 3D visualization of a montage.

Parameters:
  • amp (xr.DataArray) – Time series data array.

  • geo3d (xr.DataArray) – Landmark coordinates.

cedalion.plots.plot3d(
brain_mesh,
scalp_mesh,
geo3d,
timeseries,
poly_lines=[],
brain_scalars=None,
plotter=None,
)[source]

Plots a 3D visualization of brain and scalp meshes.

Parameters:
  • brain_mesh (TrimeshSurface) – The brain mesh as a TrimeshSurface object.

  • scalp_mesh (TrimeshSurface) – The scalp mesh as a TrimeshSurface object.

  • geo3d (xarray.Dataset) – Dataset containing 3-dimentional point centers.

  • timeseries – Time series data array.

  • poly_lines – List of lists of points to be plotted as polylines.

  • brain_scalars – Scalars to be used for coloring the brain mesh.

  • plotter (pv.Plotter, optional) – An existing PyVista plotter instance to use for plotting. If None, a new PyVista plotter instance is created. Default: None.

Initial Contributors:
cedalion.plots.plot_surface(
plotter: pv.Plotter,
surface: cdc.Surface,
color: pv.ColorLike | None = None,
opacity: float = 1.0,
pick_landmarks: bool = False,
**kwargs,
)[source]

Plots a surface mesh with optional landmark picking in a PyVista plotter.

Parameters:
  • plotter – A PyVista plotter instance used for rendering the surface.

  • surface – The surface object to be plotted.

  • color – Color of the mesh.

  • opacity – Opacity of the mesh, ranging from 0 (transparent) to 1 (opaque). Default is 1.0.

  • pick_landmarks – If True, enables interactive picking of landmarks on the surface. Default is False.

  • **kwargs – Additional keyword arguments are passed to pv.add_mesh.

Returns:

If pick_landmarks is True, returns a function that when called, provides the current picked points and their labels. This function prints warnings if some labels are missing or are repeated.

Return type:

function

Initial Contributors:
cedalion.plots.plot_labeled_points(
plotter: pv.Plotter,
points: cdt.LabeledPointCloud,
color: pv.ColorLike = None,
show_labels: bool = False,
ppoints: bool = None,
labels: list[str] | None = None,
)[source]

Plots a labeled point cloud with optional interaction for picking points.

This function visualizes a point cloud where each point can have a label. Points can be interactively picked if enabled. Picked point is indicated by increased radius.

Parameters:
  • plotter – A PyVista plotter instance used for rendering the points.

  • points – A labeled point cloud data structure containing points and optional labels.

  • color – Override color for all points. If None, colors are assigned based on point types.

  • show_labels – If True, labels are displayed next to the points.

  • ppoints – A list to store indices of picked points, enables picking if not None.

  • labels – List of labels to show if show_labels is True. If None and show_labels is True, the labels from points are used.

Initial Contributors:
cedalion.plots.plot_vector_field(
plotter: Plotter,
points: cdt.LabeledPointCloud,
vectors: DataArray,
ppoints=None,
)[source]

Plots a vector field on a PyVista plotter.

Parameters:
  • plotter (pv.Plotter) – A PyVista plotter instance used for rendering the vector field.

  • points (cdt.LabeledPointCloud) – A labeled point cloud data structure containing point coordinates.

  • vectors (xr.DataArray) – A data array containing the vector field.

  • ppoints (list, optional) – A list to store indices of picked points, enables picking if not None. Default is None.

class cedalion.plots.OptodeSelector(surface, points, normals=None, plotter=None, labels=None)[source]

Bases: object

A class for visualizing point clouds with interactive features in PyVista.

This class provides functionality to visualize and interact with labeled point clouds using a PyVista plotter. It allows points to be dynamically added or removed by picking them directly from the plot interface.

surface[source]

The surface of a head for normals.

Type:

cdc.Surface

points[source]

The point cloud data containing point coordinates.

Type:

cdt.LabeledPointCloud

normals[source]

Normal vectors to the points.

Type:

xr.DataArray

plotter[source]

A PyVista plotter instance for rendering the point cloud.

Type:

pv.Plotter

labels[source]

Labels corresponding to the points, displayed if provided.

Type:

list of str, optional

actors[source]

List of PyVista actor objects representing the points in the visualization.

Type:

list

color[source]

Default color for points if not specified by point type.

Type:

str or tuple, optional

plot()[source]

Renders the point cloud using the current settings.

on_pick(picked_point)[source]

Callback function for picking points in the visualization

update_visualization()[source]

Clears the existing plot and re-renders the point cloud.

enable_picking()[source]

Enables interactive picking of points on the plot.

Initial Contributors:
plot()[source]
on_pick(picked_point)[source]
update_visualization()[source]
enable_picking()[source]
find_surface_normal(picked_point, radius=6)[source]
update_normals(normal_at_picked_point, label)[source]
cedalion.plots.plot_stim_markers(
ax,
stim: DataFrame,
fmt: dict[str, dict] | None = None,
y: float = 0.03,
)[source]

Add stimulus indicators to an Axes.

For each trial a Rectangle is plotted in x from onset to onset+duration. The height of the rectangle is specified in axes coordinates. In the default setting a small bar at bottom of the axes is drawn. By setting y to 1. the stimulus marker covers the full height of the axes.

Parameters:
  • ax – the matplotlib axes to operate on

  • stim – a stimulas data frame

  • fmt – for each trial_type a dictioniary of keyword arguments can be provided. These kwargs are passed to matplotlib.patches.Rectangle to format the stimulus indicator.

  • y – the height of the Rectangle in axes coordinates.

Initial Contributors:
cedalion.plots.scalp_plot(
ts: cdt.NDTimeSeries,
geo3d: cdt.LabeledPointCloud,
metric: xr.DataArray | ArrayLike,
ax,
title: str | None = None,
vmin: float | None = None,
vmax: float | None = None,
cmap: str | matplotlib.colors.Colormap = 'bwr',
norm: object | None = None,
bad_color: ColorType = [0.7, 0.7, 0.7],
min_dist: Quantity | None = None,
min_metric: float | None = None,
channel_lw: float = 2.0,
optode_size: float = 36.0,
optode_labels: bool = False,
cb_label: str | None = None,
cb_ticks_labels: list[float, str] | None = None,
add_colorbar: bool = True,
zorder: str | None = None,
)[source]

Creates a 2D plot of the head with channels coloured according to a given metric.

Parameters:
  • ts – a NDTimeSeries to provide channel definitions

  • geo3d – a LabeledPointCloud to provide the probe geometry

  • metric ((DataArray, (channel,) | ArrayLike)) – the scalar metric to be plotted for each channel. If provided as a DataArray it needs a channel dimension. If provided as a plain array or list it must have the same length as ts.channel and the matching is done by position.

  • ax – the matplotlib.Axes object into which to draw

  • title – the axes title

  • vmin – the minimum value of the metric

  • vmax – the maximum value of the metric

  • cmap – the name of the colormap

  • bad_color – the color to use when the metric contains NaNs

  • min_dist – if provided channels below this distance threshold are not drawn

  • min_metric – if provided channels below this metric threshold are toned down

  • channel_lw – channel line width

  • optode_size – optode marker size

  • optode_labels – if True draw optode labels instead of markers

  • cb_label – colorbar label

  • zorder – ‘ascending’ or ‘descending’ or None. Controls whether channels with high or low metric values are plotted on top.

Initial Contributors:
cedalion.plots.scalp_plot_gif(
data_ts: cdt.NDTimeSeries,
geo3d: cdt.LabeledPointCloud,
filename: str,
time_range: tuple = None,
cmap: str | Colormap = 'seismic',
scl=None,
fps: int = 10,
optode_size: float = 6,
optode_labels: bool = False,
str_title: str = '',
)[source]

Generate a GIF of scalp topographies over time from time-series data.

Parameters:
  • data_ts – xarray.DataArray A 2D DataArray with dimensions (channel, time). Must include coordinate labels for ‘source’ and ‘detector’ in the ‘channel’ dimension.

  • geo3d – cedalion.core.LabeledPointCloud 3D geometry object defining optode locations for projecting onto the scalp surface.

  • filename – str Full path to the output GIF file without file extension.

  • time_range – tuple, optional Provides (start_time, stop_time, step_time) in quantity ‘s’ for generating animation.

  • cmap – string, optional A matplotlib colormap name or a Colormap object. Default is ‘seismic’.

  • scl – tuple of (float, float), optional Tuple defining the (vmin, vmax) for the color scale. If None, the color scale is set to ± the maximum absolute value of the data.

  • fps – int, optional Frames per second for the output GIF. Default is 10.

  • optode_size – float, optional Size of optode markers on the plot. Default is 6.

  • optode_labels – bool, optional Whether to show text labels for optodes instead of markers. Default is False.

  • str_title – str, optional Extra string to append to the title of each frame.

Returns: None

The function saves a GIF file to the specified location.

Initial Contributors: - David Boas | dboas@bu.edu | 2025 - Alexander von Lühmann | vonluehmann@tu-berlin.de | 2025

cedalion.plots.image_recon(
X: cdt.NDTimeSeries,
head: TwoSurfaceHeadModel,
cmap: str | Colormap = 'seismic',
clim=None,
view_type: str = 'hbo_brain',
view_position: str = 'superior',
p0=None,
title_str: str = None,
off_screen: bool = False,
plotshape=(1, 1),
iax=(0, 0),
show_scalar_bar: bool = False,
wdw_size: tuple = (1024, 768),
)[source]

Render a single frame of brain or scalp activity on a specified view.

This function creates (or reuses) a PyVista plotter, applies a custom colormap, sets the camera view according to the given view_position, adds the surface mesh with the scalar data (extracted from X), and returns the plotter, the mesh, and a text label.

Parameters:
  • X – cdt.NDTimeSeries (or similar) Scalar data for the current frame. Expected to have a boolean attribute is_brain indicating brain vs. non-brain vertices, and HbO / HbR chromophore dimension

  • head – TwoSurfaceHeadModel A head model containing attributes such as head.brain and head.scalp.

  • cmap – str or matplotlib.colors.Colormap, default ‘seismic’ The colormap to use.

  • clim – tuple, optional Color limits. If None, they are computed from the data.

  • view_type – str, default ‘hbo_brain’ Indicates whether to plot brain (‘hbo_brain’ or ‘hbr_brain’) or scalp (‘hbo_scalp’ or ‘hbr_scalp’) data.

  • view_position – str, default ‘superior’ The view direction. Options are: ‘superior’, ‘anterior’, ‘posterior’,’left’, ‘right’, and ‘scale_bar’.

  • p0 – PyVista Plotter instance, optional If provided the mesh is added to this plotter; else a new plotter is created.

  • title_str – str, optional Title to use on the scalar bar.

  • off_screen – bool, default False Whether to use off-screen rendering.

  • plotshape – tuple, default (1, 1) The subplot grid shape.

  • iax – tuple, default (0, 0) The target subplot index (row, col).

  • show_scalar_bar – bool, optional Flag to control scalar bar visibility

  • wdw_size – tuple, default (1024, 768) The window size for the plotter (the plot resolution)

Returns:

  • p0: the PyVista Plotter instance.

  • surf: the wrapped surface mesh (a pyvista mesh).

  • surf_label: a text actor (e.g., the scalar bar label).

Return type:

A tuple (p0, surf, surf_label) where

Initial Contributors: - David Boas | dboas@bu.edu | 2025 - Laura Carlton | lcarlton@bu.edu | 2025 - Alexander von Lühmann | vonluehmann@tu-berlin.de | 2025

cedalion.plots.image_recon_view(
X_ts: cdt.NDTimeSeries,
head: TwoSurfaceHeadModel,
cmap: str | Colormap = 'seismic',
clim=None,
view_type: str = 'hbo_brain',
view_position: str = 'superior',
title_str: str = None,
filename: str = None,
SAVE: bool = False,
time_range: tuple = None,
fps: int = 6,
geo3d_plot: cdt.LabeledPointCloud = None,
wdw_size: tuple = (1024, 768),
)[source]

Generate a single-view visualization of head activity.

For static data (2D: vertex × channel) the function can display (or save) a single frame. For time series data (3D: vertex × channel × time) the function can create an animated GIF by looping over the specified frame indices.

Parameters:
  • X_ts – xarray.DataArray or NDTimeSeries Activity data. If 2D, a single static frame is plotted; if 3D, a time series is used. Expected to have a boolean attribute is_brain indicating brain vs. non-brain vertices, and HbO / HbR chromophore dimension

  • head – TwoSurfaceHeadModel The head mesh data to plot activity on.

  • cmap – str or matplotlib.colors.Colormap, default ‘seismic’ The colormap to use.

  • view_position – str, default ‘superior’ The view to render.

  • clim – tuple, optional Color limits. If None, they are computed from the data.

  • view_type – str, default ‘hbo_brain’ Indicates whether to plot brain (‘hbo_brain’ or ‘hbr_brain’) or scalp (‘hbo_scalp’ or ‘hbr_scalp’) data.

  • view_position – str, default ‘superior’ The view direction. Options are: ‘superior’, ‘anterior’, ‘posterior’,’left’, ‘right’, and ‘scale_bar’.

  • title_str – str, optional Title to use on the scalar bar.

  • filename – str, optional The output filename (without extension) for saving the image/GIF.

  • SAVE – bool, default False If True, the resulting still image is saved, otherwise only shown. Rendered gifs are always saved.

  • time_range – tuple, optional Provides (start_time, stop_time, step_time) in quantity ‘s’ for generating animation.

  • fps – int, default 6 Frames per second for the GIF.

  • geo3d_plot – cdt.LabeledPointCloud, optional A 3D point cloud for plotting labeled points (e.g. optodes) on the mesh.

  • wdw_size – tuple, default (1024, 768) The window size for the plotter (the plot resolution)

Returns: Nothing

Initial Contributors: - David Boas | dboas@bu.edu | 2025 - Laura Carlton | lcarlton@bu.edu | 2025 - Alexander von Lühmann | vonluehmann@tu-berlin.de | 2025

cedalion.plots.image_recon_multi_view(
X_ts: cdt.NDTimeSeries,
head: TwoSurfaceHeadModel,
cmap: str | Colormap = 'seismic',
clim=None,
view_type: str = 'hbo_brain',
title_str: str = None,
filename: str = None,
SAVE: bool = True,
time_range: tuple = None,
fps: int = 6,
geo3d_plot: cdt.LabeledPointCloud = None,
wdw_size: tuple = (1024, 768),
)[source]

Generate a multi-view (2×3 grid) visualization of head activity across different views.

For static data (2D: vertex × channel) the function can display (or save) a single frame. For time series data (3D: vertex × channel × time) the function creates an animated GIF where each frame updates all views.

Parameters:
  • X_ts – xarray.DataArray or NDTimeSeries Activity data. If 2D, a single static frame is plotted; if 3D, a time series is used. Expected to have a boolean attribute is_brain indicating brain vs. non-brain vertices, and HbO / HbR chromophore dimension

  • head – TwoSurfaceHeadModel The head mesh data to plot activity on.

  • cmap – str or matplotlib.colors.Colormap, default ‘seismic’ The colormap to use.

  • view_position – str, default ‘superior’ The view to render.

  • clim – tuple, optional Color limits. If None, they are computed from the data.

  • view_type – str, default ‘hbo_brain’ Indicates whether to plot brain (‘hbo_brain’ or ‘hbr_brain’) or scalp (‘hbo_scalp’ or ‘hbr_scalp’) data.

  • title_str – str, optional Title to use on the scalar bar.

  • filename – str, optional The output filename (without extension) for saving the image/GIF.

  • SAVE – bool, default False If True, the resulting still image is saved, otherwise only shown. Rendered gifs are always saved.

  • time_range – tuple, optional Provides (start_time, stop_time, step_time) in quantity ‘s’ for generating animation.

  • fps – int, default 6 Frames per second for the GIF.

  • geo3d_plot – cdt.LabeledPointCloud, optional A 3D point cloud for plotting labeled points (e.g. optodes) on the mesh.

  • wdw_size – tuple, default (1024, 768) The window size for the plotter (the plot resolution)

Returns: Nothing

Initial Contributors: - David Boas | dboas@bu.edu | 2025 - Laura Carlton | lcarlton@bu.edu | 2025 - Alexander von Lühmann | vonluehmann@tu-berlin.de | 2025