plotter — figure rendering + mathtext facade
Purpose
The pipeline’s only rendering layer: prepared series (
PlotLine/PlotAxis/FigureSpec) → PNG.
matplotlib/seaborn/pylablive nowhere else (hook-enforced).render_line_panelsis the one
sanctioned figure entry point for validation scripts and agents.
Role in the system
- Consumed by orchestrator (
Plotter().plot_configured_figures,plot_reduction_comparison,
figure_spec_from_fields) — the only module that drives the run-specfigures:/overlay:path. - Consumed by committed
validation/scripts via therender_line_panelsshim (they prepare series
through the signal_measurement facade and hand them here). Worked examples:
validation/washout_theta3_figures.py,validation/chaos_divergence_figures.py. - Imports
GuidanceModefrom guidance_classes (shade styling) andPackage/object_fieldsfrom infra. - Renders prepared axes from data_analyzer (
DataSummary.plot_axis); never reduces data itself. - Sibling of plotter3d (3-D scene rendering, separate path).
Inputs / Outputs
- In: prepared
PlotAxis/FigureSpecobjects (or raw panel dicts via the shim), figure defaults
fromanalysis_YAMLs/default_figure_specs.yaml. - Out: PNG files written to the run-stamped figures dir; the list of saved paths. The
Agg
backend is forced at import (headless).
Key methods / functions
render_line_panels— sanctioned shim: stacked panel dicts → rendered PNG(s), no matplotlib import for the caller —analysis/plotter.py:986Plotter.plot_configured_figures— render a list ofFigureSpecs; returns all saved paths —:963figure_spec_from_fields— build aFigureSpecfrom a loose field mapping + axes + figsize —:469PlotAxis.plot— render one subplot end-to-end (settings, shades, lines, scatters, markers, twin, decorate) —:277PlotAxis.plot_secondary_lines— twin y-axis for a second signal at its own scale —:289to_mathtext— label → matplotlib mathtext (wrap math-like tokens in$…$, title-case prose) —:492ComparisonPlotter.plot_reduction_comparison— one figure per (group, reduction) block across variants —:798figure_smoke— Stage-3 boundary smoke (python -m analysis.plotter) —:1033
Footguns
plot_sectioncoerces a terminal list to{}
plot_section("comparison", "figure")returns a dict even whenfigsizeis a list-valued leaf.
Readfigsizedirectly from the mapping with.get(), never viaplot_section
(reduction_comparison_figure). (analysis/INSIGHTS.md[footgun])
Normalize Line2D aliases before they reach
ax.plot
render_line_panelsrunscbook.normalize_kwargs(…, Line2D)so aliases (lw→linewidth,
ls→linestyle,c→color) collapse to canonical keys before merging with per-line overrides.
Without it a defaultlwand a callerlinewidthboth reachax.plot→ duplicate-argument error.
(analysis/INSIGHTS.md[footgun])
Markers carry a
valuekey thataxhline/axvlinereject
marker_kwargsdrops thevaluekey (it is the line position, not aLine2Dkwarg) and applies
to_mathtextto the label before passing through. (analysis/INSIGHTS.md[plotting])
The versine map doesn't commute with rms
Pointing labels are math-like (
z_b,p_e):to_mathtextmathtext-wraps them, but the number
stays the catalog versine — render an angle only withas_pointing_degfor human prints, never
rmsthe degrees. (See signal_measurement /MEASUREMENT.md.)
Pseudocode (render_line_panels)
default_line = normalize_kwargs(line.default, Line2D) # collapse aliases first
for each panel:
lines = PlotLine(x, y, label, {default_line, **normalize_kwargs(extra)})
PlotAxis(loc, lines, scatters, hlines/vlines, secondary_lines/hlines, scales, xlim)
spec = figure_spec_from_fields({name, suptitle}, axes, figsize)
return Plotter().plot_configured_figures(out_dir, [spec]) # mkdir + savefig + provenance
Panel dict schema: lines / scatter / hlines / vlines / secondary_lines /
secondary_hlines / secondary_ylabel / title / xlabel / ylabel / xscale / yscale /
xlim. Panels stack top-to-bottom; pass layout=(rows, cols) for a row-major grid.
Mathtext (to_mathtext family)
needs_mathflags a token as math-like via theMATH_TOKENSGreek table or short multi-part
snake-case (p_e); plain prose is title-cased throughdisplay_label.- Space-separated strings get per-token treatment so decimals survive (“gate 0.99” stays, never
“Gate 0 99”). math_word/math_subscript/math_namerender snake/caret words as TeX (subscripts, superscripts,
\mathrm{…}for multi-letter bases).
Related
orchestrator · data_analyzer · signal_measurement · star_reporter · plotter3d · guidance_classes · infra · terminology