Visualization (rheojax.visualization)

The visualization module provides publication-quality plotting functions for rheological data.

Plotting Functions

Core plotting functions for rheological data visualization.

This module provides publication-quality plotting utilities for rheological data, with automatic plot type selection based on data characteristics.

rheojax.visualization.plotter.plot_rheo_data(data, style='default', **kwargs)[source]

Plot RheoData with automatic plot type selection.

This function automatically selects the appropriate plot type based on the data domain, test mode, and data characteristics.

Parameters:
  • data (RheoData) – RheoData object to plot

  • style (str) – Plotting style (‘default’, ‘publication’, ‘presentation’)

  • **kwargs (Any) – Additional keyword arguments passed to matplotlib

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

Examples

>>> time = np.linspace(0, 10, 100)
>>> stress = 1000 * np.exp(-time / 2)
>>> data = RheoData(x=time, y=stress, domain="time")
>>> fig, ax = plot_rheo_data(data)
rheojax.visualization.plotter.plot_time_domain(x, y, x_units=None, y_units=None, log_x=False, log_y=False, style='default', **kwargs)[source]

Plot time-domain rheological data.

Parameters:
  • x (ndarray) – Independent variable (typically time)

  • y (ndarray) – Dependent variable (stress, strain, etc.)

  • x_units (str | None) – Units for x-axis

  • y_units (str | None) – Units for y-axis

  • log_x (bool) – Use logarithmic scale for x-axis

  • log_y (bool) – Use logarithmic scale for y-axis

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

rheojax.visualization.plotter.plot_frequency_domain(x, y, x_units=None, y_units=None, style='default', **kwargs)[source]

Plot frequency-domain rheological data (complex modulus).

For complex data, creates two subplots for G’ (storage modulus) and G’’ (loss modulus). For real data, creates a single plot.

Parameters:
  • x (ndarray) – Frequency data

  • y (ndarray) – Complex modulus data (G* = G’ + iG’’)

  • x_units (str | None) – Units for frequency axis

  • y_units (str | None) – Units for modulus

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot. deformation_mode: str, optional — ‘tension’/’bending’/’compression’ causes labels to show E’/E’’ instead of G’/G’’.

Return type:

tuple[Figure, ndarray]

Returns:

Tuple of (Figure, np.ndarray of Axes). For complex data the array has shape (2,); for real data it has shape (1,) so callers can always index the result uniformly (e.g. axes[0]).

rheojax.visualization.plotter.plot_flow_curve(x, y, x_units=None, y_units=None, x_label=None, y_label=None, style='default', **kwargs)[source]

Plot flow curve (viscosity or stress vs shear rate).

Parameters:
  • x (ndarray) – Shear rate data

  • y (ndarray) – Viscosity or stress data

  • x_units (str | None) – Units for shear rate

  • y_units (str | None) – Units for y-axis

  • x_label (str | None) – Custom x-axis label

  • y_label (str | None) – Custom y-axis label

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

rheojax.visualization.plotter.plot_residuals(x, residuals, y_true=None, y_pred=None, x_units=None, style='default', **kwargs)[source]

Plot residuals from model fitting.

If y_true and y_pred are provided, creates two subplots: one with data and predictions, and one with residuals. Otherwise, plots only residuals.

Parameters:
  • x (ndarray) – Independent variable

  • residuals (ndarray) – Residual values (y_true - y_pred)

  • y_true (ndarray | None) – True y values (optional)

  • y_pred (ndarray | None) – Predicted y values (optional)

  • x_units (str | None) – Units for x-axis

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

rheojax.visualization.plotter.compute_uncertainty_band(model_fn, x_pred, popt, pcov, confidence=0.95)[source]

Compute prediction uncertainty band via error propagation.

Uses the formula: sigma_y(x) = sqrt(diag(J @ pcov @ J.T)) where J is the Jacobian of the model with respect to parameters.

For 95% confidence interval, the band is +/-1.96 * sigma_y(x).

Parameters:
  • model_fn (Any) – Model function that takes (x, params) and returns predictions. Must be compatible with JAX autodiff for Jacobian computation.

  • x_pred (ndarray) – X values for prediction (n_points,)

  • popt (ndarray) – Optimal parameter values (n_params,)

  • pcov (ndarray) – Parameter covariance matrix (n_params x n_params)

  • confidence (float) – Confidence level (default: 0.95 for 95% CI)

