diff --git a/rugnux/Rugnux.cpp b/rugnux/Rugnux.cpp index c8119f214..6fcb5a959 100644 --- a/rugnux/Rugnux.cpp +++ b/rugnux/Rugnux.cpp @@ -2665,7 +2665,9 @@ ProcessResult Rugnux::RunAllPasses(RugnuxObserver *observer) { logger.Info("Rotation two-pass geometry post-refinement: second pass (refined geometry, canonical) -> {}_*", base_prefix); speculate_geometry_probe_ = true; // a walk that follows starts with an indexing probe + rerun_if_starved_ = true; auto pass2 = RunPipeline(observer, /*write_output=*/true, /*geometry_prepass=*/false); + rerun_if_starved_ = false; speculate_geometry_probe_ = false; // Walk the geometry to the fit's fixed point. The post-refinement is fitted to reflections @@ -2860,7 +2862,9 @@ ProcessResult Rugnux::RunAllPasses(RugnuxObserver *observer) { "the last one that lowered the realised residual", best_round, best_geometry[2]); set_geometry(best_geometry); } + rerun_if_starved_ = true; pass2 = RunPipeline(observer, /*write_output=*/true, /*geometry_prepass=*/false); + rerun_if_starved_ = false; ++walk_passes; } @@ -3184,6 +3188,7 @@ void Rugnux::StartSpeculativeGeometryProbe(const std::array &geometry) run->indexing_probe_only_ = true; run->postrefine_probe_ = false; run->postrefine_probe_only_ = false; + run->rerun_if_starved_ = false; auto sp = std::make_shared(); sp->run = run; // A probe that fails leaves no memo, and the walk's own probe then runs it again and meets the @@ -6674,6 +6679,24 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b return result; } } + // A pass RunAllPasses re-runs at the fixed radius for a starved background ring: its merge, + // search and files are all replaced by the re-run's, and what anything reads from it - the + // post-refinement and validation evidence above, and bkg_starved_fraction_ - is in hand. The + // pass after it starts from the group the run was asked for (top of RunPipeline), so the + // space group this pass would have determined is not carried either. Not with a _process.h5 + // writer open: that file is written whole by every pass that opens it. + if (rerun_if_starved_ && !writer && !cancelled_ && bragg_adaptive_ && bkg_starved_fraction_ + && *bkg_starved_fraction_ > spot_width::BKG_STARVED_MAX_FRACTION) { + if (census_future.valid()) + census_future.wait(); + result.processing_time_s = std::chrono::duration( + std::chrono::steady_clock::now() - start_time).count(); + logger.Info("Starved pass: {} images integrated in {:.2f} s - {:.2f}% of the reflections " + "lost their background ring, so this pass is re-run at the fixed radius and " + "does not merge", result.images_processed, result.processing_time_s, + 100.0 * *bkg_starved_fraction_); + return result; + } if (is_rotation) { if (experiment_.GetRefineRotationWedgeInScaling() || rot_ss.GetRotationWedgeForScaling().has_value()) diff --git a/rugnux/Rugnux.h b/rugnux/Rugnux.h index bf5017a8c..714dba77c 100644 --- a/rugnux/Rugnux.h +++ b/rugnux/Rugnux.h @@ -715,6 +715,11 @@ class Rugnux { // Everything below that point - the merges, the space-group search, the correction surfaces, the // reports - is work no comparison looks at, and on a long sweep it is four fifths of the pass. bool postrefine_probe_only_ = false; + // Whether RunAllPasses re-runs this pass at the fixed integration radius when its background + // ring is starved (bkg_starved_fraction_ over the bound). Such a pass learns it at integration, + // and what is read from it afterwards - the post-refinement and the validation evidence the + // geometry walk decides on - is in hand at the same point as on a probe pass, so it stops there. + bool rerun_if_starved_ = false; // The demoted arm of an ANGLE promotion (see RunAllPasses): the first pass takes the indexer's // free (triclinic) refinement in place of a monoclinic or orthorhombic class. bool lattice_angles_demoted_ = false;