viewer: control _process.h5 and merged .mtz/.cif output independently

The 'Save _process.h5' checkbox drove output_prefix, so unchecking it also
suppressed the merged .mtz/.cif, and there was no way to run for the ISa/R-meas
numbers only. Split it into two checkboxes wired to independent flags:
- Save _process.h5  -> ProcessConfig::write_process_h5 (also drives the viewer
  snapshot, so unchecking it means the viewer is not updated with spots/results)
- Write merged .mtz/.cif -> new ProcessConfig::write_merged

output_prefix is set when either is wanted; both off = process for stats only.
Scaling/merge statistics (hence the ISa/R-meas window) are independent of file
writing, so they show in every case. RugnuxCommandLine now emits
--write-process-h5 so a copied command matches the GUI's choice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 09:42:23 +02:00
co-authored by Claude Opus 4.8
parent 343af8deed
commit 9b1ab02c41
5 changed files with 32 additions and 8 deletions
+1 -1
View File
@@ -831,7 +831,7 @@ ProcessResult Rugnux::Run(RugnuxObserver *observer) {
result.merge_statistics = sm.statistics;
result.has_reference = !config_.reference_data.empty();
if (result.consensus_cell && write_files) {
if (result.consensus_cell && write_files && config_.write_merged) {
phase("Writing reflections");
WriteReflections(sm.merged, *result.consensus_cell, experiment_, sm.statistics,
result.error_model_isa > 0 ? fmt::format("{:.2f}", result.error_model_isa) : "?",
+5
View File
@@ -46,6 +46,11 @@ struct ProcessConfig {
// (the .mtz/.cif is the wanted output and the h5 is large) unless --write-process-h5 is given.
bool write_process_h5 = true;
// Write the merged reflections (.mtz/.cif). Defaults true (the CLI always writes them when
// merging); the viewer can turn them off independently of the _process.h5 (e.g. a quick run that
// only wants the ISa/R-meas numbers). Only relevant to FullAnalysis with scaling.
bool write_merged = true;
SpotFindingSettings spot_finding; // FullAnalysis spot finding
// Rotation indexing (FullAnalysis)
+5
View File
@@ -127,6 +127,11 @@ std::string RugnuxCommandLine(const ProcessConfig &config,
args.emplace_back("-A");
if (sc.GetRefineB())
args.emplace_back("-B");
// When merging, the CLI skips the large _process.h5 unless asked; emit the flag when it is
// wanted so a copied command matches the GUI's "Save _process.h5" choice. (write_merged has
// no CLI equivalent - the CLI always writes the .mtz/.cif when merging.)
if (config.write_process_h5)
args.emplace_back("--write-process-h5");
} else {
args.emplace_back("--no-merge");
}
+19 -6
View File
@@ -138,8 +138,15 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec
threads->setRange(1, 256);
threads->setValue(default_threads());
auto *save = new QCheckBox("Save _process.h5", &dlg);
save->setChecked(true);
// Two independent outputs: the large per-image _process.h5 (updates the viewer with spots/results)
// and the small merged .mtz/.cif. Either can be turned off; the ISa/R-meas window is shown
// regardless (it needs only the in-memory merge statistics), so a stats-only run turns both off.
auto *save_h5 = new QCheckBox("Save _process.h5 (per-image results; updates viewer)", &dlg);
save_h5->setChecked(true);
auto *save_merged = new QCheckBox("Write merged .mtz/.cif", &dlg);
save_merged->setChecked(true);
save_merged->setEnabled(!azint); // no merged output in azimuthal-integration mode
// Default the output next to the input file, not the viewer's working directory (the viewer starts
// wherever it was installed). This is an absolute path; Rugnux writes it via the trusted setter,
@@ -160,7 +167,8 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec
form->addRow("Start image", start_image);
form->addRow("End image", end_image);
form->addRow("Threads", threads);
form->addRow(save);
form->addRow(save_h5);
form->addRow(save_merged);
form->addRow("Output prefix", prefix);
form->addRow(scaling);
@@ -189,7 +197,8 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec
spec.start_image = start_image->value();
spec.end_image = end_image->value();
spec.threads = threads->value();
spec.save = save->isChecked();
spec.save_h5 = save_h5->isChecked();
spec.save_merged = save_merged->isEnabled() && save_merged->isChecked();
spec.prefix = prefix->text();
spec.scaling = scaling->isEnabled() && scaling->isChecked();
}
@@ -202,7 +211,11 @@ ProcessConfig JFJochProcessingJobsWindow::buildConfig(const JobSpec &spec, const
config.nthreads = spec.threads;
config.start_image = spec.start_image;
config.end_image = spec.end_image > 0 ? spec.end_image : -1; // 0 => to the end
config.output_prefix = spec.save ? spec.prefix.toStdString() : std::string();
// Files land at output_prefix; leave it empty (write nothing, stats only) when neither output is
// wanted. The two flags then select which files are actually written there.
config.output_prefix = (spec.save_h5 || spec.save_merged) ? spec.prefix.toStdString() : std::string();
config.write_process_h5 = spec.save_h5;
config.write_merged = spec.save_merged;
config.spot_finding = inputs.spot_finding;
if (spec.mode == ProcessMode::FullAnalysis) {
// Rotation indexing follows the panel's "Process as stills" (= the experiment's indexing
@@ -256,7 +269,7 @@ void JFJochProcessingJobsWindow::newJob(bool azint) {
JobInfo info;
info.id = id;
info.label = label;
if (spec.save)
if (spec.save_h5)
info.snapshot_path = QString::fromStdString(config.output_prefix) + "_process.h5";
const int row = table_->rowCount();
+2 -1
View File
@@ -71,7 +71,8 @@ private:
int start_image = 0;
int end_image = 0; // 0 == to the end
int threads = 4;
bool save = true;
bool save_h5 = true; // write the per-image _process.h5 (also drives the viewer snapshot)
bool save_merged = true; // write the merged .mtz/.cif
QString prefix;
bool rotation = false;
int rotation_images = 30; // images used to find the rotation lattice (first pass)