rugnux: remove --single-pass-rotation
Rotation data are indexed in two passes, always: the online-like single pass (--single-pass-rotation[=deg]) is gone with its min-angular-range argument, and ProcessConfig::two_pass_rotation, which only that flag ever set false, goes with it and with the conditions that read it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
1 parent
b00e2fbe19
commit
5d24eac3ce
9 files changed
+12
-43
No files matched your search
+2
-3
@@ -242,8 +242,8 @@ The radial profile behind the per-image ice-ring score, and what `--mode azint`
|
||||
|
||||
A dataset with a **rotation goniometer axis** is processed as rotation data (two-pass rotation
|
||||
indexing) by default; a dataset without one is processed as independent stills. `--force-still`
|
||||
overrides the former; the `-R` / `--single-pass-rotation` / `--force-rotation-lattice` flags request
|
||||
rotation explicitly and pick the pass or lattice.
|
||||
overrides the former; the `-R` / `--force-rotation-lattice` flags request rotation explicitly and
|
||||
set the first pass's image count or skip it with a given lattice.
|
||||
|
||||
The FFT search looks for cell axes between 10 Å (`--fft-min-unit-cell`) and a default **longest
|
||||
axis of 500 Å**, which has no flag of its own — a reference cell (`-C`) moves both bounds to cover
|
||||
@@ -270,7 +270,6 @@ For very long axes the direction grid's angular resolution binds well below 500
|
||||
| `-S, --space-group <num\|symbol>` | Space group number (`96`) or Hermann-Mauguin symbol (`P43212`) — for indexing and scaling. On serial stills whose group admits two indexings, it also lets the crystals be put on one from the data ([the indexing ambiguity](RUGNUX_ADVANCED.md#the-indexing-ambiguity)) |
|
||||
| `-r, --geom-refine <txt>` | Geometry refinement: `none` \| `orientation` \| `beam_and_lattice` (default) \| `flex` (try all three per image, keep whichever indexes the most spots; alias `multi`) |
|
||||
| `-R, --two-pass-rotation[=num]` | Two-pass offline rotation indexing (default for goniometer data; optional first-pass image count, default 100) |
|
||||
| `--single-pass-rotation[=num]` | Online-like single-pass rotation indexing (optional min angular range, deg) |
|
||||
| `--force-rotation-lattice <vec>` | Force rotation lattice (9 floats, Å), skipping the first pass |
|
||||
| `--rotation-no-postrefine` | Rotation: disable the default-on two-pass geometry post-refine (see [Rotation data](RUGNUX_TUTORIAL.md#rotation-data)) |
|
||||
| `--prepass-fraction <f>` | Rotation: the two-pass geometry pre-pass integrates the first fraction `f` of the sweep, but at least 120° of it (0.05-1, default **0.5**; `1` integrates the whole sweep twice). The second pass always integrates every frame. The pre-scan and the first-pass indexing sample the same part of the sweep |
|
||||
|
||||
+4
-4
@@ -883,7 +883,7 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
// The run as this pass finds it, for the re-check of a near tie its first pass may decide early.
|
||||
std::shared_ptr<Rugnux> recheck;
|
||||
if (!decide_late_ && !config_.fast_live && config_.mode == ProcessMode::FullAnalysis && config_.rotation_indexing
|
||||
&& config_.two_pass_rotation && !force_rotation_result_.has_value()
|
||||
&& !force_rotation_result_.has_value()
|
||||
&& !config_.forced_rotation_lattice.has_value() && experiment_.IsRotationIndexing())
|
||||
recheck = std::make_shared<Rugnux>(*this);
|
||||
|
||||
@@ -1024,7 +1024,7 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
// that pass found before anything is built for it - the mapping below alone is 0.15 s on a 16M
|
||||
// detector. Nothing between here and the first pass changes what the key reads.
|
||||
if (full && indexing_probe_only_ && !force_rotation_result_.has_value()
|
||||
&& !config_.forced_rotation_lattice.has_value() && config_.rotation_indexing && config_.two_pass_rotation
|
||||
&& !config_.forced_rotation_lattice.has_value() && config_.rotation_indexing
|
||||
&& !config_.verify_first_pass_memo) {
|
||||
const std::vector<double> first_pass_key = FirstPassInputKey();
|
||||
const auto memo = std::find_if(first_pass_memo_.begin(), first_pass_memo_.end(),
|
||||
@@ -1142,7 +1142,7 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
// parallel (the main per-image loop then uses the forced lattice, no FFT). Size the pool to
|
||||
// those two so a rotation run doesn't pay to initialise (cuFFT plan + GPU alloc) indexers it
|
||||
// never uses. Stills fire the FFT once per image across all workers, so keep the default there.
|
||||
if (config_.rotation_indexing && config_.two_pass_rotation && experiment_.IsRotationIndexing()) {
|
||||
if (config_.rotation_indexing && experiment_.IsRotationIndexing()) {
|
||||
indexing_settings.IndexingThreads(FirstPassIndexerThreads());
|
||||
// Two indexer threads leave the rest of the machine idle for the whole first pass, which is
|
||||
// a third of the run. Split each scheme's candidate-cell refinement over -N/2 threads so the
|
||||
@@ -1250,7 +1250,7 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
|
||||
} else if (indexing && config_.forced_rotation_lattice.has_value()) {
|
||||
indexer->ForceRotationIndexerLattice(*config_.forced_rotation_lattice);
|
||||
logger.Info("Rotation indexer lattice forced externally - skipping first pass");
|
||||
} else if (indexing && config_.rotation_indexing && config_.two_pass_rotation) {
|
||||
} else if (indexing && config_.rotation_indexing) {
|
||||
TimingMark mark(logger, "first-pass indexing");
|
||||
const bool probe_done = FirstPassRotationIndexing(p);
|
||||
if (recheck && near_tie_carried_)
|
||||
|
||||
@@ -154,7 +154,6 @@ struct ProcessConfig {
|
||||
|
||||
// Rotation indexing (FullAnalysis)
|
||||
bool rotation_indexing = false;
|
||||
bool two_pass_rotation = true;
|
||||
int rotation_indexing_image_count = 100;
|
||||
// The geometry pre-pass integrates this fraction of the sweep, from its start (pass 2 reads all of it).
|
||||
double prepass_fraction = 0.5;
|
||||
|
||||
@@ -192,12 +192,9 @@ std::string RugnuxCommandLine(const ProcessConfig &config,
|
||||
add("--integration-high-resolution", num(*d_min));
|
||||
|
||||
if (config.rotation_indexing) {
|
||||
if (config.two_pass_rotation)
|
||||
// -R takes an optional argument, which getopt only accepts attached (-R100), never as a
|
||||
// separate token - so emit it joined or the copied command line will not re-parse.
|
||||
args.push_back("-R" + std::to_string(config.rotation_indexing_image_count));
|
||||
else
|
||||
args.emplace_back("--single-pass-rotation");
|
||||
// -R takes an optional argument, which getopt only accepts attached (-R100), never as a
|
||||
// separate token - so emit it joined or the copied command line will not re-parse.
|
||||
args.push_back("-R" + std::to_string(config.rotation_indexing_image_count));
|
||||
} else if (experiment.GetGoniometer().has_value()) {
|
||||
// rotation dataset processed as stills -> the user overrode the default with --force-still
|
||||
args.emplace_back("--force-still");
|
||||
|
||||
@@ -48,7 +48,6 @@ RugnuxLiveSetup MakeRugnuxLiveSetup(const JFJochReaderDataset &dataset, int nthr
|
||||
c.export_unmerged = false;
|
||||
c.spot_finding = RugnuxDefaultSpotFinding(true);
|
||||
c.rotation_indexing = true;
|
||||
c.two_pass_rotation = true;
|
||||
c.rotation_postrefine_geometry = true;
|
||||
c.rotation_indexing_image_count = RUGNUX_ROTATION_INDEXING_IMAGES;
|
||||
c.detect_beam_stop = RUGNUX_DETECT_BEAM_STOP_FRAMES;
|
||||
|
||||
+3
-23
@@ -227,7 +227,6 @@ enum {
|
||||
OPT_RESOLUTION_CC_TARGET,
|
||||
OPT_RESOLUTION_SHELLS,
|
||||
OPT_REPORT_RESOLUTION,
|
||||
OPT_SINGLE_PASS_ROTATION,
|
||||
OPT_FORCE_ROTATION_LATTICE,
|
||||
OPT_MIN_INDEXED_SPOTS,
|
||||
OPT_ROTATION_NO_POSTREFINE,
|
||||
@@ -372,7 +371,6 @@ static option long_options[] = {
|
||||
{"geom-refine", required_argument, nullptr, 'r'},
|
||||
|
||||
{"two-pass-rotation", optional_argument, nullptr, 'R'},
|
||||
{"single-pass-rotation", optional_argument, nullptr, OPT_SINGLE_PASS_ROTATION},
|
||||
{"force-still", no_argument, nullptr, OPT_FORCE_STILL},
|
||||
{"azim-q-spacing", required_argument, nullptr, 'q'},
|
||||
{"azim-min-q", required_argument, nullptr, OPT_AZIM_MIN_Q},
|
||||
@@ -885,7 +883,6 @@ struct RugnuxCli {
|
||||
bool calibration_refine_tilt = true; // --no-refine-tilt
|
||||
bool rotation_indexing = false;
|
||||
bool force_still = false; // --force-still: process a rotation dataset as stills (indexing + scaling)
|
||||
bool two_pass_rotation = true;
|
||||
// Set by any spot-finding option. The two-pass rotation first pass reuses the spots stored in the
|
||||
// file when it has them, so those options would otherwise not reach the pass that determines the
|
||||
// lattice - the setting would appear to do nothing at all on rotation data.
|
||||
@@ -893,7 +890,6 @@ struct RugnuxCli {
|
||||
std::optional<float> rotation_scale; // --rotation-scale: asserted stage calibration
|
||||
int rotation_indexing_image_count = RUGNUX_ROTATION_INDEXING_IMAGES;
|
||||
double prepass_fraction = 0.5;
|
||||
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
|
||||
std::optional<bool> scale_fulls_arg; // --scale-fulls / --no-scale-fulls; default on for rot3d
|
||||
@@ -1109,22 +1105,10 @@ int RugnuxCli::Parse(int argc, char **argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
rotation_indexing = true;
|
||||
two_pass_rotation = true;
|
||||
if (optarg)
|
||||
rotation_indexing_image_count = atoi(optarg);
|
||||
|
||||
break;
|
||||
case OPT_SINGLE_PASS_ROTATION:
|
||||
if (rotation_indexing) {
|
||||
logger.Error("Rotation indexing already enabled");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
rotation_indexing = true;
|
||||
two_pass_rotation = false;
|
||||
|
||||
if (optarg)
|
||||
rotation_indexing_range = atof(optarg);
|
||||
break;
|
||||
case OPT_ROTATION_NO_POSTREFINE:
|
||||
rotation_postrefine_geometry = false;
|
||||
break;
|
||||
@@ -3340,13 +3324,13 @@ int RugnuxInputRun::PrepareRugnuxInput() {
|
||||
|
||||
// Rotation vs stills. A dataset collected on a rotation goniometer is processed as rotation data
|
||||
// (two-pass indexing) by default; --force-still forces per-frame stills. The rotation flags
|
||||
// (-R / --single-pass-rotation / --force-rotation-lattice) still request rotation explicitly and
|
||||
// choose the pass/lattice; at this point they show up as rotation_indexing already being set.
|
||||
// (-R / --force-rotation-lattice) still request rotation explicitly and
|
||||
// choose the first-pass size/lattice; at this point they show up as rotation_indexing already being set.
|
||||
// A stationary axis is stills (RugnuxRotationData).
|
||||
const bool has_goniometer = RugnuxRotationData(experiment);
|
||||
if (force_still) {
|
||||
if (rotation_indexing) {
|
||||
logger.Error("--force-still conflicts with -R / --single-pass-rotation / --force-rotation-lattice");
|
||||
logger.Error("--force-still conflicts with -R / --force-rotation-lattice");
|
||||
throw RugnuxInputFailed{EXIT_FAILURE};
|
||||
}
|
||||
if (has_goniometer)
|
||||
@@ -3356,7 +3340,6 @@ int RugnuxInputRun::PrepareRugnuxInput() {
|
||||
experiment.Goniometer(std::nullopt);
|
||||
} else if (!rotation_indexing && has_goniometer) {
|
||||
rotation_indexing = true;
|
||||
two_pass_rotation = true;
|
||||
logger.Info("Dataset has a rotation goniometer axis: processing as rotation data (two-pass "
|
||||
"indexing). Use --force-still to treat it as stills.");
|
||||
}
|
||||
@@ -3391,8 +3374,6 @@ int RugnuxInputRun::PrepareRugnuxInput() {
|
||||
indexing_settings.Algorithm(indexing_algorithm);
|
||||
if (min_indexed_spots) indexing_settings.ViableCellMinSpots(min_indexed_spots.value());
|
||||
indexing_settings.RotationIndexing(rotation_indexing);
|
||||
if (rotation_indexing_range.has_value())
|
||||
indexing_settings.RotationIndexingMinAngularRange_deg(rotation_indexing_range.value());
|
||||
indexing_settings.GeomRefinementAlgorithm(refinement_algorithm);
|
||||
indexing_settings.IndexIceRings(index_ice_rings);
|
||||
if (fft_min_unit_cell_A) indexing_settings.FFT_MinUnitCell_A(fft_min_unit_cell_A.value());
|
||||
@@ -3641,7 +3622,6 @@ int RugnuxInputRun::PrepareRugnuxInput() {
|
||||
config.nthreads_auto = nthreads_auto;
|
||||
config.spot_finding = spot_settings;
|
||||
config.rotation_indexing = rotation_indexing;
|
||||
config.two_pass_rotation = two_pass_rotation;
|
||||
config.detect_beam_stop = detect_beam_stop;
|
||||
config.beam_center_check = beam_center_check;
|
||||
config.detector_distance_given = detector_distance_mm.has_value();
|
||||
|
||||
@@ -69,7 +69,6 @@ TEST_CASE("Rugnux_Rotation", "[large]") {
|
||||
config.spot_finding = DiffractionExperiment::DefaultDataProcessingSettings();
|
||||
config.spot_finding.indexing = true;
|
||||
config.rotation_indexing = true;
|
||||
config.two_pass_rotation = true;
|
||||
|
||||
Rugnux process(reader, experiment, *dataset->pixel_mask, config);
|
||||
ProcessResult result;
|
||||
@@ -114,7 +113,6 @@ TEST_CASE("Rugnux_FirstPassMemoMatchesRecomputation", "[large]") {
|
||||
config.spot_finding = DiffractionExperiment::DefaultDataProcessingSettings();
|
||||
config.spot_finding.indexing = true;
|
||||
config.rotation_indexing = true;
|
||||
config.two_pass_rotation = true;
|
||||
config.rotation_postrefine_geometry = true;
|
||||
config.run_scaling = true;
|
||||
config.verify_first_pass_memo = true;
|
||||
@@ -159,7 +157,6 @@ TEST_CASE("Rugnux_HostBudgetChangesOnlyTheSchedule", "[large]") {
|
||||
config.spot_finding = DiffractionExperiment::DefaultDataProcessingSettings();
|
||||
config.spot_finding.indexing = true;
|
||||
config.rotation_indexing = true;
|
||||
config.two_pass_rotation = true;
|
||||
config.rotation_postrefine_geometry = true;
|
||||
config.run_scaling = true;
|
||||
config.host_memory_budget_bytes = budget;
|
||||
|
||||
@@ -421,7 +421,6 @@ TEST_CASE("RugnuxCommandLine_Full", "[process]") {
|
||||
config.nthreads = 8;
|
||||
config.end_image = 500;
|
||||
config.rotation_indexing = true;
|
||||
config.two_pass_rotation = true;
|
||||
config.rotation_indexing_image_count = 30;
|
||||
config.spot_finding = DiffractionExperiment::DefaultDataProcessingSettings();
|
||||
|
||||
|
||||
@@ -382,7 +382,6 @@ ProcessConfig JFJochProcessingJobsWindow::buildConfig(const JobSpec &spec, const
|
||||
// Rotation indexing follows the panel's rotation axis (= the experiment's indexing
|
||||
// setting); the first pass finds the lattice on as many images as rugnux's.
|
||||
config.rotation_indexing = inputs.experiment.GetIndexingSettings().GetRotationIndexing();
|
||||
config.two_pass_rotation = true;
|
||||
config.rotation_indexing_image_count = RUGNUX_ROTATION_INDEXING_IMAGES;
|
||||
// Measured in the pre-scan on rotation data, unless the panel's radii were changed by hand.
|
||||
config.adaptive_integration_radius = config.rotation_indexing && !radii_set_by_hand(inputs.experiment);
|
||||
|
||||
Reference in new issue
Block a user