Files
Jungfraujoch/image_analysis/geom_refinement
leonarski_fandClaude Opus 5 6a87d097b1 rotation indexing: the chain commits its best round, not the round it stops on
The post-selection refinement chain solves, re-accumulates the reciprocal-space
cloud under the refined geometry and solves again, up to twenty times, and then
commits whatever round it stopped on. Which round that is, is decided by a test
on the detector-tilt step - and the unrestrained perpendicular component of that
step is scatter at the size of its own bound, taking values over three decades
with no trend. So the round a run commits is settled by the last bits, and the
compiler flags settle it: on a C-centred monoclinic crystal refined free, the
two primitive axes the lattice makes equal walk from 0.84 % apart one way,
through equality, to 1.15 % apart the other, and the plain-Release and
-march=x86-64-v3 builds stopped seventeen rounds apart on that one walk.

The walk is an overfit, and that is the larger half. Every solve ends by fitting
only the spots inside its tightest gate, so a free cell whose metric is near a
Bravais class can slide along the one direction the data barely constrain,
pulling a core of spots tighter while the periphery falls out of the fit
altogether. Over those seventeen rounds the spots inside the tight gate rise
0.295 -> 0.327 while the spots inside the widest gate peak at round three
(0.754) and fall to 0.730 - and round three is the round that merges ISa 11.0
against 6.3 and R_meas 0.148 against 0.213, and the one that agrees with the
archived reference cell. Nothing the run consulted could see it: indexed
fraction, validation frames, validation spots and the tight-gate count all
prefer the overfitted end.

So score every round on the widest gate - the one XtalOptimizer's first pass
selects on and its last pass does not fit, which makes it the population a
converged solve is not optimising - and commit the best-scoring round. Two
conditions keep that from acting on noise. The score is a COUNT of spots, and a
lead of fewer than sqrt(count) of them is inside the count's own noise, so a
smaller lead leaves the last round standing; at the default accumulation cap
that bound is about 0.9 percentage points, against the 2.4 the case above leads
by. And the round taken has to be the less distorted lattice as well as the
better-fitting one: LatticeSearch is re-asked every round to MEASURE the drift
from the class the metric matches - imposing that class is measured fatal, the
snap puts almost everything outside the refinement's own gate - and the earlier
round is taken only when it matched the same class and sits closer to it.

Same class is a precondition, not a precaution. The deviation is a fraction of
the tolerance of whichever class the round matched, so two classes' deviations
are not the same quantity; and a round that matched no class reports 0, which
means "nothing was asserted", not "undistorted". Comparing that against a
class's deviation reads the absence of a constraint as the absence of
distortion, and switches the veto off - measured, on 11 of 1132 traced chains,
four of them against a round with no class at all - which leaves the spot count
deciding alone. That configuration was measured: it costs another crystal
R_meas 0.2553 -> 0.3181 by firing on a symmetry-constrained chain whose cell
moves 0.10 % over twenty rounds and which is not drifting anywhere.

Measured over 31 datasets and 914 chains: an earlier round scores higher on
44 % of chains, but the rule changes the committed round on 1 of 54. Both
conditions are why - a chain that has settled scores its rounds within a spot or
two of each other, and a symmetry-constrained solve holds its distortion at zero
throughout, so the rule cannot fire on either. Twelve paired datasets are
byte-identical, including five where it fires on a chain whose result the run
does not use, and including the tilt-critical sweeps whose committed chains peak
at their last round 19 times out of 19. Both builds now agree on the crystal
above at ISa 11.00 against 11.01, and the second flag-dependent crystal is
byte-identical in both builds. Deterministic across -N 6/8/32.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GxZqDiFP3KqriBhNdcR56
2026-09-14 18:47:43 +02:00
..
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-08-13 17:03:10 +02:00
2026-06-23 20:29:49 +02:00
2026-06-23 20:29:49 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-02 21:17:31 +02:00
2026-09-09 07:25:13 +02:00