Base Plotting (marEx.plotX.base)

The 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

PlotConfig([title, var_units, issym, cmap, ...])

Configuration class for plot parameters

PlotterBase(xarray_obj[, dimensions, ...])

Base class for all plotters providing common functionality.

make_frame(data_slice, time_ind, temp_dir, ...)

Create a single frame for movies - minimise memory usage with dask

Configuration Management

PlotConfig Class

class marEx.plotX.base.PlotConfig(title=None, var_units='', issym=False, cmap=None, cperc=None, clim=None, show_colorbar=True, grid_lines=True, grid_labels=False, dimensions=None, coordinates=None, norm=None, plot_IDs=False, extend='both', verbose=None, quiet=None, projection=None, framerate=10)[source]

Bases: object

Configuration class for plot parameters

Parameters:
title

Plot title

Type:

str | None

var_units

Variable units for colorbar label

Type:

str

issym

Whether data is symmetric (centers colormap at 0)

Type:

bool

cmap

Colormap name or ListedColormap object

Type:

str | matplotlib.colors.ListedColormap | None

cperc

Percentile range for automatic color limits [min, max]

Type:

List[int]

clim

Manual color limits (vmin, vmax)

Type:

Tuple[float, float] | None

show_colorbar

Whether to display colorbar

Type:

bool

grid_lines

Whether to display grid lines

Type:

bool

grid_labels

Whether to display grid labels

Type:

bool

dimensions

Mapping of conceptual to actual dimension names

Type:

Dict[str, str]

coordinates

Mapping of conceptual to actual coordinate names

Type:

Dict[str, str]

norm

Custom normalization (BoundaryNorm or Normalize)

Type:

matplotlib.colors.BoundaryNorm | matplotlib.colors.Normalize | None

plot_IDs

Whether to plot object IDs with random colors

Type:

bool

extend

Colorbar extension (‘neither’, ‘both’, ‘min’, ‘max’)

Type:

str

verbose

Enable verbose logging

Type:

bool | None

quiet

Enable quiet logging

Type:

bool | None

projection

Cartopy projection for map plots

Type:

Any | None

framerate

Frames per second for animations (default 10)

Type:

int

title: str | None = None
var_units: str = ''
issym: bool = False
cmap: str | ListedColormap | None = None
cperc: List[int] = None
clim: Tuple[float, float] | None = None
show_colorbar: bool = True
grid_lines: bool = True
grid_labels: bool = False
dimensions: Dict[str, str] = None
coordinates: Dict[str, str] = None
norm: BoundaryNorm | Normalize | None = None
plot_IDs: bool = False
extend: str = 'both'
verbose: bool | None = None
quiet: bool | None = None
projection: Any | None = None
framerate: int = 10
__post_init__()[source]

Initialise default values and configure logging.

Return type:

None

__init__(title=None, var_units='', issym=False, cmap=None, cperc=None, clim=None, show_colorbar=True, grid_lines=True, grid_labels=False, dimensions=None, coordinates=None, norm=None, plot_IDs=False, extend='both', verbose=None, quiet=None, projection=None, framerate=10)
Parameters:
Return type:

None

The PlotConfig dataclass provides comprehensive configuration options for all plotting operations:

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

class marEx.plotX.base.PlotterBase(xarray_obj, dimensions=None, coordinates=None)[source]

Bases: object

Base class for all plotters providing common functionality.

This class provides the core infrastructure for plotting marine extreme event data, including parameter setup, map features, colorbars, and animation capabilities.

Initialise the plotter with data and coordinate mappings.

Parameters:
  • xarray_obj (DataArray) – The data to plot

  • dimensions (Dict[str, str] | None) – Mapping of conceptual to actual dimension names

  • coordinates (Dict[str, str] | None) – Mapping of conceptual to actual coordinate names

__init__(xarray_obj, dimensions=None, coordinates=None)[source]

Initialise the plotter with data and coordinate mappings.

Parameters:
  • xarray_obj (DataArray) – The data to plot

  • dimensions (Dict[str, str] | None) – Mapping of conceptual to actual dimension names

  • coordinates (Dict[str, str] | None) – Mapping of conceptual to actual coordinate names

Return type:

None

single_plot(config, ax=None)[source]

Make a single plot with given configuration

Parameters:
Return type:

Tuple[Figure, Axes, Any]

multi_plot(config, col='time', col_wrap=3)[source]

Make wrapped subplots with given configuration

Parameters:
Return type:

Tuple[Figure, ndarray[tuple[Any, …], dtype[Any]]]

animate(config, plot_dir='./', file_name=None, centroids=None, object_ids=None)[source]

Create an animation from time series data

Parameters:
  • config (PlotConfig) – Plot configuration (including framerate for animation, default 10 fps)

  • plot_dir (str | Path) – Directory to save animation files

  • file_name (str | None) – Name for the output animation file

  • centroids (DataArray | None) – Optional DataArray containing centroid data with dimensions (component, time, ID)

  • object_ids (DataArray | None) – Optional DataArray containing object ID field with integers > 0 for drawing contour outlines

Return type:

str | None

clim_robust(data, issym, percentiles=None)[source]

Compute robust colour limits from data percentiles.

Parameters:
Return type:

ndarray[tuple[Any, …], dtype[float64]]

setup_plot_params()[source]

Set up common plotting parameters

Return type:

None

setup_id_plot_params(cmap=None)[source]

Set up parameters for plotting IDs

Parameters:

cmap (str | ListedColormap | None)

Return type:

Tuple[ListedColormap, BoundaryNorm, str]

plot(ax, cmap='viridis', clim=None, norm=None)[source]

Abstract method to be implemented by subclasses

Parameters:
Return type:

Tuple[Axes, Any]

The PlotterBase class provides the core plotting infrastructure:

# 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:

# 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:

# 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:

# 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

marEx.plotX.base.make_frame(data_slice, time_ind, temp_dir, plot_params, grid_info=None)

Create a single frame for movies - minimise memory usage with dask

Parameters:
  • data_slice (DataArray) – The data for this specific frame

  • time_ind (int) – Frame index

  • temp_dir (Path) – Directory for temporary files

  • plot_params (Dict[str, Any]) – Dict containing plotting parameters

  • grid_info (Dict[str, Any] | None) – Dict containing grid paths and settings for unstructured data

Return type:

str

The make_frame function is decorated with @dask.delayed for parallel processing:

# 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:

# 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:

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:

# Cartopy projections handled automatically
# - PlateCarree for data transformation
# - Robinson for default display
# - Automatic feature addition

Customisation Examples

Custom Colormap

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

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