rugnux: --report-resolution, a second statistics table at a reference range
Comparing a run with another program's table has meant running rugnux AT that program's resolution range (--scaling-high-resolution), which is a different run: the range moves the cut, the space-group decision and everything after them, so the comparison buys itself a different answer. --report-resolution <dmin>[,<dmax>] instead leaves the run alone and adds a second table to section 3 of the report - the REFRES_* keys and a shell table - binned from the same merged reflections over the range given, with the completeness denominator enumerated over that range and the shells in equal steps of 1/d^2 so they read row for row against a CORRECT.LP at the same range. Report-only: the merged files and every decision are byte-identical with and without it. The table holds only what the run kept. Where the reference range is finer than the run's own limit, the shells past it are printed as not merged (with their possible count) rather than as zeros, REFRES_SHELLS_PAST_LIMIT counts them so a consumer can tell "not merged" from a measured zero, REFRES_ COMPLETENESS counts their reflections as missing, and the other overall numbers are over the shells the run reached; nothing is read from the observations the run judged to carry no signal. REFRES_ISA is the error model refitted on the reflections of the table alone, in XDS's convention (rotation only; the stills model is fitted over the whole range already). On the rotation path the statistics block of MergeAndStats becomes a lambda over a shell grid, called once for the run's own grid and once for the reference one; the reference call floors every observation-level count at the cut by group d, the rule the erase applied. The stills MergeStats takes a declared range, whose bounds are the grid's whether or not any reflection reaches them. Both --mode mx and --mode scale report it, the viewer's command line echoes it, and the docs describe the keys. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -259,6 +259,47 @@ TEST_CASE("MergeStats_NoReferenceCellLeavesCompletenessUnmeasured") {
|
||||
}
|
||||
}
|
||||
|
||||
// The reference-range table (--report-resolution) is binned over the range it is GIVEN, whether or
|
||||
// not the data reach it: its last shell ends at the declared d_min, and past the run's own limit
|
||||
// nothing is read from anywhere - the reflections the run did not keep count as missing.
|
||||
TEST_CASE("MergeStats_ReferenceRangeIsBinnedOverTheDeclaredRange") {
|
||||
const auto &sg = TestSpaceGroup();
|
||||
const auto merged = MeasuredBetween(sg, TEST_CELL, 2.0, 20.0, true); // what the run kept
|
||||
DiffractionExperiment x;
|
||||
x.SetSpaceGroup(sg);
|
||||
MergeOnTheFly merge(x);
|
||||
merge.ReferenceCell(TEST_CELL);
|
||||
const auto own = merge.MergeStats(merged, {});
|
||||
|
||||
// A range coarser than the run's own: a complete subset, on a grid ending at the declared bound.
|
||||
const auto within = merge.MergeStats(merged, {}, {}, std::nullopt, ReportResolutionRange{3.0, 50.0});
|
||||
CHECK(within.shells.back().d_min == Catch::Approx(3.0));
|
||||
CHECK(within.shells.front().d_max == Catch::Approx(50.0));
|
||||
int coarser_than_3 = 0;
|
||||
for (const auto &m: merged)
|
||||
if (m.d > 3.0f) ++coarser_than_3;
|
||||
CHECK(within.overall.unique_reflections == coarser_than_3);
|
||||
CHECK(within.overall.unique_reflections < own.overall.unique_reflections);
|
||||
CHECK(Completeness(within.overall) > 99.0);
|
||||
|
||||
// A range finer than the run kept: the grid still ends at 1.5 A, the outer shell is empty and its
|
||||
// possible reflections are in the denominator, and the measured range says where the data stop.
|
||||
const auto beyond = merge.MergeStats(merged, {}, {}, std::nullopt, ReportResolutionRange{1.5, 50.0});
|
||||
CHECK(beyond.shells.back().d_min == Catch::Approx(1.5));
|
||||
CHECK(beyond.overall.unique_reflections == own.overall.unique_reflections);
|
||||
CHECK(beyond.overall.possible_unique_reflections > own.overall.possible_unique_reflections);
|
||||
CHECK(Completeness(beyond.overall) < Completeness(own.overall));
|
||||
CHECK(beyond.shells.back().unique_reflections == 0);
|
||||
CHECK(beyond.shells.back().possible_unique_reflections > 0);
|
||||
CHECK(beyond.overall.d_min == Catch::Approx(own.overall.d_min));
|
||||
|
||||
// A range the data never reach at all is still a grid, not an error.
|
||||
const auto empty = merge.MergeStats(merged, {}, {}, std::nullopt, ReportResolutionRange{1.0, 1.5});
|
||||
CHECK(empty.overall.unique_reflections == 0);
|
||||
CHECK(empty.overall.possible_unique_reflections > 0);
|
||||
CHECK(empty.overall.d_min == 0.0f);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- the automatic resolution cutoff
|
||||
namespace {
|
||||
// Half-set pairs spread uniformly in s = 1/d^2 over [s_from, s_to), either correlated with each
|
||||
|
||||
Reference in New Issue
Block a user