Space-group search: name the veto that actually refused a promotion

The refusal message fell through to the chi^2 branch whenever the
systematic-b balloon veto was the binding test, so it reported a chi^2 ratio
that did not justify the refusal at all - on one battery crystal it printed
"merge chi^2 is 1.25x the subgroup's (bound 1.85)", i.e. a number comfortably
inside its own bound, as the reason for processing in the lower symmetry. A
diagnostic that names the wrong cause is worse than none: it sends the reader
after the wrong statistic.

Report the b test when it is what fired, with both b values and the bound.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-27 21:38:07 +02:00
co-authored by Claude Opus 5
parent 3171b071e6
commit 0cd8cb7ba3
@@ -563,9 +563,12 @@ SearchSpaceGroupResult SearchSpaceGroup(
// The parent b is floored (min_systematic_b_for_veto) so a near-zero parent on excellent data cannot
// fabricate a huge ratio out of a still-tiny absolute b (a genuine 422 at b=0.05 over a 222 parent at
// b=0.008 is not a twin - a real twin drives b to ~0.19 regardless).
bool b_refused = false;
if (consistent && parent_b > 1e-4
&& c.b_extra > std::max(parent_b, opt.min_systematic_b_for_veto) * opt.max_systematic_b_veto)
&& c.b_extra > std::max(parent_b, opt.min_systematic_b_for_veto) * opt.max_systematic_b_veto) {
consistent = false;
b_refused = true;
}
// The H test is a necessary condition for promotion where it can be computed: it is the only
// statistic measured to separate genuine symmetry from a merohedral twin across data amounts.
@@ -582,6 +585,11 @@ SearchSpaceGroupResult SearchSpaceGroup(
refused_why = "operator disagreement H is " + FormatDouble(h_ratio, 2)
+ "x the parent's (bound " + FormatDouble(opt.max_operator_h_ratio, 2)
+ ") - the added operator relates unequal intensities, as a twin law does";
else if (b_refused)
refused_why = "its merge's systematic error b is " + FormatDouble(c.b_extra, 3)
+ " against the subgroup's " + FormatDouble(parent_b, 3)
+ " (bound " + FormatDouble(opt.max_systematic_b_veto, 2)
+ "x) - the added operator forces unequal intensities together";
else if (std::isfinite(c.chi2) && std::isfinite(chi2_ref))
refused_why = "merge chi^2 is " + FormatDouble(c.chi2 / chi2_ref, 2)
+ "x the subgroup's (bound " + FormatDouble(opt.max_merge_chi2_ratio, 2) + ")";