Revert "rugnux: the first pass takes the larger of two domains of one lattice"

This reverts commit c5a13d212.

The second-domain test fixed its target (a low-ISa insulin set) but was
evaluated 1132 times on 212 battery sets and adopted a "second domain"
on 50 of them; three sets that passed went to fail (5j23, 9qw2 and one
private set: F432 -> P432). It never asks whether the other domain is a
different orientation, so near-ties at 54:46 decide it. A narrowed
version (regr2-domain) still costs about 120-200 s battery-wide for one
difficult set. It is parked for rc176, where near-tie domains are to be
carried as two hypotheses and decided late.

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:
leonarski_fandClaude Opus 5.5 committed 2026-10-09 09:13:43 +02:00
1 parent c6412819ba
commit dc92359f09
1 file changed
-61
-61
View File
@@ -2407,67 +2407,6 @@ bool Rugnux::FirstPassRotationIndexing(PipelineLocals &p) {
best = *rescued;
}
// A second domain of the same lattice. Two twin domains, or two crystals of one cell, each
// index every validation frame, so the frame count cannot say which of them is the crystal,
// and the FFT returns whichever its sample happens to favour. On the first part of a sweep
// that can be the domain there is less of (measured: an I-centred cubic crystal with a second
// domain at 60 deg about [111] took the smaller one; integrated, it carried the larger one's
// intensity on every reflection the two share, which broke the cubic 2-folds and merged in
// R3). So the spots the lattice leaves on the spread frames are indexed again, as the
// leftover-lattice census below does, and where they give the same lattice in another
// orientation, the two are judged on the validation spots each puts on itself.
if (!cancelled_ && best.result.has_value()) {
indexer->ForceRotationIndexerResult(*best.result);
prefetch_spots(spread_ordinals);
std::vector<std::vector<SpotToSave>> left(spread_ordinals.size());
ParallelFor(static_cast<int>(spread_ordinals.size()),
std::min<size_t>(spread_ordinals.size(), config_.nthreads), [&](int i) {
const auto &sp = spot_cache.at(spread_ordinals[i]);
DataMessage m{};
m.number = spread_ordinals[i];
m.spots = sp;
indexer->CountSpotsOnLattice(m, validation_settings);
for (size_t k = 0; k < sp.size(); k++)
if (m.spots.size() != sp.size() || !(m.spots[k].indexed && m.spots[k].lattice == 0))
left[i].push_back(sp[k]);
});
RotationIndexer leftover(experiment_, *indexer_pool);
leftover.MaxSpotsPerImage(first_pass_spots_per_image);
leftover.VerifyMemo(config_.verify_first_pass_memo);
for (size_t i = 0; i < spread_ordinals.size() && !leftover.AccumulationFull(); i++)
leftover.ProcessImage(spread_ordinals[i], left[i], rot_angle(spread_ordinals[i]));
leftover.RunIndexing();
const auto reduced_edges = [](const RotationIndexerResult &r) {
const auto uc = r.lattice.ToPrimitive(r.search_result.centering).NiggliReduce().GetUnitCell();
std::array<double, 3> e = {uc.a, uc.b, uc.c};
std::sort(e.begin(), e.end());
return e;
};
if (auto other = leftover.GetLattice()) {
const auto e1 = reduced_edges(*best.result);
const auto e2 = reduced_edges(*other);
bool same_lattice = true;
for (int i = 0; i < 3; i++)
same_lattice = same_lattice && std::abs(e2[i] - e1[i]) <= 0.02 * e1[i];
if (same_lattice) {
const PooledEvidence e_best = pooled_evidence(*indexer, *best.result);
const PooledEvidence e_other = pooled_evidence(*indexer, *other);
const bool adopt = ValidationEvidencePrefers(e_best, e_other);
logger.Info("Second domain: the spots the lattice leaves give the same lattice in "
"another orientation, which puts {}/{} validation spots on itself ({} at "
"a wrong spindle angle) against the lattice's {}/{} ({}) - {}",
e_other.on_lattice, e_other.spots, e_other.by_chance, e_best.on_lattice,
e_best.spots, e_best.by_chance,
adopt ? "it is the crystal, adopting it" : "keeping the lattice");
if (adopt) {
best.result = std::move(*other);
best.score = count_indexed(*indexer, *best.result);
best.name += " (second domain)";
}
}
}
}
// Whether the run has a lattice at all is decided here, on the pooled spots rather than on
// the frame count the rescues above are steered by. A frame count asks each frame to clear
// a bar of its own and then counts the frames that did, which measures the spots per frame