1"""LaTeX tables generated from the estimates (no manual numeric editing)."""2import os, sys3sys.path.insert(0, os.path.dirname(__file__))4from common import *5TAB = os.path.join(REPO, "results", "tables"); os.makedirs(TAB, exist_ok=True)67def fmt(x, nd=3):8 if x is None or (isinstance(x, float) and np.isnan(x)): return "--"9 return f"{x:.{nd}f}" if isinstance(x, (float, np.floating)) else str(x)1011def table_arms(split):12 at = pd.read_csv(os.path.join(EST, f"{split}_arm_table.csv"))13 lines = [r"\begin{tabular}{lcccccccc}", r"\toprule", r"Arm & Runs & Tasks & $\hat p_a$ & Correct (any) & Viol.\ rate & Repro. & Quality & Cost/run (USD) \\", r"\midrule"]14 for _, r in at.iterrows():15 lines.append(f"{r['arm']} & {int(r['n_runs'])} & {int(r['n_tasks'])} & {fmt(r['Y_task_weighted'])} & {fmt(r['correct_any_task_weighted'])} & {fmt(r['violation_rate'])} & {fmt(r['reproducible_rate'])} & {fmt(r['quality_mean'])} & {fmt(r['cost_mean_usd'],2)} \\\\")16 lines += [r"\bottomrule", r"\end{tabular}"]17 open(os.path.join(TAB, f"tab_arms_{split}.tex"), "w").write("\n".join(lines) + "\n")1819def table_contrasts(split):20 ct = pd.read_csv(os.path.join(EST, f"{split}_contrasts.csv"))21 lines = [r"\begin{tabular}{llcccccc}", r"\toprule", r"Endpoint & Contrast & Role & $J$ & $\hat\Delta$ & 95\% CI & Perm.\ $p$ & Holm $p$ \\", r"\midrule"]22 names = {"Y": "Primary $Y$", "Y_any": "Correct (any)", "viol": "Violation", "quality_score": "Quality"}23 for _, r in ct.iterrows():24 lines.append(f"{names.get(r['endpoint'], r['endpoint'])} & {r['contrast']} & {r['role']} & {int(r['n_task_clusters'])} & {fmt(r['estimate'])} & [{fmt(r['ci_low'])}, {fmt(r['ci_high'])}] & {fmt(r['perm_p'])} & {fmt(r['holm_p']) if not pd.isna(r['holm_p']) else '--'} \\\\")25 lines += [r"\bottomrule", r"\end{tabular}"]26 open(os.path.join(TAB, f"tab_contrasts_{split}.tex"), "w").write("\n".join(lines) + "\n")2728def table_cost(split):29 at = pd.read_csv(os.path.join(EST, f"{split}_arm_table.csv"))30 lines = [r"\begin{tabular}{lccccccccc}", r"\toprule", r"Arm & Mean & Median & P90 & Total & Reviewer & Wall med.\ (s) & Wall P90 & Timeouts & Cost/success \\", r"\midrule"]31 for _, r in at.iterrows():32 lines.append(f"{r['arm']} & {fmt(r['cost_mean_usd'],2)} & {fmt(r['cost_median_usd'],2)} & {fmt(r['cost_p90_usd'],2)} & {fmt(r['cost_total_usd'],2)} & {fmt(r['reviewer_usd_total'],2)} & {fmt(r['wall_median_s'],0)} & {fmt(r['wall_p90_s'],0)} & {int(r['n_timeout'])} & {fmt(r['cost_per_success_usd'],2) if not pd.isna(r['cost_per_success_usd']) else 'undefined'} \\\\")33 lines += [r"\bottomrule", r"\end{tabular}"]34 open(os.path.join(TAB, f"tab_cost_{split}.tex"), "w").write("\n".join(lines) + "\n")3536def table_family(split):37 fam = pd.read_csv(os.path.join(EST, f"{split}_family_table.csv")); fams = sorted(fam["family"].unique())38 lines = [r"\begin{tabular}{l" + "c" * (2 * len(ARMS) + 1) + "}", r"\toprule", "Family & Tasks & " + " & ".join(f"$\\hat p_{a}$ & viol.\\ {a}" for a in ARMS) + r" \\", r"\midrule"]39 for f in fams:40 d = fam[fam["family"] == f].set_index("treatment")41 lines.append(f"{f} & {int(d['n_tasks'].iloc[0])} & " + " & ".join(f"{fmt(d.loc[a, 'Y'],2) if a in d.index else '--'} & {fmt(d.loc[a, 'viol'],2) if a in d.index else '--'}" for a in ARMS) + r" \\")42 lines += [r"\bottomrule", r"\end{tabular}"]43 open(os.path.join(TAB, f"tab_family_{split}.tex"), "w").write("\n".join(lines) + "\n")4445def table_accounting():46 df = pd.read_csv(os.path.join(DATA, "runs.csv"))47 lines = [r"\begin{tabular}{lcccccccc}", r"\toprule", r"Split & Assigned & Launched & Completed & Timeout & Budget & Infra.\ error & Evaluated & Successes \\", r"\midrule"]48 for s in ["development", "pilot", "confirmatory", "transfer", "recovery", "ablation"]:49 d = df[df["split"] == s]50 if d.empty: continue51 tr = d["terminal_reason"].fillna("")52 lines.append(f"{s} & {len(d)} & {int((d['status'] != 'not_started').sum())} & {int(tr.str.startswith('executor_finished').sum() + tr.eq('max_turns_reached').sum())} & {int(tr.eq('wall_clock_limit').sum())} & {int(tr.str.contains('budget').sum())} & {int(tr.str.startswith('infrastructure').sum())} & {int((d['status'] == 'evaluated').sum())} & {int((d['scientific_success'] == 1).sum())} \\\\")53 lines += [r"\bottomrule", r"\end{tabular}"]54 open(os.path.join(TAB, "tab_accounting.tex"), "w").write("\n".join(lines) + "\n")5556def table_robustness(split):57 rb = pd.read_csv(os.path.join(EST, f"{split}_robustness.csv"))58 lines = [r"\begin{tabular}{lcccc}", r"\toprule", r"Analysis (D$-$A) & $J$ & $\hat\Delta$ & 95\% CI & Perm.\ $p$ \\", r"\midrule"]59 for _, r in rb.iterrows():60 lines.append(f"{r['analysis'].replace('_', ' ')} & {int(r['n_tasks'])} & {fmt(r['estimate'])} & [{fmt(r['ci_low'])}, {fmt(r['ci_high'])}] & {fmt(r['perm_p'])} \\\\")61 lines += [r"\bottomrule", r"\end{tabular}"]62 open(os.path.join(TAB, "tab_robustness.tex"), "w").write("\n".join(lines) + "\n")6364def table_order_node(split):65 on = pd.read_csv(os.path.join(EST, f"{split}_order_node.csv"))66 lines = [r"\begin{tabular}{llcccc}", r"\toprule", r"Factor & Level & A & B & C & D \\", r"\midrule"]67 for fac in ["order", "node"]:68 d = on[on.factor == fac]69 for lev in sorted(d["half"].unique()):70 dd = d[d["half"] == lev].set_index("treatment")71 lines.append(f"{fac} & {lev} & " + " & ".join(fmt(dd.loc[a, 'Y'], 2) if a in dd.index else "--" for a in ARMS) + r" \\")72 lines += [r"\bottomrule", r"\end{tabular}"]73 open(os.path.join(TAB, "tab_order_node.tex"), "w").write("\n".join(lines) + "\n")7475if __name__ == "__main__":76 split = sys.argv[1] if len(sys.argv) > 1 else "confirmatory"77 for f in (table_arms, table_contrasts, table_cost, table_family, table_robustness, table_order_node):78 try: f(split); print("ok", f.__name__)79 except Exception as e: print("skip", f.__name__, e)80 table_accounting()8182