RotationIndexer: drop real_time
Only rugnux runs the rotation indexer now, and it always passed false: the candidate-cell refinements are bounded by iteration count, the post-search fixed-point walk and tilt hold always run, and the memo key loses the flag. IndexAndRefine keeps its own real_time, which bounds the per-image refinement of the online receivers and live stills. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
1 parent
0d2a1c6783
commit
3d631d2f69
4 files changed
+18
-23
No files matched your search
@@ -72,7 +72,7 @@ IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool
|
||||
experiment(x),
|
||||
indexer_(indexer) {
|
||||
if (indexer && x.IsRotationIndexing())
|
||||
rotation_indexer = std::make_unique<RotationIndexer>(x, *indexer, real_time);
|
||||
rotation_indexer = std::make_unique<RotationIndexer>(x, *indexer);
|
||||
// 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());
|
||||
|
||||
@@ -221,10 +221,10 @@ class IndexAndRefine {
|
||||
std::unique_ptr<ReindexAmbiguityResolver> reindex_resolver;
|
||||
void ScaleImage(DataMessage &msg, IntegrationOutcome& outcome);
|
||||
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.
|
||||
// Offline (rugnux, the viewer) passes false and they are bounded by iteration count instead, so the
|
||||
// same file reprocesses to the same answer regardless of what else the machine was doing.
|
||||
// real_time: bound the per-image geometry refinement by WALL CLOCK, as online acquisition must, it
|
||||
// having a real budget. Offline (rugnux, the viewer) passes false and it is bounded by iteration
|
||||
// count instead, so the same file reprocesses to the same answer regardless of what else the
|
||||
// machine was doing.
|
||||
IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer, bool retain_outcomes = true,
|
||||
bool real_time = false);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace {
|
||||
// How far from a whole number the volume ratio may sit and still count as an axis multiple.
|
||||
constexpr double ROT_SUPERCELL_INTEGER_TOL = 0.15;
|
||||
|
||||
// Iteration bound for the candidate-cell refinements when the run is not real-time. Without one,
|
||||
// Iteration bound for the candidate-cell refinements. Without one,
|
||||
// XtalOptimizerData falls back to its wall-clock bound and the cell a candidate refines to - and
|
||||
// therefore which candidate wins - depends on how busy the machine was. Same value as Ceres' own
|
||||
// default iteration limit, so it only bites where the clock was biting before.
|
||||
@@ -116,11 +116,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
RotationIndexer::RotationIndexer(const DiffractionExperiment &x, IndexerThreadPool &indexer,
|
||||
bool real_time)
|
||||
RotationIndexer::RotationIndexer(const DiffractionExperiment &x, IndexerThreadPool &indexer)
|
||||
: experiment(x),
|
||||
index_ice_rings(x.GetIndexingSettings().GetIndexIceRings()),
|
||||
real_time(real_time),
|
||||
v_(experiment.GetImageNum()),
|
||||
angle_deg_(experiment.GetImageNum()),
|
||||
axis_(x.GetGoniometer()),
|
||||
@@ -211,7 +209,7 @@ namespace {
|
||||
}
|
||||
|
||||
std::vector<double> RotationIndexer::InputKey() const {
|
||||
std::vector<double> k{static_cast<double>(real_time), static_cast<double>(v_.size()),
|
||||
std::vector<double> k{static_cast<double>(v_.size()),
|
||||
static_cast<double>(experiment.GetImageNum()),
|
||||
static_cast<double>(experiment.GetSpaceGroupOrP1().number)};
|
||||
if (const auto uc = experiment.GetUnitCell())
|
||||
@@ -374,7 +372,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
.refine_detector_angles = true,
|
||||
.refine_rotation_axis = true,
|
||||
.index_ice_rings = experiment.GetIndexingSettings().GetIndexIceRings(),
|
||||
.max_iterations = real_time ? 0 : ROT_REFINE_ITERATIONS,
|
||||
.max_iterations = ROT_REFINE_ITERATIONS,
|
||||
.axis = orig_axis
|
||||
};
|
||||
if (d.crystal_system == gemmi::CrystalSystem::Trigonal)
|
||||
@@ -578,7 +576,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
// answer near the header into a per-step limit that lets the pair walk to their joint optimum -
|
||||
// pinning its anchor across the rounds instead leaves the tilt at 0.014 deg and the data worse
|
||||
// than doing nothing. The winner only: the other candidates are discarded, and these solves are
|
||||
// the dominant first-pass cost. Not in real time, where the budget is wall-clock.
|
||||
// the dominant first-pass cost.
|
||||
//
|
||||
// The chain is a trajectory, and its last point is not always its best one. Every solve ends
|
||||
// by fitting only the spots inside its tightest gate (0.1), so a cell with a direction the
|
||||
@@ -662,7 +660,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
best = std::move(kept);
|
||||
return best;
|
||||
};
|
||||
if (have_best && !real_time)
|
||||
if (have_best)
|
||||
best_data = drive_to_fixed_point(best_data);
|
||||
|
||||
// The tilt is refined freely above because on a sweep whose spots reach far enough in 2theta
|
||||
@@ -694,7 +692,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
// tilt standing only when it leads by more than the count's own noise. Held, not bounded - a
|
||||
// box the fit lands on is the same wrong answer at a smaller size.
|
||||
constexpr double ROT_TILT_PRIOR_DEG = 1.0;
|
||||
if (have_best && !real_time) {
|
||||
if (have_best) {
|
||||
const double walk_deg = std::hypot(best_data.geom.GetPoniRot1_rad() - geom_.GetPoniRot1_rad(),
|
||||
best_data.geom.GetPoniRot2_rad() - geom_.GetPoniRot2_rad())
|
||||
* 180.0 / PI;
|
||||
@@ -731,7 +729,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (have_best && !real_time)
|
||||
if (have_best)
|
||||
best_frac = IndexedFraction(best_data.latt, accumulate(best_data.geom, best_data.axis), index_tol);
|
||||
|
||||
if (have_best) {
|
||||
@@ -783,7 +781,7 @@ void RotationIndexer::RunIndexingLocked() {
|
||||
.refine_unit_cell = false,
|
||||
.refine_rotation_axis = false,
|
||||
.index_ice_rings = experiment.GetIndexingSettings().GetIndexIceRings(),
|
||||
.max_iterations = real_time ? 0 : ROT_REFINE_ITERATIONS,
|
||||
.max_iterations = ROT_REFINE_ITERATIONS,
|
||||
.axis = axis_
|
||||
};
|
||||
|
||||
@@ -877,7 +875,7 @@ RotationIndexer::RefineConstrained(const CrystalLattice &latt, gemmi::CrystalSys
|
||||
.refine_detector_angles = false,
|
||||
.refine_rotation_axis = false,
|
||||
.index_ice_rings = index_ice_rings,
|
||||
.max_iterations = real_time ? 0 : ROT_REFINE_ITERATIONS,
|
||||
.max_iterations = ROT_REFINE_ITERATIONS,
|
||||
.axis = axis_
|
||||
};
|
||||
|
||||
|
||||
@@ -97,7 +97,6 @@ private:
|
||||
bool verify_memo = false;
|
||||
|
||||
const bool index_ice_rings;
|
||||
const bool real_time; // see the constructor
|
||||
|
||||
std::vector<std::vector<SpotToSave>> v_;
|
||||
// Per-image rotation angle (mid-exposure, deg) supplied by the caller; falls back to the
|
||||
@@ -129,11 +128,9 @@ private:
|
||||
[[nodiscard]] IndexingOutcome Outcome() const;
|
||||
void RunIndexingLocked();
|
||||
public:
|
||||
// real_time: bound the candidate-cell refinements by WALL CLOCK, as online acquisition must - it
|
||||
// has a real budget. Offline (rugnux, the viewer) passes false and they are bounded by iteration
|
||||
// count instead, so the same file reprocesses to the same cell regardless of what else the machine
|
||||
// was doing at the time.
|
||||
RotationIndexer(const DiffractionExperiment& x, IndexerThreadPool& indexer, bool real_time = false);
|
||||
// The candidate-cell refinements are bounded by iteration count, not wall clock, so the same file
|
||||
// reprocesses to the same cell regardless of what else the machine was doing at the time.
|
||||
RotationIndexer(const DiffractionExperiment& x, IndexerThreadPool& indexer);
|
||||
// Keep only this many spots per image in the accumulated cloud (strongest, non-ring first).
|
||||
void MaxSpotsPerImage(size_t n) { max_spots_per_image = n > 0 ? n : DEFAULT_MAX_SPOTS_PER_IMAGE; }
|
||||
// Recompute on a memo hit and throw if the two differ - the tests' check that the memo is exact.
|
||||
|
||||
Reference in new issue
Block a user