From 74363b7219a4d2c23bbfd5b6ed2ffcc8162253ac Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Fri, 25 Sep 2026 20:51:16 +0200 Subject: [PATCH] paper_plots: R-free figure from the refined protocol on the shared free set by default The R-free figure now draws refmac_refined_rfree_shared(_depdata): the deposited model refined against each data set at its own resolution, R-free over the depositor's free reflections both data sets share. --rfree first-cycle keeps the previous first-cycle rigid-body pair at the common resolution. With the rechecked hq-pool3 runs the figure covers 160 structures (was 135). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C --- tools/battery/README.md | 9 +++++---- tools/battery/paper_plots.py | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/battery/README.md b/tools/battery/README.md index 897912b13..599ddb53e 100644 --- a/tools/battery/README.md +++ b/tools/battery/README.md @@ -509,10 +509,11 @@ whole range; the manifest keeps the rule used as `dmin_rule`. ## Figures for publication -`paper_plots.py RUN [RUN-REDO ...] --out DIR [--time-runs RUN ...] [--uncontended RUN]` draws three -open-arm figures from a run's `results.json`: R-free of the deposited model after the REFMAC check -(`--model-check`) on the depositor's data against Rugnux's data (same model, protocol, resolution -and the depositor's free set), the deposited high-resolution limit against Rugnux's cut, and a +`paper_plots.py RUN [RUN-REDO ...] --out DIR [--time-runs RUN ...] [--uncontended RUN] [--rfree refined|first-cycle]` +draws three open-arm figures from a run's `results.json`: R-free of the deposited model after the REFMAC +check (`--model-check`) on the depositor's data against Rugnux's data (by default the refined protocol: +each data set at its own resolution, R-free on the shared free set; `--rfree first-cycle` for the +first-cycle numbers at the common resolution), the deposited high-resolution limit against Rugnux's cut, and a histogram of the processing time per dataset with the median marked. Later runs fill in sets an earlier one did not run (a `-redo`). `--time-runs` takes the time histogram from other runs - one whose sets had the GPU to themselves - and `summary.txt` lists the provenance of both. Beside the PDF/PNG figures it writes the diff --git a/tools/battery/paper_plots.py b/tools/battery/paper_plots.py index 2ca9e5b38..5eca81264 100644 --- a/tools/battery/paper_plots.py +++ b/tools/battery/paper_plots.py @@ -15,9 +15,11 @@ statistics), figures.gp (the gnuplot script) and the rendered figures: a single- with embedded fonts and the same figure as a 600 d.p.i. PNG. gnuplot and pdftoppm (poppler) must be on PATH; gemmi reads the facility and beamline from each entry's cached mmCIF (_diffrn_source). -Left figure: R-free of the deposited model after the battery's REFMAC check (model_check.py: the -same model, protocol, resolution and the depositor's free set) on the depositor's data (x) and on -Rugnux's data (y). Right figure: the deposited high-resolution limit (x) against Rugnux's own cut +Left figure: R-free of the deposited model after the battery's REFMAC check on the depositor's data +(x) and on Rugnux's data (y). By default the refined protocol (model_check.py: the same model +refined against each data set at its own resolution, R-free over the free reflections both data sets +share); --rfree first-cycle draws the first-cycle rigid-body numbers at the common resolution instead. +Right figure: the deposited high-resolution limit (x) against Rugnux's own cut (y), log axes so the low-resolution entries show. Small molecules (no deposited model) and sets whose verdict is `fail` (a wrong lattice: nothing to compare) are left out. @@ -67,7 +69,7 @@ set style line 1 lc rgb "black" lw 1.5 dt 2 set style line 2 pt 7 ps 0.35 lc rgb "#0072b2" # counts: names left-aligned, numbers right-aligned in a column beside them set label 11 "Structures\nFacilities\nBeamlines" at graph 0.05, graph 0.93 left front -set label 12 "%(n)d\n%(nf)d\n%(nb)d" at graph 0.36, graph 0.93 right front +set label 12 "%(n)d\n%(nf)d\n%(nb)d" at graph 0.31, graph 0.93 right front # --- R-free set output "%(out)s/rfree.pdf" @@ -88,7 +90,7 @@ set ylabel "{/:Italic d}_{min}, Rugnux (Å)" set xrange [%(dlo).2f:%(dhi).2f]; set yrange [%(dlo).2f:%(dhi).2f] set xtics (0.5, 1, 2, 4, 8); set ytics (0.5, 1, 2, 4, 8) set format x "%%.1f"; set format y "%%.1f" -set label 12 "%(dn)d\n%(dnf)d\n%(dnb)d" at graph 0.36, graph 0.93 right front +set label 12 "%(dn)d\n%(dnf)d\n%(dnb)d" at graph 0.31, graph 0.93 right front set label 3 "Rugnux deeper: %(deeper)d" at graph 0.95, graph 0.07 right front set label 4 "Deposition deeper: %(shallower)d" at graph 0.05, graph 0.68 left front plot x ls 1, "%(out)s/dmin.dat" using 1:2 ls 2 @@ -161,6 +163,8 @@ def main(): ap = argparse.ArgumentParser(description=__doc__.split("\n\n")[0]) ap.add_argument("runs", nargs="+", help="battery run directories or names (later ones fill in)") ap.add_argument("--out", required=True, help="output directory") + ap.add_argument("--rfree", choices=["refined", "first-cycle"], default="refined", + help="which REFMAC R-free pair to draw (default: refined, on the shared free set)") ap.add_argument("--time-runs", nargs="+", help="runs to draw the time histogram from " "(default: the runs above)") ap.add_argument("--uncontended", help="a run of the same sets with the GPU to itself, to size the " @@ -188,11 +192,14 @@ def main(): excluded.append((s, "both", "verdict fail: " + str(r.get("reason")))) continue where[s] = source(r["model"]) - dep, rug = r.get("refmac_rfree_depdata"), r.get("refmac_rfree_depflags") + if a.rfree == "refined": + dep, rug = r.get("refmac_refined_rfree_shared_depdata"), r.get("refmac_refined_rfree_shared") + else: + dep, rug = r.get("refmac_rfree_depdata"), r.get("refmac_rfree_depflags") if dep and rug: rfree.append((dep, rug, s)) else: - excluded.append((s, "rfree", "no REFMAC pair: " + str(r.get("refmac_reason") + excluded.append((s, "rfree", "no REFMAC pair: " + str(r.get("refmac_refined_reason") or r.get("refmac_reason") or r.get("dep_reason") or "depositor data not scored"))) if r.get("d_min_ref") and r.get("d_min"): dmin.append((r["d_min_ref"], r["d_min"], s))