"""Export key numbers from results/tables as LaTeX macros (paper/tables/numbers.tex) so that prose never hard-codes values.""" from __future__ import annotations import re, pandas as pd, numpy as np, json from pathlib import Path from ..util import ROOT, read_json TAB = ROOT / "results/tables"; OUT = ROOT / "paper/tables/numbers.tex" def _key(s: str) -> str: s = re.sub(r"[^A-Za-z0-9]", " ", s).title().replace(" ", "") return re.sub(r"\d", lambda m: "ZOTTFFSSEN"[int(m.group(0))], s) # LaTeX macro names cannot contain digits def main(): lines = ["% auto-generated by wp30.analysis.numbers — do not edit"] def add(name, val, fmt="{:.2f}"): if val is None or (isinstance(val, float) and np.isnan(val)): lines.append(f"\\newcommand{{\\{name}}}{{--}}") else: lines.append(f"\\newcommand{{\\{name}}}{{{fmt.format(val) if not isinstance(val, str) else val}}}") prim = TAB / "E1_core_primary.csv" if prim.exists(): t = pd.read_csv(prim) add("nCoreTrials", int(pd.read_csv(TAB / "E1_core_failures.csv").iloc[:, 1:].to_numpy().sum()) if (TAB / "E1_core_failures.csv").exists() else None, "{:,}") for _, r in t.iterrows(): k = _key(f"{r['family']} {r['pair']} {r['condition']}") add("Q" + k, r["quality"] * 100, "{:.0f}"); add("Qlo" + k, r["q_lo"] * 100, "{:.0f}"); add("Qhi" + k, r["q_hi"] * 100, "{:.0f}") add("B" + k, r["payload_bytes_median"], "{:,.0f}"); add("Tcold" + k, r["cold_ms_p50"], "{:,.0f}"); add("Twarm" + k, r["warm_ms_p50"], "{:,.0f}") tests = pd.read_csv(TAB / "E1_core_primary_tests.csv") if (TAB / "E1_core_primary_tests.csv").exists() else None if tests is not None: for _, r in tests.iterrows(): k = _key(r["name"].split(" ")[0]) add("Diff" + k, r["diff"] * 100, "{:+.1f}"); add("Lo" + k, r["lo"] * 100, "{:+.1f}"); add("Hi" + k, r["hi"] * 100, "{:+.1f}"); add("P" + k, r["p_holm"], "{:.3f}"); add("N" + k, int(r["n"]), "{:d}") if (ROOT / "protocol/frozen.json").exists(): add("protocolHash", read_json(ROOT / "protocol/frozen.json")["protocol_hash"][:16], "{}") OUT.parent.mkdir(parents=True, exist_ok=True); OUT.write_text("\n".join(lines) + "\n") print(f"{len(lines)-1} macros -> {OUT}") if __name__ == "__main__": main()