rugnux: .hkl holds the unmerged scaled fulls on rotation data
The SHELX HKLF 4 file now has one record per full reflection - its partials summed, the per-frame scale and every correction applied, sigma(I) as the merge weighted it - at the index it was measured at, not averaged with its equivalents: the chemical crystallographer's convention, so SHELXL computes Rint and Rsigma itself. Outliers the merge rejected and fulls beyond its resolution cut are left out; no batch column (it would select a BASF scale in SHELXL). The engine hands the fulls back only for a merge that may be written (RotationScaleMerge::SetExportScaledFulls), so the search merges, the pre-pass and the P1 cross-check carry no copy; the fulls follow the same relabelling as the merged reflections (merge_to_written). Stills keep the merged file. --mode scale writes the unmerged form too. Validation: p.mtz md5 unchanged on myob/cytc/thau (GPU). SHELXL on the same runs, merged-old vs unmerged-new (COD models, harness /data/tmp/sm_shared): aspirin 20 keV Rint 0 -> 0.071, Rsigma 0.036 -> 0.043, R1 0.0964 -> 0.0969, wR2 0.312 -> 0.310, GooF 1.53 -> 1.47; HEPES 20 keV Rint 0 -> 0.163, Rsigma 0.057 -> 0.068, R1 0.0903 -> 0.0897, wR2 0.318 -> 0.263, GooF 1.57 -> 1.10; the "input data appear to be merged" warning is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5K8jvPPbmCrbqnWkddTuB
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
@@ -185,3 +186,31 @@ TEST_CASE("Unmerged MTZ: built on several workers, the same rows as on one", "[w
|
||||
CHECK(parallel.batches.back().number == serial.batches.back().number);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SHELX .hkl of unmerged fulls: fixed 3I4,2F8.2, scaled to fit, 0 0 0 terminator",
|
||||
"[write_reflections][portable]") {
|
||||
// Two fulls of the same reflection and a Friedel mate: written as measured, nothing averaged. The
|
||||
// largest |I| or sigma is put at 9999.00; an unusable full (sigma not positive) is left out.
|
||||
const std::vector<ScaledFull> fulls{
|
||||
{1, 2, 3, 200000.0f, 2000.0f},
|
||||
{-1, -2, -3, 100000.0f, 1200.0f},
|
||||
{1, 2, 3, -50.0f, 20.0f},
|
||||
{4, 5, 6, 10.0f, 0.0f},
|
||||
};
|
||||
const auto path = (std::filesystem::temp_directory_path() / "jfjoch_scaled_fulls_test.hkl").string();
|
||||
WriteShelxHklReflections(fulls, path, 2);
|
||||
|
||||
std::ifstream in(path);
|
||||
std::vector<std::string> lines;
|
||||
for (std::string line; std::getline(in, line);)
|
||||
lines.push_back(line);
|
||||
std::filesystem::remove(path);
|
||||
|
||||
REQUIRE(lines.size() == 4);
|
||||
for (const auto &line : lines)
|
||||
CHECK(line.size() == 28);
|
||||
CHECK(lines[0] == " 1 2 3 9999.00 99.99");
|
||||
CHECK(lines[1] == " -1 -2 -3 4999.50 59.99");
|
||||
CHECK(lines[2] == " 1 2 3 -2.50 1.00");
|
||||
CHECK(lines[3] == " 0 0 0 0.00 0.00");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user