File size: 6,803 Bytes
ef53368
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""Source of truth for the MagNET-benchmark table notebooks (Tables S3/S4 and Table S5). Edit the
cell sources here, then regenerate and re-execute ONLY the notebook you touched, e.g.:

    python3 build_nb_magnet_benchmark.py si_table_s03_s04_performance
    jupyter nbconvert --to notebook --execute --inplace ../si_tables/si_table_s03_s04_performance.ipynb

    python3 build_nb_magnet_benchmark.py si_table_s05_qcd
    jupyter nbconvert --to notebook --execute --inplace ../si_tables/si_table_s05_qcd.ipynb

Regenerating overwrites the .ipynb (clearing its execution outputs), so do not hand-edit the
notebooks and regenerate only what you changed. All real code lives in magnet_benchmark.py (the
PUBLISHED reference values and the exact-reproduction group mapping); the notebooks only read
data/magnet_test_predictions/ through it. The notebooks live in analysis/si_tables/ (grouped by
role), not here.

Run with no arguments to list the available notebook names.
"""
import os
import sys

from nb_build import md, code, save_notebook as _save


_BOOTSTRAP = r"""
import os, sys

# make the in-repo modules importable (not pip-installed)
REPO = os.path.abspath("../..")
for _p in ("data/magnet_test_predictions", "analysis/code", "analysis/code/shared"):
    sys.path.insert(0, os.path.join(REPO, _p))
"""

_IMPORTS = r"""
import pandas as pd
import magnet_test_predictions_reader
import magnet_benchmark
import paths
"""

_SETUP = r"""
PREDICTIONS = paths.dataset_file("magnet_test_predictions", root=REPO)

def document_path(name):
    # table/spreadsheet outputs go under this notebook's documents/ folder, created on first save
    os.makedirs("documents", exist_ok=True)
    return os.path.join("documents", name)
"""

si_table_s03_s04_performance = [
    md(r"""
# Tables S3 and S4: MagNET performance across geometries

How accurately MagNET reproduces its DFT training reference (PBE0/pcSseg-1) as geometries move from
stationary to vibrated to solvated, for the foundation model and the chloroform MagNET-x.
"""),
    code(_BOOTSTRAP),
    code(_IMPORTS),
    code(_SETUP),
    code(r"""
rows = magnet_benchmark.exact_stats_table(PREDICTIONS, magnet_test_predictions_reader)
res = pd.DataFrame(rows).set_index(["nucleus", "model", "test_set"])

table_rows = []
for nucleus in ("1H", "13C"):
    for model in magnet_benchmark.MODELS:
        for ts in magnet_benchmark.TEST_SETS:
            r = res.loc[(nucleus, model, ts)]
            pmed, pmae, prmse = magnet_benchmark.PUBLISHED[nucleus][(model, ts)]
            table_rows.append(dict(nucleus=nucleus, model=model, test_set=ts, n=int(r.n),
                                   median_repro=round(r.median_ae, 6), median_SI=round(pmed, 6),
                                   mae_repro=round(r.mae, 6), mae_SI=round(pmae, 6),
                                   rmse_repro=round(r.rmse, 5), rmse_SI=round(prmse, 5)))
table = pd.DataFrame(table_rows)
table_s3 = table[table.nucleus == "1H"].drop(columns="nucleus")
table_s4 = table[table.nucleus == "13C"].drop(columns="nucleus")
print("Table S3 (1H):"); display(table_s3)
print("Table S4 (13C):"); display(table_s4)

# write the reproduced tables to this notebook's documents/ folder, one sheet per SI table
out = document_path("si_table_s03_s04_performance.xlsx")
with pd.ExcelWriter(out) as writer:
    table_s3.to_excel(writer, sheet_name="Table S3 (1H)", index=False)
    table_s4.to_excel(writer, sheet_name="Table S4 (13C)", index=False)
