SPB Git

spb/wp29_uqo

Public
7.5 KB · 101 lines python
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")7475def table_claims(split):76    c = pd.read_csv(os.path.join(EST, f"{split}_claims_by_arm.csv"))77    lines = [r"\begin{tabular}{lcccccc}", r"\toprule", r"Arm & Runs & Claims/run & Supported/run & Unsupported ``supported''/run & Runs with $\geq$1 & Not assessable/run \\", r"\midrule"]78    for _, r in c.iterrows():79        lines.append(f"{r['treatment']} & {int(r['runs'])} & {fmt(r['claims_per_run'],2)} & {fmt(r['supported_per_run'],2)} & {fmt(r['unsupported_per_run'],3)} & {int(r['runs_with_unsupported'])} & {fmt(r['not_assessable_per_run'],2)} \\\\")80    lines += [r"\bottomrule", r"\end{tabular}"]81    open(os.path.join(TAB, f"tab_claims_{split}.tex"), "w").write("\n".join(lines) + "\n")8283def table_postfix(split=None):84    """Post-fix verification runs (amendment A-006): smoke task × 4 arms and T1-forecast arm C with the corrected launcher; never pooled."""85    r = pd.read_csv(os.path.join(DATA, "runs.csv")); r = r[r["notes"].fillna("").str.contains("seed 102|seed 402")]86    lines = [r"\begin{tabular}{llcccccc}", r"\toprule", r"Run & Task & Arm & Status & Success & Viol. & Sessions & USD \\", r"\midrule"]87    for _, x in r.sort_values("run_id").iterrows():88        lines.append(f"{x.run_id} & {x.task_id} & {x.treatment} & {str(x.terminal_reason or x.status).replace('_', ' ')[:20]} & {'yes' if x.scientific_success == 1 else ('no' if x.scientific_success == 0 else '--')} & {int(x.n_violations) if pd.notna(x.n_violations) else '--'} & {int(x.n_sessions) if pd.notna(x.n_sessions) else '--'} & {x.spent_usd:.2f} \\\\")89    lines += [r"\bottomrule", r"\end{tabular}"]90    open(os.path.join(TAB, "tab_postfix.tex"), "w").write("\n".join(lines) + "\n")9192if __name__ == "__main__":93    split = sys.argv[1] if len(sys.argv) > 1 else "confirmatory"94    for f in (table_arms, table_contrasts, table_cost, table_family, table_robustness, table_order_node, table_claims, table_postfix):95        try: f(split); print("ok", f.__name__)96        except Exception as e: print("skip", f.__name__, e)97    table_accounting()9899100101
Files · 452964ee0fbbaa40fbbed2c87a54ca798ffd6a85
Menu

Theme