reader: the stored images are int32, so say so
b81c6f00b took the container depth from bit_depth_image in the file, which fixed
32-bit EIGER2 files but got the general case wrong: the reader converts every
image to SIGNED int32 (PixelSigned(true) a few lines up), while bit_depth_image
describes an unsigned container, and GetOverflow() combines the two. So a 16-bit
file still capped at INT16_MAX rather than 65535, and an 8-bit file newly capped
at 127 - flagging counts 127..254 as saturated, which drops the whole reflection
at the integration accept gate.
Declare 32 bits, matching what the reader actually hands out. The saturation cap
then comes from the file's own saturation_value, which is what it is for, and
the error value reported for a read dataset becomes INT32_MIN - the sentinel the
reader really uses. A file whose bit_depth_image is not 8/16/32 also stops
throwing on open.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -661,15 +661,17 @@ HDF5MetadataSource::OpenResult HDF5MetadataSource::Open(const std::string &filen
|
||||
if (master_file->Exists("/entry/instrument/detector/sensor_material"))
|
||||
detector.SensorMaterial(master_file->GetString("/entry/instrument/detector/sensor_material"));
|
||||
detector.SaturationLimit(master_file->GetInt("/entry/instrument/detector/saturation_value"));
|
||||
// The container depth of the stored images, NOT the detector's counter depth. DetectorSetup
|
||||
// defaults DECTRIS to 16 bits, and GetByteDepthImage() prefers that over the value the image
|
||||
// format carries - so without this an EIGER2 file that stores 32-bit images has its overflow
|
||||
// computed as a 16-bit one and every count above 32767 is called saturated. The integration
|
||||
// accept gate then drops the WHOLE reflection, which silently removes the strongest
|
||||
// reflections of a strong crystal (measured on a lysozyme set: max accepted pixel 32738
|
||||
// against a declared saturation of 108833).
|
||||
if (master_file->Exists("/entry/instrument/detector/bit_depth_image"))
|
||||
detector.BitDepthImage(master_file->GetInt("/entry/instrument/detector/bit_depth_image"));
|
||||
// The reader hands every image out as signed int32 whatever the file stored (see PixelSigned
|
||||
// below), so that is the container depth the rest of the code has to see. DetectorSetup defaults
|
||||
// DECTRIS to 16 bits and GetByteDepthImage() prefers the detector's value over the image
|
||||
// format's, so leaving it at the default computed the overflow as a 16-bit one and called every
|
||||
// count above 32767 saturated - the integration accept gate then dropped the WHOLE reflection,
|
||||
// silently removing the strongest reflections of a strong crystal (measured on a lysozyme set:
|
||||
// max accepted pixel 32738 against a declared saturation of 108833). Taking bit_depth_image from
|
||||
// the file instead does not work either: it describes an UNSIGNED container, so pairing it with
|
||||
// signed pixels halves the range (a 16-bit file capped at 32767, an 8-bit one at 127). The real
|
||||
// cap is the file's own saturation_value, set just above.
|
||||
detector.BitDepthImage(32);
|
||||
detector.MinFrameTime(std::chrono::microseconds(0));
|
||||
detector.MinCountTime(std::chrono::microseconds(0));
|
||||
detector.ReadOutTime(std::chrono::nanoseconds(0));
|
||||
|
||||
Reference in New Issue
Block a user