From af88d62201667bba1c360dda74fc032b5a08053c Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 11 Oct 2026 06:46:59 +0200 Subject: [PATCH] rugnux metric-symmetry check: no demoted arm where it indexes the same lattice The demoted arm of the metric-symmetry check integrated and post-refined the whole sweep even where, released from the equality, its first pass ended on exactly the lattice the promoted class indexes. It then integrates the same reflections the canonical pass does, realises the same held-out residual, and the promoted class stands on the tie - 4nwv spent 14 s to report "I-centred orthorhombic does not beat I-centred orthorhombic". The promoted class's first pass now runs first as an indexing probe (memo cleared, so it always records its outcome), and the demoted arm stops right after its own first pass when that ends on the same first-pass outcome string (lattice vectors to the last bit, path, class, geometry, spot-finding state). No comparison is made and the canonical pass runs as before. The decision is unchanged by construction; the geometry the arm used to hand on is the promoted pass's own fit in that case either way. Output-identical: p.hkl md5 and MTZ arrays equal on all 34 metric-check and scale-walk sets of the battery (31 open/in-house + 3 private) against 56bad5fdb. The skip fired on 5 sets; metric-check step time 4nwv 14.0 -> 2.9 s, 7kcn 6.9 -> 1.6 s, in-house lysozyme sets -1.3..-1.7 s; the promoted probe costs ~0.1-0.8 s on the sets where the lattices differ. Battery metric-check step total 129 -> 107 s. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01EizBKhTqrAYago9KJG3dA3 --- rugnux/Rugnux.h | 5 +++++ rugnux/RugnuxFirstPass.cpp | 5 +++++ rugnux/RugnuxPasses.cpp | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/rugnux/Rugnux.h b/rugnux/Rugnux.h index 24b901afc..f63008b89 100644 --- a/rugnux/Rugnux.h +++ b/rugnux/Rugnux.h @@ -938,6 +938,11 @@ class Rugnux { // lattice on the validation frames (ProcessResult::validation_evidence), before a single image is // integrated. The rotation-scale walk (see RunAllPasses) compares angle models on that score. bool indexing_probe_only_ = false; + // Where a pass stops right after its first pass: when that pass ends exactly on this outcome + // (first_pass_outcome_). The demoted arm of the metric-symmetry check (see RefinedPasses) is + // given the promoted class's own, because a demoted arm that indexes the same lattice the same + // way integrates the same reflections and can only tie. + std::string stop_at_first_pass_outcome_; // --- Near ties: decided early, re-checked late (see FirstPassRun::DecideLate) --- // diff --git a/rugnux/RugnuxFirstPass.cpp b/rugnux/RugnuxFirstPass.cpp index 7f8281b00..e1bd20d49 100644 --- a/rugnux/RugnuxFirstPass.cpp +++ b/rugnux/RugnuxFirstPass.cpp @@ -444,6 +444,11 @@ bool Rugnux::FirstPassRotationIndexing(PipelineLocals &p) { 100.0 * verdict.pooled, 100.0 * verdict.pooled_chance); return true; } + if (!stop_at_first_pass_outcome_.empty() && first_pass_outcome_ == stop_at_first_pass_outcome_) { + logger.Info("First pass: scheme '{}' ends exactly where the promoted class's first pass does, " + "so this pass stops before integrating", best.name); + return true; + } run.RejectChanceLattice(best, verdict); run.AdoptLattice(best, verdict); if (!p.geometry_prepass && !postrefine_probe_only_) diff --git a/rugnux/RugnuxPasses.cpp b/rugnux/RugnuxPasses.cpp index 212851a93..77eb1b006 100644 --- a/rugnux/RugnuxPasses.cpp +++ b/rugnux/RugnuxPasses.cpp @@ -916,6 +916,26 @@ std::optional Rugnux::RefinedPasses(RugnuxObserver *observer, Pro // budget its first pass measures, which the canonical pass would otherwise start from - // except the geometry its post-refinement asks for, which the promoted arm reads (see // ScaleMergeAndSymmetry), and its first-pass memo. + // + // Before it, the promoted class's own first pass, as an indexing probe: the demoted arm + // stops after its first pass where that ends exactly where this one does. Released from the + // equality, the indexing can still find the same lattice - on the same spots, by the same + // path, to the last bit - and then it integrates the same reflections the canonical pass + // will and realises the same residual, which cannot beat it. Measured: an I-centred + // orthorhombic arm integrated a whole sweep to report "I-ortho does not beat I-ortho". + Rugnux promoted_probe(*this); + promoted_probe.indexing_probe_only_ = true; + promoted_probe.postrefine_probe_ = false; + promoted_probe.first_pass_memo_.clear(); // a memo answers without the outcome + try { + promoted_probe.RunPipeline(observer, /*write_output=*/false, /*geometry_prepass=*/false); + } catch (const std::exception &e) { + if (IsFatalResourceError(e)) throw; + promoted_probe.first_pass_outcome_.clear(); + } + ++arm_passes; + for (const auto &m : promoted_probe.first_pass_memo_) + AddFirstPassMemo(m); Rugnux demoted_run(*this); demoted_run.postrefine_probe_ = true; demoted_run.postrefine_probe_only_ = true; @@ -923,12 +943,25 @@ std::optional Rugnux::RefinedPasses(RugnuxObserver *observer, Pro demoted_settings.LatticeClassDemoted(length_arm); demoted_run.experiment_.ImportIndexingSettings(demoted_settings); demoted_run.lattice_angles_demoted_ = angle_arm; + demoted_run.stop_at_first_pass_outcome_ = promoted_probe.first_pass_outcome_; demoted_arm = demoted_run.RunPipeline(observer, /*write_output=*/false, /*geometry_prepass=*/false); ++arm_passes; - prepass_detector_geometry_ = demoted_run.prepass_detector_geometry_; for (const auto &m : demoted_run.first_pass_memo_) AddFirstPassMemo(m); - lattice_arm_check_ = LatticeArmCheck{.demoted = demoted_arm->post_refine}; + const bool same_first_pass = !promoted_probe.first_pass_outcome_.empty() + && demoted_run.first_pass_outcome_ == promoted_probe.first_pass_outcome_; + if (same_first_pass) { + logger.Info("Metric symmetry: released from the equality the first pass ends exactly where " + "the promoted class's does, so the two arms are one and the higher symmetry " + "stands with nothing to compare"); + lattice_arm = fmt::format( + "the metric symmetry stands: released from the {} the first pass indexes the same " + "lattice, so there was nothing to compare", length_arm ? "a = b equality" : "90 deg angle"); + note("the metric symmetry stands: the demoted arm indexes the same lattice"); + } else { + prepass_detector_geometry_ = demoted_run.prepass_detector_geometry_; + lattice_arm_check_ = LatticeArmCheck{.demoted = demoted_arm->post_refine}; + } } else { logger.Info("Metric symmetry: {} - the free refinement departs from it by {:.2f} {}, " "{:.1f} px at the far corner, inside the integration disc of {:.1f} px, so "