Returns:

  • y_fit: Fitted values at x_pred

  • y_lower: Lower bound of confidence interval

  • y_upper: Upper bound of confidence interval

Return type:

tuple[ndarray, ndarray, ndarray]

Example

>>> def model(x, params):
...     a, b = params
...     return a * x + b
>>> x = np.linspace(0, 10, 50)
>>> popt = np.array([2.0, 1.0])
>>> pcov = np.array([[0.01, 0.0], [0.0, 0.05]])
>>> y_fit, y_lo, y_hi = compute_uncertainty_band(model, x, popt, pcov)

Note

Complex-valued y_fit is not supported for uncertainty bands. If y_fit is complex, the function returns (y_fit, None, None) and logs a debug message. Callers should check for None before using y_lower and y_upper.

rheojax.visualization.plotter.plot_fit_with_uncertainty(x_data, y_data, x_fit, y_fit, y_lower=None, y_upper=None, log_x=True, log_y=True, data_label='Data', fit_label='Fit', band_label='95% CI', x_label=None, y_label=None, style='default', ax=None, **kwargs)[source]

Plot data with fitted curve and optional uncertainty band.

Creates publication-quality fit plots with: - Scatter data points - Solid fitted curve - Shaded uncertainty band (if y_lower/y_upper provided) - Legend with customizable labels

Parameters:
  • x_data (ndarray) – Experimental x values

  • y_data (ndarray) – Experimental y values

  • x_fit (ndarray) – X values for fitted curve (can be denser than data)

  • y_fit (ndarray) – Fitted y values

  • y_lower (ndarray | None) – Lower bound of uncertainty band (optional)

  • y_upper (ndarray | None) – Upper bound of uncertainty band (optional)

  • log_x (bool) – Use log scale for x-axis (default: True)

  • log_y (bool) – Use log scale for y-axis (default: True)

  • data_label (str) – Legend label for data points

  • fit_label (str) – Legend label for fitted curve

  • band_label (str) – Legend label for uncertainty band

  • x_label (str | None) – X-axis label

  • y_label (str | None) – Y-axis label

  • style (str) – Plot style (‘default’, ‘publication’, ‘presentation’)

  • ax (Axes | None) – Optional existing axes to plot on

  • **kwargs (Any) – Additional arguments passed to scatter/plot

Return type:

tuple[Figure | None, Axes]

Returns:

Tuple of (Figure, Axes). Figure is None if ax was provided.

Example

>>> x = np.logspace(-1, 2, 20)
>>> y = 100 * x ** -0.5 + np.random.randn(20) * 5
>>> x_fit = np.logspace(-1, 2, 100)
>>> y_fit = 100 * x_fit ** -0.5
>>> fig, ax = plot_fit_with_uncertainty(x, y, x_fit, y_fit)
rheojax.visualization.plotter.save_figure(fig, filepath, format=None, dpi=300, bbox_inches='tight', **kwargs)[source]

Save matplotlib figure to file with publication-quality defaults.

This convenience function wraps matplotlib’s savefig() with sensible defaults for publication-quality figures, automatic format detection, and path validation.

Parameters:
  • fig (Figure) – Figure object to save

  • filepath (str | Path) – Output file path. Format inferred from extension if not specified.

  • format (str | None) – File format. Supported: ‘pdf’, ‘svg’, ‘png’, ‘eps’, ‘tiff’, ‘jpg’, ‘webp’. Auto-detected from file extension if None.

  • dpi (int) – Resolution for raster formats (PNG). Ignored for vector formats (PDF, SVG, EPS). Common values: - 150: Draft quality - 300: Publication quality (default) - 600: High-resolution print

  • bbox_inches (str) – Bounding box adjustment. ‘tight’ removes extra whitespace around figure.

  • **kwargs (Any) – Additional keyword arguments passed to matplotlib’s savefig(). Common options: - transparent : bool - Transparent background (default False) - facecolor : color - Figure background color - edgecolor : color - Figure edge color - pad_inches : float - Padding around figure

Returns:

Absolute path to saved file (for confirmation/logging)

Return type:

Path

Raises:
  • ValueError – If format cannot be inferred from filepath or is unsupported

  • OSError – If filepath directory doesn’t exist or lacks write permissions

Examples

Save figure to PDF with defaults:

>>> fig, ax = plot_rheo_data(data)
>>> save_figure(fig, 'analysis.pdf')
PosixPath('/path/to/analysis.pdf')

Save PNG with high resolution:

