From bf41b1fab1ba50fd39573fbcc151f61246ce1371 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 30 Aug 2026 10:28:35 +0200 Subject: [PATCH] rugnux: index both beam centres always, without a significance gate first The second first pass was skipped where the measured centre sat within three times the fit's own sigma of the file's - a quarter of the non-SLS corpus, eight of thirty-two runs. That is a decision taken at a threshold before the evidence is in, and the evidence here costs a median 0.55 s: the spots are already found and cached, and their positions do not depend on the centre, so a second first pass is a median 20 % of what the first one costs. Worse, the gate removed exactly the case worth asking about. A centre error ALONG the spindle does not fail - it holds 96-100 % of frames indexed and quietly returns an axis harmonic - and the scale it turns on is a fraction of a pixel: measured on real data, 0.12 px of centre is the whole difference between the deposited cell and a halved axis. No sigma small enough to gate on would notice that, so the gate could only ever hide the question, never answer it. The three-sigma test stays where it belongs, in the report: it says whether the difference is a measurement or noise, which is what a reader wants to know. It no longer decides whether to look. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01T3yNBXk4wKdMZy1ak2NY7f --- rugnux/Rugnux.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rugnux/Rugnux.cpp b/rugnux/Rugnux.cpp index e25479c79..c3626ed07 100644 --- a/rugnux/Rugnux.cpp +++ b/rugnux/Rugnux.cpp @@ -894,7 +894,9 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru // g', confidently. A move it cannot resolve is not evidence about the header either way. if (moved <= 3.0f * background_center_->sigma_pxl) logger.Info("Beam centre check: that is under three times the fit's own sigma, so the " - "file's centre is as good as this measurement can tell"); + "file's centre is as good as this measurement can tell - the second first " + "pass below indexes it anyway, because a fraction of a pixel is enough to " + "decide a cell and no sigma small enough to gate on would notice"); else if (across && *across > need) // Info and not a warning: `need` is where the FFT amplitude at a 200 A axis has fallen // to 0.70, which is a floor under what matters and not a threshold for failure - it is @@ -2224,8 +2226,13 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b const float measured_x = measured.beam_x_pxl; const float measured_y = measured.beam_y_pxl; const float moved = std::hypot(measured_x - header_x, measured_y - header_y); - // A move the fit cannot resolve is not a different hypothesis, only the same one twice. - if (moved > 3.0f * measured.sigma_pxl) { + // No gate on how significant the move is. It is tempting to skip the second pass when the + // two centres are within the fit's own noise - it would save it on a quarter of the runs + // here - but that is deciding at a threshold before the evidence is in, and the evidence + // is cheap. It would also gate away exactly the case worth asking about: measured on real + // data, a 0.12 px change of centre is the whole difference between the deposited cell and + // a halved axis, and 0.12 px is well inside the sigma of any fit that could gate it. + { const int majority = static_cast(validation.size()) / 2; experiment_.BeamX_pxl(measured_x).BeamY_pxl(measured_y); FirstPass alt = pick_best(*indexer_pool, *indexer);