From ccbc366e2f894205475e70070dcd85df26afbd8c Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 2 Aug 2026 13:37:13 +0200 Subject: [PATCH] reader: read the frame number back with the reflections The per-reflection frame number is written to the process file and always has been, but the reader's designated initialiser simply omitted it, so every reflection came back at frame zero. Nothing complained, because zero is a valid frame. It matters because the 3D combine splits a reflection's partials into rocking events by frame contiguity. With every observation claiming frame zero there are no gaps to split on, so a reflection's entire rotation range collapses into ONE event: measured on a rotation dataset, 216066 fulls against 216705 distinct reflections, where the pipeline finds 367416. Forty-two per cent of the observations disappear, the goniometer-frame absorption surface evaluates every observation at a single angle, and the radiation-damage estimate is computed over a run that appears to last no time at all. The reason this survived is that the damage flatters: fewer, better-agreeing observations per reflection give R_meas sixteen per cent lower, ISa thirty per cent higher and a slightly better CC1/2 than the real merge. Anyone re-scaling a stored file was reading numbers that looked better than the pipeline's while standing on less than two thirds of the data, and one radiation-damage figure that was pure artefact. Read it as mandatory rather than optional-with-default, like h/k/l and the intensities: a silent zero is precisely the failure being fixed, and every file this function can read carries the dataset. After the fix the combine reproduces the pipeline exactly. The normal path does not go through this reader and is byte-identical before and after. Co-Authored-By: Claude Opus 5 (1M context) --- reader/HDF5MetadataSource.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reader/HDF5MetadataSource.cpp b/reader/HDF5MetadataSource.cpp index 989f9102..27eb96d3 100644 --- a/reader/HDF5MetadataSource.cpp +++ b/reader/HDF5MetadataSource.cpp @@ -141,6 +141,7 @@ bool ReadReflectionsFromGroup(HDF5Object &file, auto h = file.ReadOptVector(image_group_name + "/h"); auto k = file.ReadOptVector(image_group_name + "/k"); auto l = file.ReadOptVector(image_group_name + "/l"); + auto image_number = file.ReadOptVector(image_group_name + "/observed_frame"); auto predicted_x = file.ReadOptVector(image_group_name + "/predicted_x"); auto predicted_y = file.ReadOptVector(image_group_name + "/predicted_y"); auto obs_x = file.ReadOptVector(image_group_name + "/observed_x"); @@ -157,7 +158,8 @@ bool ReadReflectionsFromGroup(HDF5Object &file, if (h.size() != l.size() || h.size() != k.size() || h.size() != d.size() || h.size() != predicted_x.size() || h.size() != predicted_y.size() - || h.size() != int_sum.size() || h.size() != int_err.size() || h.size() != bkg.size()) + || h.size() != int_sum.size() || h.size() != int_err.size() || h.size() != bkg.size() + || h.size() != image_number.size()) throw JFJochException(JFJochExceptionCategory::HDF5, "Wrong size of reflections dataset"); for (size_t i = 0; i < h.size(); i++) { @@ -191,6 +193,7 @@ bool ReadReflectionsFromGroup(HDF5Object &file, .h = h.at(i), .k = k.at(i), .l = l.at(i), + .image_number = image_number.at(i), .delta_phi_deg = delta_phi_val, .predicted_x = predicted_x.at(i), .predicted_y = predicted_y.at(i),