>>> save_figure(fig, 'figure.png', dpi=600)
PosixPath('/path/to/figure.png')

Save SVG with transparent background:

>>> save_figure(fig, 'diagram.svg', transparent=True)
PosixPath('/path/to/diagram.svg')

Explicit format specification:

>>> save_figure(fig, 'output', format='pdf')
PosixPath('/path/to/output.pdf')

See also

plot_rheo_data

Automatic plot type selection

Pipeline.save_figure

Fluent API integration

Notes

Supported formats: - PDF: Vector format, ideal for publications and LaTeX documents - SVG: Vector format, editable in Inkscape/Illustrator - PNG: Raster format, good for presentations and web - EPS: Vector format, legacy publication format - TIFF: Raster format, lossless, common in scientific publishing - JPG/JPEG: Raster format, lossy, good for photos - WEBP: Raster format, modern lossy/lossless, good for web

DPI only affects raster formats (PNG, TIFF, JPG, WEBP). Vector formats (PDF, SVG, EPS) are resolution-independent.

Main Plotting Function

rheojax.visualization.plotter.plot_rheo_data(data, style='default', **kwargs)[source]

Plot RheoData with automatic plot type selection.

This function automatically selects the appropriate plot type based on the data domain, test mode, and data characteristics.

Parameters:
  • data (RheoData) – RheoData object to plot

  • style (str) – Plotting style (‘default’, ‘publication’, ‘presentation’)

  • **kwargs (Any) – Additional keyword arguments passed to matplotlib

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

Examples

>>> time = np.linspace(0, 10, 100)
>>> stress = 1000 * np.exp(-time / 2)
>>> data = RheoData(x=time, y=stress, domain="time")
>>> fig, ax = plot_rheo_data(data)

Main entry point for plotting RheoData with automatic plot type selection.

Plot type selection logic:

  1. Frequency domain or oscillation test -> plot_frequency_domain()

  2. Rotation test or shear rate units -> plot_flow_curve()

  3. Time domain -> plot_time_domain()

Specialized Plot Types

rheojax.visualization.plotter.plot_time_domain(x, y, x_units=None, y_units=None, log_x=False, log_y=False, style='default', **kwargs)[source]

Plot time-domain rheological data.

Parameters:
  • x (ndarray) – Independent variable (typically time)

  • y (ndarray) – Dependent variable (stress, strain, etc.)

  • x_units (str | None) – Units for x-axis

  • y_units (str | None) – Units for y-axis

  • log_x (bool) – Use logarithmic scale for x-axis

  • log_y (bool) – Use logarithmic scale for y-axis

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

Plot time-domain data (relaxation, creep).

rheojax.visualization.plotter.plot_frequency_domain(x, y, x_units=None, y_units=None, style='default', **kwargs)[source]

Plot frequency-domain rheological data (complex modulus).

For complex data, creates two subplots for G’ (storage modulus) and G’’ (loss modulus). For real data, creates a single plot.

Parameters:
  • x (ndarray) – Frequency data

  • y (ndarray) – Complex modulus data (G* = G’ + iG’’)

  • x_units (str | None) – Units for frequency axis

  • y_units (str | None) – Units for modulus

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot. deformation_mode: str, optional — ‘tension’/’bending’/’compression’ causes labels to show E’/E’’ instead of G’/G’’.

Return type:

tuple[Figure, ndarray]

Returns:

Tuple of (Figure, np.ndarray of Axes). For complex data the array has shape (2,); for real data it has shape (1,) so callers can always index the result uniformly (e.g. axes[0]).

Plot frequency-domain data (oscillatory tests).

