render_mod.subprocess is the stdlib subprocess module itself, not a copy —
patching .run unconditionally also intercepted the real subprocess.run
calls matplotlib's texmanager makes to compile LaTeX during savefig, so
those returned the test's fake return value instead of a real
CompletedProcess and crashed with AttributeError: 'NoneType' object has no
attribute 'stdout' on any environment where render_all runs before the
gallery call (i.e. everywhere but this dev machine's warm state that
happened to mask it). Only intercept the "gallery generate" call now;
everything else passes through to the real subprocess.run.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
render.py was at 58% coverage — the module's plotting dispatch (router_gating,
router_share, unavailable) and glue logic (_figure_params/_figure_params_v2,
_plot_metadata, render_all's gallery subprocess call, render_run's condor
RunMeta wiring) had no tests at all. Brings it to 100%: pure-function unit
tests for the v0.2/v0.3.0 figure-param branches and _plot_metadata, real
LaTeX-rendered fixtures for the previously-untested plot kinds and a
4-group grouped_hist (exercises the hidden-leftover-axis branch), and
mocked subprocess/condor calls to isolate render_all/render_run's own logic.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace the monolithic giant/analysis.py (predict-local + RolloutVsTruth
diagnostics) with a lean giant/analysis/ package that compares one
autoregressive `giant rollout` for a checkpoint against a held-out
miniCaloSim reference file, and generates publication-styled plots in
parallel on HTCondor.
Rollout output and a raw reference file share a world-frame physical
column subset under identical names, so the old ALR/local-frame decode
machinery is gone — everything is world-frame mm/MeV.
- sources.py: canonical LazyFrames, synthetic-termination-row filtering,
the secondary view (rollout generation>0 tracks vs reference sec_*_list).
- reduce.py: streaming primitives — a single hist1d group_by pass, per-event
scalars, edep-weighted depth/transverse profiles, species share, leakage.
- context.py/grouping.py: prep resolves fixed bin edges + energy/pdg/material
group sets once into shared.json, so each compute job is one pass, no range
scan (histogram efficiency).
- catalog.py: declarative PlotSpec registry — marginals x {overall,energy,pdg,
material}, per-event totals, shower profiles, species/leakage, secondaries.
- render.py: the only plotstyle/LaTeX importer; PDFs + gallery metadata.
- condor.py + `giant analyze` CLI (prep/compute-one/list/render/submit):
one job per plot, compute/render split (workers polars-only, no LaTeX).
Styling via ETPlot's plotstyle (added to the analysis extra). New tests cover
the reduce primitives, catalog id uniqueness + compute, condor submit, and a
guarded render smoke test. Delete the two predict-diagnostics notebooks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>