=============================== Base Plotting (:mod:`marEx.plotX.base`) =============================== .. currentmodule:: marEx.plotX.base The :mod:`marEx.plotX.base` module provides the foundational classes and utilities for marEx plotting. It defines the base plotting interface, configuration management, and common functionality shared across different grid types. Overview ======== This module implements the core plotting architecture using object-oriented design patterns. It provides the base plotter class and configuration dataclass that define the plotting interface and common functionality inherited by specialised plotters for different grid types. **Key Components:** * **PlotConfig**: Dataclass for comprehensive plot configuration * **PlotterBase**: Abstract base class defining the plotting interface * **Animation Support**: Built-in animation capabilities with ffmpeg integration * **Error Handling**: Comprehensive error handling and validation Classes and Functions ===================== .. autosummary:: :toctree: ../../generated/ PlotConfig PlotterBase make_frame Configuration Management ======================== PlotConfig Class ---------------- .. autoclass:: PlotConfig :members: :undoc-members: :show-inheritance: The PlotConfig dataclass provides comprehensive configuration options for all plotting operations: .. code-block:: python from marEx.plotX import PlotConfig # Basic configuration config = PlotConfig( title='Sea Surface Temperature', var_units='°C', cmap='RdBu_r', show_colorbar=True ) # Advanced configuration config = PlotConfig( title='Temperature Anomalies', var_units='°C', issym=True, # Symmetric color scaling cmap='RdBu_r', cperc=[5, 95], # Percentile limits show_colorbar=True, grid_lines=True, grid_labels=True, extend='both', # Custom dimension mapping dimensions={'time': 'time', 'y': 'latitude', 'x': 'longitude'}, coordinates={'time': 'time', 'y': 'latitude', 'x': 'longitude'} ) Configuration Options -------------------- **Visual Appearance:** * **title**: Plot title (optional) * **var_units**: Units for colorbar label * **cmap**: Colormap name or ListedColormap object * **show_colorbar**: Whether to display colorbar (default: True) **Color Scaling:** * **issym**: Symmetric color scaling around zero (default: False) * **cperc**: Percentile limits for color scaling (default: [4, 96]) * **clim**: Manual color limits as tuple (vmin, vmax) * **norm**: Custom matplotlib normalisation object * **extend**: Colorbar extension ('both', 'min', 'max', 'neither') **Grid and Labels:** * **grid_lines**: Show grid lines (default: True) * **grid_labels**: Show grid labels (default: False) **Special Modes:** * **plot_IDs**: Special handling for event ID plotting (default: False) * **dimensions**: Custom dimension name mapping * **coordinates**: Custom coordinate name mapping **Logging:** * **verbose**: Enable verbose logging (optional) * **quiet**: Enable quiet logging (optional) Base Plotter Class ================== PlotterBase Class ----------------- .. autoclass:: PlotterBase :members: :undoc-members: :show-inheritance: The PlotterBase class provides the core plotting infrastructure: .. code-block:: python # PlotterBase is typically not used directly # It's inherited by GriddedPlotter and UnstructuredPlotter # Example of common workflow (implemented by subclasses): plotter = GriddedPlotter(data_array) fig, ax, im = plotter.single_plot(config) Common Methods -------------- **single_plot(config, ax=None)** Create a single plot with the given configuration. Args: config (PlotConfig): Plot configuration ax (matplotlib.axes.Axes, optional): Existing axes to use Returns: tuple: (figure, axes, image) objects **multi_plot(config, col='time', col_wrap=3)** Create multiple subplots wrapped in a grid. Args: config (PlotConfig): Plot configuration col (str): Dimension to plot across panels col_wrap (int): Number of columns before wrapping Returns: tuple: (figure, axes_array) objects **animate(config, plot_dir='./', file_name=None)** Create an animation from time series data. Args: config (PlotConfig): Plot configuration plot_dir (str or Path): Directory for output files file_name (str, optional): Output filename (without extension) Returns: str: Path to created animation file Implementation Details ====================== Color Scaling ------------- The base class provides robust color scaling methods: .. code-block:: python # Automatic percentile-based scaling config = PlotConfig(cperc=[10, 90]) # Symmetric scaling around zero config = PlotConfig(issym=True) # Manual color limits config = PlotConfig(clim=(-2, 5)) Map Features ------------ Common map features are automatically added: .. code-block:: python # Default map features include: # - Land areas (dark grey) # - Coastlines (black, 0.5 linewidth) # - Grid lines (optional, grey dashed) # - Grid labels (optional) Animation ========= Animation Creation ------------------ The animation system uses dask for parallel frame generation: .. code-block:: python # Create animation config = PlotConfig( title='Temperature Evolution', var_units='°C', cmap='thermal' ) # Generate animation (requires ffmpeg) movie_path = data.plotX.animate( config, plot_dir='./animations', file_name='temperature_movie' ) Frame Generation ---------------- .. autofunction:: make_frame The make_frame function is decorated with @dask.delayed for parallel processing: .. code-block:: python # Internal animation workflow: # 1. Create delayed tasks for each frame # 2. Parallel frame generation using dask # 3. Combine frames with ffmpeg delayed_tasks = [] for time_ind in range(len(data.time)): data_slice = data.isel(time=time_ind) delayed_tasks.append(make_frame(data_slice, time_ind, temp_dir, plot_params)) # Execute in parallel filenames = dask.compute(*delayed_tasks) Requirements ------------ Animation requires additional dependencies: * **ffmpeg**: For video encoding (must be in system PATH) * **PIL/Pillow**: For image processing * **dask**: For parallel frame generation Utilities ========= Common Utilities ---------------- The base class provides several utility methods: .. code-block:: python # Robust color limit calculation def clim_robust(data, issym=False, percentiles=[2, 98]): # Calculate color limits from data percentiles pass # ID plotting setup def setup_id_plot_params(cmap=None): # Special configuration for event ID plotting pass # Common parameter setup def setup_plot_params(): # Configure matplotlib parameters pass Integration Points ================== Matplotlib Integration ---------------------- Full compatibility with matplotlib: .. code-block:: python import matplotlib.pyplot as plt # Use existing figure/axes fig, ax = plt.subplots(figsize=(12, 8)) config = PlotConfig(title='Custom Plot') fig, ax, im = data.plotX.single_plot(config, ax=ax) # Add custom elements ax.set_title('Modified Title') plt.tight_layout() Cartopy Integration ------------------- Automatic geographic projection handling: .. code-block:: python # Cartopy projections handled automatically # - PlateCarree for data transformation # - Robinson for default display # - Automatic feature addition Customisation Examples ====================== Custom Colormap --------------- .. code-block:: python import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap # Create custom colormap custom_cmap = ListedColormap(['blue', 'white', 'red']) config = PlotConfig( title='Custom Colors', cmap=custom_cmap, issym=True ) Custom Normalisation -------------------- .. code-block:: python from matplotlib.colors import BoundaryNorm # Create custom normalisation levels = [-2, -1, 0, 1, 2] norm = BoundaryNorm(levels, ncolors=256) config = PlotConfig( title='Custom Normalisation', norm=norm, extend='both' ) See Also ======== * :mod:`marEx.plotX.gridded` - Structured grid plotting * :mod:`marEx.plotX.unstructured` - Unstructured grid plotting * :mod:`marEx.plotX` - Main plotting module * `matplotlib documentation `_ * `cartopy documentation `_