Visualization (rheojax.visualization) ===================================== The visualization module provides publication-quality plotting functions for rheological data. Plotting Functions ------------------ .. automodule:: rheojax.visualization.plotter :members: :undoc-members: :show-inheritance: Main Plotting Function ~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: rheojax.visualization.plotter.plot_rheo_data :noindex: Main entry point for plotting RheoData with automatic plot type selection. **Plot type selection logic:** 1. Frequency domain or oscillation test -> :func:`plot_frequency_domain` 2. Rotation test or shear rate units -> :func:`plot_flow_curve` 3. Time domain -> :func:`plot_time_domain` Specialized Plot Types ~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: rheojax.visualization.plotter.plot_time_domain :noindex: Plot time-domain data (relaxation, creep). .. autofunction:: rheojax.visualization.plotter.plot_frequency_domain :noindex: Plot frequency-domain data (oscillatory tests). For complex data (G*), creates two subplots for :math:`G'` and :math:`G''`. For real data, creates a single plot. .. autofunction:: rheojax.visualization.plotter.plot_flow_curve :noindex: Plot flow curves (viscosity or stress vs shear rate). .. autofunction:: rheojax.visualization.plotter.plot_residuals :noindex: 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: .. data:: rheojax.visualization.plotter.DEFAULT_STYLE General-purpose style for interactive work. - Figure size: 8x6 inches - Font size: 11 pt - Line width: 1.5 pt .. data:: 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 .. data:: 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 --------- .. automodule:: rheojax.visualization.templates :members: :undoc-members: :show-inheritance: The templates module provides reusable plot templates for common visualization tasks. EPM Visualization ----------------- .. automodule:: rheojax.visualization.epm_plots :members: :undoc-members: :show-inheritance: Tools for visualizing spatially heterogeneous fields in Lattice EPM simulations. Functions ~~~~~~~~~ .. autofunction:: rheojax.visualization.epm_plots.plot_lattice_fields :noindex: Plots stress and yield threshold fields side-by-side. .. autofunction:: rheojax.visualization.epm_plots.animate_stress_evolution :noindex: Creates an animation of the stress field evolution over time. Examples -------- Basic Plotting ~~~~~~~~~~~~~~ Auto-Detection ^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^ .. code-block:: python # 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 ^^^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^ .. code-block:: python # 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 ^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^^^^^^^ .. code-block:: python 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 ^^^^^^^^^^^^^^ .. code-block:: python 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: .. code-block:: python 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 ~~~~~~~~~~~~~~~~ .. code-block:: python 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 ~~~~~~~~~~~~~~~~~~~ .. code-block:: python 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 ~~~~~~~~~~~~~~ .. code-block:: python # 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 ~~~~~~~~~~~~~~ .. code-block:: python # 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 ~~~~~~~~~~~~~~~~ .. code-block:: python # Save in all formats for fmt in ['png', 'pdf', 'svg']: fig.savefig(f'figure.{fmt}', dpi=300, bbox_inches='tight') Color and Markers ----------------- Colors ~~~~~~ .. code-block:: python # 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 ~~~~~~~ .. code-block:: python # 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 ----------- .. code-block:: python # 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 ~~~~~~~~~~~~~~~~~~~ .. code-block:: python # 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 ~~~~~~~~~~~ .. code-block:: python # 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 ~~~~~~~~~~~~~~~~~~~ .. code-block:: python # 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 -------- - :doc:`../user_guide/visualization_guide` - Comprehensive visualization guide - :doc:`core` - RheoData structure - `Matplotlib documentation `_ - Advanced plotting - `Matplotlib gallery `_ - Examples