=======================================
Gridded Plotting (:mod:`marEx.plotX.gridded`)
=======================================
.. currentmodule:: marEx.plotX.gridded
The :mod:`marEx.plotX.gridded` module provides specialised plotting functionality for
structured (regular) grids, such as latitude-longitude gridded datasets commonly found
in climate models, reanalysis products, and satellite observations.
Overview
========
This module implements the `GriddedPlotter` class, which is optimised for handling regular
rectangular grids with coordinates organised as (time, lat, lon) or similar structures.
It provides advanced geographic visualisation capabilities with full cartographic projection
support through Cartopy.
**Key Features:**
* **Geographic Projections**: Full support for cartographic projections via Cartopy
* **Longitude Wrapping**: Automatic handling of periodic longitude boundaries
* **High-Performance Rendering**: Optimised for large gridded datasets
* **Seamless Integration**: Works seamlessly with xarray DataArrays via `.plotX` accessor
Classes
=======
.. autosummary::
:toctree: ../../generated/
GriddedPlotter
GriddedPlotter Class
====================
.. autoclass:: GriddedPlotter
:members:
:undoc-members:
:show-inheritance:
The GriddedPlotter class handles structured grids with regular lat/lon coordinates:
.. code-block:: python
# GriddedPlotter is typically accessed via the plotX accessor
# Automatic selection based on grid type detection
import xarray as xr
import marEx
# Load regular gridded data
data = xr.open_dataset('regular_grid.nc').temperature
# Plotting automatically uses GriddedPlotter
config = marEx.PlotConfig(title='Temperature', var_units='°C')
fig, ax, im = data.plotX.single_plot(config)
Methods
=======
Longitude Wrapping
------------------
.. automethod:: GriddedPlotter.wrap_lon
The `wrap_lon` method handles periodic longitude boundaries for global datasets:
.. code-block:: python
# Longitude wrapping is automatically applied when needed
# For global data spanning 360 degrees, adds duplicate column at lon=360
# Example: data with longitude from 0 to 359.5
# wrap_lon will add a column at lon=360 equal to lon=0
# This prevents gaps in global plots
Plot Method
-----------
.. automethod:: GriddedPlotter.plot
The core plotting method for structured grids:
.. code-block:: python
# The plot method is called internally by single_plot, multi_plot, etc.
# It handles:
# - Longitude wrapping for global data
# - Cartopy coordinate transformations
# - Optimal rendering with pcolormesh
Basic Usage Examples
====================
Simple Gridded Plot
--------------------
.. code-block:: python
import xarray as xr
import marEx
# Load gridded SST data
sst = xr.open_dataset('sst_gridded.nc').sst
# Basic plot with automatic grid detection
config = marEx.PlotConfig(
title='Sea Surface Temperature',
var_units='°C',
cmap='thermal'
)
fig, ax, im = sst.plotX.single_plot(config)
Global Dataset Visualization
----------------------------
.. code-block:: python
# Global dataset with longitude wrapping
config = marEx.PlotConfig(
title='Global Temperature',
var_units='°C',
cmap='RdBu_r',
issym=True,
show_colorbar=True,
grid_lines=True,
grid_labels=True
)
# Longitude wrapping handled automatically
fig, ax, im = global_temp.plotX.single_plot(config)
Regional Subset
---------------
.. code-block:: python
# Regional subset (no longitude wrapping needed)
regional_data = sst.sel(lat=slice(30, 60), lon=slice(-180, -120))
config = marEx.PlotConfig(
title='North Pacific SST',
var_units='°C',
cmap='coolwarm',
show_colorbar=True,
grid_lines=True,
grid_labels=True
)
fig, ax, im = regional_data.plotX.single_plot(config)
Time Series Visualization
=========================
Multi-Panel Time Series
------------------------
.. code-block:: python
# Plot multiple time steps
config = marEx.PlotConfig(
var_units='°C',
cmap='RdBu_r',
issym=True,
show_colorbar=True
)
# Create wrapped subplots
fig, axes = sst.plotX.multi_plot(config, col='time', col_wrap=4)
Animation
---------
.. code-block:: python
# Create time series animation
config = marEx.PlotConfig(
title='SST Evolution',
var_units='°C',
cmap='thermal',
show_colorbar=True
)
# Generate animation (requires ffmpeg)
movie_path = sst.plotX.animate(
config,
plot_dir='./animations',
file_name='sst_evolution'
)
Advanced Configuration
======================
Custom Dimension Names
----------------------
.. code-block:: python
# For data with non-standard coordinate names
config = marEx.PlotConfig(
title='Temperature',
var_units='°C',
cmap='viridis',
# Custom dimension mapping
dimensions={'time': 'time', 'y': 'latitude', 'x': 'longitude'},
coordinates={'time': 'time', 'y': 'latitude', 'x': 'longitude'}
)
fig, ax, im = data.plotX.single_plot(config)
Color Scaling Options
---------------------
.. code-block:: python
# Percentile-based scaling
config = marEx.PlotConfig(
title='Temperature Anomalies',
var_units='°C',
cmap='RdBu_r',
cperc=[5, 95], # Use 5th and 95th percentiles
extend='both'
)
# Symmetric scaling around zero
config = marEx.PlotConfig(
title='Temperature Anomalies',
var_units='°C',
cmap='RdBu_r',
issym=True, # Symmetric around zero
extend='both'
)
# Manual color limits
config = marEx.PlotConfig(
title='Temperature',
var_units='°C',
cmap='plasma',
clim=(-2, 5), # Manual color limits
extend='both'
)
Integration with Matplotlib
===========================
Custom Figure Setup
--------------------
.. code-block:: python
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
# Create custom figure with specific projection
fig = plt.figure(figsize=(12, 8))
ax = plt.axes(projection=ccrs.PlateCarree())
# Use existing axes
config = marEx.PlotConfig(
title='Custom Projection',
var_units='°C',
cmap='viridis'
)
fig, ax, im = data.plotX.single_plot(config, ax=ax)
# Add custom elements
ax.set_title('Modified Title', fontsize=16)
plt.tight_layout()
Subplot Integration
-------------------
.. code-block:: python
# Multi-panel comparison with custom layout
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
datasets = [sst_obs, sst_model1, sst_model2, sst_diff]
titles = ['Observations', 'Model 1', 'Model 2', 'Difference']
for ax, dataset, title in zip(axes.flat, datasets, titles):
config = marEx.PlotConfig(
title=title,
var_units='°C',
cmap='RdBu_r',
show_colorbar=False # Add single colorbar later
)
fig, ax, im = dataset.plotX.single_plot(config, ax=ax)
# Add single colorbar for all subplots
fig.subplots_adjust(right=0.9)
cbar_ax = fig.add_axes([0.92, 0.15, 0.02, 0.7])
fig.colorbar(im, cax=cbar_ax, extend='both')
Geographic Projections
======================
The GriddedPlotter uses Cartopy for geographic projections. The default projection is Robinson, but data is always transformed from PlateCarree:
.. code-block:: python
# Default projection handling:
# - Data coordinates assumed to be in PlateCarree (regular lat/lon)
# - Display projection defaults to Robinson
# - Coordinate transformation handled automatically
# The plot method internally uses:
plot_kwargs = {
'transform': ccrs.PlateCarree(), # Input data coordinate system
'cmap': cmap,
'shading': 'auto'
}
# And the axes are created with:
ax = plt.axes(projection=ccrs.Robinson()) # Display projection
Global vs Regional Data
=======================
Longitude Wrapping Logic
-------------------------
The `wrap_lon` method automatically detects if longitude wrapping is needed:
.. code-block:: python
# Wrapping is applied when:
# - Data spans approximately 360 degrees
# - abs(360 - (lon.max() - lon.min())) < 2 * lon_spacing
# Example: longitude from 0 to 359.5 with 0.5 degree spacing
# - Total span: 359.5 degrees
# - Spacing: 0.5 degrees
# - 360 - 359.5 = 0.5 < 2 * 0.5 = 1.0 → wrapping applied
# No wrapping for regional data:
# - longitude from -180 to -120 (60 degree span)
# - longitude from 0 to 90 (90 degree span)
Grid Detection
==============
The GriddedPlotter is automatically selected when:
* Data has separate latitude and longitude **dimensions**
* Coordinates follow structured grid patterns
* Typical dimension structure: `(time, lat, lon)` or `(lat, lon)`
.. code-block:: python
# Automatic detection based on:
# - 'lat' and 'lon' in data.dims
# - Regular spacing in lat/lon coordinates
# - Rectangular grid structure
# Override detection if needed:
marEx.specify_grid(grid_type='gridded')
See Also
========
* :mod:`marEx.plotX.base` - Base plotting functionality
* :mod:`marEx.plotX.unstructured` - Unstructured grid plotting
* :mod:`marEx.plotX` - Main plotting module
* `Cartopy documentation `_
* `xarray plotting guide `_