pelutils.plots package

Ergonomic matplotlib plotting with sensible defaults out of the box.

matplotlib’s defaults are built for small inline figures: fonts are tiny on a saved image, every plot needs its own savefig/close boilerplate, and tweaking rcParams leaks those settings into every later figure in the process. Figure is a context manager that fixes all of this — you get readable font and figure sizes by default, the figure is saved (creating missing directories) and closed for you on exit, and the rcParams changes are scoped to the with block so they never bleed into the next plot. The module also bundles the plotting odds and ends that are fiddly to get right by hand: line histogram() binning, a set of distinct colours, and human-readable date ticks via get_dateticks().

Quick start

import matplotlib.pyplot as plt
from pelutils.plots import Figure, histogram, normal_binning

with Figure("plot.png", figsize=(20, 10), fontsize=20):
    plt.scatter(x, y, label="Data")
    plt.grid()
    plt.title("Very nice plot")
# Saved to plot.png and closed here; rcParams restored

# histogram returns x and y coordinates ready for unpacking into plt.plot
plt.plot(*histogram(data, binning_fn=normal_binning))

Three binning functions are provided for histogram() — linear_binning(), log_binning(), and normal_binning() (more resolution near the centre of roughly-normal data) — and any custom (x, bins) -> edges function works too. See Figure for the full list of styling options.

class pelutils.plots.Figure(savepath: str | Path, *, tight_layout: bool = True, style: str | None = None, figsize: tuple[float, float] = (15, 10), dpi: float = 150, fontsize: float = 26, title_fontsize: float = 0.5, ticksize: float = 0.85, labelsize: float = 1, legend_fontsize: float = 0.85, legend_framealpha: float = 0.8, legend_edgecolor: tuple[float, float, float, float] = (0, 0, 0, 1), other_rc_params: dict[str, Any] | None = None)[source]

Context manager that applies plotting defaults and saves the figure on exit.

On entering the with block the given rcParams are applied within a scoped context; on exit the figure is saved to savepath (creating missing parent directories), the figure is closed, and the previous rcParams are restored. If the block raises, the figure is closed without saving.

Parameters:
  • savepath (str | Path) – Where the figure is written on a clean exit.

  • tight_layout (bool, optional) – Call plt.tight_layout() before saving.

  • style (str | None, optional) – Name of a matplotlib style to apply, e.g. "seaborn-v0_8".

  • figsize (tuple[float, float], optional) – Figure size in inches.

  • dpi (float, optional) – Resolution of the saved figure.

  • fontsize (float, optional) – Base font size. Specific font sizes are given as a fraction of this value.

  • title_fontsize (float, optional) – Title, tick-label, axis-label, and legend font sizes, each as a fraction of fontsize.

  • ticksize (float, optional) – Title, tick-label, axis-label, and legend font sizes, each as a fraction of fontsize.

  • labelsize (float, optional) – Title, tick-label, axis-label, and legend font sizes, each as a fraction of fontsize.

  • legend_fontsize (float, optional) – Title, tick-label, axis-label, and legend font sizes, each as a fraction of fontsize.

  • legend_framealpha (float, optional) – Opacity of the legend background.

  • legend_edgecolor (tuple[float, float, float, float], optional) – RGBA colour of the legend border.

  • other_rc_params (dict[str, Any] | None, optional) – Extra rcParams merged in last, overriding any of the above.

Example

with Figure("figure.png", figsize=(20, 10), fontsize=50):
    plt.plot(x, y)
    plt.title("Very large title")
    plt.grid()

# The finished figure is saved to "figure.png".
# All settings are reset here.
pelutils.plots.get_dateticks(x: ArrayLike, num: int = 6, date_format: str = '%b %d') → tuple[FloatArray, list[str]][source]

Produce date labels for the x axis given an array of epoch times in seconds.

Example

# x is an array of epoch times in seconds
plt.plot(x, y)
plt.xticks(*get_dateticks(x))
pelutils.plots.histogram(data: npt.ArrayLike, binning_fn: Callable[[npt.ArrayLike, int], FloatArray] = <function linear_binning>, bins: int = 25, density: bool = True, ignore_zeros: bool = False) → tuple[FloatArray, FloatArray | IntArray][source]

Create bins for plotting a line histogram. Simplest usage is plt.plot(*histogram(data)).

pelutils.plots.linear_binning(x: ArrayLike, bins: int) → FloatArray[source]

Calculate linear binning for an array.

pelutils.plots.log_binning(x: ArrayLike, bins: int) → FloatArray[source]

Calculate logarithmic binning for an array, meaning more bins close to zero.

pelutils.plots.normal_binning(x: ArrayLike, bins: int, scale: float = 3) → FloatArray[source]

Calculate bins that work well for normal-ish distributed data, meaning more bins closer to the mean of x.

scale determines how spread out the spacing is. The default value works pretty well in most cases.