Record the corrections a DECTRIS detector applied; read multichannel NXmx
The broker rebuilds the outgoing StartMessage from DiffractionExperiment, and FillMessage hard-coded countrate_correction_enabled and flatfield_enabled to false. JFJochReceiverLite parsed the true values from the detector's stream2 start message and dropped them, so every DECTRIS file written through the broker said neither correction was applied - DECTRIS enables both by default. pixel_mask_applied had the same defect: it reported the local apply_mask setting (an FPGA feature), not what the detector did to the pixels, which ReceiverLite forwards byte for byte. These now come from the stream: DetectorSetup carries them, ReceiverLite copies them in Configure, FillMessage reads them. Two more fields the DECTRIS stream sends and NXmx defines are passed through to the master file: countrate_correction_lookup_table (uint32, possibly bslz4/bszstd compressed in the stream) and virtual_pixel_interpolation_applied. The flatfield is deliberately not written - it makes the master file too large. PSI EIGER is unchanged: jfjoch never enables rate correction and the detector server starts with it off. The reader also opens the DECTRIS "hdf5 nexus v2024.2 nxmx" layout, where /entry/data/data is 4D [image, channel, y, x] and the pixel mask is kept per channel. Only the first channel is read; this is compatibility, not full multichannel support. A _process.h5 made from such a file links its pictures to that channel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nW6FNRP1bBJJ8pfHiByAT
This commit is contained in:
1 parent
0252880e06
commit
aea13044b5
18 files changed
+397
-31
No files matched your search
@@ -12,7 +12,8 @@ namespace {
|
||||
const std::string &dataset,
|
||||
uint64_t source_first_image,
|
||||
uint64_t virtual_first_image,
|
||||
uint64_t image_count) {
|
||||
uint64_t image_count,
|
||||
std::optional<uint64_t> source_channel = {}) {
|
||||
if (image_count == 0)
|
||||
return;
|
||||
|
||||
@@ -20,6 +21,7 @@ namespace {
|
||||
auto &last = ret.back();
|
||||
if (last.filename == filename
|
||||
&& last.dataset == dataset
|
||||
&& last.source_channel == source_channel
|
||||
&& last.source_first_image + last.image_count == source_first_image
|
||||
&& last.virtual_first_image + last.image_count == virtual_first_image) {
|
||||
last.image_count += image_count;
|
||||
@@ -32,9 +34,22 @@ namespace {
|
||||
.dataset = dataset,
|
||||
.source_first_image = source_first_image,
|
||||
.virtual_first_image = virtual_first_image,
|
||||
.image_count = image_count
|
||||
.image_count = image_count,
|
||||
.source_channel = source_channel
|
||||
});
|
||||
}
|
||||
|
||||
// A 4D mapping, [image, channel, y, x], may cover only some of the channels; the reader wants
|
||||
// the first one.
|
||||
bool CoversFirstChannel(const HDF5VirtualDatasetMapping &mapping) {
|
||||
return mapping.virtual_start.size() != 4 || mapping.virtual_start[1] == 0;
|
||||
}
|
||||
|
||||
std::optional<hsize_t> SourceChannel(const HDF5VirtualDatasetMapping &mapping) {
|
||||
if (mapping.source_start.size() == 4)
|
||||
return mapping.source_start[1];
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void HDF5ImageLocator::Configure(Layout layout) {
|
||||
@@ -71,10 +86,10 @@ HDF5ImageLocator::Location HDF5ImageLocator::Resolve(int64_t global_image) const
|
||||
&& layout_.data_layout == HDF5DataSetLayout::VIRTUAL) {
|
||||
const auto image = static_cast<hsize_t>(global_image);
|
||||
for (const auto &mapping: layout_.vds_mappings) {
|
||||
if (!mapping.ContainsVirtualImage(image))
|
||||
if (!CoversFirstChannel(mapping) || !mapping.ContainsVirtualImage(image))
|
||||
continue;
|
||||
return {OpenCached(mapping.filename), static_cast<uint32_t>(mapping.SourceImage(image)),
|
||||
mapping.filename, mapping.dataset};
|
||||
mapping.filename, mapping.dataset, SourceChannel(mapping).value_or(0)};
|
||||
}
|
||||
throw JFJochException(JFJochExceptionCategory::HDF5,
|
||||
"Image not covered by /entry/data/data VDS mappings");
|
||||
@@ -127,13 +142,14 @@ std::vector<HDF5DataSourceMessage> HDF5ImageLocator::GetSourceMapping(uint64_t f
|
||||
|
||||
bool found = false;
|
||||
for (const auto &mapping: layout_.vds_mappings) {
|
||||
if (!mapping.ContainsVirtualImage(virtual_image))
|
||||
if (!CoversFirstChannel(mapping) || !mapping.ContainsVirtualImage(virtual_image))
|
||||
continue;
|
||||
|
||||
const uint64_t source_image = mapping.SourceImage(virtual_image);
|
||||
const std::string dataset = mapping.dataset.empty() ? "/entry/data/data" : mapping.dataset;
|
||||
|
||||
AppendOrExtendSourceMapping(ret, mapping.filename, dataset, source_image, local_image, 1);
|
||||
AppendOrExtendSourceMapping(ret, mapping.filename, dataset, source_image, local_image, 1,
|
||||
SourceChannel(mapping));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user