From a1b48e945486da56a7c91a29c751dd43da4e1c1c Mon Sep 17 00:00:00 2001 From: leonarski_f Date: Sun, 23 Aug 2026 12:42:47 +0200 Subject: [PATCH] Mark unreadable frames in the reprocessing virtual dataset too The master's own virtual dataset fills with the error marker, so a source file that cannot be resolved reads as masked rather than as zero counts. The virtual dataset rugnux writes into _process.h5 was left at HDF5's default fill of zero, which is a legitimate count - the same silent failure, one file along. The helper moves above its first user; it has to be set before SetVirtual. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01VfYvJT5Nb71suJCowRBn5z --- writer/HDF5NXmx.cpp | 53 +++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/writer/HDF5NXmx.cpp b/writer/HDF5NXmx.cpp index e0f1f2ae..351c2edb 100644 --- a/writer/HDF5NXmx.cpp +++ b/writer/HDF5NXmx.cpp @@ -194,6 +194,30 @@ void NXmx::LinkToData_VDS(const StartMessage &start, const EndMessage &end) { } } +namespace { + void SetFillValue(HDF5Dcpl &dcpl, const HDF5DataType &data_type, + const std::optional &fill_value) { + if (!fill_value.has_value()) + return; + const int64_t value = fill_value.value(); + if (data_type.IsSigned()) { + switch (data_type.GetElemSize()) { + case 1: dcpl.SetFillValue8(static_cast(value)); break; + case 2: dcpl.SetFillValue16(static_cast(value)); break; + case 4: dcpl.SetFillValue32(static_cast(value)); break; + default: break; + } + } else { + switch (data_type.GetElemSize()) { + case 1: dcpl.SetFillValueU8(static_cast(value)); break; + case 2: dcpl.SetFillValueU16(static_cast(value)); break; + case 4: dcpl.SetFillValueU32(static_cast(value)); break; + default: break; + } + } + } +} + void NXmx::LinkToData_ProcessingVDS(const StartMessage &start, const EndMessage &end) { if (start.hdf5_source_data.empty() || end.max_image_number == 0) return; @@ -207,6 +231,11 @@ void NXmx::LinkToData_ProcessingVDS(const StartMessage &start, const EndMessage HDF5DataSpace full_data_space({total_images, height, width}); HDF5Dcpl dcpl; dcpl.SetChunking({1, height, width}); + // Same reason as the master's own virtual dataset: a source file that cannot be resolved reads + // as the fill value, and HDF5's default fill is zero - which is a legitimate count. Fill with the + // error marker instead, so an unreadable frame is masked rather than integrated as blank. Must be + // set before SetVirtual. + SetFillValue(dcpl, HDF5DataType(start.bit_depth_image / 8, start.pixel_signed), start.error_value); for (const auto &mapping: start.hdf5_source_data) { if (mapping.image_count == 0) @@ -282,30 +311,6 @@ void NXmx::LinkToReflections_VDS(const StartMessage &start, const EndMessage &en } } -namespace { - void SetFillValue(HDF5Dcpl &dcpl, const HDF5DataType &data_type, - const std::optional &fill_value) { - if (!fill_value.has_value()) - return; - const int64_t value = fill_value.value(); - if (data_type.IsSigned()) { - switch (data_type.GetElemSize()) { - case 1: dcpl.SetFillValue8(static_cast(value)); break; - case 2: dcpl.SetFillValue16(static_cast(value)); break; - case 4: dcpl.SetFillValue32(static_cast(value)); break; - default: break; - } - } else { - switch (data_type.GetElemSize()) { - case 1: dcpl.SetFillValueU8(static_cast(value)); break; - case 2: dcpl.SetFillValueU16(static_cast(value)); break; - case 4: dcpl.SetFillValueU32(static_cast(value)); break; - default: break; - } - } - } -} - std::unique_ptr NXmx::VDS(const StartMessage &start, const std::string &name, const std::vector &dim,