diff --git a/rugnux/RugnuxPasses.cpp b/rugnux/RugnuxPasses.cpp index a1f73d2ec..212851a93 100644 --- a/rugnux/RugnuxPasses.cpp +++ b/rugnux/RugnuxPasses.cpp @@ -912,21 +912,22 @@ std::optional Rugnux::RefinedPasses(RugnuxObserver *observer, Pro // The demoted arm runs first, as a probe: it is compared on the post-refinement's held-out // residual, so it has to measure one, and a canonical pass only does where the pre-pass // moved the geometry. The canonical pass below is the promoted arm (lattice_arm_check_). - const bool probe_was = postrefine_probe_; - postrefine_probe_ = true; - postrefine_probe_only_ = true; + // The probe runs on a copy of the run, so it leaves nothing on the run - not the spot + // budget its first pass measures, which the canonical pass would otherwise start from - + // except the geometry its post-refinement asks for, which the promoted arm reads (see + // ScaleMergeAndSymmetry), and its first-pass memo. + Rugnux demoted_run(*this); + demoted_run.postrefine_probe_ = true; + demoted_run.postrefine_probe_only_ = true; IndexingSettings demoted_settings = experiment_.GetIndexingSettings(); demoted_settings.LatticeClassDemoted(length_arm); - experiment_.ImportIndexingSettings(demoted_settings); - lattice_angles_demoted_ = angle_arm; - demoted_arm = RunPipeline(observer, /*write_output=*/false, /*geometry_prepass=*/false); + demoted_run.experiment_.ImportIndexingSettings(demoted_settings); + demoted_run.lattice_angles_demoted_ = angle_arm; + demoted_arm = demoted_run.RunPipeline(observer, /*write_output=*/false, /*geometry_prepass=*/false); ++arm_passes; - postrefine_probe_only_ = false; - postrefine_probe_ = probe_was; - IndexingSettings promoted_settings = experiment_.GetIndexingSettings(); - promoted_settings.LatticeClassDemoted(false); - experiment_.ImportIndexingSettings(promoted_settings); - lattice_angles_demoted_ = false; + prepass_detector_geometry_ = demoted_run.prepass_detector_geometry_; + for (const auto &m : demoted_run.first_pass_memo_) + AddFirstPassMemo(m); lattice_arm_check_ = LatticeArmCheck{.demoted = demoted_arm->post_refine}; } else { logger.Info("Metric symmetry: {} - the free refinement departs from it by {:.2f} {}, " @@ -942,6 +943,7 @@ std::optional Rugnux::RefinedPasses(RugnuxObserver *observer, Pro base_prefix); speculate_geometry_probe_ = true; // a walk that follows starts with an indexing probe rerun_if_starved_ = true; + const DiffractionExperiment before_pass2 = experiment_; auto pass2 = RunPipeline(observer, /*write_output=*/true, /*geometry_prepass=*/false); if (lattice_arm_check_) { // The metric-symmetry check above, decided inside the pass just run (the promoted arm). @@ -970,8 +972,10 @@ std::optional Rugnux::RefinedPasses(RugnuxObserver *observer, Pro length_arm ? "axes" : "an angle", length_arm ? 100.0 * split : split * 180.0 / PI, length_arm ? "% apart" : "deg from 90", demoted_class, realised_demoted, realised_promoted); - // The promoted arm stopped before its merge; the demoted class is the canonical pass. + // The promoted arm stopped before its merge; the demoted class is the canonical pass, and + // it starts where the promoted one did, not from the spot budget that one measured. ++arm_passes; + experiment_ = before_pass2; IndexingSettings demoted_settings = experiment_.GetIndexingSettings(); demoted_settings.LatticeClassDemoted(length_arm); experiment_.ImportIndexingSettings(demoted_settings);