For complex data (G*), creates two subplots for \(G'\) and \(G''\). For real data, creates a single plot.

rheojax.visualization.plotter.plot_flow_curve(x, y, x_units=None, y_units=None, x_label=None, y_label=None, style='default', **kwargs)[source]

Plot flow curve (viscosity or stress vs shear rate).

Parameters:
  • x (ndarray) – Shear rate data

  • y (ndarray) – Viscosity or stress data

  • x_units (str | None) – Units for shear rate

  • y_units (str | None) – Units for y-axis

  • x_label (str | None) – Custom x-axis label

  • y_label (str | None) – Custom y-axis label

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

Plot flow curves (viscosity or stress vs shear rate).

rheojax.visualization.plotter.plot_residuals(x, residuals, y_true=None, y_pred=None, x_units=None, style='default', **kwargs)[source]

Plot residuals from model fitting.

If y_true and y_pred are provided, creates two subplots: one with data and predictions, and one with residuals. Otherwise, plots only residuals.

Parameters:
  • x (ndarray) – Independent variable

  • residuals (ndarray) – Residual values (y_true - y_pred)

  • y_true (ndarray | None) – True y values (optional)

  • y_pred (ndarray | None) – Predicted y values (optional)

  • x_units (str | None) – Units for x-axis

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib plot

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

Plot residuals from model fitting.

If y_true and y_pred are provided, creates two subplots. Otherwise, plots residuals only.

Plotting Styles

Three built-in styles for different contexts:

rheojax.visualization.plotter.DEFAULT_STYLE

General-purpose style for interactive work.

  • Figure size: 8x6 inches

  • Font size: 11 pt

  • Line width: 1.5 pt

rheojax.visualization.plotter.PUBLICATION_STYLE

Optimized for journal publications.

  • Figure size: 6x4.5 inches

  • Font size: 10 pt

  • Line width: 1.2 pt

  • Smaller markers

rheojax.visualization.plotter.PRESENTATION_STYLE

Large, clear plots for presentations.

  • Figure size: 10x7 inches

  • Font size: 14 pt

  • Line width: 2.0 pt

  • Larger markers

Templates

Plot templates for common rheological visualizations.

This module provides template-based plotting functions for standard rheological plots including stress-strain, modulus-frequency, and mastercurve plots.

rheojax.visualization.templates.plot_stress_strain(data, style='default', **kwargs)[source]

Plot stress-strain or time-dependent rheological data.

This template is designed for relaxation and creep tests, plotting stress or strain versus time.

Parameters:
  • data (RheoData) – RheoData object containing time-domain data

  • style (str) – Plotting style (‘default’, ‘publication’, ‘presentation’)

  • **kwargs (Any) – Additional keyword arguments for matplotlib

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

Examples

>>> time = np.linspace(0, 100, 200)
>>> stress = 1000 * np.exp(-time / 20)
>>> data = RheoData(x=time, y=stress, domain="time")
>>> fig, ax = plot_stress_strain(data)
rheojax.visualization.templates.plot_modulus_frequency(data, separate_axes=True, style='default', **kwargs)[source]

Plot storage and loss modulus versus frequency.

This template is designed for oscillatory (SAOS) test data, plotting G’ and G’’ versus frequency on log-log axes.

Parameters:
  • data (RheoData) – RheoData object containing frequency-domain data

  • separate_axes (bool) – If True, plot G’ and G’’ on separate axes

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

Examples

>>> frequency = np.logspace(-2, 2, 50)
>>> G_complex = 1e5 / (1 + 1j * frequency)
>>> data = RheoData(x=frequency, y=G_complex, domain="frequency")
>>> fig, axes = plot_modulus_frequency(data)
rheojax.visualization.templates.plot_mastercurve(datasets, reference_temp=None, shift_factors=None, show_shifts=False, style='default', **kwargs)[source]

Plot mastercurve from multiple temperature datasets.

This template creates a time-temperature superposition plot, overlaying data from multiple temperatures with optional shift factors.

Parameters:
  • datasets (list[RheoData]) – List of RheoData objects at different temperatures

  • reference_temp (float | None) – Reference temperature (if None, uses first dataset)

  • shift_factors (dict[float, float] | None) – Dictionary mapping temperature to shift factor

  • show_shifts (bool) – If True, display shift factors in legend

  • style (str) – Plotting style

  • **kwargs (Any) – Additional keyword arguments for matplotlib

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes)

Examples

>>> datasets = []
>>> for temp in [20, 25, 30]:
...     freq = np.logspace(-2, 2, 50)
...     G = 1e5 / (1 + 1j * freq)
...     datasets.append(RheoData(x=freq, y=G, metadata={'temperature': temp}))
>>> fig, ax = plot_mastercurve(datasets)
rheojax.visualization.templates.plot_model_fit(data, predictions, show_residuals=True, style='default', model_name=None, **kwargs)[source]

Plot experimental data with model predictions and residuals.

This template creates a standard model fitting visualization showing data, model predictions, and optionally residuals.

Parameters:
  • data (RheoData) – RheoData object with experimental data

  • predictions (ndarray | Array) – Model predictions

  • show_residuals (bool) – If True, add residuals subplot

  • style (str) – Plotting style

  • model_name (str | None) – Name of the model (for title)

  • **kwargs (Any) – Additional keyword arguments for matplotlib

