From 750579bfe42c15cf80af8a79fca99686533a48b5 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Tue, 20 Oct 2026 14:52:09 +0200 Subject: [PATCH] _process.h5 carries the offline per-image scale; -e documented as exclusive The writer's MX plugin decided the image-scale arrays were present whenever its own vector was non-empty, which is always, so every data file wrote them as NaN - and the master's SaveVectorIfMissing then left the end message's values out. It now marks them present only when an image message carries a scale. rugnux, whose scale exists only after the image messages went to the file, puts the per-image scale, its CC and mosaicity into the end message, so imageScaleFactor/imageScaleCC/imageScaleMosaicity hold the run's values (NaN only for frames without a scale). The usage line of -e now says the end image is exclusive, which is what the code does. Co-Authored-By: Claude Opus 5.5 --- rugnux/Rugnux.cpp | 9 +++++++++ rugnux/rugnux_cli.cpp | 2 +- writer/HDF5DataFilePluginMX.cpp | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rugnux/Rugnux.cpp b/rugnux/Rugnux.cpp index c81c21744..ed5a51d6d 100644 --- a/rugnux/Rugnux.cpp +++ b/rugnux/Rugnux.cpp @@ -1252,6 +1252,15 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b result.outputs->plot = std::move(plot); } + // The per-image scale exists only now, after scaling - long after the image messages went to the + // file - so it reaches the _process.h5 through the end message. + if (indexer && full && !cancelled_ && !superseded) { + const ScalingResult scaling(indexer->GetIntegrationOutcome()); + end_msg.image_scale_factor = scaling.image_scale_g; + end_msg.image_scale_cc = scaling.image_cc; + end_msg.image_scale_mosaicity = scaling.mosaicity_deg; + } + if (sink) sink->End(end_msg); result.end_message = end_msg; diff --git a/rugnux/rugnux_cli.cpp b/rugnux/rugnux_cli.cpp index 071cc599a..1dcf98c1c 100644 --- a/rugnux/rugnux_cli.cpp +++ b/rugnux/rugnux_cli.cpp @@ -129,7 +129,7 @@ void print_usage() { std::cout << " --no-gpu Run on the CPU only, as on a machine without a GPU: CUDA is not " "touched and every GPU step takes its CPU path (-X Auto and FFT index with FFTW)" << std::endl; std::cout << " -s, --start-image Start image number (default: 0)" << std::endl; - std::cout << " -e, --end-image End image number (default: all)" << std::endl; + std::cout << " -e, --end-image End image number, exclusive: -s 0 -e 100 processes images 0-99 (default: all)" << std::endl; std::cout << " -t, --stride Image stride (default: 1)" << std::endl; std::cout << " -v, --verbose Show the whole log on the terminal in place of the steps " "(the log file is written either way)" << std::endl; diff --git a/writer/HDF5DataFilePluginMX.cpp b/writer/HDF5DataFilePluginMX.cpp index ea4c7d81a..3acf351ab 100644 --- a/writer/HDF5DataFilePluginMX.cpp +++ b/writer/HDF5DataFilePluginMX.cpp @@ -195,7 +195,7 @@ void HDF5DataFilePluginMX::Write(const DataMessage &msg, uint64_t image_number) niggli_class[image_number] = 0; } - if (!image_scale_factor.empty()) + if (msg.image_scale_factor.has_value()) image_scale_present = true; image_scale_factor[image_number] = msg.image_scale_factor.value_or(NAN);