Everything the ring fit reads was binned with the geometry the run started
from, and a calibration is run precisely because that geometry is in doubt.
Binning is not something a later fit can undo: which pixel landed in which
(q, phi) bin was decided when the images were read. Get the distance wrong and
the radial sampling is the wrong scale - a run recovering 110 mm from a 250 mm
header ended at rms 1.07 px where the same data from a right header gives 0.42.
Get the centre wrong and every ring is smeared across its own sectors, and past
about a hundred pixels the fit leaves rms 4.8 px even when it is started from
the exact answer, because there is nothing left in the profile to fit.
So integrate the images a second time, binned about what was fitted, and fit
that. A calibration run is a handful of images and the answer is worth far more
than the extra read.
Re-binning about the FIRST fit is not enough on its own. Where the beam centre
was badly out that fit is itself wrong, and binning about it digs deeper - rms
3.75 -> 5.66 on an exposure 200 px off. The spots' geometry is the one that does
not degrade there, having never read the header, so both are tried where they
differ and whichever comes back better is kept. On that exposure the first
candidate gives 288 points at rms 5.66 and the second 369 at 0.81.
The second pass is taken only if it is actually better, by the same rule that
ranks everything else here - at least half as many ring points and a smaller
residual - and it is skipped altogether when the fitted geometry moves a ring by
less than the radial width of one profile bin, since re-binning would then put
every pixel back where it already is. On the 110 mm exposure with its own header
that is 1.77 px against a 1.84 px bin, so the run is untouched and its answer
bit-identical.
Measured on the 110 mm LaB6 exposure, true PONI x 765.90 at 110.03 mm. The
calibration is now independent of the header it was given:
beam-x out by +20 +40 +100 +200 +400 px -> 765.9-766.6, 110.02-110.05 mm
250 mm header, beam-x 780 -> 765.998 at 110.037, rms 0.394
250 mm header, beam-x 867 -> 765.723 at 110.038, rms 0.413
900 mm header, beam-x 1167 -> 766.496 at 110.038, rms 0.804
30 mm header, beam-x 967 -> 766.486 at 110.039, rms 0.807
All of those failed before this, most of them catastrophically. The residual
inflation is gone with them: the 250 mm case now leaves 0.394 px, better than
the same data from its own correct header.
The four other datasets are unchanged where the re-bin fires, and slightly
better where it does: rms 0.433 -> 0.423 at 150 mm and 0.555 -> 0.550 at 200 mm,
with the geometry moving under a tenth of a pixel. A run that needs the second
pass costs about twice one that does not.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NfuDvf5ipV3Hi8TiCUKD27