Space-group search: report the order of the point group it chose
The two-arm search compared its arms by the order of the space group each had picked, but Stage B leaves best_space_group unset whenever no candidate is eligible - no candidate had enough observed absences to trust. That is not rare on the Lorentz-filtered arm, and for a systematic reason: the filter removes the badly-measured observations, which is where the weak systematically-absent reflections are. An arm that confirmed 422 but stopped short of naming a space group therefore scored order 0 and lost to an arm supporting P2, and the demotion was logged as "taking the higher symmetry" - the comparison and the message both wrong, in the one direction the design says cannot happen. Carry the point-group order in the result, set from the order Stage A actually adopted, and compare on that. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -640,6 +640,7 @@ SearchSpaceGroupResult SearchSpaceGroup(
|
||||
|
||||
if (best_pg->representative)
|
||||
result.point_group_hm = best_pg->representative->point_group_hm();
|
||||
result.point_group_order = best_pg_order;
|
||||
|
||||
// Only report a refusal that is actually ABOVE what was adopted.
|
||||
if (refused_order > best_pg_order) {
|
||||
|
||||
@@ -219,6 +219,11 @@ struct SearchSpaceGroupResult {
|
||||
std::vector<gemmi::SpaceGroup> alternatives;
|
||||
|
||||
std::string point_group_hm; // chosen point group, e.g. "422"
|
||||
// Order of that point group (its number of rotations). Reported separately because Stage B can
|
||||
// leave best_space_group unset - no candidate had enough absences to be eligible - while Stage A
|
||||
// has confirmed the point group perfectly well, and a caller comparing two searches has to see
|
||||
// the symmetry that was found either way. 0 only when no point group was chosen at all.
|
||||
int point_group_order = 0;
|
||||
std::vector<SpaceGroupOperatorScore> operator_scores; // Stage A, all distinct operators tested
|
||||
std::vector<SpaceGroupCandidateScore> candidates; // Stage B, ranked
|
||||
|
||||
|
||||
+7
-7
@@ -1223,13 +1223,13 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
auto sm_all = scale_and_merge("P1, all observations", true);
|
||||
rsm->SetSearchMinZeta(zeta);
|
||||
const auto alt = SearchSpaceGroup(sm_all.merged, sg_opts);
|
||||
// Point-group order = the number of rotations, which is what sym_ops holds (centering
|
||||
// lives in cen_ops). Taken from the space group the search chose - a point-group symbol
|
||||
// like "422" is not a space-group name and cannot be looked up.
|
||||
const auto order_of = [](const SearchSpaceGroupResult &r) -> size_t {
|
||||
return r.best_space_group.has_value()
|
||||
? r.best_space_group->operations().sym_ops.size() : 0;
|
||||
};
|
||||
// The order of the point group each arm confirmed. Read from the search, not from the
|
||||
// space group it went on to pick: Stage B leaves best_space_group unset when no
|
||||
// candidate has enough absences to be eligible, which is common on the filtered arm
|
||||
// precisely because the filter removes the weak reflections the absences live in. An
|
||||
// arm that confirmed 422 would then have scored 0 and lost to a P2 arm - a demotion,
|
||||
// reported as "taking the higher symmetry".
|
||||
const auto order_of = [](const SearchSpaceGroupResult &r) { return r.point_group_order; };
|
||||
logger.Info("Space-group search: all-observation merge -> {} (order {}), "
|
||||
"Lorentz-filtered -> {} (order {})",
|
||||
alt.point_group_hm.empty() ? "?" : alt.point_group_hm, order_of(alt),
|
||||
|
||||
Reference in New Issue
Block a user