DetectorSetup hardcodes bit_depth_image = 16 for every DECTRIS detector
(DetectorSetup.cpp:78), and GetByteDepthImage() consults that BEFORE the depth
the reader takes from the file - so a file storing 32-bit images had its
overflow computed as a 16-bit one. With the reader also declaring the images
signed, GetOverflow() returned INT16_MAX and GetSaturationLimit() became
min(file value, 32767).
Every count above 32767 was therefore marked saturated, and because the
integration accept gate requires ALL inner pixels valid, the whole reflection
was discarded. That silently removes the strongest reflections of a strong
crystal - the low-resolution ones that anchor scaling - while the file itself
declares saturation at 105000-133000.
Measured on a lysozyme rotation set (200 frames), before -> after:
saturated pixels per frame 0.815 -> 0.000
brightest accepted pixel 32738 -> 87633
mean per-frame maximum 26218 -> 37390
i.e. the ceiling was exactly INT16_MAX and nothing genuine reached it.
Which datasets this touches depends on how bright they are: measured pixels
above the old ceiling range from 0.0 per frame on some rotation sets to 6.1 on
others, so the fix is a no-op on weak data and only ever adds reflections.
Rotation battery, 33 crystals: no point group changed (30/33 before and after)
and no run failed. Four crystals move on quality, in both directions - ISa
1.90 -> 2.40 and 3.29 -> 4.80 on two, 2.97 -> 1.85 and 20.83 -> 18.47 on two
others; three of the four are the battery's known weak or run-to-run-unstable
crystals. The one strong crystal that moves gains 136 observations out of
1.9 million and loses 2.4 ISa: the reflections restored are by construction the
brightest ones, and they carry the systematic error that the strongest
reflections always carry. That is a real cost, but it is the cost of MEASURING
them rather than discarding them unseen, and a lower asymptotic I/sigma on data
that are now complete is preferable to a flattering one on data that quietly
are not.
Only the offline file reader is affected; the online path builds its detector
setup from configuration.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>