Beam-centre ladder: each trial centre fed, indexed and scored in one go

The ladder fed a ring's four centres, indexed them together, then set every
centre up a second time (new mapping, new spot engines, re-detected
validation frames) to score it. Each centre is now evaluated completely
before the next, which removes the second set-up and the centres indexed
after an adoption. Adoption order and rule are unchanged.

p.mtz md5 and the adopted centre unchanged on kdp (no adoption, 48 rungs),
9qw8 (+2 px at ring 2) and cuhf2 (+10 px at ring 10). Ladder time kdp
68.8 -> 64.2 s, 9qw8 8.6 -> 7.4 s, cuhf2 21.3 -> 22.9 s (loaded box). The
cost of a centre is its spot re-detection (kdp: ~1150 frames per centre).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
This commit is contained in:
2026-10-06 23:10:26 +02:00
co-authored by Claude Opus 5.5
parent 76b3956e11
commit 0f9f3ac73c
+11 -16
View File
@@ -5264,26 +5264,21 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
int seen = best.score;
for (int k = 1; k <= reach && !cancelled_ && !adopted && !centre_past_reach; k++) {
const std::array<std::pair<int, int>, 4> ring = {{{-k, 0}, {k, 0}, {0, -k}, {0, k}}};
// The ring's four centres are fed first and indexed at once, each on its own copy of
// the experiment at that centre, then read in order as before. A centre after the one
// adopted is indexed for nothing.
std::array<std::unique_ptr<DiffractionExperiment>, 4> ring_experiment;
std::array<SchemeIndexers, 4> ring_ris;
std::vector<RotationIndexer *> all_ris;
for (size_t h = 0; h < ring.size() && !cancelled_; h++) {
try_beam_center(beam_x + static_cast<float>(ring[h].first),
beam_y + static_cast<float>(ring[h].second));
ring_experiment[h] = std::make_unique<DiffractionExperiment>(experiment_);
ring_ris[h] = feed_schemes(*indexer_pool, ring_experiment[h].get());
for (const auto &ri : ring_ris[h])
all_ris.push_back(ri.get());
}
run_indexing(all_ris);
// One centre at a time, fed, indexed and scored under the one mapping and spot list it
// was set up with. The cost of a centre is re-finding its spots, which is the same
// whether four are indexed at once or one; indexing the four together saved only the
// short indexing step, while setting each centre up a second time to score it cost
// more than that, and every centre after the adopted one was indexed for nothing.
for (size_t h = 0; h < ring.size() && !cancelled_; h++) {
const float trial_x = beam_x + static_cast<float>(ring[h].first);
const float trial_y = beam_y + static_cast<float>(ring[h].second);
try_beam_center(trial_x, trial_y);
FirstPass alt = score_schemes(ring_ris[h], *indexer);
SchemeIndexers ris = feed_schemes(*indexer_pool);
std::vector<RotationIndexer *> ris_ptrs;
for (const auto &ri : ris)
ris_ptrs.push_back(ri.get());
run_indexing(ris_ptrs);
FirstPass alt = score_schemes(ris, *indexer);
logger.Info("Beam-centre hypothesis ({:.2f},{:.2f}): {}/{} frames", trial_x,
trial_y, alt.score, static_cast<int>(validation.size()));
seen = std::max(seen, alt.score);