Return type:

tuple[Figure, Axes | ndarray]

Returns:

Tuple of (Figure, Axes) or (Figure, array of Axes)

Examples

>>> freq = np.logspace(-2, 2, 50)
>>> G_data = 1e5 / (1 + 1j * freq)
>>> G_pred = G_data * 1.02  # Slight variation
>>> data = RheoData(x=freq, y=G_data, domain="frequency")
>>> fig, axes = plot_model_fit(data, G_pred)
rheojax.visualization.templates.apply_template_style(ax, style='default', **kwargs)[source]

Apply template styling to an existing axis.

This function applies consistent styling to matplotlib axes based on the selected template style.

Parameters:
  • ax (Axes) – Matplotlib axis to style

  • style (str) – Style name (‘default’, ‘publication’, ‘presentation’)

  • **kwargs (Any) – Additional style parameters to override

Return type:

None

Examples

>>> fig, ax = plt.subplots()
>>> ax.plot([1, 2, 3], [1, 2, 3])
>>> apply_template_style(ax, style='publication')

The templates module provides reusable plot templates for common visualization tasks.

EPM Visualization

Visualization tools for Lattice Elasto-Plastic Models.

rheojax.visualization.epm_plots.plot_lattice_fields(stress, thresholds, title=None, figsize=None, cmap_stress='coolwarm', cmap_thresh='viridis')[source]

Plot EPM lattice fields with auto-detection of scalar vs tensorial stress.

Automatically detects whether stress is scalar (L, L) or tensorial (3, L, L) and dispatches to the appropriate plotting function.

Parameters:
  • stress (ndarray | Array) – Either (L, L) scalar or (3, L, L) tensorial stress field.

  • thresholds (ndarray | Array) – 2D array of local yield thresholds (L, L).

  • title (str | None) – Overall figure title (auto-generated if None).

  • figsize (tuple[int, int] | None) – Figure size (width, height) (auto-selected if None).

  • cmap_stress (str) – Colormap for stress field (diverging).

  • cmap_thresh (str) – Colormap for threshold field (sequential).

Return type:

Figure

Returns:

Matplotlib Figure object.

Raises:

ValueError – If stress shape is invalid.

rheojax.visualization.epm_plots.animate_stress_evolution(stress_history, interval=50, cmap='coolwarm', save_path=None)[source]

Create an animation of the stress field evolution.

Parameters:
  • stress_history (ndarray | Array) – 3D array of stress history (Time, L, L).

  • interval (int) – Delay between frames in milliseconds.

  • cmap (str) – Colormap for stress.

  • save_path (str | None) – If provided, save the animation to this path (e.g. ‘movie.mp4’).

Return type:

FuncAnimation

Returns:

Matplotlib FuncAnimation object.

rheojax.visualization.epm_plots.plot_tensorial_fields(stress, figsize=(15, 4), cmap='coolwarm', ax=None, **kwargs)[source]

Plot all three stress tensor components in a 3-panel layout.

Parameters:
  • stress (ndarray | Array) – Stress tensor of shape (3, L, L) with [σ_xx, σ_yy, σ_xy].

  • figsize (tuple[int, int]) – Figure size (width, height).

  • cmap (str) – Colormap for stress fields (diverging, centered at 0).

  • ax (Axes | list[Axes] | None) – Optional pre-existing axes (3 axes required).

  • **kwargs – Additional arguments passed to imshow.

Return type:

tuple[Figure, list[Axes]]

Returns:

Tuple of (Figure, list of 3 Axes).

rheojax.visualization.epm_plots.plot_normal_stress_field(stress, nu=0.5, figsize=(6, 5), cmap='coolwarm', ax=None, **kwargs)[source]

Plot first normal stress difference field N₁ = σ_xx - σ_yy.

Parameters:
  • stress (ndarray | Array) – Stress tensor of shape (3, L, L) with [σ_xx, σ_yy, σ_xy].

  • nu (float) – Poisson’s ratio (not used for N₁, but kept for consistency).

  • figsize (tuple[int, int]) – Figure size (width, height).

  • cmap (str) – Colormap (diverging, centered at 0).

  • ax (Axes | None) – Optional pre-existing axis.

  • **kwargs – Additional arguments passed to imshow.

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes).

rheojax.visualization.epm_plots.plot_von_mises_field(stress, thresholds, nu=0.5, figsize=(12, 5), ax=None, **kwargs)[source]

Plot von Mises effective stress and normalized yield map.

