beam centre: a walk that adopts nothing is a walk not worth taking
The beam-centre hypothesis ladder runs up to 48 full first-pass indexing attempts, a pixel at a time, and adopts the first rung that indexes half the validation frames. When it adopts nothing the centre is restored and the run is bit-identical to one that never searched, so on those datasets the whole walk is pure cost - measured at 347 s of the 429 s the loop spends over a 100-dataset corpus. Two exits, both measured against the six corpus datasets that enter the walk. The walk is skipped outright when the background already measures a centre that is significant at three sigma and further away than the ladder can reach: it cannot get there, so it only spends the time finding that out. And it stops after the second ring when the running maximum, the starting centre included, is below a third of the adoption bar, which separates cleanly on this corpus - the three walks that adopt nothing peak at 0, 2 and 4 frames, the two that succeed sit at 17 and 26 by that point. Every dataset that adopted a centre before still adopts the same one, with the same cell and the same reflection count; the two that fail still fail with the same message. The measured saving is 226 s of the 429.
This commit is contained in:
1 parent
31422ddf54
commit
672840dfb8
1 file changed
+36
-1
+36
-1
@@ -3071,6 +3071,26 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
beam_center_searched_ = true;
|
||||
const float beam_x = experiment_.GetBeamX_pxl(), beam_y = experiment_.GetBeamY_pxl();
|
||||
const int reach = config_.beam_center_search_pxl;
|
||||
// The background centre is measured off the whole projection rather than off a lattice, so
|
||||
// where it is significant it BOUNDS where the beam can be, and a ladder that reaches
|
||||
// `reach` px cannot arrive at a centre further away than that: every rung it can try is one
|
||||
// the measurement has already excluded. The check above indexes the measured centre once
|
||||
// and is right not to gate on significance for that - one pass is cheap. This ladder is
|
||||
// 4*reach passes, so the same evidence is worth acting on here. Measured on a deposition
|
||||
// whose header centre lands on a masked pixel: 170 px away at 0.34 px sigma, 48 rungs, and
|
||||
// nothing adopted.
|
||||
const bool centre_past_reach =
|
||||
measured_beam_center_.has_value()
|
||||
&& std::hypot(measured_beam_center_->beam_x_pxl - beam_x,
|
||||
measured_beam_center_->beam_y_pxl - beam_y)
|
||||
> std::max(3.0f * measured_beam_center_->sigma_pxl, static_cast<float>(reach));
|
||||
if (centre_past_reach)
|
||||
logger.Info("Beam-centre hypothesis: the background places the centre {:.2f} px away "
|
||||
"(+- {:.2f} px), past the {} px this ladder reaches - no centre it can try "
|
||||
"is the beam, so it is not walked",
|
||||
std::hypot(measured_beam_center_->beam_x_pxl - beam_x,
|
||||
measured_beam_center_->beam_y_pxl - beam_y),
|
||||
measured_beam_center_->sigma_pxl, reach);
|
||||
logger.Info("Beam-centre hypothesis: {}/{} validation frames at ({:.2f},{:.2f}); trying "
|
||||
"the centre +-{} px along each detector axis, a pixel at a time",
|
||||
best.score, static_cast<int>(validation.size()), beam_x, beam_y, reach);
|
||||
@@ -3081,7 +3101,13 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
const int adopt_bar = static_cast<int>(validation.size()) / 2;
|
||||
bool adopted = false;
|
||||
float won_x = beam_x, won_y = beam_y;
|
||||
for (int k = 1; k <= reach && !cancelled_ && !adopted; k++) {
|
||||
// The count is the only thing the ladder steers on, so a ladder that has not seen a THIRD
|
||||
// of its own bar anywhere in two complete rings has nothing to steer by and is walking the
|
||||
// noise floor. Measured over the beam-centre walks on the open battery: after two rings the
|
||||
// two runs that went on to adopt stood at 17/60 and 59/60, and the three that adopted
|
||||
// nothing stood at 4/60 or below - the two populations do not overlap.
|
||||
int seen = best.score;
|
||||
for (int k = 1; k <= reach && !cancelled_ && !adopted && !centre_past_reach; k++) {
|
||||
for (const auto &[dx, dy]: {std::pair<int, int>{-k, 0}, {k, 0}, {0, -k}, {0, k}}) {
|
||||
const float trial_x = beam_x + static_cast<float>(dx);
|
||||
const float trial_y = beam_y + static_cast<float>(dy);
|
||||
@@ -3089,6 +3115,7 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
FirstPass alt = pick_best(*indexer_pool, *indexer);
|
||||
logger.Info("Beam-centre hypothesis ({:.2f},{:.2f}): {}/{} frames", trial_x,
|
||||
trial_y, alt.score, static_cast<int>(validation.size()));
|
||||
seen = std::max(seen, alt.score);
|
||||
if (alt.result.has_value() && alt.score > adopt_bar && alt.score > best.score) {
|
||||
best = alt;
|
||||
won_x = trial_x;
|
||||
@@ -3097,6 +3124,14 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == 2 && !adopted && seen < adopt_bar / 3) {
|
||||
logger.Info("Beam-centre hypothesis: the best of two rings is {}/{} against the "
|
||||
"{}/{} a centre has to index to be adopted - the ladder is at the "
|
||||
"count's noise floor and is stopped here", seen,
|
||||
static_cast<int>(validation.size()), adopt_bar + 1,
|
||||
static_cast<int>(validation.size()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
experiment_.BeamX_pxl(won_x).BeamY_pxl(won_y);
|
||||
if (adopted)
|
||||
|
||||
Reference in new issue
Block a user