From b2f0af12db377026cc2d5ba2d2270988149edcb9 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 9 Jul 2026 11:02:10 +0200 Subject: [PATCH] image_analysis: add retain_outcomes flag to IndexAndRefine; viewer opts out IndexAndRefine::integration_outcome is a whole-run vector (resize(GetImageNum())) holding up to ~0.8 MB of reflections per indexed image. It is consumed only by the offline scaling/merge pass in rugnux (ScaleAllImages / GetIntegrationOutcome). In the viewer's interactive/live analysis it is written but never read - dead storage that, with auto-reanalyze on during live follow, grew ~0.8 MB per frame for the whole run. Add a retain_outcomes constructor flag (default true). When false, skip the whole-run resize and the per-image store; the current image's reflections are still returned via the outgoing message. The viewer's live IndexAndRefine passes false. rugnux (including GUI processing jobs, which build their own Rugnux -> IndexAndRefine) and the online receiver keep the default true, so scaling/merge still has the accumulated data. Co-Authored-By: Claude Fable 5 --- image_analysis/IndexAndRefine.cpp | 11 ++++++++--- image_analysis/IndexAndRefine.h | 6 +++++- viewer/JFJochImageReadingWorker.cpp | 4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/image_analysis/IndexAndRefine.cpp b/image_analysis/IndexAndRefine.cpp index 02ee88ac..5f248b69 100644 --- a/image_analysis/IndexAndRefine.cpp +++ b/image_analysis/IndexAndRefine.cpp @@ -12,15 +12,18 @@ #include "lattice_search/LatticeSearch.h" #include "scale_merge/ScaleOnTheFly.h" -IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer) +IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer, bool retain_outcomes) : index_ice_rings(x.GetIndexingSettings().GetIndexIceRings()), + retain_outcomes_(retain_outcomes), experiment(x), geom_(x.GetDiffractionGeometry()), indexer_(indexer), rotation_indexer_counter(x) { if (indexer && x.IsRotationIndexing()) rotation_indexer = std::make_unique(x, *indexer); - integration_outcome.resize(x.GetImageNum()); + // Only retain the whole-run per-image reflections when a later scaling/merge pass will read them. + if (retain_outcomes_) + integration_outcome.resize(x.GetImageNum()); mosaicity.resize(x.GetImageNum(), NAN); scale_cc.resize(x.GetImageNum(), 0); @@ -363,7 +366,9 @@ void IndexAndRefine::QuickPredictAndIntegrate(DataMessage &msg, // Copy reflections to outgoing message msg.reflections = i_outcome.reflections; - { + // Persist the per-image result for the whole-run scaling/merge pass, unless the caller opted out + // (viewer interactive use only needs the current image, returned above via msg). + if (retain_outcomes_) { const std::unique_lock ul(reflections_mutex); integration_outcome[msg.number] = std::move(i_outcome); } diff --git a/image_analysis/IndexAndRefine.h b/image_analysis/IndexAndRefine.h index 45fe5593..1b25e73b 100644 --- a/image_analysis/IndexAndRefine.h +++ b/image_analysis/IndexAndRefine.h @@ -30,6 +30,10 @@ using BraggIntegrateFn = std::function( class IndexAndRefine { const bool index_ice_rings; + // When false, the current image's result is still returned via the outgoing message, but the + // whole-run integration_outcome vector is not retained (viewer live/interactive use, which never + // scales the accumulated run). rugnux/receiver keep it true so ScaleAllImages/merge have the data. + const bool retain_outcomes_; const DiffractionExperiment& experiment; const DiffractionGeometry geom_; @@ -79,7 +83,7 @@ class IndexAndRefine { std::optional RotationAngle(int64_t image) const; // mid-exposure angle for the indexer public: - IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer); + IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer, bool retain_outcomes = true); void AddImageToRotationIndexer(DataMessage &msg); void ForceRotationIndexerLattice(const CrystalLattice& lattice); diff --git a/viewer/JFJochImageReadingWorker.cpp b/viewer/JFJochImageReadingWorker.cpp index 9195c884..356f36ba 100644 --- a/viewer/JFJochImageReadingWorker.cpp +++ b/viewer/JFJochImageReadingWorker.cpp @@ -364,7 +364,9 @@ void JFJochImageReadingWorker::LoadImage(int64_t image_number, int64_t summation void JFJochImageReadingWorker::UpdateAzint_i(const JFJochReaderDataset *dataset) { if (dataset) { azint_mapping = std::make_unique(curr_experiment, *dataset->pixel_mask); - index_and_refine = std::make_unique(curr_experiment, indexing.get()); + // Interactive/live analysis only needs the current image's result (returned per image); it + // never scales the accumulated run, so don't retain the whole-run integration_outcome vector. + index_and_refine = std::make_unique(curr_experiment, indexing.get(), /*retain_outcomes=*/false); image_analysis = std::make_unique(curr_experiment, *azint_mapping, *dataset->pixel_mask, *index_and_refine.get());