Creates a 2-panel figure:

  • Left: σ_eff with viridis (sequential)

  • Right: σ_eff/σ_c with RdYlGn_r centered at 1 (Green <1: elastic, Yellow ≈1: near yield, Red >1: plastic)

Parameters:
  • stress (ndarray | Array) – Stress tensor of shape (3, L, L) with [σ_xx, σ_yy, σ_xy].

  • thresholds (ndarray | Array) – Yield thresholds of shape (L, L).

  • nu (float) – Poisson’s ratio for plane strain constraint.

  • figsize (tuple[int, int]) – Figure size (width, height).

  • ax (Axes | list[Axes] | None) – Optional pre-existing axes (2 axes required).

  • **kwargs – Additional arguments passed to imshow.

Return type:

tuple[Figure, list[Axes]]

Returns:

Tuple of (Figure, list of 2 Axes).

rheojax.visualization.epm_plots.plot_normal_stress_ratio(shear_rates, N1, sigma_xy, figsize=(8, 6), ax=None, **kwargs)[source]

Plot log-log of N₁/σ_xy vs shear rate.

Parameters:
  • shear_rates (ndarray | Array) – Array of shear rates.

  • N1 (ndarray | Array) – First normal stress difference values.

  • sigma_xy (ndarray | Array) – Shear stress values.

  • figsize (tuple[int, int]) – Figure size (width, height).

  • ax (Axes | None) – Optional pre-existing axis.

  • **kwargs – Additional arguments passed to plot.

Return type:

tuple[Figure, Axes]

Returns:

Tuple of (Figure, Axes).

rheojax.visualization.epm_plots.animate_tensorial_evolution(history, component='all', interval=50, save_path=None, **kwargs)[source]

Create animation of tensorial stress field evolution.

Parameters:
  • history (dict[str, ndarray | Array]) – Dictionary with keys: - ‘stress’: Stress history of shape (T, 3, L, L) - ‘time’: Time array of shape (T,)

  • component (str) – Component to animate: - ‘all’: All 3 components (3-panel animation) - ‘xx’, ‘yy’, ‘xy’: Individual components - ‘N1’: First normal stress difference - ‘vm’: von Mises effective stress

  • interval (int) – Delay between frames in milliseconds.

  • save_path (str | None) – If provided, save animation to this path.

  • **kwargs – Additional arguments (e.g., nu for von Mises).

Return type:

FuncAnimation

Returns:

Matplotlib FuncAnimation object.

Tools for visualizing spatially heterogeneous fields in Lattice EPM simulations.

Functions

rheojax.visualization.epm_plots.plot_lattice_fields(stress, thresholds, title=None, figsize=None, cmap_stress='coolwarm', cmap_thresh='viridis')[source]

Plot EPM lattice fields with auto-detection of scalar vs tensorial stress.

Automatically detects whether stress is scalar (L, L) or tensorial (3, L, L) and dispatches to the appropriate plotting function.

Parameters:
  • stress (ndarray | Array) – Either (L, L) scalar or (3, L, L) tensorial stress field.

  • thresholds (ndarray | Array) – 2D array of local yield thresholds (L, L).

  • title (str | None) – Overall figure title (auto-generated if None).

  • figsize (tuple[int, int] | None) – Figure size (width, height) (auto-selected if None).

  • cmap_stress (str) – Colormap for stress field (diverging).

  • cmap_thresh (str) – Colormap for threshold field (sequential).

Return type:

Figure

Returns:

Matplotlib Figure object.

Raises:

ValueError – If stress shape is invalid.

Plots stress and yield threshold fields side-by-side.

rheojax.visualization.epm_plots.animate_stress_evolution(stress_history, interval=50, cmap='coolwarm', save_path=None)[source]

Create an animation of the stress field evolution.

Parameters:
  • stress_history (ndarray | Array) – 3D array of stress history (Time, L, L).

  • interval (int) – Delay between frames in milliseconds.

  • cmap (str) – Colormap for stress.

  • save_path (str | None) – If provided, save the animation to this path (e.g. ‘movie.mp4’).

Return type:

FuncAnimation

Returns:

Matplotlib FuncAnimation object.

Creates an animation of the stress field evolution over time.

Examples

Basic Plotting

Auto-Detection

from rheojax.core import RheoData
from rheojax.visualization import plot_rheo_data
import matplotlib.pyplot as plt
import numpy as np

