--prepass-fraction: the geometry pre-pass image loop on the first part of the sweep only

The two-pass rotation pipeline's first image loop (the geometry pre-pass whose reflections
feed post-refinement) stops after the given fraction of the sweep; pass 2 still integrates
every frame and is the only one written. Default 1 (unchanged).

On the 25 sets ranked by the post-refinement held-out gain, --prepass-fraction 0.5 vs rc174
(REFMAC check): 0 verdict changes, d_min change median 0.000, R-free worse by >0.005 on 1/17;
image-loop seconds -17%, myob wall 11.9 -> 10.5 s. Without post-refinement at all
(--rotation-no-postrefine) the same sets had 5 verdict changes and 11/17 R-free worse.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-10-07 06:30:20 +02:00
1 parent 9b9c5118c5
commit 801faa797c
3 files changed
+14 -1

No files matched your search

+4 -1
View File
@@ -6231,11 +6231,14 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
AzimuthalIntegrationProfile profile(mapping);
HarmonicEvidence worker_harmonic;
std::vector<FootprintOffset> worker_offsets;
const int loop_end = geometry_prepass
? start_image + static_cast<int>(std::lround((end_image - start_image) * config_.prepass_fraction))
: end_image;
while (!cancelled_) {
const int ordinal = next_ordinal.fetch_add(1);
const int image_idx = start_image + ordinal * config_.stride;
if (image_idx >= end_image) break;
if (image_idx >= loop_end) break;
// Reuse the raw image frame to frame - a fresh 4-byte 16 Mpx frame is 72 MB of
// untouched pages the decoder faults in one by one - except while the writer thread
+2
View File
@@ -100,6 +100,8 @@ struct ProcessConfig {
bool rotation_indexing = false;
bool two_pass_rotation = true;
int rotation_indexing_image_count = 100;
// The geometry pre-pass image loop stops after this fraction of the sweep (pass 2 reads all of it).
double prepass_fraction = 1.0;
std::optional<CrystalLattice> forced_rotation_lattice;
// Stills global geometry-refinement two-pass (FullAnalysis, stills only). When set, an extra first
+8
View File
@@ -142,6 +142,7 @@ void print_usage() {
std::cout << " --force-rotation-lattice <vec> Force rotation indexer with external lattice (in Angstrom) : \"a0x,a0y,a0z,a1x,a1y,a1z,a2x,a2y,a2z\" (9 floats, skips first pass)" << std::endl;
std::cout << " --rotation-scale <k> Goniometer rotation scale: the stage turned k times the angle stored in the file (the commanded one). Applied to both passes; overrides the fitted correction" << std::endl;
std::cout << " --rotation-no-postrefine Disable the (default-on) two-pass rotation post-refine (post-refine detector distance/beam + cell/axis, then re-integrate; only the refined pass is written, as the canonical <prefix>_* output)" << std::endl;
std::cout << " --prepass-fraction <f> Run the two-pass rotation geometry pre-pass on only the first fraction f of the sweep (0.05-1, default 1); pass 2 still reads every frame" << std::endl;
std::cout << " -X, --indexing-algorithm <txt> Indexing algorithm (FFBIDX|FFT|FFTW|Auto|None)" << std::endl;
std::cout << " -S, --space-group <num|symbol> Space group number (96) or symbol (P43212) - for indexing and scaling" << std::endl;
std::cout << " -C, --unit-cell <cell> Fix reference unit cell: \"a,b,c,alpha,beta,gamma\"" << std::endl;
@@ -249,6 +250,7 @@ enum {
OPT_FORCE_ROTATION_LATTICE,
OPT_MIN_INDEXED_SPOTS,
OPT_ROTATION_NO_POSTREFINE,
OPT_PREPASS_FRACTION,
OPT_ROTATION_SCALE,
OPT_BACKGROUND_CLIP,
OPT_BACKGROUND_RADIAL,
@@ -380,6 +382,7 @@ static option long_options[] = {
{"polarization", required_argument, nullptr, OPT_POLARIZATION},
{"force-rotation-lattice", required_argument, nullptr, OPT_FORCE_ROTATION_LATTICE},
{"rotation-no-postrefine", no_argument, nullptr, OPT_ROTATION_NO_POSTREFINE},
{"prepass-fraction", required_argument, nullptr, OPT_PREPASS_FRACTION},
{"rotation-scale", required_argument, nullptr, OPT_ROTATION_SCALE},
{"refine-geometry", optional_argument, nullptr, OPT_REFINE_GEOMETRY},
{"detect-beam-stop", optional_argument, nullptr, OPT_DETECT_BEAM_STOP},
@@ -752,6 +755,7 @@ static int RunRugnux(int argc, char **argv) {
bool rotation_postrefine_geometry = true; // default on; --rotation-no-postrefine disables it
std::optional<float> rotation_scale; // --rotation-scale: asserted stage calibration
int rotation_indexing_image_count = 100;
double prepass_fraction = 1.0;
std::optional<float> rotation_indexing_range;
std::optional<int64_t> min_indexed_spots; // --min-indexed-spots: spots on the lattice for a frame to count as indexed
bool run_scaling = true; // merge is on by default; --no-merge turns it off
@@ -894,6 +898,9 @@ static int RunRugnux(int argc, char **argv) {
case OPT_ROTATION_NO_POSTREFINE:
rotation_postrefine_geometry = false;
break;
case OPT_PREPASS_FRACTION:
prepass_fraction = parse_number_arg<double>(optarg, "--prepass-fraction", logger, 0.05, 1.0);
break;
case OPT_ROTATION_SCALE:
rotation_scale = parse_number_arg<float>(optarg, "--rotation-scale", logger, 0.9f, 1.1f);
break;
@@ -2813,6 +2820,7 @@ static int RunRugnux(int argc, char **argv) {
config.measure_spot_budget = !max_spot_count_override.has_value();
config.rotation_scale = rotation_scale;
config.rotation_indexing_image_count = rotation_indexing_image_count;
config.prepass_fraction = prepass_fraction;
config.forced_rotation_lattice = forced_rotation_lattice;
config.refine_geometry = refine_geometry;
config.run_scaling = run_scaling;