print("wrote", os.path.relpath(out, REPO))
"""),
    md("## Exact-reproduction check"),
    code(r"""
# every row's reproduced median/MAE/RMSE should match the published SI value to a few parts per million
max_dev = (table[["median_repro", "median_SI"]].diff(axis=1).iloc[:, -1].abs().max(),
          table[["mae_repro", "mae_SI"]].diff(axis=1).iloc[:, -1].abs().max(),
          table[["rmse_repro", "rmse_SI"]].diff(axis=1).iloc[:, -1].abs().max())
print("largest reproduced-vs-published deviation (median, MAE, RMSE):", max_dev)
assert max(max_dev) < 1e-3, "a row diverged from the SI by more than float rounding"
"""),
]


si_table_s05_qcd = [
    md(r"""
# Table S5: Performance statistics for predicting QCD corrections

Foundation MagNET's accuracy at predicting the rovibrational (QCD) correction (stationary vs
trajectory-averaged shielding) over qcdtraj2500 (2500 molecules), ¹H and ¹³C, all shieldings at
PBE0/pcSseg-1.
"""),
    code(_BOOTSTRAP),
    code(_IMPORTS),
    code(_SETUP),
    code(r"""
rows = magnet_benchmark.qcd_stats_table(PREDICTIONS, magnet_test_predictions_reader)
table_rows = []
for r in rows:
    nucleus = r["model"].split("(")[1].rstrip(")")   # "1H" / "13C"
    pmed, pmae, prmse = magnet_benchmark.PUBLISHED_S5[nucleus]
    table_rows.append(dict(model=r["model"], n=int(r["n"]),
                           median_repro=round(r["median_ae"], 8), median_SI=round(pmed, 8),
                           mae_repro=round(r["mae"], 8), mae_SI=round(pmae, 8),
                           rmse_repro=round(r["rmse"], 8), rmse_SI=round(prmse, 8)))
table_s5 = pd.DataFrame(table_rows)
print("Table S5 (QCD corrections):"); display(table_s5)

# write the reproduced table to this notebook's documents/ folder
out = document_path("si_table_s05_qcd.xlsx")
with pd.ExcelWriter(out) as writer:
    table_s5.to_excel(writer, sheet_name="Table S5", index=False)
print("wrote", os.path.relpath(out, REPO))
"""),
    md("## Exact-reproduction check"),
    code(r"""
# every reproduced median/MAE/RMSE should match the published SI value to a few parts per million
dev = max((table_s5[["median_repro", "median_SI"]].diff(axis=1).iloc[:, -1].abs().max(),
           table_s5[["mae_repro", "mae_SI"]].diff(axis=1).iloc[:, -1].abs().max(),
           table_s5[["rmse_repro", "rmse_SI"]].diff(axis=1).iloc[:, -1].abs().max()))
print("largest reproduced-vs-published deviation:", dev)
assert dev < 1e-3, "a row diverged from the SI by more than float rounding"
"""),
]


# name -> (cells, path relative to repo root)
NOTEBOOKS = {
    "si_table_s03_s04_performance": (si_table_s03_s04_performance,
                                     "analysis/si_tables/si_table_s03_s04_performance.ipynb"),
    "si_table_s05_qcd": (si_table_s05_qcd, "analysis/si_tables/si_table_s05_qcd.ipynb"),
}

if __name__ == "__main__":
    here = os.path.dirname(os.path.abspath(__file__))
    repo = os.path.abspath(os.path.join(here, "..", ".."))
    names = sys.argv[1:]
    if not names:
        print("available names:", ", ".join(NOTEBOOKS))
        sys.exit(0)
    unknown = [n for n in names if n not in NOTEBOOKS]
    if unknown:
        raise SystemExit(f"unknown notebook name(s): {unknown}; available: {', '.join(NOTEBOOKS)}")
    for name in names:
        cells, relpath = NOTEBOOKS[name]
        _save(cells, os.path.join(repo, relpath))