IndexAndRefine: remove the online rotation-indexer trigger

With --single-pass-rotation gone and the broker no longer asking for rotation
indexing, nothing reaches the counter-driven path any more: rugnux's rotation
run always forces the first pass's lattice (a failed first pass stops the run).
Removed: RotationIndexerCounter, the counter branch of
DetermineLatticeAndSymmetryRotation (and RotationAngle, its only user), the
RunIndexing fallback in FinalizeRotationIndexing, the uncalled
AddImageToRotationIndexer, and IndexingSettings' rotation-indexing minimum
angular range and stride with their entries in the rotation indexer's and
rugnux's memo keys (constants there, so no key changes meaning).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-11-08 08:57:20 +01:00
1 parent d279827a82
commit 0d2a1c6783
11 files changed
+9 -152

No files matched your search

+1 -2
View File
@@ -1913,8 +1913,7 @@ int64_t DiffractionExperiment::GetDarkMaskNumberOfFrames() const {
}
bool DiffractionExperiment::IsRotationIndexing() const {
// A stationary axis is not rotation data, however it got here. Without this, a constant axis
// reaches RotationIndexerCounter, whose stride stays zero, and indexing then never runs at all.
// A stationary axis is not rotation data, however it got here.
const auto goniometer = GetGoniometer();
return goniometer.has_value() && goniometer->IsScanning() && indexing.GetRotationIndexing();
}
-22
View File
@@ -197,32 +197,10 @@ IndexingSettings & IndexingSettings::RotationIndexing(bool input) {
return*this;
}
IndexingSettings & IndexingSettings::RotationIndexingMinAngularRange_deg(float input) {
check_finite("Rotation indexing minimum angular range (deg.)", input);
check_min("Rotation indexing minimum angular range (deg.)", input, 1.0);
rotation_indexing_min_angular_range_deg = input;
return *this;
}
IndexingSettings & IndexingSettings::RotationIndexingAngularStride_deg(float input) {
check_finite("Rotation indexing angular stride (deg.)", input);
check_min("Rotation indexing angular stride (deg.)", input, 0.0);
rotation_indexing_angular_stride_deg = input;
return *this;
}
bool IndexingSettings::GetRotationIndexing() const {
return enable_rotation_indexing;
}
float IndexingSettings::GetRotationIndexingMinAngularRange_deg() const {
return rotation_indexing_min_angular_range_deg;
}
float IndexingSettings::GetRotationIndexingAngularStride_deg() const {
return rotation_indexing_angular_stride_deg;
}
IndexingSettings & IndexingSettings::LatticeClassDemoted(bool input) {
lattice_class_demoted = input;
return *this;
-6
View File
@@ -71,8 +71,6 @@ private:
bool lattice_class_demoted = false;
bool enable_rotation_indexing = false;
float rotation_indexing_min_angular_range_deg = 20.0;
float rotation_indexing_angular_stride_deg = 0.5;
GeomRefinementAlgorithmEnum refinement = GeomRefinementAlgorithmEnum::BeamCenter;
public:
@@ -93,8 +91,6 @@ public:
IndexingSettings& GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum input);
IndexingSettings& IndexIceRings(bool input);
IndexingSettings& RotationIndexing(bool input);
IndexingSettings& RotationIndexingMinAngularRange_deg(float input);
IndexingSettings& RotationIndexingAngularStride_deg(float input);
IndexingSettings& BlockingBehavior(bool input);
IndexingSettings& MaxExtraLattices(int64_t input);
IndexingSettings& LatticeClassDemoted(bool input);
@@ -115,8 +111,6 @@ public:
[[nodiscard]] float GetUnitCellAngleTolerance_deg() const;
[[nodiscard]] bool GetIndexIceRings() const;
[[nodiscard]] bool GetRotationIndexing() const;
[[nodiscard]] float GetRotationIndexingMinAngularRange_deg() const;
[[nodiscard]] float GetRotationIndexingAngularStride_deg() const;
[[nodiscard]] bool GetBlockingBehavior() const;
[[nodiscard]] int64_t GetMaxExtraLattices() const;
[[nodiscard]] bool GetLatticeClassDemoted() const;
+1 -2
View File
@@ -116,8 +116,7 @@ ADD_LIBRARY(JFJochImageAnalysis STATIC
UpdateReflectionResolution.cpp
UpdateReflectionResolution.h
IntegrationOutcome.h
rotation_indexer/RotationIndexerCounter.cpp
rotation_indexer/RotationIndexerCounter.h)
)
ADD_SUBDIRECTORY(spot_finding)
ADD_SUBDIRECTORY(bragg_integration)
+3 -40
View File
@@ -70,8 +70,7 @@ IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool
: retain_outcomes_(retain_outcomes),
real_time(real_time),
experiment(x),
indexer_(indexer),
rotation_indexer_counter(x) {
indexer_(indexer) {
if (indexer && x.IsRotationIndexing())
rotation_indexer = std::make_unique<RotationIndexer>(x, *indexer, real_time);
// Only retain the whole-run per-image reflections when a later scaling/merge pass will read them.
@@ -85,13 +84,6 @@ IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool
unit_cells.resize(x.GetImageNum());
}
std::optional<float> IndexAndRefine::RotationAngle(int64_t image) const {
// Mid-exposure rotation angle for image index `image`, matching the angle used for prediction.
if (const auto g = experiment.GetGoniometer())
return g->GetAngle_deg(static_cast<float>(image)) + g->GetWedge_deg() / 2.0f;
return std::nullopt;
}
void IndexAndRefine::RecordIndexerError(std::exception_ptr e) {
std::lock_guard lock(indexer_error_mutex_);
if (!first_indexer_error_)
@@ -110,33 +102,13 @@ void IndexAndRefine::RethrowIndexerError() const {
std::rethrow_exception(first_indexer_error_);
}
void IndexAndRefine::AddImageToRotationIndexer(DataMessage &msg) {
if (rotation_indexer)
rotation_indexer->ProcessImage(msg.number, msg.spots, RotationAngle(msg.number));
}
IndexAndRefine::IndexingOutcome IndexAndRefine::DetermineLatticeAndSymmetryRotation(DataMessage &msg) {
IndexingOutcome outcome(experiment);
if (!rotation_indexer)
return outcome;
auto result = rotation_indexer->GetLattice();
if (!result.has_value()) {
auto rot_cnt = rotation_indexer_counter.Process(msg.number);
if (rot_cnt.first)
rotation_indexer->ProcessImage(msg.number, msg.spots, RotationAngle(msg.number));
if (rot_cnt.second) {
try {
rotation_indexer->RunIndexing();
} catch (...) {
RecordIndexerError(std::current_exception());
}
}
result = rotation_indexer->GetLattice();
}
const auto result = rotation_indexer->GetLattice();
if (result.has_value()) {
// For rotation indexing, indexing rate is calculated only for frames, where "global" rotation indexing solution was found
msg.indexing_result = false;
@@ -976,17 +948,8 @@ int64_t IndexAndRefine::CountSpotsOnLattice(DataMessage &msg, const SpotFindingS
}
std::optional<RotationIndexerResult> IndexAndRefine::FinalizeRotationIndexing() {
if (rotation_indexer) {
if (const auto latt = rotation_indexer->GetLattice())
return latt;
try {
rotation_indexer->RunIndexing();
} catch (...) {
RecordIndexerError(std::current_exception());
}
if (rotation_indexer)
return rotation_indexer->GetLattice();
}
return {};
}
-5
View File
@@ -20,7 +20,6 @@
#include "indexing/IndexerThreadPool.h"
#include "lattice_search/LatticeSearch.h"
#include "rotation_indexer/RotationIndexer.h"
#include "rotation_indexer/RotationIndexerCounter.h"
#include "scale_merge/ReindexAmbiguity.h"
#include "scale_merge/ScaleOnTheFly.h"
#include "scale_merge/ScalingResult.h"
@@ -114,7 +113,6 @@ class IndexAndRefine {
IndexerThreadPool *indexer_;
std::unique_ptr<RotationIndexer> rotation_indexer;
RotationIndexerCounter rotation_indexer_counter;
struct IndexingOutcome {
std::optional<CrystalLattice> lattice_candidate;
@@ -222,8 +220,6 @@ class IndexAndRefine {
std::unique_ptr<ReindexAmbiguityResolver> reindex_resolver;
void ScaleImage(DataMessage &msg, IntegrationOutcome& outcome);
std::optional<float> RotationAngle(int64_t image) const; // mid-exposure angle for the indexer
public:
// real_time: bound the geometry refinements - the per-image one here and the candidate-cell ones
// in the rotation indexer - by WALL CLOCK, as online acquisition must, it having a real budget.
@@ -232,7 +228,6 @@ public:
IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer, bool retain_outcomes = true,
bool real_time = false);
void AddImageToRotationIndexer(DataMessage &msg);
// An indexer that fails says nothing about the frame and everything about the machine, so it is
// not a frame that did not index. Online, a collection goes on and reports how often it happened
// (GetIndexerErrorCount); offline, the run stops on it (RethrowIndexerError).
@@ -154,8 +154,7 @@ namespace {
static_cast<double>(x.GetFFT_NumVectors()), x.GetFFT_HighResolution_A(),
x.GetFFT_MinAngle_deg(), x.GetFFT_MaxAngle_deg(), x.GetUnitCellDistTolerance(),
x.GetUnitCellAngleTolerance_deg(), static_cast<double>(x.GetIndexIceRings()),
x.GetRotationIndexingMinAngularRange_deg(), x.GetRotationIndexingAngularStride_deg(),
static_cast<double>(x.GetMaxExtraLattices()), static_cast<double>(x.GetLatticeClassDemoted()),
static_cast<double>(x.GetMaxExtraLattices()), static_cast<double>(x.GetLatticeClassDemoted()),
static_cast<double>(x.GetViableCellMinSpots()), static_cast<double>(x.GetAlgorithm()),
static_cast<double>(x.GetGeomRefinementAlgorithm()),
static_cast<double>(x.GetIndexingThreads()), static_cast<double>(x.GetRefineThreads())});
@@ -1,45 +0,0 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "RotationIndexerCounter.h"
RotationIndexerCounter::RotationIndexerCounter(const DiffractionExperiment &x) {
const auto axis = x.GetGoniometer();
if (x.IsRotationIndexing() && axis.has_value()) {
float angle_norm_deg = std::fabs(axis->GetIncrement_deg());
if (angle_norm_deg >= 1e-6) {
if (x.GetImageNum() < min_images_for_indexing) {
// For short measurements - no trying to index during the measurement
image_to_try_indexing = x.GetImageNum();
image_stride = 1;
} else {
image_to_try_indexing = std::max<int64_t>(min_images_for_indexing,
x.GetIndexingSettings().
GetRotationIndexingMinAngularRange_deg() / angle_norm_deg);
image_stride = std::ceil(
x.GetIndexingSettings().GetRotationIndexingAngularStride_deg() / angle_norm_deg);
if (image_stride == 0)
image_stride = 1;
}
}
}
}
std::pair<bool, bool> RotationIndexerCounter::Process(int64_t image) {
std::unique_lock ul(m);
std::pair<bool, bool> ret = {false, false};
if (image_stride == 0)
return ret;
accumulated_images++;
ret.first = (image_stride == 1) || (image % image_stride == 0);
if (accumulated_images >= image_to_try_indexing) {
image_to_try_indexing += 10;
ret.second = true;
}
return ret;
}
@@ -1,24 +0,0 @@
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <cstdint>
#include <mutex>
#include "../common/DiffractionExperiment.h"
class RotationIndexerCounter {
mutable std::mutex m;
int64_t image_stride = 0;
int64_t image_to_try_indexing = INT64_MAX;
int64_t indexing_range_multiplier = 1;
size_t accumulated_images = 0;
constexpr static int64_t min_images_for_indexing = 10;
public:
RotationIndexerCounter(const DiffractionExperiment &experiment);
std::pair<bool, bool> Process(int64_t image); // Should you add image to a pile? Should you try indexing?
};
-1
View File
@@ -782,7 +782,6 @@ std::vector<double> Rugnux::ExperimentKey(const DiffractionExperiment &e, bool r
static_cast<double>(x.GetFFT_NumVectors()), x.GetFFT_HighResolution_A(),
x.GetFFT_MinAngle_deg(), x.GetFFT_MaxAngle_deg(), x.GetUnitCellDistTolerance(),
x.GetUnitCellAngleTolerance_deg(), static_cast<double>(x.GetIndexIceRings()),
x.GetRotationIndexingMinAngularRange_deg(), x.GetRotationIndexingAngularStride_deg(),
static_cast<double>(x.GetMaxExtraLattices()), static_cast<double>(x.GetLatticeClassDemoted()),
static_cast<double>(x.GetViableCellMinSpots()), static_cast<double>(x.GetAlgorithm()),
static_cast<double>(x.GetGeomRefinementAlgorithm())});
+3 -3
View File
@@ -20,7 +20,7 @@ TEST_CASE("RotationIndexer") {
IndexingSettings settings;
settings.Algorithm(IndexingAlgorithmEnum::Auto); // rotation: FFT with a GPU, FFTW without
settings.RotationIndexing(true).RotationIndexingAngularStride_deg(1.0).RotationIndexingMinAngularRange_deg(30.0);
settings.RotationIndexing(true);
exp_i.ImportIndexingSettings(settings);
// Base lattice (non-pathological)
@@ -105,7 +105,7 @@ TEST_CASE("RotationIndexer::RefineConstrained puts a free metric back on its cla
IndexingSettings settings;
settings.Algorithm(IndexingAlgorithmEnum::Auto); // rotation: FFT with a GPU, FFTW without
settings.RotationIndexing(true).RotationIndexingAngularStride_deg(1.0).RotationIndexingMinAngularRange_deg(30.0);
settings.RotationIndexing(true);
exp_i.ImportIndexingSettings(settings);
const CrystalLattice latt_base =
@@ -181,7 +181,7 @@ static std::optional<RotationIndexerResult> IndexOnTiltedDetector(double true_ti
IndexingSettings settings;
settings.Algorithm(IndexingAlgorithmEnum::Auto); // rotation: FFT with a GPU, FFTW without
settings.RotationIndexing(true).RotationIndexingAngularStride_deg(1.0).RotationIndexingMinAngularRange_deg(30.0);
settings.RotationIndexing(true);
exp_header.ImportIndexingSettings(settings);
GoniometerAxis axis("omega", 0.0f, 1.0f, Coord(1, 0, 0), std::nullopt);