Add multi-rollout support to giant analyze (gitea #77) #80
@@ -21,6 +21,7 @@ cycle.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
@@ -32,6 +33,27 @@ from giant.analysis.reduced import Reduced
|
||||
|
||||
_REFERENCE_LABEL = "reference (Geant4)"
|
||||
|
||||
_TEX_ESCAPE_MAP = {
|
||||
"\\": r"\textbackslash{}",
|
||||
"%": r"\%",
|
||||
"&": r"\&",
|
||||
"#": r"\#",
|
||||
"$": r"\$",
|
||||
"_": r"\_",
|
||||
"{": r"\{",
|
||||
"}": r"\}",
|
||||
}
|
||||
|
||||
|
||||
def _tex_escape(text: str) -> str:
|
||||
"""Escape characters LaTeX treats specially in catalog-authored title/xlabel
|
||||
text (e.g. a literal ``%`` in a "90% of deposited energy" title, which
|
||||
``usetex`` otherwise reads as a comment marker and aborts the whole figure —
|
||||
see gitea #81). A single pass over the *original* characters, so the
|
||||
backslashes an escape itself introduces (e.g. ``\textbackslash{}``) are
|
||||
never re-escaped."""
|
||||
return "".join(_TEX_ESCAPE_MAP.get(c, c) for c in text)
|
||||
|
||||
|
||||
def _ref_color() -> str:
|
||||
return ps.colors.INK["primary"]
|
||||
@@ -421,8 +443,14 @@ _RENDERERS = {
|
||||
|
||||
|
||||
def render(r: Reduced, run_meta: dict | None = None):
|
||||
"""Build the matplotlib figure for one reduced artifact (dispatch on kind)."""
|
||||
return _RENDERERS[r.kind](r, _figure_params(run_meta or {}))
|
||||
"""Build the matplotlib figure for one reduced artifact (dispatch on kind).
|
||||
|
||||
``title``/``xlabel`` are LaTeX-escaped here, at the one point every kind's
|
||||
renderer draws them from — ``_plot_metadata`` deliberately keeps using the
|
||||
unescaped ``r`` for the gallery YAML, which isn't LaTeX.
|
||||
"""
|
||||
escaped = dataclasses.replace(r, title=_tex_escape(r.title), xlabel=_tex_escape(r.xlabel))
|
||||
return _RENDERERS[r.kind](escaped, _figure_params(run_meta or {}))
|
||||
|
||||
|
||||
def _plot_metadata(r: Reduced, run_meta: dict) -> dict:
|
||||
|
||||
@@ -461,3 +461,30 @@ def test_plot_metadata_omits_parameters_when_run_meta_empty():
|
||||
meta = render_mod._plot_metadata(r, {})
|
||||
assert "parameters" not in meta
|
||||
assert "note" not in meta
|
||||
|
||||
|
||||
def test_tex_escape_handles_percent_and_other_special_chars():
|
||||
assert render_mod._tex_escape("90% of deposited energy") == r"90\% of deposited energy"
|
||||
assert render_mod._tex_escape(r"a_b & c#d $e {f} \bar") == r"a\_b \& c\#d \$e \{f\} \textbackslash{}bar"
|
||||
|
||||
|
||||
def test_render_survives_title_and_xlabel_with_literal_percent(tmp_path: Path):
|
||||
# Regression test for gitea #81: a literal "%" in a catalog title (e.g.
|
||||
# "Shower containment depth (90% of deposited energy)") crashed the whole
|
||||
# LaTeX render, since usetex treats an unescaped "%" as a comment marker.
|
||||
reduced = [
|
||||
Reduced(
|
||||
"shower_containment_depth_90",
|
||||
"shower",
|
||||
"single_hist",
|
||||
"Shower containment depth (90% of deposited energy)",
|
||||
"depth containing 90% of deposited energy [mm]",
|
||||
{"edges": [0, 1, 2], "series": {"flow": [5, 1]}},
|
||||
),
|
||||
]
|
||||
try:
|
||||
pdfs = _try_render(reduced, tmp_path)
|
||||
except RuntimeError as e: # LaTeX missing at render time
|
||||
pytest.skip(f"LaTeX rendering unavailable: {e}")
|
||||
assert len(pdfs) == 1
|
||||
assert pdfs[0].exists()
|
||||
|
||||
Reference in New Issue
Block a user