rugnux: veto a b-ballooning merohedral-twin over-promotion (space-group search)
The systematic-b test (a genuine symmetry step barely moves the merge error model's b; a merohedral twin, forcing non-equivalent reflections together, balloons it) was only ever a RESCUE - it could promote a chi^2-borderline genuine step but never demote a chi^2-passing one. So a partial twin whose within-orbit scatter looks self-consistent (merged chi^2 below the ratio bound) slipped through on chi^2 alone and was over-promoted to the holohedral group, ballooning b and collapsing the merged ISa. Make the same test a VETO: a chi^2-passing high-symmetry promotion whose b, relative to the largest confirmed subgroup, exceeds max_systematic_b_veto is kept in its true lower symmetry. Calibrated on the rotation-test battery, where the largest genuine step (a P422 tetragonal) sits at b-ratio ~1.8 and a merohedral R3->R32 twin at ~2.6 - an empty gap - so 2.0 catches the twin while never demoting a genuine high-symmetry merge. Battery space-group match 20->21/25 (an R3 case previously merged as R32 is now correct), every other crystal unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -465,14 +465,14 @@ SearchSpaceGroupResult SearchSpaceGroup(
|
||||
bool consistent = c.pg->rotations.empty() || !std::isfinite(c.chi2) ||
|
||||
!std::isfinite(chi2_ref) || c.chi2 <= chi2_ref * opt.max_merge_chi2_ratio;
|
||||
|
||||
// Rescue a genuine high-symmetry merge whose chi^2 lands just past the ratio bound because its
|
||||
// data are imperfectly scaled (see max_merge_chi2_rescue). The systematic-error test tells it
|
||||
// apart from a twin: promote only if the extra intensity-proportional error b, relative to the
|
||||
// largest confirmed subgroup (by rotation-set inclusion), stayed within max_systematic_b_ratio -
|
||||
// a genuine step barely moves it, a twin's balloons.
|
||||
if (!consistent && std::isfinite(c.chi2) && std::isfinite(chi2_ref)
|
||||
&& c.chi2 <= chi2_ref * opt.max_merge_chi2_rescue) {
|
||||
double parent_b = -1.0;
|
||||
// Systematic-error test vs the largest confirmed subgroup (by rotation-set inclusion): merging
|
||||
// under a genuine operator gains multiplicity without intensity-proportional disagreement, so the
|
||||
// merge error model's b barely moves; a merohedral twin forces non-equivalent reflections together
|
||||
// and b balloons. It both RESCUES a genuine step whose chi^2 drifts just past the ratio bound
|
||||
// (imperfectly scaled data) and VETOES a twin whose chi^2 now looks self-consistent but whose b
|
||||
// balloons - the chi^2 ratio alone no longer separates them.
|
||||
double parent_b = -1.0;
|
||||
if (!c.pg->rotations.empty()) {
|
||||
int parent_order = 0;
|
||||
for (const auto& s : pg_cands)
|
||||
if (s.order < c.order && s.order > parent_order
|
||||
@@ -481,9 +481,16 @@ SearchSpaceGroupResult SearchSpaceGroup(
|
||||
parent_order = s.order;
|
||||
parent_b = s.b_extra;
|
||||
}
|
||||
if (parent_b > 1e-4 && c.b_extra <= parent_b * opt.max_systematic_b_ratio)
|
||||
consistent = true;
|
||||
}
|
||||
if (!consistent && std::isfinite(c.chi2) && std::isfinite(chi2_ref)
|
||||
&& c.chi2 <= chi2_ref * opt.max_merge_chi2_rescue
|
||||
&& parent_b > 1e-4 && c.b_extra <= parent_b * opt.max_systematic_b_ratio)
|
||||
consistent = true;
|
||||
// Veto a chi^2-passing promotion whose b clearly ballooned (above the largest genuine step, below a
|
||||
// twin); a genuine but imperfectly-scaled high-symmetry merge stays under the bound and is untouched.
|
||||
if (consistent && parent_b > 1e-4 && c.b_extra > parent_b * opt.max_systematic_b_veto)
|
||||
consistent = false;
|
||||
|
||||
if (!consistent)
|
||||
continue;
|
||||
if (c.order > best_pg_order || (c.order == best_pg_order && c.min_class_cc > best_pg_min_cc)) {
|
||||
|
||||
@@ -106,6 +106,17 @@ struct SearchSpaceGroupOptions {
|
||||
double max_merge_chi2_rescue = 2.30;
|
||||
double max_systematic_b_ratio = 1.90;
|
||||
|
||||
// Veto bound. The systematic-b test above is otherwise only a rescue - it can promote a chi^2-borderline
|
||||
// genuine step but never demote a chi^2-passing one. A merohedral twin whose within-orbit scatter looks
|
||||
// self-consistent (chi^2 ratio below max_merge_chi2_ratio) therefore slips through on chi^2 alone even
|
||||
// though merging its non-equivalent reflections balloons b. So a chi^2-passing high-symmetry promotion
|
||||
// whose b, relative to the largest confirmed subgroup, exceeds this bound is vetoed and kept in its true
|
||||
// lower symmetry. Calibrated on the rotation-test battery, where the largest genuine step (a P422
|
||||
// tetragonal) sits at b-ratio ~1.8 and a merohedral R3->R32 twin at ~2.6 - an empty gap - so 2.0 keeps
|
||||
// every genuine high-symmetry merge (they are never demoted) while catching the twin. The veto only ever
|
||||
// keeps a clearly-ballooned promotion down, never promotes.
|
||||
double max_systematic_b_veto = 2.0;
|
||||
|
||||
// --- Stage B: space group (screw axes / centering) ---
|
||||
bool determine_space_group = true; // false: stop at the symmorphic representative
|
||||
|
||||
|
||||
Reference in New Issue
Block a user