SFI.utils.plotting module

SFI.utils.plotting.SFI_COLORS = {'bootstrap': '#5D3A9B', 'data': '#3B9EFF', 'error': '#FF2D6F', 'exact': '#FF7A1A', 'highlight': '#40B0A6', 'inferred': '#FFC20A', 'secondary': '#1A85FF', 'tertiary': '#D35FB7'}

Named colour palette for consistent plotting across gallery examples and user notebooks. Adjusted for readability on both dark (#131416) and light backgrounds.

SFI.utils.plotting.animate_particles(coll, *, dataset=0, dims=(0, 1), trail=0, overlay_fn=None, skip=1, cmap='magma', s=100.0, color_dim=None, vmin=None, vmax=None, quiver=False, heading_dim=None, box=None, interval=50, ax=None, fig=None, blit=False, **anim_kw)[source]

Animate particle positions over time (frames read via the collection).

Returns a matplotlib.animation.FuncAnimation. With trail>0 each particle leaves a fading tail; overlay_fn(ax, t_index, X_t) is called per frame for custom overlays. For active matter, color points by a state dimension (color_dim, e.g. heading angle), overlay heading arrows (quiver=True + heading_dim), and wrap into a periodic box (box=(Lx, Ly)) — mirroring plot_particles().

Parameters:
  • coll (TrajectoryCollection)

  • dataset (int)

  • trail (int)

  • skip (int)

  • cmap (str)

  • s (float)

  • quiver (bool)

  • interval (int)

  • blit (bool)

SFI.utils.plotting.animate_spde_comparison(coll_a, coll_b, *, dataset=0, field_component=0, grid_shape=None, skip=1, vmin=None, vmax=None, cmap='magma', titles=('A', 'B'), interval=50, plot_colorbar=True, blit=False, **anim_kw)[source]

Side-by-side animation of one channel of two gridded collections.

Returns a matplotlib.animation.FuncAnimation with two image panels sharing color limits (e.g. data vs bootstrap SPDE fields).

Parameters:
SFI.utils.plotting.axisvector(index, dim)[source]

d-dimensional unit vector pointing in direction index.

SFI.utils.plotting.comparison_scatter(Xexact, Xinferred, error=None, maxpoints=10000, vmax=None, color=None, alpha=0.05, y=0.8, mode='both', fontsize=9)[source]

This method is used to compare inferred components to the exact ones along the trajectory, in a graphical way.

Xexact, Xinferred: jnp arrays (Nsteps,…); must have the same shape.

error: predicted standard deviation for X_inferred.

maxpoints: if Nsteps / 2 * maxpoints, data will be subsampled.

SFI.utils.plotting.dark_ax(ax)[source]

Style a matplotlib Axes for a dark background.

Sets black face colour, white ticks and labels, and dark-grey spines.

SFI.utils.plotting.dark_fig(nrows=1, ncols=1, **kw)[source]

Create a figure and axes with a black background.

All arguments are forwarded to plt.subplots. Returns (fig, axes) like plt.subplots.

SFI.utils.plotting.phase2d(coll, *, dataset=0, dims=None, dir1=None, dir2=None, shift=(0.0, 0.0), tmin=None, tmax=None, particles=None, cmap='viridis', linewidth=1.5, alpha=1.0, plot_colorbar=False, box=None, transform=None, color=None, ax=None, drop_masked=True)[source]

2D phase-space plot with connected line segments colored along the trajectory.

Parameters:
  • coll (TrajectoryCollection) – TrajectoryCollection containing the data.

  • dataset (int) – Dataset index inside the collection.

  • dims – Pair of coordinate indices (i, j) to plot. Ignored if dir1/dir2 are provided. If None and no directions are given, defaults to (0, 1).

  • dir1 – Optional projection directions in R^d. If given, positions are projected onto these directions instead of using coordinate axes.

  • dir2 – Optional projection directions in R^d. If given, positions are projected onto these directions instead of using coordinate axes.

  • shift – (xshift, yshift) added to all positions.

  • tmin – Integer time-index bounds. If None, full range is used. Negative tmax is interpreted as from the end.

  • tmax – Integer time-index bounds. If None, full range is used. Negative tmax is interpreted as from the end.

  • particles – Sequence of particle indices to include. If None, include all.

  • cmap – Colormap for the time-coloring.

  • linewidth (float) – Line width of the trajectory segments.

  • alpha (float) – Global alpha for the line collection.

  • plot_colorbar (bool) – If True, add a colorbar for the time coloring.

  • box – Optional periodic box (Lx, Ly). If given, positions are wrapped modulo the box and segments that cross a boundary are dropped, so trajectories render correctly in a periodic domain.

  • transform – Optional callable applied elementwise to the projected x and y (e.g. np.exp to map a log-space coordinate back to population space). Applied after projection/shift/box-wrap.

  • color – Optional single color. If given, draw the trajectory in this solid color instead of the time-colored gradient (incompatible with plot_colorbar).

  • ax – Optional Matplotlib Axes. If None, use plt.gca().

  • drop_masked (bool) – If True, drop segments where either endpoint is masked.

Returns:

The created matplotlib.collections.LineCollection.

Return type:

lc

SFI.utils.plotting.phase2d_scalar(coll, *, color_fn, dataset=0, dims=(0, 1), tmin=None, tmax=None, particles=None, cmap='plasma', linewidth=1.5, alpha=1.0, plot_colorbar=True, colorbar_label='', ax=None, drop_masked=True)[source]

2D phase-space plot colored by a scalar field of the coordinate.

Like phase2d(), but each segment is colored by color_fn(midpoint) rather than by time — e.g. the local diffusivity D(x), the speed, or a potential. color_fn receives the full d-dimensional segment midpoints, shape (n_segments, d), and must return a scalar per segment, shape (n_segments,).

Parameters:
  • coll (TrajectoryCollection)

  • dataset (int)

  • linewidth (float)

  • alpha (float)

  • plot_colorbar (bool)

  • colorbar_label (str)

  • drop_masked (bool)

Return type:

LineCollection

SFI.utils.plotting.phase3d(coll, *, dataset=0, dims=(0, 1, 2), tmin=None, tmax=None, particles=None, cmap='viridis', linewidth=1.5, alpha=1.0, scatter_endpoints=True, scatter_size=30.0, ax=None, drop_masked=True)[source]

3D trajectory plot with segments colored along time.

The 3D analog of phase2d(): draws each particle’s path as a time-colored Line3DCollection. Pass a 3D axes via ax or a new one is created (projection="3d").

Parameters:
  • coll (TrajectoryCollection)

  • dataset (int)

  • linewidth (float)

  • alpha (float)

  • scatter_endpoints (bool)

  • scatter_size (float)

  • drop_masked (bool)

SFI.utils.plotting.plot_field(coll, field, *, dataset=0, dir1=None, dir2=None, center=None, N=10, scale=1.0, autoscale=False, color='g', radius=None, positions=None, powernorm=0.0, mask_unvisited=False, clip_magnitude=None, **kwargs)[source]

Plot a 2D vector field (or a 2D slice of a higher-dimensional field).

Parameters:
  • coll (TrajectoryCollection) – TrajectoryCollection providing typical positions for scaling/centering.

  • field – Callable field(X) -> F with X of shape (n_points, d) and F of same shape.

  • dataset (int) – Dataset index inside the collection used to estimate center/radius.

  • dir1 – Projection directions in R^d. If None, use coordinate axes 0 and 1.

  • dir2 – Projection directions in R^d. If None, use coordinate axes 0 and 1.

  • center – Grid / scaling controls.

  • N (int) – Grid / scaling controls.

  • scale (float) – Grid / scaling controls.

  • autoscale (bool) – Grid / scaling controls.

  • color – Grid / scaling controls.

  • radius – Grid / scaling controls.

  • positions – Grid / scaling controls.

  • powernorm (float) – Grid / scaling controls.

  • **kwargs – Grid / scaling controls.

  • mask_unvisited (bool) – If True, drop arrows in grid cells with no trajectory data within one grid spacing (keeps the quiver legible in sparsely-sampled regions).

  • clip_magnitude – If set, clip each arrow’s magnitude to this value (long arrows in high-force regions no longer dominate the plot).

SFI.utils.plotting.plot_field_error(coll, field_inferred, field_exact, *, dataset=0, N=60, norm='l2', cmap='inferno', vmax=None, ax=None)[source]

2D heatmap of the pointwise force-reconstruction error.

Evaluates both fields on a grid spanning the (masked) data bounding box and renders ||F_exact - F_inferred|| as a pcolormesh. The spatial complement to comparison_scatter().

Parameters:
SFI.utils.plotting.plot_nematic_director(ax, Qxx, Qxy, rho, *, skip=2, scale=2.5, color='white', alpha=0.55, linewidth=0.45, **quiver_kw)[source]

Overlay the nematic director field of a Q-tensor on an image axes.

Given the order-parameter fields Qxx, Qxy and density rho (each a 2D grid), draws a headless quiver of the director ψ = ½·atan2(Qxy, Qxx) on a subsampled grid — the canonical active-nematic overlay.

Parameters:
  • ax – Target axes (typically holding an imshow of the density).

  • Qxx – 2D arrays of equal shape.

  • Qxy – 2D arrays of equal shape.

  • rho – 2D arrays of equal shape.

  • skip (int) – Subsampling stride for the director glyphs.

  • scale (float) – Glyph length (passed through to quiver scale).

  • color (str)

  • alpha (float)

  • linewidth (float)

SFI.utils.plotting.plot_pareto_front(result, *, criteria=('PASTIS', 'BIC', 'AIC'), ax=None)[source]

Plot the Pareto front: information gain vs model size, with IC optima.

Parameters:
  • result (SparsityResult) – As returned by inf.sparsify_force().

  • criteria (tuple of str) – Information-criterion names to mark on the plot.

  • ax (matplotlib Axes, optional) – If None, a new figure is created.

Returns:

ax

Return type:

matplotlib Axes

SFI.utils.plotting.plot_particles(coll, a=0, b=1, t_index=-1, colored=True, active=False, u=0.35, *, dataset=0, color_dim=None, cmap=None, vmin=None, vmax=None, quiver=False, heading_dim=None, box=None, s=100.0, ax=None, quiver_kw=None, **kwargs)[source]

Display all particles at time index t_index from a collection.

Parameters:
  • a (int) – State dimensions for the x/y axes of the snapshot.

  • b (int) – State dimensions for the x/y axes of the snapshot.

  • t_index (int) – Frame index (negative counts from the end).

  • colored (bool) – If True (and no color_dim), color particles by index (magma).

  • color_dim – Color particles by the value of this state dimension instead of by index — e.g. heading angle (default colormap "hsv").

  • cmap – Colormap / normalisation for the coloring.

  • vmin – Colormap / normalisation for the coloring.

  • vmax – Colormap / normalisation for the coloring.

  • quiver (bool) – If quiver=True, overlay heading arrows from cos/sin(X[:, heading_dim]) (heading_dim defaults to 2, the orientation channel of an active particle).

  • heading_dim – If quiver=True, overlay heading arrows from cos/sin(X[:, heading_dim]) (heading_dim defaults to 2, the orientation channel of an active particle).

  • box – Optional periodic box (Lx, Ly); positions are wrapped into it.

  • active (bool) – Legacy orientation marker (a dot at u·(cosθ, sinθ)); superseded by quiver for active-matter snapshots.

  • u (float) – Legacy orientation marker (a dot at u·(cosθ, sinθ)); superseded by quiver for active-matter snapshots.

  • ax – Target axes (default: current axes).

  • coll (TrajectoryCollection)

  • dataset (int)

  • s (float)

SFI.utils.plotting.plot_particles_field(coll, field, *, dataset=0, t_index=-1, dir1=None, dir2=None, center=None, radius=None, scale=1.0, autoscale=False, color='g', **kwargs)[source]

Plot a 2D vector field evaluated at particle positions at a given time.

Parameters:
SFI.utils.plotting.plot_profile_1d(coll, field, *, exact_field=None, dataset=0, dim=0, component=None, N=200, ci=None, samples=False, ax=None, margin=0.05, label_exact='Exact', label_inferred='Inferred')[source]

1D profile of an inferred field, optionally overlaid on the exact one.

Evaluates field on a grid spanning the data range along dim and plots the inferred profile (gold), an optional exact overlay (orange dashes), an optional confidence band, and an optional sample histogram backdrop. The 1D analog of plot_field() for forces F(x) and scalar diffusion profiles D(x) / D(v).

Parameters:
  • field – Callables f(X) -> array (vector (N, d) or tensor (N, d, d)). exact_field is optional.

  • exact_field – Callables f(X) -> array (vector (N, d) or tensor (N, d, d)). exact_field is optional.

  • dim (int) – Coordinate axis to sweep.

  • component – Which output component to plot. Defaults to dim for a vector field and (dim, dim) for a tensor field.

  • ci – Optional dict with "lower"/"upper" arrays (same length as the grid) for a confidence band.

  • samples (bool) – If True, draw a faint histogram of the data along dim behind the curves.

  • coll (TrajectoryCollection)

  • dataset (int)

  • N (int)

  • margin (float)

  • label_exact (str)

  • label_inferred (str)

SFI.utils.plotting.plot_recovery_bar(coeffs_inferred, support_inferred, *, coeffs_true=None, support_true=None, labels=None, stderr=None, yscale='linear', sort=False, show_pruned=False, ax=None)[source]

Bar chart of inferred sparse coefficients vs ground truth.

Parameters:
  • coeffs_inferred (array_like) – Coefficient values for the inferred support.

  • support_inferred (array_like) – Indices of the selected basis functions.

  • coeffs_true (array_like, optional) – Ground-truth coefficients / support (paired comparison).

  • support_true (array_like, optional) – Ground-truth coefficients / support (paired comparison).

  • labels (list of str, optional) – Tick labels for basis functions.

  • stderr (array_like, optional) – Standard errors for the inferred coefficients (drawn as error caps).

  • yscale (str) – Matplotlib y-scale ("linear" or "log"; use "log" for magnitude bars with widely varying scales).

  • sort (bool) – If True, order bars by descending |coefficient|.

  • show_pruned (bool) – If True (and labels given), append faded zero-bars for basis functions outside the inferred support.

  • ax (matplotlib Axes, optional) – If None, a new figure is created.

Returns:

ax

Return type:

matplotlib Axes

SFI.utils.plotting.plot_recovery_bar_multi(coeffs_list, labels, *, coeffs_true=None, group_names=None, ax=None)[source]

Grouped bar chart comparing coefficients across several models.

coeffs_list is a list of coefficient vectors (one per regime / solver), each aligned to labels. An optional coeffs_true is overlaid as a step reference.

SFI.utils.plotting.plot_recovery_matrix(true, inferred, *, row_labels=None, col_labels=None, cmap='RdBu_r', vmax=None, axes=None)[source]

Side-by-side imshow of a true vs inferred parameter matrix.

SFI.utils.plotting.plot_rods(ax, X_frame, *, angle_index=2, length=0.85, color='#d4a96a', linewidth=2.8, capstyle='round', **kwargs)[source]

Draw oriented rods (active-matter particles) as a LineCollection.

Each particle in X_frame (rows (x, y, …, θ, …)) becomes a short segment of length length centred on (x, y) and oriented at θ = X_frame[:, angle_index].

Parameters:
  • angle_index (int)

  • length (float)

  • color (str)

  • linewidth (float)

  • capstyle (str)

SFI.utils.plotting.plot_spde_snapshot(coll, t_indices, *, dataset=0, scalar_channel=0, vector_channels=None, grid_shape=None, dx=None, render='imshow', streamplot_kw=None, quiver_kw=None, axes=None, vmin=None, vmax=None, cmap='magma')[source]

Render SPDE field snapshots from a gridded TrajectoryCollection.

Reshapes each requested frame X[t] of shape (N, n_channels) to (*grid_shape, n_channels) and draws scalar_channel as an imshow image, optionally overlaying vector_channels as streamlines (render="streamplot") or arrows (render="quiver").

Parameters:
  • t_indices – A single frame index, or a sequence of indices (one panel each).

  • grid_shape(nx, ny) of the field grid. Inferred as a square grid when omitted.

  • dx – Physical grid spacing (default 1.0).

  • vmin – Color limits; default to the 0.5/99.5 percentiles of the field.

  • vmax – Color limits; default to the 0.5/99.5 percentiles of the field.

  • coll (TrajectoryCollection)

  • dataset (int)

  • scalar_channel (int)

  • render (str)

  • cmap (str)

SFI.utils.plotting.plot_tensor_field(coll, field, *, dataset=0, center=None, N=10, scale=1.0, autoscale=False, color='g', radius=None, positions=None, mode='eigencross', **kwargs)[source]

Plot a tensor field for 2D processes from a TrajectoryCollection.

mode="eigencross" (default) draws each tensor as a pair of eigen-axis arrows; mode="ellipse" draws an eigen-aligned ellipse glyph (axis lengths sqrt(eigenvalue)), a clearer rendering for anisotropic diffusion fields.

Parameters:
SFI.utils.plotting.plot_time_profile_comparison(t, true_profiles, inferred_profiles, *, labels=None, axes=None)[source]

Plot true vs inferred time-dependent profiles (e.g. k(t), a(t)).

true_profiles and inferred_profiles are sequences of 1D arrays (one per panel); true_profiles entries may be None to skip the reference. labels gives a title per panel.

SFI.utils.plotting.spatial_acorr2d(field_2d, *, dx=1.0, n_bins=None, normalize=True)[source]

Radially-averaged 2D spatial autocorrelation via FFT (periodic).

Returns (r, C) where C(r) is the angle-averaged autocorrelation of field_2d (mean removed) at radial separation r. Assumes a periodic grid.

Parameters:
  • dx (float)

  • normalize (bool)

SFI.utils.plotting.stamp_fig(fig=None)[source]

Add a discreet generation timestamp to the bottom-right of a figure.

Useful for tracking when a cached or gallery figure was last rendered. Idempotent: a figure is only stamped once.

Parameters:

fig (matplotlib.figure.Figure, optional) – Figure to stamp. Defaults to plt.gcf().

SFI.utils.plotting.stamp_output()[source]

Print a discreet generation timestamp to stdout.

Call once per script so the timestamp appears in terminal output blocks on gallery pages and in notebook cells.

SFI.utils.plotting.stream_field(coll, field, *, dataset=0, dir1=None, dir2=None, center=None, radius=None, N=20, density=1.0, color='#808080', ax=None, **streamplot_kw)[source]

Streamplot of a callable vector field over the data domain.

The streamline counterpart to plot_field() (quiver): integrates field(X) -> F into flow lines on a grid spanning the data bounding box. Useful for visualising the topology of an inferred or analytic drift field.

Parameters:
SFI.utils.plotting.timeseries(coll, *, dims=None, dataset=0, particles=None, transform=None, ax=None, **plot_kw)[source]

Plot x[dim](t) for one or many particles from a TrajectoryCollection.

By default, plot all dimensions for the selected particles.

Parameters:
  • coll (TrajectoryCollection) – TrajectoryCollection containing the data.

  • dims – Iterable of state dimensions to plot. If None, plot all dims.

  • dataset (int) – Dataset index inside the collection (default 0).

  • particles – Iterable of particle indices to include. If None, include all particles.

  • transform – Optional callable applied elementwise to the plotted values (e.g. np.exp to map a log-space coordinate back to population space).

  • ax – Optional Matplotlib Axes. If None, use plt.gca().

  • **plot_kw – Forwarded to ax.plot.

Returns:

Matplotlib Axes used.

Return type:

ax

SFI.utils.plotting.timeseries_colored(coll, *, color_fn, dataset=0, dims=None, particles=None, cmap='plasma', colorbar_label='', plot_colorbar=True, ax=None, s=4.0, alpha=1.0, rasterized=True, **scatter_kw)[source]

Plot x[dim](t) as a scatter colored by a scalar field.

Mask-aware time series in which each point is colored by color_fn(X) — e.g. the local diffusivity along the trajectory. color_fn receives points of shape (n_points, d) and returns a scalar per point. A single shared colorbar spans all series.

Parameters:
  • coll (TrajectoryCollection)

  • dataset (int)

  • colorbar_label (str)

  • plot_colorbar (bool)

  • s (float)

  • alpha (float)

  • rasterized (bool)

SFI.utils.plotting.trajectory_scatter(coll, *, dataset=0, dims=(0, 1), particles=None, tmin=None, tmax=None, cmap=None, s=2.0, alpha=0.1, ax=None, drop_masked=True, **scatter_kw)[source]

All-frames density scatter cloud of a 2D projection.

Unlike phase2d() (connected lines) or plot_particles() (one frame), this scatters every valid (particle, frame) position — useful for occupancy / home-range visualisations. With cmap set, points are colored by time.

Parameters:
SFI.utils.plotting.wrap_positions(X, box)[source]

Wrap positions into a periodic box [0, box_i) per axis.

Parameters:
  • X (array_like, shape (..., d)) – Position array.

  • box (array_like, shape (d,) or (2,)) – Box dimensions.

Returns:

X_wrapped – Copy of X with each column wrapped modulo the corresponding box dimension.

Return type:

ndarray