1"""CSV -> LaTeX fragments for the paper (booktabs). Numbers are formatted here only; values come from results/tables CSVs."""2from __future__ import annotations3import pandas as pd, numpy as np4from pathlib import Path5from ..util import ROOT6TAB = ROOT / "results/tables"; OUT = ROOT / "paper/tables"78def esc(s):9 return str(s).replace("_", "\\_").replace("%", "\\%").replace("&", "\\&").replace("→", "$\\to$").replace("≥", "$\\ge$").replace("×", "$\\times$").replace("—", "--")1011def df_to_tex(df: pd.DataFrame, path: Path, colfmt: str | None = None, floatfmt="{:.2f}"):12 cols = list(df.columns); colfmt = colfmt or "l" * len(cols)13 lines = ["\\begin{tabular}{@{}" + colfmt + "@{}}", "\\toprule", " & ".join(esc(c) for c in cols) + " \\\\", "\\midrule"]14 for _, r in df.iterrows():15 cells = []16 for c in cols:17 v = r[c]18 if isinstance(v, float):19 cells.append("--" if np.isnan(v) else (floatfmt.format(v) if abs(v) < 1e4 else f"{v:,.0f}"))20 else:21 cells.append(esc(v))22 lines.append(" & ".join(cells) + " \\\\")23 lines += ["\\bottomrule", "\\end{tabular}"]24 OUT.mkdir(parents=True, exist_ok=True); path.write_text("\n".join(lines) + "\n")2526def main():27 t1 = pd.read_csv(TAB / "table1_taxonomy.csv"); df_to_tex(t1, OUT / "table1_taxonomy.tex", "lp{4.2cm}p{2cm}p{2.3cm}p{2.3cm}p{1.6cm}p{2.6cm}")28 t2 = pd.read_csv(TAB / "table2_models.csv")[["alias", "repo", "revision", "layers", "kv_heads", "q_heads", "head_dim", "max_pos", "cache_bytes_per_token_bf16", "prefill_ms_8k", "prefill_ms_16k"]]29 t2.columns = ["alias", "checkpoint", "rev.", "L", "H_kv", "H_q", "d_h", "max pos", "cache B/token", "prefill 8k", "prefill 16k"]; df_to_tex(t2, OUT / "table2_models.tex", "llllllllrrr")30 t3 = pd.read_csv(TAB / "table3_datasets.csv"); df_to_tex(t3, OUT / "table3_datasets.tex", "llrrr", "{:.0f}")31 h = TAB / "ED_hosted.csv"32 if h.exists():33 th = pd.read_csv(h)34 th["cond"] = th["condition"].str.replace(r"\|(anthropic|openai)\|", "|", regex=True).str.replace("|budget_tokens=512", " (512)", regex=False).str.replace("|max_fetch_bytes=2000|max_lookups=6", "", regex=False).str.replace("|provider_cache=True", " +cache", regex=False).str.rstrip("|")35 th["model"] = th["provider_model"].str.replace("-20251001", "").str.replace("-2025-08-07", "")36 th["quality_ci"] = th.apply(lambda r: f"{r.quality:.2f} [{r.lo:.2f}, {r.hi:.2f}]", axis=1)37 th["cost_musd"] = (th["cost_usd_mean"] * 1e3).round(2)38 out = th[["model", "cond", "family", "n", "quality_ci", "cost_musd", "ttft_ms_p50", "total_ms_p50"]].rename(columns={"cond": "condition", "cost_musd": "cost (m\\$)", "ttft_ms_p50": "TTFT p50 (ms)", "total_ms_p50": "total p50 (ms)"})39 out["family"] = out["family"].str.replace("public_", "")40 df_to_tex(out.sort_values(["model", "family", "condition"]), OUT / "table_hosted.tex", "llllrrrr", "{:,.0f}")41 print("latex tables written")4243if __name__ == "__main__":44 main()45