Space-group search: a screw threshold needs a row with controls behind it
The row-relative cut scales the "too strong to be absent" threshold by the axial row's own median E^2, floored at the plain value - so it can only raise the bar, and a row whose control class holds a single strong reflection sets it from that one reflection. That direction invents screws: a genuine 4_2 whose 00l happen to be observed only at l=4n reads its l=4n+2 reflections as absent and ranks 4_1/4_3 above the truth. Require three controls before the row may set the scale; below that the row keeps the plain cut. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -732,9 +732,16 @@ SearchSpaceGroupResult SearchSpaceGroup(
|
||||
// control rows, and on the same crystal one row can be 20x an average reflection while another
|
||||
// is half of one. Pooling them lets the weak rows set the threshold for the strong one and the
|
||||
// rescue never fires (that very crystal pooled to a row median of 0.7 and stayed at P42_12).
|
||||
// A row needs more than a reflection or two behind its median before that median may set the
|
||||
// threshold. The scale only ever RAISES the cut, so a row whose control class holds one strong
|
||||
// reflection would license a screw claim the row does not support - a genuine 4_2 whose 00l are
|
||||
// observed only at l=4n, strongly, would read its l=4n+2 reflections as absent and be reported as
|
||||
// 4_1/4_3. Below this count the row falls back to the plain cut, i.e. no rescue.
|
||||
constexpr size_t MIN_ROW_CONTROL_REFLECTIONS = 3;
|
||||
std::map<AxialRow, double> row_median;
|
||||
for (auto& [row, esq] : row_present_esq)
|
||||
row_median[row] = MedianOf(esq);
|
||||
if (esq.size() >= MIN_ROW_CONTROL_REFLECTIONS)
|
||||
row_median[row] = MedianOf(esq);
|
||||
|
||||
const int screw_absent = static_cast<int>(screw_absent_refl.size());
|
||||
int screw_violations = 0;
|
||||
|
||||
Reference in New Issue
Block a user