"""Recompute every number of F0003 from data/ and assert it matches the recorded values (finding.yaml in the findings repo, expected_numbers.json in a downloaded copy). python check.py # assert python check.py --print # show computed values """ import csv import json import statistics as st import sys from pathlib import Path HERE = Path(__file__).parent def pct(k, n): return round(100 * k / n, 1) if n else 0.0 def compute(): rows = list(csv.DictReader(open(HERE / "data" / "search_outcomes.csv", newline=""))) sset = list(csv.DictReader(open(HERE / "data" / "benchmark_set.csv", newline=""))) done = [r for r in rows if r["status"] == "done"] lower = [r for r in done if r["outcome"] == "lower"] kind = lambda k: [float(r["lower_by_kcal"]) for r in lower if r["best_kind"] == k] gap = [float(r["lower_by_kcal"]) for r in lower] med = lambda xs: round(st.median(xs), 2) if xs else None atoms = [int(r["n_atoms"]) for r in sset] left = list(csv.DictReader(open(HERE / "data" / "left_out_irc.csv", newline=""))) return { "set": len(sset), "searched": len(rows), "with_route": len(done), "lower": len(lower), "lower_pct_of_searched": pct(len(lower), len(rows)), "lower_single_step": len(kind("direct")), "lower_multistep": len(kind("multistep")), "matched": sum(r["outcome"] == "matched" for r in done), "higher": sum(r["outcome"] == "higher" for r in done), "no_route": sum(r["status"] == "no_route" for r in rows), "no_route_pct_of_searched": pct(sum(r["status"] == "no_route" for r in rows), len(rows)), "time_limit": sum(r["status"] == "timeout" for r in rows), "crashed": sum(r["status"] not in ("done", "no_route", "timeout") for r in rows), "lower_median_kcal": med(gap), "lower_median_single_step_kcal": med(kind("direct")), "lower_median_multistep_kcal": med(kind("multistep")), "lower_max_kcal": round(max(gap), 2) if gap else None, "top_n": 10, "n_atoms_min": min(atoms), "n_atoms_max": max(atoms), "left_out_irc": len(left), "left_out_drop_over_20_kcal": sum(max(float(r["start_end_drop_kcal"]), float(r["end_end_drop_kcal"])) > 20 for r in left), "left_out_soft_saddle": sum(float(r["ts_imaginary_cm"]) > -200 for r in left), "left_out_clear_saddle_small_drop": sum(float(r["ts_imaginary_cm"]) <= -200 and max(float(r["start_end_drop_kcal"]), float(r["end_end_drop_kcal"])) <= 5 for r in left), } def expected(): if (HERE / "finding.yaml").exists(): import yaml return yaml.safe_load((HERE / "finding.yaml").read_text())["evidence"]["numbers"] return json.loads((HERE / "expected_numbers.json").read_text()) if __name__ == "__main__": got = compute() if "--print" in sys.argv: print(json.dumps(got, indent=1)) sys.exit(0) want = expected() bad = [f"{k}: recorded {want.get(k)!r}, data gives {v!r}" for k, v in got.items() if want.get(k) != v] bad += [f"{k}: recorded but not computed" for k in want if k not in got] if bad: print("\n".join(bad)) sys.exit(1) print(f"all {len(got)} numbers reproduce from data/")