From d987bd6178483aa3dec53dcc7cea53d8b46b9591 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 26 Aug 2026 10:29:58 +0200 Subject: [PATCH] Space-group search: record what the E^2 shell count does on a small merge The shell count is order.size() / 100 in integer arithmetic, so a merge of fewer than two hundred reflections gets a single shell and E^2 becomes I divided by one global mean. That is harmless for the thing E^2 was introduced for - the operator correlation is a Pearson coefficient and is invariant to a common scale, so it lands on exactly the value raw I would have given. It is not harmless for the overlap cap, which then rejects reflections by their intensity against the whole merge rather than against their own resolution shell, and so cuts the low-resolution end and spares the high. No behaviour change; a merge that small has already failed for other reasons. This is here so the next reader does not have to rediscover that the normalisation quietly switches off at the bottom of the range. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01CHMmeM1d489zvNFT7ZMN2P --- image_analysis/scale_merge/SearchSpaceGroup.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/image_analysis/scale_merge/SearchSpaceGroup.cpp b/image_analysis/scale_merge/SearchSpaceGroup.cpp index fd328b0d..19d7989c 100644 --- a/image_analysis/scale_merge/SearchSpaceGroup.cpp +++ b/image_analysis/scale_merge/SearchSpaceGroup.cpp @@ -289,6 +289,11 @@ SearchSpaceGroupResult SearchSpaceGroup( order.push_back(i); std::sort(order.begin(), order.end(), [&](size_t a, size_t b) { return merged[a].d > merged[b].d; }); // low res -> high res + // A hundred reflections a shell, at most twenty-five shells - and integer division, so + // below two hundred there is a single shell and E^2 is I over one global mean. That + // leaves the operator correlation exactly where it was, Pearson being invariant to a + // common scale, but not the E^2 overlap cap below: it then cuts on I against the whole + // merge instead of against each reflection's own shell. const int bins = std::clamp(static_cast(order.size() / 100), 1, 25); const size_t per = (order.size() + bins - 1) / std::max(1, bins); for (size_t b = 0; b * per < order.size(); ++b) {