# Create data
time = np.logspace(-1, 2, 50)
stress = 1000 * np.exp(-time / 5)
data = RheoData(x=time, y=stress, x_units="s", y_units="Pa", domain="time")

# Plot with automatic type detection
fig, ax = plot_rheo_data(data)
plt.show()

Using Styles

# Default style
fig, ax = plot_rheo_data(data, style='default')

# Publication style
fig, ax = plot_rheo_data(data, style='publication')
fig.savefig('figure.pdf', bbox_inches='tight')

# Presentation style
fig, ax = plot_rheo_data(data, style='presentation')

Time-Domain Plots

Stress Relaxation

from rheojax.visualization import plot_time_domain

time = np.logspace(-1, 2, 50)
stress = 1000 * np.exp(-time / 5)

fig, ax = plot_time_domain(
    x=time,
    y=stress,
    x_units="s",
    y_units="Pa",
    log_x=True,
    log_y=False,
    style='publication'
)

ax.set_title("Stress Relaxation")
plt.show()

Creep Compliance

time = np.logspace(-1, 2, 50)
compliance = 1e-4 * (1 + time**0.5)

fig, ax = plot_time_domain(
    x=time,
    y=compliance,
    x_units="s",
    y_units="1/Pa",
    log_x=True,
    log_y=True,
    style='publication'
)

ax.set_title("Creep Compliance")
ax.set_ylabel("J(t) (1/Pa)")
plt.show()

Frequency-Domain Plots

Complex Modulus

from rheojax.visualization import plot_frequency_domain

# Complex modulus
omega = np.logspace(-2, 2, 50)
Gp = 1000 * omega**0.5        # G'
Gpp = 500 * omega**0.3        # G"
G_star = Gp + 1j * Gpp

fig, axes = plot_frequency_domain(
    x=omega,
    y=G_star,
    x_units="rad/s",
    y_units="Pa",
    style='publication'
)

# axes[0] is for G', axes[1] is for G"
axes[0].set_title("Storage Modulus")
axes[1].set_title("Loss Modulus")
plt.show()

Single Modulus

# Plot only G'
fig, axes = plot_frequency_domain(
    x=omega,
    y=Gp,  # Real values
    x_units="rad/s",
    y_units="Pa"
)

# axes is a list with single element
axes[0].set_title("Storage Modulus")
plt.show()

Flow Curves

Viscosity vs Shear Rate

from rheojax.visualization import plot_flow_curve

shear_rate = np.logspace(-2, 3, 50)
viscosity = 100 * shear_rate**(-0.7)  # Shear thinning

fig, ax = plot_flow_curve(
    x=shear_rate,
    y=viscosity,
    x_units="1/s",
    y_units="Pa.s",
    x_label="Shear Rate (1/s)",
    y_label="Viscosity (Pa·s)",
    style='publication'
)

ax.set_title("Flow Curve")
plt.show()

Stress vs Shear Rate

stress = 50 * shear_rate**0.5  # Shear thickening

fig, ax = plot_flow_curve(
    x=shear_rate,
    y=stress,
    x_units="1/s",
    y_units="Pa",
    y_label="Shear Stress (Pa)",
    style='publication'
)

Residual Plots

With Data Comparison

from rheojax.visualization import plot_residuals

# Experimental and predicted data
time = np.linspace(0, 10, 50)
stress_true = 1000 * np.exp(-time / 5)
stress_pred = 980 * np.exp(-time / 4.8)
residuals = stress_true - stress_pred

fig, axes = plot_residuals(
    x=time,
    residuals=residuals,
    y_true=stress_true,
    y_pred=stress_pred,
    x_units="s",
    style='publication'
)

# axes[0]: Data and predictions
# axes[1]: Residuals
axes[0].set_title("Model Fit")
axes[1].set_title("Residuals")
plt.show()

Residuals Only

fig, ax = plot_residuals(
    x=time,
    residuals=residuals,
    x_units="s"
)

ax.set_title("Residuals")
plt.show()

Customization

Matplotlib Keyword Arguments

All plotting functions accept matplotlib kwargs:

fig, ax = plot_time_domain(
    x=time,
    y=stress,
    color='red',
    marker='s',
    markersize=8,
    linestyle='--',
    label='Experimental',
    alpha=0.7
)

ax.legend()

Advanced Styling

import matplotlib.pyplot as plt

# Custom figure size
fig, ax = plt.subplots(figsize=(10, 6))

# Manual plotting with rheojax data
ax.semilogy(data.x, data.y, 'o-', label='Data')

