Source code for pyradtran.viz._style

"""Publication-grade theme, colorblind-safe palette, and save helper.

matplotlib is imported lazily: :func:`require_mpl` is the single chokepoint so
``import pyradtran`` never requires matplotlib.
"""

from __future__ import annotations

from pathlib import Path

# Okabe-Ito colorblind-safe palette.
_OKABE_ITO = [
    "#0072B2",  # blue
    "#D55E00",  # vermillion
    "#009E73",  # bluish green
    "#CC79A7",  # reddish purple
    "#F0E442",  # yellow
    "#56B4E9",  # sky blue
    "#E69F00",  # orange
    "#000000",  # black
]


def require_mpl():
    """Import and return matplotlib, or raise an actionable ImportError."""
    try:
        import matplotlib
    except ImportError as e:  # pragma: no cover - exercised only without matplotlib
        raise ImportError(
            "pyradtran.viz requires matplotlib; install it with `pip install pyradtran[plot]`"
        ) from e
    return matplotlib


[docs] def set_theme(style: str = "publication") -> None: """Apply rcParams for the requested style. ``publication`` (default): higher DPI, larger fonts, tighter layout. ``diagnostic``: lighter settings for quick iteration. """ mpl = require_mpl() if style == "publication": mpl.rcParams.update( { "figure.dpi": 150, "savefig.dpi": 300, "font.size": 11, "axes.labelsize": 11, "axes.titlesize": 12, "legend.fontsize": 9, "xtick.labelsize": 9, "ytick.labelsize": 9, "axes.grid": True, "grid.alpha": 0.3, "figure.autolayout": True, } ) elif style == "diagnostic": mpl.rcParams.update( { "figure.dpi": 100, "savefig.dpi": 100, "font.size": 9, "axes.grid": True, "grid.alpha": 0.3, "figure.autolayout": True, } ) else: raise ValueError(f"Unknown style: {style!r} (use 'publication' or 'diagnostic')")
[docs] def get_palette(n: int) -> list[str]: """Return ``n`` colorblind-safe colors (cycling the Okabe-Ito set).""" if n <= 0: return [] return [_OKABE_ITO[i % len(_OKABE_ITO)] for i in range(n)]
[docs] def save(fig, path, *, formats=("pdf", "png")) -> None: """Save ``fig`` to ``path`` with each extension in ``formats`` appended.""" base = Path(path) for ext in formats: fig.savefig(base.with_suffix(f".{ext}"))