The score exists so beamline automation can engage a recovery protocol - a two-sweep collection,
a goniometer reorientation - with no human in the loop, so its canonical reading is fixed in one
place with nothing for a beamline to tune: engage at 0.5, do not below, and NO VALUE is a third
state that automation must treat as engage. The error costs are asymmetric - a false negative
leaves the data permanently short, a false positive costs minutes of beamtime - and a frame
nobody could measure must not be read as a frame measured safe.
The 0.5 is derived, not tuned: the score is monotone in the folded miss-angle, so any threshold
is a fold-angle gate, and 0.5 gates at fold <= 0.4040 * theta_max (verified root). Engaging on
any overlap at all would gate at fold < theta_max, whose perpendicular band alone spans
sin(theta_max) per row - 26% of orientation space at 15 deg - and unions over a frame's rows to
well over half of all mountings, degenerating the trigger into "always"; at 0.5 the residual
missed loss stays below half the cone.
Also correct the message-field comment that said the whole cone means "1 - cos theta_max of
every shell": an inner shell loses 1 - cos theta(d) at its own, smaller theta(d).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
The score gated on 60 spots, but the seed escalation stops at the leanest seed that indexes -
30 spots on precisely the clean frames a grid scan produces - so the value was absent exactly
where beamline automation most needs it, and absence maps to "engage": the protocol would have
fired on every good frame, which degenerates the trigger into "always". The floor itself stays
where it was calibrated; what changes is what it gates. When no escalation pass could answer,
one severity-only pass runs over the full spot list - the row search alone, no reduction, no
refinement - purely to produce the number.
The same was true of the indexer choice: only the FFT family computes a row shortlist, so a
deployment configured with the known-cell indexer - the ordinary online stills path - never
produced the score at all. Where the severity-only pass has no row search to run, the severity
is read off the rows of the winning lattice instead, which any indexer produces: the lattice's
shortest few distinct directions, as many as the FFT shortlist resolves in practice, fed through
the same window and scoring with equal magnitudes. The count parity is load-bearing - a worst
case over every enumerable lattice direction fires on 100% of harmless mounts of a generic
triclinic cell against 74% for this selection at theta_max = 15 deg, and an always-firing
trigger decides nothing - while the diad-detection rate stays 1.00 on the monoclinic classes
either way, a dropped axis row being recovered by the pair normals exactly as an invisible one
is. A frame that neither indexed nor reached the spot floor still reports nothing, which is the
honest answer and maps to the recoverable error.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
The length window is deliberate - a row 2.5x the crystal's shortest is not a plausible symmetry
axis in a crystal that small - but it made the score blind to a lone 2-fold on an axis LONGER
than the window: a monoclinic crystal with a long unique axis, mounted near-perpendicular at an
unlucky azimuth, returned a confident 0 rather than a refusal. The axis is recoverable without
ever seeing its row: the normal to two direct-lattice rows is itself a reciprocal-lattice row,
and a symmetry axis is parallel in the direct and reciprocal bases, so cross(a, c) is the
unique-axis direction whatever the length of b. The normals of the strong in-window row pairs
are now scored alongside the rows themselves, with row_length_A = 0 marking a direction the
frame inferred rather than measured.
Measured on a synthetic lone-diad crystal with a 300 A unique axis over random mounts, the
fraction of severe mounts reported severe at the 0.5 trigger rises from 0.60 to 1.00, the
engagement rate on harmless mounts of that class does not move, and the recovered direction
reproduces the true axis exactly (every visible row is perpendicular to it).
Also state the shortlist-consistency calibration on its per-crystal basis - 22 independent
mounts, not the several hundred frames they contributed - and carry the conditioning the
perpendicular case needs: an axis of order >= 3 there fully repairs the cone (measured 0.000
unrepaired for orders 3, 4, 6 against 1.000 for a diad), which a still cannot know, so the lone
diad stays the operative worst case and the bound stays deliberately pessimistic on
higher-symmetry crystals.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
The blind region a sweep leaves is a double cone, so a 2-fold sends it to two
places: 2*beta away, and 180-2*beta away. The severity took only the first, and
scored a row perpendicular to the spindle as 0 - "symmetry repairs everything" -
when such a 2-fold in fact carries the cone onto its opposite lobe, which the
sweep leaves equally unmeasured. Folding the miss-angle to min(beta, 90-beta)
covers both images and reproduces a Monte-Carlo of the true overlap to 0.002.
The failure was silent and in the dangerous direction, and it fired on the more
common geometry: for a random axis the perpendicular band is several times wider
than the aligned one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
A rotation sweep never records a double cone of half-angle asin(lambda/2d) about the spindle.
That loss is normally repaired by the point group; it is not repaired when an operator's axis
lies inside the cone, because the cone then maps onto itself. A still cannot know the point
group, but it can see where the crystal's short lattice rows are, and a symmetry axis is always
one of them - measured over 107 solved cells its length is 1.4x the shortest row at the median.
The number is the fraction of the blind cone that a 2-fold about the nearest short row carries
back into the blind cone: two equal caps of angular radius theta_max whose centres are 2*beta
apart, which is the circle-lens area in beta/theta_max and within 0.035 of the spherical value
even for a 55 deg cone. 0 means one sweep reaches everything symmetry could give; 1 means the
row is on the spindle and the whole cone is lost coherently. No goniometer geometry enters, so
the number describes the problem and leaves the remedy to the beamline.
Free: it rides on the FilterFFTResults shortlist the indexer already builds, needing only the
spindle, the wavelength and the frame's own resolution. FilterFFTResults gains an optional
out-parameter for each row's peak prominence, which the length window is taken over.
Measured on 384 stills of 22 solved crystals against the frames' own symmetry axes, with the
same procedure re-run along five decoy directions per frame as the null: 0.93 of severe
orientations reported severe, 0.010 of harmless ones reported severe, AUC 0.948, and the value
tracks the true severity to 0.10 at the 90th percentile. Below 60 spots the misses triple, so
that is where it stops answering.
It is blind to a symmetry axis much longer than the crystal's shortest row: measured on
synthetic stills the search grid finds a 150 A row every time, a 200 A row half the time and a
300 A row once in sixteen. Two cheap consistency tests refuse to answer for part of that regime
and cost nothing on real frames, but they do not cover it - the reach is a documented property
of the number, not something every frame can detect.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N