The null costs about 12 s - five replicates, each a full fit and a rigid-body
placement - and it gates exactly two decisions: the enantiomorph label and the
merohedral indexing. A model that claims neither, already in the group the data
were merged in on a crystal with no indexing ambiguity, has nothing for the null
to arbitrate, and paying for it there is 12 s spent gating a decision nobody is
making. That is the isomorphous fragment-screening run - hundreds of crystals of
one form against one apo model, a map wanted seconds after the last image - and
it is the case that has to be fast.
So the null runs only when a decision is pending: an enantiomorph candidate
exists, or the indexing probe returned a winner that is not the identity. The
probe is a handful of scaling fits and had to run first anyway, so the question
is answered before the expensive part starts.
Measured on a rotation dataset, --mode scale --model, interleaved on a loaded
machine: the isomorphous case is 3.6-4.7 s before this whole line of work and
3.8-4.7 s with the gate, against 16.5 s while the null ran unconditionally. The
case that still pays is unchanged at 17 s, and the three wrong-model cases give
bit-identical verdicts and bit-identical files to before.
The rigid-body refinement of the replicates stays: 3 of 5 commit a placement, so
without it the null would score a weaker procedure than the one it judges.
MODEL_FIT gains a third value, NOT_TESTED, alongside ACCEPTED and REJECTED - the
question was never put, which is not the data answering it badly - and the
MODEL_FIT_NULL_* and MODEL_FIT_SIGMA keys are absent with it rather than
reporting a null that was never built. REPORT_VERSION stays 6: MODEL_FIT is
itself new in this release, so its vocabulary has never shipped and a consumer
cannot be relying on the two-value form.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N