Visualization (sanafe.viz)

The sanafe.viz module provides plotting helpers for SANA-FE trace outputs, built on top of matplotlib. Each plotting function accepts the same input forms as sanafe.data:

  • a path or Path to a CSV produced by chip.sim()

  • the dict returned by chip.sim()

  • the raw in-memory values

  • a DataFrame (returned as-is)

Plots share a common styling system (see Styling) so that figures look consistent across spike, potential, and performance views.

Quickstart

Run a simulation and generate the standard set of plots:

import sanafe
import sanafe.viz
import matplotlib.pyplot as plt

arch, snn = sanafe.load_example()
chip = sanafe.SpikingChip(arch)
chip.load(snn)
results_dict = chip.sim(5, spike_trace=True, potential_trace=True,
                        perf_trace=True, message_trace=True)
sanafe.viz.plot_raster(results_dict)
sanafe.viz.plot_potential(results_dict)
sanafe.viz.plot_energy(results_dict)
sanafe.viz.plot_throughput(results_dict)
sanafe.viz.plot_message_latency(results_dict)
plt.show()

Spike Plots

sanafe.viz.raster.plot_raster(source: Any, groups: Sequence[str] | None = None, time_range: Tuple[int, int] | None = None, colors: dict | None = None, group_spacing: float = 0.5, show_legend: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str = 'Neuron', **scatter_kwargs) Tuple[Figure, Axes][source]
sanafe.viz.raster.raster_plot_matrix(spike_matrix: ndarray, neuron_ids: Sequence[str] | None = None, time_range: Tuple[int, int] | None = None, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str = 'Neuron', color: str = '#1f77b4', **scatter_kwargs) Tuple[Figure, Axes][source]

Membrane Potential Plots

The default rendering is a heatmap, which is consistent with the raster view for spikes. plot_potential_lines is available for traditional per-neuron line plots, which is more useful when only a handful of neurons are being inspected.

sanafe.viz.potential.plot_potential(source: Any, neuron_ids: Sequence[str] | None = None, time_range: Tuple[int, int] | None = None, cmap: str = 'viridis', vmin: float | None = None, vmax: float | None = None, show_colorbar: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str = 'Neuron', **imshow_kwargs) Tuple[Figure, Axes][source]
sanafe.viz.potential.plot_potential_lines(source: Any, neuron_ids: Sequence[str] | None = None, time_range: Tuple[int, int] | None = None, colors: Sequence[str] | None = None, show_threshold: float | None = None, threshold_color: str = '#d62728', threshold_linestyle: str = '--', show_legend: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str = 'Membrane Potential', **plot_kwargs) Tuple[Figure, Axes][source]

Performance Plots

Hardware performance plots cover energy breakdowns, throughput, and message latency distributions. Energy and time values are automatically rescaled to sensible units (e.g., pJ, nJ, µs, ms) based on the magnitude of the data.

sanafe.viz.performance.plot_energy(source: Any, time_range: Tuple[int, int] | None = None, mode: str = 'stacked_area', components: Sequence[str] | None = None, normalize: bool = False, show_total: bool = False, colors: Sequence[str] | None = None, component_labels: Sequence[str] | None = None, show_legend: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str | None = None, **kwargs) Tuple[Figure, Axes][source]
sanafe.viz.performance.plot_throughput(source: Any, metrics: Sequence[str] | None = None, time_range: Tuple[int, int] | None = None, colors: Sequence[str] | None = None, labels: Sequence[str] | None = None, secondary_y: Sequence[str] | None = None, show_legend: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str = 'Time-step', ylabel: str | None = None, **plot_kwargs) Tuple[Figure, Axes][source]
sanafe.viz.performance.plot_message_latency(source: Any, metrics: Sequence[str] | None = None, filter_placeholder: bool = True, time_range: Tuple[int, int] | None = None, bins: int | None = None, colors: Sequence[str] | None = None, labels: Sequence[str] | None = None, log_scale: bool = False, show_legend: bool = True, ax: Axes | None = None, style: SANAFEStyle | None = None, figsize: Tuple[float, float] | None = None, title: str | None = None, xlabel: str | None = None, ylabel: str = 'Count', **hist_kwargs) Tuple[Figure, Axes][source]

Styling

All plots share a common styling system controlled by SANAFEStyle. A few preset styles are provided for common use cases:

  • PUBLICATION_STYLE — serif fonts, 300 DPI, compact figure sizes

  • PRESENTATION_STYLE — large fonts and thick lines for slides

  • NOTEBOOK_STYLE — larger figures with a light grid for interactive use

Apply a preset globally with set_default_style(), or pass a SANAFEStyle instance to any individual plotting function via its style argument.

import sanafe.viz
from sanafe.viz.styles import PUBLICATION_STYLE

sanafe.viz.set_default_style(PUBLICATION_STYLE)
sanafe.viz.apply_style()

