solarwindpy.plotting.tools

Utility functions for common matplotlib tasks.

These helpers provide shortcuts for creating figures, saving output, building grids of axes with shared colorbars, and NaN-aware image filtering.

Functions

build_ax_array_with_common_colorbar([nrows, ...])

Build an array of axes that share a colour bar.

calculate_nrows_ncols(n)

Determine a sensible (nrows, ncols) pair for n axes.

joint_legend(*axes[, idx_for_legend])

Create a combined legend for multiple axes.

nan_gaussian_filter(array, sigma, **kwargs)

Apply Gaussian filter with proper NaN handling via normalized convolution.

save(fig, spath[, add_info, info_x, info_y, ...])

Save a figure in both PDF and PNG formats.

subplots([nrows, ncols, scale_width, ...])

Create a grid of subplots with a scaled figure size.

use_style()

Apply the SolarWindPy matplotlib style.

use_style()[source]

Apply the SolarWindPy matplotlib style.

This sets publication-ready defaults including: - 4x4 inch figure size - 12pt base font size - Spectral_r colormap - 300 DPI PDF output

Examples

>>> import solarwindpy.plotting as swp_pp
>>> swp_pp.use_style()
subplots(nrows=1, ncols=1, scale_width=1.0, scale_height=1.0, **kwargs)[source]

Create a grid of subplots with a scaled figure size.

Parameters:
  • nrows (int, optional) – Number of subplot rows.

  • ncols (int, optional) – Number of subplot columns.

  • scale_width (float, optional) – Factor applied to the default figure width.

  • scale_height (float, optional) – Factor applied to the default figure height.

  • **kwargs – Additional keyword arguments passed directly to matplotlib.pyplot.subplots().

Returns:

Examples

>>> fig, ax = subplots(2, 2, scale_width=1.5)
save(fig, spath, add_info=True, info_x=0, info_y=0, log=True, pdf=True, png=True, **kwargs)[source]

Save a figure in both PDF and PNG formats.

Parameters:
  • fig (matplotlib.figure.Figure or matplotlib.axes.Axes) – The figure or axis to save.

  • spath (pathlib.Path) – Base path for the output files. The appropriate extension will be added automatically.

  • add_info (bool, optional) – If True, add an attribution and timestamp to the bottom left of the PNG version.

  • info_x (float, optional) – X-position of the attribution text in figure coordinates.

  • info_y (float, optional) – Y-position of the attribution text in figure coordinates.

  • log (bool, optional) – If True, write information about the saved files to alog.

  • pdf (bool, optional) – Save a PDF version of the figure.

  • png (bool, optional) – Save a PNG version of the figure.

  • **kwargs – Additional keyword arguments passed to Figure.savefig().

Return type:

None

Examples

>>> fig, ax = subplots()
>>> save(fig, Path('my_plot'))
joint_legend(*axes, idx_for_legend=-1, **kwargs)[source]

Create a combined legend for multiple axes.

Parameters:
  • *axes (matplotlib.axes.Axes) – Axes objects from which to collect legend handles and labels.

  • idx_for_legend (int, optional) – Index of the axis (after flattening) on which to place the legend. By default the legend is placed on the last axis. idx_for_legend=-1 assumes that the last axis is on the right hand side of the figure.

  • **kwargs – Extra keyword arguments forwarded to Axes.legend().

Returns:

legend

Return type:

matplotlib.legend.Legend

Examples

>>> fig, ax = subplots(1, 2)
>>> ax[0].plot([1, 2], label='a')
[<matplotlib.lines.Line2D object at 0x...>]
>>> ax[1].plot([2, 3], label='b')
[<matplotlib.lines.Line2D object at 0x...>]
>>> joint_legend(ax[0], ax[1])
<matplotlib.legend.Legend object at 0x...>
build_ax_array_with_common_colorbar(nrows=1, ncols=1, cbar_loc='top', figsize='auto', sharex=True, sharey=True, hspace=0, wspace=0, fig_kwargs=None, gs_kwargs=None)[source]

Build an array of axes that share a colour bar.

Parameters:
  • nrows (int, optional) – Desired grid shape.

  • ncols (int, optional) – Desired grid shape.

  • cbar_loc ({"top", "bottom", "left", "right"}, optional) – Location of the colorbar relative to the axes grid.

  • figsize (tuple or "auto", optional) – Figure size as (width, height) in inches. If "auto" (default), scales from rcParams["figure.figsize"] based on nrows/ncols.

  • sharex (bool, optional) – If True, share x-axis limits across all panels. Default True.

  • sharey (bool, optional) – If True, share y-axis limits across all panels. Default True.

  • hspace (float, optional) – Vertical spacing between subplots. Default 0.

  • wspace (float, optional) – Horizontal spacing between subplots. Default 0.

  • fig_kwargs (dict, optional) – Keyword arguments forwarded to matplotlib.pyplot.figure().

  • gs_kwargs (dict, optional) – Additional options for matplotlib.gridspec.GridSpec.

Returns:

Examples

>>> fig, axes, cax = build_ax_array_with_common_colorbar(2, 3, cbar_loc='right')
>>> fig, axes, cax = build_ax_array_with_common_colorbar(3, 1, figsize=(5, 12))
calculate_nrows_ncols(n)[source]

Determine a sensible (nrows, ncols) pair for n axes.

The heuristic attempts to generate a nearly square layout while also taking typical display aspect ratios into account.

Parameters:

n (int) – Total number of axes required.

Returns:

  • nrows (int)

  • ncols (int)

Examples

>>> calculate_nrows_ncols(5)
(...2..., ...3...)
nan_gaussian_filter(array, sigma, **kwargs)[source]

Apply Gaussian filter with proper NaN handling via normalized convolution.

Unlike scipy.ndimage.gaussian_filter() which propagates NaN values to all neighboring cells, this function:

  1. Smooths valid data correctly near NaN regions

  2. Preserves NaN locations (no interpolation into NaN cells)

The algorithm uses normalized convolution: both the data (with NaN replaced by 0) and a weight mask (1 for valid, 0 for NaN) are filtered. The result is the ratio of filtered data to filtered weights, ensuring proper normalization near boundaries.

Parameters:
  • array (np.ndarray) – 2D array possibly containing NaN values.

  • sigma (float) – Standard deviation for the Gaussian kernel, in pixels.

  • **kwargs – Additional keyword arguments passed to scipy.ndimage.gaussian_filter().

Returns:

Filtered array with original NaN locations preserved.

Return type:

np.ndarray

See also

scipy.ndimage.gaussian_filter

Underlying filter implementation.

Notes

This implementation follows the normalized convolution approach described in [1]. The key insight is that filtering a weight mask alongside the data allows proper normalization at boundaries and near missing values.

References

[1]

Knutsson, H., & Westin, C. F. (1993). Normalized and differential convolution. In Proceedings of IEEE Conference on Computer Vision and Pattern Recognition (pp. 515-523).

Examples

>>> import numpy as np
>>> arr = np.array([[1, 2, np.nan], [4, 5, 6], [7, 8, 9]])
>>> result = nan_gaussian_filter(arr, sigma=1.0)
>>> bool(np.isnan(result[0, 2]))  # NaN preserved
True
>>> bool(np.isfinite(result[0, 1]))  # Neighbor is valid
True