Files
ETPlot/plotstyle/style.py
T
lars 36ae18e880 Add plotstyle: reusable KIT-branded matplotlib styling toolkit
Introduces a new plotstyle package providing consistent, presentation/thesis-ready
matplotlib figures: a KIT corporate-design color palette (categorical, sequential,
diverging, status), a theme applied via use() (KIT-black bottom spine only, left/bottom
ticks, horizontal gridlines, left-aligned titles, LaTeX text in Latin Modern Sans),
new_figure() with size presets and figure-level title/params subtitles, a
same-size colorbar() helper, style_legend() and panel_label() building blocks, and
savefig(). Ships as an optional "plotting" extra so core gallery installs stay
lightweight, with a full test suite and a runnable example notebook.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 14:19:30 +02:00

65 lines
2.5 KiB
Python

"""Apply the plotstyle rcParams theme.
Text (titles, axis labels, legends, tick labels, annotations — the entirety
of every string) is always rendered through a real LaTeX toolchain, using
Latin Modern Sans as a modern sans-serif LaTeX font (including math mode, via
`sfmath` — otherwise tick numbers fall back to a serif math font even with
`\\familydefault` set to sans). `fontenc`'s T1 encoding is loaded too — without
it, some plain ASCII characters (e.g. "|") render as the wrong glyph under
OT1, LaTeX's default. This requires a working local `latex`/`dvipng` install;
there is no mathtext fallback.
Note: matplotlib's usetex rendering rasterizes each Text artist as a single
greyscale glyph mask via dvipng and then tints the *whole* thing with that
artist's one `color` — any in-source `\\color`/`\\textcolor` command is
ignored. So two differently-colored spans (e.g. a black title next to a grey
subtitle) can't live in one Text object; `figures.new_figure()`'s title/params
handling only varies font size (`\\small`) between lines, not color, for
exactly this reason.
"""
from __future__ import annotations
from cycler import cycler
from importlib import resources
import matplotlib.pyplot as plt
from .colors import CATEGORICAL
_LINESTYLES = ["-", "--", "-.", ":"]
_LATEX_PREAMBLE = (
r"\usepackage[T1]{fontenc}\usepackage{amsmath}\usepackage{lmodern}\usepackage{sfmath}"
r"\renewcommand{\familydefault}{\sfdefault}"
)
def use(cycle_linestyles: bool = False) -> None:
"""Apply the plotstyle theme to matplotlib's global rcParams.
Call once at the top of a plotting script, before creating any figures.
By default `axes.prop_cycle` only cycles color (all lines solid) — pass
`cycle_linestyles=True` to also cycle through a repeating linestyle
sequence, so series stay distinguishable even if color is lost
(grayscale printing, projector glare, color-vision deficiency).
"""
style_path = resources.files("plotstyle").joinpath("assets", "plotstyle.mplstyle")
plt.style.use(str(style_path))
if cycle_linestyles:
n = len(CATEGORICAL)
linestyles = (_LINESTYLES * (n // len(_LINESTYLES) + 1))[:n]
plt.rcParams["axes.prop_cycle"] = cycler(color=CATEGORICAL) + cycler(linestyle=linestyles)
else:
plt.rcParams["axes.prop_cycle"] = cycler(color=CATEGORICAL)
plt.rcParams["text.usetex"] = True
plt.rcParams["text.latex.preamble"] = _LATEX_PREAMBLE
def reset() -> None:
"""Restore matplotlib defaults (useful between tests/notebook cells)."""
plt.rcdefaults()