Geometry refinement: bound offline reprocessing by iterations, not the clock
The per-image refinement stopped on a wall-clock budget (40 ms, and 20 ms for the rotation-only extra pass). Online that is exactly right - the budget is real and an image that overruns it costs the acquisition. Offline it means the same file refines to a different lattice depending on what else the machine was doing at the time, which is not a property reprocessing should have. Bound it by iteration count instead when the caller is offline. IndexAndRefine takes the workflow as a constructor argument: the receiver asks for the wall-clock bound, rugnux and the viewer get the reproducible one. 50 iterations is Ceres' own default; the per-image problem converges well inside it, so it bounds the pathological case rather than the normal one - measured on five battery crystals, every number is unchanged from the timed version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,18 @@
|
||||
#include "scale_merge/ReindexAmbiguity.h"
|
||||
#include "scale_merge/ScaleOnTheFly.h"
|
||||
|
||||
IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer, bool retain_outcomes)
|
||||
namespace {
|
||||
// Iterations the offline geometry refinement is allowed, standing in for the 40 ms the online path
|
||||
// spends. Ceres' own default is 50; the per-image problem is small and converges well inside that,
|
||||
// so this bounds the pathological case rather than the normal one.
|
||||
constexpr int OFFLINE_REFINE_ITERATIONS = 50;
|
||||
}
|
||||
|
||||
IndexAndRefine::IndexAndRefine(const DiffractionExperiment &x, IndexerThreadPool *indexer,
|
||||
bool retain_outcomes, bool real_time)
|
||||
: index_ice_rings(x.GetIndexingSettings().GetIndexIceRings()),
|
||||
retain_outcomes_(retain_outcomes),
|
||||
real_time(real_time),
|
||||
experiment(x),
|
||||
geom_(x.GetDiffractionGeometry()),
|
||||
indexer_(indexer),
|
||||
@@ -258,7 +267,11 @@ void IndexAndRefine::RefineGeometryIfNeeded(DataMessage &msg, IndexAndRefine::In
|
||||
// enters the fit at the loose first tolerance is arbitrarily indexed noise. Weight every spot by
|
||||
// how strong it is for its resolution so those contribute without dragging the orientation.
|
||||
.weight_spots_by_confidence = true,
|
||||
.max_time = 0.04 // 40 ms is max allowed time for the operation
|
||||
// Online: 40 ms is the real budget per image, so the wall clock is the right bound even though
|
||||
// it makes the answer depend on machine load. Offline: bound the same refinement by iterations
|
||||
// instead, so reprocessing the same file twice gives the same lattice.
|
||||
.max_time = 0.04,
|
||||
.max_iterations = real_time ? 0 : OFFLINE_REFINE_ITERATIONS
|
||||
};
|
||||
|
||||
|
||||
@@ -346,7 +359,8 @@ void IndexAndRefine::RefineGeometryIfNeeded(DataMessage &msg, IndexAndRefine::In
|
||||
.refine_unit_cell = false,
|
||||
.refine_rotation_axis = false,
|
||||
.index_ice_rings = experiment.GetIndexingSettings().GetIndexIceRings(),
|
||||
.max_time = 0.02
|
||||
.max_time = 0.02,
|
||||
.max_iterations = real_time ? 0 : OFFLINE_REFINE_ITERATIONS / 2
|
||||
};
|
||||
XtalOptimizerRotationOnly(data_extra, msg.spots, 0.1);
|
||||
el = data_extra.latt;
|
||||
|
||||
Reference in New Issue
Block a user