3b9d1ef1a8
- Replace the Docker build/publish CI stages with ruff (lint + format check), ty (type check), pip-audit, and pytest run directly against python:3.11-slim; Docker remains for manual/server deployment only. - Swap black/pylint/mypy for ruff/ty across pyproject.toml, and fix every resulting lint, format, and type diagnostic in gallery/ and plotstyle/. - Fix tests broken/stale from before the package restructuring: wrong `utils.*` import paths, mock patch targets pointed at the wrong module, and PDF-conversion tests still assuming ImageMagick instead of the current PyMuPDF-first path. Drop test_container.py (obsolete Docker-container smoke tests, fully superseded elsewhere). - Add a plain-venv + systemd --user timer deployment path (deploy/systemd/) for HPC login nodes without a Docker daemon, where public_html is already served by existing infrastructure. - Document both in CLAUDE.md, including running CI's checks locally before committing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
65 lines
2.5 KiB
Python
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 importlib import resources
|
|
|
|
import matplotlib.pyplot as plt
|
|
from cycler import cycler
|
|
|
|
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").joinpath("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()
|