# Customize
ax.set_xlabel('Time (s)', fontsize=14, fontweight='bold')
ax.set_ylabel('Stress (Pa)', fontsize=14, fontweight='bold')
ax.set_title('Custom Plot', fontsize=16)
ax.grid(True, which='both', linestyle=':', alpha=0.5)
ax.legend(fontsize=12)

fig.tight_layout()

Multi-Panel Figures

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# Top-left: Relaxation
axes[0, 0].semilogx(time, stress, 'o-')
axes[0, 0].set_ylabel('Stress (Pa)')
axes[0, 0].set_title('Relaxation')

# Top-right: Creep
axes[0, 1].loglog(time, compliance, 's-')
axes[0, 1].set_ylabel('Compliance (1/Pa)')
axes[0, 1].set_title('Creep')

# Bottom-left: Oscillatory
axes[1, 0].loglog(omega, Gp, 'o-', label="G'")
axes[1, 0].loglog(omega, Gpp, 's-', label='G"')
axes[1, 0].set_xlabel('omega (rad/s)')
axes[1, 0].set_ylabel('Modulus (Pa)')
axes[1, 0].legend()

# Bottom-right: Flow curve
axes[1, 1].loglog(shear_rate, viscosity, '^-')
axes[1, 1].set_xlabel('Shear Rate (1/s)')
axes[1, 1].set_ylabel('Viscosity (Pa·s)')

fig.tight_layout()

Saving Figures

Raster Formats

# PNG - high resolution
fig.savefig('figure.png', dpi=300, bbox_inches='tight')

# JPEG - smaller file
fig.savefig('figure.jpg', dpi=150, quality=95)

Vector Formats

# PDF - best for publications
fig.savefig('figure.pdf', bbox_inches='tight')

# SVG - editable
fig.savefig('figure.svg', bbox_inches='tight')

# EPS - for some journals
fig.savefig('figure.eps', bbox_inches='tight')

Multiple Formats

# Save in all formats
for fmt in ['png', 'pdf', 'svg']:
    fig.savefig(f'figure.{fmt}', dpi=300, bbox_inches='tight')

Color and Markers

Colors

# Matplotlib colors
ax.plot(x, y, color='C0')  # Default color cycle
ax.plot(x, y, color='red')  # Named color
ax.plot(x, y, color='#1f77b4')  # Hex color
ax.plot(x, y, color=(0.2, 0.4, 0.6))  # RGB tuple

# Colormaps
colors = plt.cm.viridis(np.linspace(0, 1, n_datasets))

Markers

# Common markers
ax.plot(x, y, 'o-')   # Circles
ax.plot(x, y, 's-')   # Squares
ax.plot(x, y, '^-')   # Triangles
ax.plot(x, y, 'D-')   # Diamonds

# Empty markers
ax.plot(x, y, 'o', markerfacecolor='none', markeredgecolor='blue')

Annotations

# Text
ax.text(x=5, y=500, s='Important region',
        fontsize=12, ha='center', va='center')

# Arrow annotation
ax.annotate(
    text='Transition',
    xy=(10, 800),
    xytext=(15, 900),
    arrowprops=dict(arrowstyle='->', color='red')
)

# Lines
ax.axhline(y=500, color='r', linestyle='--')
ax.axvline(x=10, color='g', linestyle=':')

# Regions
ax.axvspan(xmin=5, xmax=15, alpha=0.2, color='yellow')

Best Practices

Publication Quality

# Use publication style
fig, ax = plot_rheo_data(data, style='publication')

# Save at 300 DPI
fig.savefig('figure.pdf', dpi=300, bbox_inches='tight')

# Use consistent fonts
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Arial']
plt.rcParams['pdf.fonttype'] = 42  # TrueType fonts

Readability

# Clear labels with units
ax.set_xlabel('Time (s)', fontsize=12)
ax.set_ylabel('Stress (Pa)', fontsize=12)

# Grid for easier reading
ax.grid(True, which='both', alpha=0.3, linestyle='--')

# Legend when multiple series
ax.legend(fontsize=10, framealpha=0.9)

Colorblind-Friendly

# Use distinguishable colors
colors = ['#0173B2', '#DE8F05', '#029E73']  # Blue, orange, green

# Or use different markers
markers = ['o', 's', '^']

for i, (x, y) in enumerate(datasets):
    ax.plot(x, y, marker=markers[i], color=colors[i])

See Also