sanafe.viz.plot_raster(results_dict)
class sanafe.viz.styles.SANAFEStyle(colors: List[str] = <factory>, figure_size: Tuple[float, float]=(8.0, 5.0), dpi: int = 100, font_family: str = 'sans-serif', font_size: float = 11.0, title_size: float = 13.0, label_size: float = 11.0, tick_size: float = 10.0, line_width: float = 1.5, marker_size: float = 30.0, spine_width: float = 1.0, grid: bool = False, grid_alpha: float = 0.3, tight_layout: bool = True, raster_marker: str = '|', raster_marker_size: float = 100.0, raster_line_width: float = 1.5, potential_line_width: float = 1.5, potential_marker: str | None = None, potential_marker_size: float = 4.0, perf_line_width: float = 1.5, perf_marker: str | None = 'o', perf_marker_size: float = 3.0, perf_fill_alpha: float = 0.3, energy_colors: List[str] = <factory>, energy_component_names: List[str] = <factory>, hist_bins: int = 30, hist_alpha: float = 0.7, hist_edgecolor: str = 'white', hist_edgewidth: float = 0.5)[source]

Style configuration for plots

colors: List of colors for different groups/series figure_size: Default (width, height) in inches dpi: Resolution for saved figures font_family: Font family for text font_size: Base font size in points title_size: Title font size in points label_size: Axis label font size in points tick_size: Tick label font size in points line_width: Default line width marker_size: Default marker size for scatter plots spine_width: Width of axis spines grid: Whether to show grid by default grid_alpha: Transparency of grid lines tight_layout: Whether to use tight_layout by default

colors: List[str]
figure_size: Tuple[float, float] = (8.0, 5.0)
dpi: int = 100
font_family: str = 'sans-serif'
font_size: float = 11.0
title_size: float = 13.0
label_size: float = 11.0
tick_size: float = 10.0
line_width: float = 1.5
marker_size: float = 30.0
spine_width: float = 1.0
grid: bool = False
grid_alpha: float = 0.3
tight_layout: bool = True
raster_marker: str = '|'
raster_marker_size: float = 100.0
raster_line_width: float = 1.5
potential_line_width: float = 1.5
potential_marker: str | None = None
potential_marker_size: float = 4.0
perf_line_width: float = 1.5
perf_marker: str | None = 'o'
perf_marker_size: float = 3.0
perf_fill_alpha: float = 0.3
energy_colors: List[str]
energy_component_names: List[str]
hist_bins: int = 30
hist_alpha: float = 0.7
hist_edgecolor: str = 'white'
hist_edgewidth: float = 0.5
to_rc_params() Dict[str, Any][source]

Convert style to matplotlib rcParams dictionary.

__init__(colors: List[str] = <factory>, figure_size: Tuple[float, float]=(8.0, 5.0), dpi: int = 100, font_family: str = 'sans-serif', font_size: float = 11.0, title_size: float = 13.0, label_size: float = 11.0, tick_size: float = 10.0, line_width: float = 1.5, marker_size: float = 30.0, spine_width: float = 1.0, grid: bool = False, grid_alpha: float = 0.3, tight_layout: bool = True, raster_marker: str = '|', raster_marker_size: float = 100.0, raster_line_width: float = 1.5, potential_line_width: float = 1.5, potential_marker: str | None = None, potential_marker_size: float = 4.0, perf_line_width: float = 1.5, perf_marker: str | None = 'o', perf_marker_size: float = 3.0, perf_fill_alpha: float = 0.3, energy_colors: List[str] = <factory>, energy_component_names: List[str] = <factory>, hist_bins: int = 30, hist_alpha: float = 0.7, hist_edgecolor: str = 'white', hist_edgewidth: float = 0.5) None
sanafe.viz.styles.get_default_style() SANAFEStyle[source]
sanafe.viz.styles.apply_style(style: SANAFEStyle | None = None) None[source]

Apply style settings to matplotlib’s rcParams.

sanafe.viz.styles.get_group_colors(groups: Sequence[str], style: SANAFEStyle | None = None) Dict[str, str][source]

Assigns colors from the style’s color palette to each group name. Colors cycle if there are more groups than colors.

Returns: Dictionary mapping group names to color strings.

sanafe.viz.styles.get_colormap(name: str = 'neuromorphic', n_colors: int = 256) LinearSegmentedColormap[source]

Get a colormap for SANA-FE visualizations.

Parameters:
  • name – Colormap name. Options: - “neuromorphic”: Purple-to-yellow gradient (default) - “activity”: Blue-to-red for activity levels - “energy”: Green-to-red for energy consumption - Any matplotlib colormap name

  • n_colors – Number of discrete colors in the colormap

Returns: Matplotlib colormap object.

sanafe.viz.styles.create_figure(figsize: Tuple[float, float] | None = None, style: SANAFEStyle | None = None, **kwargs) Tuple[Figure, Axes][source]

Create a figure with styling applied.

Returns: Tuple of (Figure, Axes) objects.

sanafe.viz.styles.style_axis(ax: Axes, style: SANAFEStyle | None = None, xlabel: str | None = None, ylabel: str | None = None, title: str | None = None, xlim: Tuple[float, float] | None = None, ylim: Tuple[float, float] | None = None) Axes[source]