From 5d1ddccee8615b1184ba42278b3dcd59f1211625 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 15 Jul 2026 11:28:09 +0200 Subject: [PATCH] viewer: expose stills processing settings; rename geom refinement multi -> flex Wire the recently-added stills knobs into jfjoch_viewer - they were reachable only from the rugnux CLI, and the viewer had silently diverged from the CLI once --refine-geometry became default-on for stills-with-cell. - Stills geometry-refinement two-pass (--refine-geometry): a checkbox + frame count in the reprocessing-job dialog, offered (and defaulted on, matching the CLI) only for a stills-with-cell run; wired into ProcessConfig and the "Copy command" generator (joined =N, or =off to reproduce opting out of the CLI default-on). - Stills partiality (--still-partiality) checkbox in Bragg integration and the partiality-uncertainty merge term (--partiality-uncertainty) in Scaling, both mirrored in the command-line generator. Rename the "best per-image refinement" mode from "multi" to "flex" everywhere: GeomRefinementAlgorithmEnum::Flex, CLI -r flex (with "multi" kept as a hidden back-compat alias), OpenAPI enum "Flex" + regenerated C++/TS clients, viewer combo, frontend dropdown, and the stored HDF5 string. "multi" collides with CrystFEL's multi-lattice sense; "flex" = let the pipeline decide. The API now carries a dedicated Flex value instead of masquerading as BeamCenter. Also fix a pre-existing bug in Convert(IndexingSettings): OrientationOnly was missing from the outbound switch and serialized as an invalid API value. Co-Authored-By: Claude Opus 4.8 (1M context) --- broker/OpenAPIConvert.cpp | 11 ++++-- .../gen/model/Geom_refinement_algorithm.cpp | 6 ++++ broker/gen/model/Geom_refinement_algorithm.h | 5 +-- broker/jfjoch_api.yaml | 2 ++ common/IndexingSettings.h | 4 ++- frontend/src/client/types.gen.ts | 11 +++--- frontend/src/client/zod.gen.ts | 6 ++-- frontend/src/components/IndexingSettings.tsx | 1 + image_analysis/IndexAndRefine.cpp | 2 +- rugnux/RugnuxCommandLine.cpp | 16 ++++++++- rugnux/rugnux_cli.cpp | 6 ++-- viewer/widgets/JFJochViewerSettingsDock.cpp | 32 +++++++++++++++++ viewer/windows/JFJochProcessingJobsWindow.cpp | 35 +++++++++++++++++++ viewer/windows/JFJochProcessingJobsWindow.h | 2 ++ writer/HDF5NXmx.cpp | 4 +-- 15 files changed, 124 insertions(+), 19 deletions(-) diff --git a/broker/OpenAPIConvert.cpp b/broker/OpenAPIConvert.cpp index 3c3ebc8d..626fd716 100644 --- a/broker/OpenAPIConvert.cpp +++ b/broker/OpenAPIConvert.cpp @@ -972,6 +972,9 @@ IndexingSettings Convert(const org::openapitools::server::model::Indexing_settin case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY: ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::OrientationOnly); break; + case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX: + ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::Flex); + break; case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE: ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::None); break; @@ -1018,9 +1021,11 @@ org::openapitools::server::model::Indexing_settings Convert(const IndexingSettin case GeomRefinementAlgorithmEnum::BeamCenter: refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER); break; - case GeomRefinementAlgorithmEnum::Multi: - // No dedicated API value (offline rugnux only); report it as beam+lattice. - refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER); + case GeomRefinementAlgorithmEnum::OrientationOnly: + refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY); + break; + case GeomRefinementAlgorithmEnum::Flex: + refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX); break; } diff --git a/broker/gen/model/Geom_refinement_algorithm.cpp b/broker/gen/model/Geom_refinement_algorithm.cpp index 89f1be67..0cd003a5 100644 --- a/broker/gen/model/Geom_refinement_algorithm.cpp +++ b/broker/gen/model/Geom_refinement_algorithm.cpp @@ -81,6 +81,9 @@ void to_json(nlohmann::json& j, const Geom_refinement_algorithm& o) case Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY: j = "OrientationOnly"; break; + case Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX: + j = "Flex"; + break; case Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE: j = "None"; break; @@ -97,6 +100,9 @@ void from_json(const nlohmann::json& j, Geom_refinement_algorithm& o) else if (s == "OrientationOnly") { o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY); } + else if (s == "Flex") { + o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX); + } else if (s == "None") { o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE); } else { diff --git a/broker/gen/model/Geom_refinement_algorithm.h b/broker/gen/model/Geom_refinement_algorithm.h index 5bb8a42f..0182dfc1 100644 --- a/broker/gen/model/Geom_refinement_algorithm.h +++ b/broker/gen/model/Geom_refinement_algorithm.h @@ -12,7 +12,7 @@ /* * Geom_refinement_algorithm.h * - * Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. + * Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). */ #ifndef Geom_refinement_algorithm_H_ @@ -25,7 +25,7 @@ namespace org::openapitools::server::model { /// -/// Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. +/// Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). /// class Geom_refinement_algorithm { @@ -40,6 +40,7 @@ public: INVALID_VALUE_OPENAPI_GENERATED = 0, BEAMCENTER, ORIENTATIONONLY, + FLEX, NONE }; diff --git a/broker/jfjoch_api.yaml b/broker/jfjoch_api.yaml index e3d2a7f4..c2d2a7ed 100644 --- a/broker/jfjoch_api.yaml +++ b/broker/jfjoch_api.yaml @@ -343,9 +343,11 @@ components: Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. + Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). enum: - "BeamCenter" - "OrientationOnly" + - "Flex" - "None" integration_model: type: string diff --git a/common/IndexingSettings.h b/common/IndexingSettings.h index 7b92297d..258e15ba 100644 --- a/common/IndexingSettings.h +++ b/common/IndexingSettings.h @@ -6,7 +6,9 @@ #include enum class IndexingAlgorithmEnum {FFBIDX, FFT, FFTW, Auto, None}; -enum class GeomRefinementAlgorithmEnum {None, OrientationOnly, BeamCenter, Multi}; +// Flex = "let the pipeline decide": try several per-image refinements and keep whichever indexes the +// most spots (CLI -r flex; the legacy -r multi name is still accepted as an alias). +enum class GeomRefinementAlgorithmEnum {None, OrientationOnly, BeamCenter, Flex}; class IndexingSettings { IndexingAlgorithmEnum algorithm; diff --git a/frontend/src/client/types.gen.ts b/frontend/src/client/types.gen.ts index d69b6dc3..eba0e361 100644 --- a/frontend/src/client/types.gen.ts +++ b/frontend/src/client/types.gen.ts @@ -99,11 +99,13 @@ export type indexing_algorithm = typeof indexing_algorithm[keyof typeof indexing * Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. * BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). * OrientationOnly - This option is refining only orientation of the lattice. + * Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). * */ export const geom_refinement_algorithm = { BEAM_CENTER: 'BeamCenter', ORIENTATION_ONLY: 'OrientationOnly', + FLEX: 'Flex', NONE: 'None' } as const; @@ -111,6 +113,7 @@ export const geom_refinement_algorithm = { * Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. * BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). * OrientationOnly - This option is refining only orientation of the lattice. + * Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). * */ export type geom_refinement_algorithm = typeof geom_refinement_algorithm[keyof typeof geom_refinement_algorithm]; @@ -411,8 +414,8 @@ export type unit_cell = { * NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia * NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling * NXmxIntegrated - single HDF5 per dataset - * CBF - CBF format (limited metadata) - * TIFF - TIFF format (no metadata) + * CBF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. + * TIFF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. * */ export const file_writer_format = { @@ -431,8 +434,8 @@ export const file_writer_format = { * NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia * NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling * NXmxIntegrated - single HDF5 per dataset - * CBF - CBF format (limited metadata) - * TIFF - TIFF format (no metadata) + * CBF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. + * TIFF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. * */ export type file_writer_format = typeof file_writer_format[keyof typeof file_writer_format]; diff --git a/frontend/src/client/zod.gen.ts b/frontend/src/client/zod.gen.ts index 80c7afb3..e74daad1 100644 --- a/frontend/src/client/zod.gen.ts +++ b/frontend/src/client/zod.gen.ts @@ -49,11 +49,13 @@ export const zIndexingAlgorithm = z.enum([ * Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. * BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). * OrientationOnly - This option is refining only orientation of the lattice. + * Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode). * */ export const zGeomRefinementAlgorithm = z.enum([ 'BeamCenter', 'OrientationOnly', + 'Flex', 'None' ]); @@ -178,8 +180,8 @@ export const zDatasetSettings = z.object({ * NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia * NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling * NXmxIntegrated - single HDF5 per dataset - * CBF - CBF format (limited metadata) - * TIFF - TIFF format (no metadata) + * CBF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. + * TIFF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. * */ export const zFileWriterFormat = z.enum([ diff --git a/frontend/src/components/IndexingSettings.tsx b/frontend/src/components/IndexingSettings.tsx index cc8e45cb..93dbbb84 100644 --- a/frontend/src/components/IndexingSettings.tsx +++ b/frontend/src/components/IndexingSettings.tsx @@ -155,6 +155,7 @@ function IndexingSettings({s: serverS, status}: MyProps) { No refinement Lattice orientation Beam center, lattice orientation and dimensions + Flex (best per-image refinement) 0.0) + add("--partiality-uncertainty", num(sc.GetPartialityUncertaintyCoeff())); // 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.) diff --git a/rugnux/rugnux_cli.cpp b/rugnux/rugnux_cli.cpp index 6ce8e0de..80281da0 100644 --- a/rugnux/rugnux_cli.cpp +++ b/rugnux/rugnux_cli.cpp @@ -75,7 +75,7 @@ void print_usage() { std::cout << " -X, --indexing-algorithm Indexing algorithm (FFBIDX|FFT|FFTW|Auto|None)" << std::endl; std::cout << " -S, --space-group Space group number - used for both indexing and scaling" << std::endl; std::cout << " -C, --unit-cell Fix reference unit cell: \"a,b,c,alpha,beta,gamma\"" << std::endl; - std::cout << " -r, --refine Geometry refinement algorithm (none|orientation|beam_and_lattice|multi); multi tries all three per image and keeps whichever indexes the most spots" << std::endl; + std::cout << " -r, --refine Geometry refinement algorithm (none|orientation|beam_and_lattice|flex); flex tries all three per image and keeps whichever indexes the most spots (alias: multi)" << std::endl; std::cout << " --refine-geometry[=N|off] Stills: extra first pass that bundle-adjusts the shared beam/distance/cell from N strongly-indexed frames (default: 200) then re-indexes (lifts weak-stills indexing). Default ON for stills when a reference cell is given (-C / reference MTZ); =off disables" << std::endl; std::cout << std::endl; @@ -627,8 +627,8 @@ int main(int argc, char **argv) { refinement_algorithm = GeomRefinementAlgorithmEnum::BeamCenter; else if (alg == "orientation") refinement_algorithm = GeomRefinementAlgorithmEnum::OrientationOnly; - else if (alg == "multi") - refinement_algorithm = GeomRefinementAlgorithmEnum::Multi; + else if (alg == "flex" || alg == "multi") // "multi" kept as a back-compat alias + refinement_algorithm = GeomRefinementAlgorithmEnum::Flex; else { logger.Error("Invalid geom refinement algorithm: {}", alg); print_usage(); diff --git a/viewer/widgets/JFJochViewerSettingsDock.cpp b/viewer/widgets/JFJochViewerSettingsDock.cpp index 5711f7c6..70dd8d8f 100644 --- a/viewer/widgets/JFJochViewerSettingsDock.cpp +++ b/viewer/widgets/JFJochViewerSettingsDock.cpp @@ -265,6 +265,10 @@ QWidget *JFJochViewerSettingsDock::BuildMXPage() { refine->addItem("None", static_cast(GeomRefinementAlgorithmEnum::None)); refine->addItem("Orientation only", static_cast(GeomRefinementAlgorithmEnum::OrientationOnly)); refine->addItem("Beam center + lattice", static_cast(GeomRefinementAlgorithmEnum::BeamCenter)); + // "Flex" (the CLI's -r flex): tries all per-image refinements and keeps whichever indexes the most + // spots — lets the pipeline decide. Named "Flex", not "multi", to avoid the CrystFEL sense of multi + // (multi-lattice integration). + refine->addItem("Flex (best per-image refinement)", static_cast(GeomRefinementAlgorithmEnum::Flex)); refine->setCurrentIndex(refine->findData(static_cast(indexing_.GetGeomRefinementAlgorithm()))); // One high-level mode switch instead of separate partiality / rot3d / rotation-indexing options: // for a rotation dataset, unchecked = the rotation good-path (rotation indexing + Rotation @@ -442,8 +446,14 @@ QWidget *JFJochViewerSettingsDock::BuildBraggSection() { auto *r3 = new NumberLineEdit(1.0f, 30.0f, bragg_.GetR3(), 1, "px", this); auto *radii = new QHBoxLayout(); radii->addWidget(r1); radii->addWidget(r2); radii->addWidget(r3); + auto *stillPartiality = new QCheckBox("Stills partiality (experimental)", this); + stillPartiality->setChecked(bragg_.GetStillPartiality()); + stillPartiality->setToolTip("Experimental, stills only: weight each reflection by a Gaussian " + "excitation-error partiality exp(-d_ewald²/2σ²) instead of treating it as a " + "full. Pairs with \"Partiality uncertainty\" in Scaling."); form->addRow("", gaussian); form->addRow("Radii r1/r2/r3", radii); + form->addRow("", stillPartiality); section->setContentLayout(form); section->setExpanded(false); // folded on start (only geometry + unit cell start open) @@ -451,9 +461,11 @@ QWidget *JFJochViewerSettingsDock::BuildBraggSection() { bragg_.Integrator(gaussian->isChecked() ? IntegratorMode::ProfileGaussian : IntegratorMode::BoxSum); bragg_.R1(static_cast(r1->value())).R2(static_cast(r2->value())) .R3(static_cast(r3->value())); + bragg_.StillPartiality(stillPartiality->isChecked()); emit braggChanged(bragg_); }; connect(gaussian, &QCheckBox::toggled, this, [emitBragg] { emitBragg(); }); + connect(stillPartiality, &QCheckBox::toggled, this, [emitBragg] { emitBragg(); }); for (auto *f : {r1, r2, r3}) connect(f, &NumberLineEdit::newValue, this, [emitBragg] { emitBragg(); }); return section; @@ -480,6 +492,18 @@ QWidget *JFJochViewerSettingsDock::BuildScalingSection() { auto *highRes = new NumberLineEdit(0.3f, 5.0f, scaling_.GetHighResolutionLimit_A().value_or(2.0), 1, "Å", this); highRes->setEnabled(limitRes->isChecked()); + // Stills partiality-uncertainty merge term: adds a systematic sigma ~c*(1-partiality)* on partials, + // so strong low-partiality partials are not over-trusted. Pairs with "Stills partiality" (Bragg); the + // library auto-gates it to strong/medium data. 0 = off; ~2.5 recommended. + const double part_unc = scaling_.GetPartialityUncertaintyCoeff(); + auto *partUncertain = new QCheckBox("Partiality uncertainty", this); + partUncertain->setChecked(part_unc > 0.0); + partUncertain->setToolTip("Stills: add a systematic merge σ ~c·(1−partiality)·⟨I⟩ to partials so strong " + "low-partiality partials are not over-trusted. Use with \"Stills partiality\"; " + "auto-gated to strong/medium data. ~2.5 recommended; unchecked = off."); + auto *partUncertainCoeff = new NumberLineEdit(0.1f, 10.0f, part_unc > 0.0 ? part_unc : 2.5, 1, "", this); + partUncertainCoeff->setEnabled(partUncertain->isChecked()); + form->addRow("", friedel); form->addRow("", refineB); form->addRow("", corrections); @@ -489,6 +513,10 @@ QWidget *JFJochViewerSettingsDock::BuildScalingSection() { resRow->addWidget(limitRes); resRow->addWidget(highRes, 1); form->addRow("", resRow); + auto *puRow = new QHBoxLayout(); + puRow->addWidget(partUncertain); + puRow->addWidget(partUncertainCoeff, 1); + form->addRow("", puRow); section->setContentLayout(form); section->setExpanded(false); // folded on start (only geometry + unit cell start open) @@ -498,6 +526,7 @@ QWidget *JFJochViewerSettingsDock::BuildScalingSection() { scaling_.CorrectionSurfaces(corrections->isChecked()); scaling_.HighResolutionLimit_A(limitRes->isChecked() ? std::optional(highRes->value()) : std::nullopt); + scaling_.PartialityUncertaintyCoeff(partUncertain->isChecked() ? partUncertainCoeff->value() : 0.0); emit scalingChanged(scaling_); }; connect(friedel, &QCheckBox::toggled, this, [emitScaling] { emitScaling(); }); @@ -506,6 +535,9 @@ QWidget *JFJochViewerSettingsDock::BuildScalingSection() { connect(limitRes, &QCheckBox::toggled, this, [emitScaling, highRes](bool on) { highRes->setEnabled(on); emitScaling(); }); connect(highRes, &NumberLineEdit::newValue, this, [emitScaling] { emitScaling(); }); + connect(partUncertain, &QCheckBox::toggled, this, [emitScaling, partUncertainCoeff](bool on) { + partUncertainCoeff->setEnabled(on); emitScaling(); }); + connect(partUncertainCoeff, &NumberLineEdit::newValue, this, [emitScaling] { emitScaling(); }); return section; } diff --git a/viewer/windows/JFJochProcessingJobsWindow.cpp b/viewer/windows/JFJochProcessingJobsWindow.cpp index 375809a2..073a17d2 100644 --- a/viewer/windows/JFJochProcessingJobsWindow.cpp +++ b/viewer/windows/JFJochProcessingJobsWindow.cpp @@ -182,6 +182,34 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec scaling->setChecked(true); scaling->setEnabled(!azint); + // Stills geometry-refinement two-pass: an extra first pass bundle-adjusts the shared beam/distance/ + // cell from the strongest indexed frames, then the main pass re-indexes with it. It is stills-only + // and anchors on a known cell, so offer it only for a stills-with-cell run; default it on there, to + // match the rugnux CLI (a no-op for rotation / de-novo stills). Stills mode = rotation indexing off. + const bool stills_with_cell = !azint + && !inputs.experiment.GetIndexingSettings().GetRotationIndexing() + && inputs.experiment.GetUnitCell().has_value(); + auto *refine_geometry = new QCheckBox("Refine geometry (stills)", &dlg); + refine_geometry->setChecked(stills_with_cell); + refine_geometry->setEnabled(stills_with_cell); + refine_geometry->setToolTip( + "Stills only: an extra first pass bundle-adjusts the shared beam / detector distance / cell from " + "the strongest indexed frames, then re-indexes every frame with it (lifts weak/sparse-stills " + "indexing). Needs a known unit cell; a no-op for rotation data."); + auto *refine_frames = new QSpinBox(&dlg); + refine_frames->setRange(10, 100000); + refine_frames->setValue(200); + refine_frames->setEnabled(stills_with_cell); + refine_frames->setToolTip("Number of strongly-indexed frames fed to the joint bundle adjustment."); + connect(refine_geometry, &QCheckBox::toggled, refine_frames, &QWidget::setEnabled); + auto *refineRow = new QWidget(&dlg); + auto *refineRowLayout = new QHBoxLayout(refineRow); + refineRowLayout->setContentsMargins(0, 0, 0, 0); + refineRowLayout->addWidget(refine_geometry); + refineRowLayout->addWidget(new QLabel("frames:", &dlg)); + refineRowLayout->addWidget(refine_frames); + refineRowLayout->addStretch(); + auto *form = new QFormLayout; form->addRow("Start image", start_image); form->addRow("End image", end_image); @@ -190,6 +218,7 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec form->addRow(save_merged); form->addRow("Output prefix", prefixRow); form->addRow(scaling); + form->addRow(refineRow); int result = 0; auto *run = new QPushButton("Run locally", &dlg); @@ -220,6 +249,8 @@ int JFJochProcessingJobsWindow::askJob(const ReprocessingInputs &inputs, JobSpec spec.save_merged = save_merged->isEnabled() && save_merged->isChecked(); spec.prefix = prefix->text(); spec.scaling = scaling->isEnabled() && scaling->isChecked(); + spec.refine_geometry = refine_geometry->isEnabled() && refine_geometry->isChecked(); + spec.refine_geometry_frames = refine_frames->value(); } return result; } @@ -245,6 +276,10 @@ ProcessConfig JFJochProcessingJobsWindow::buildConfig(const JobSpec &spec, const config.rotation_indexing_image_count = 60; config.run_scaling = spec.scaling; config.reference_data = inputs.reference_data; // enables CCref / reference-based scaling + // Stills geometry-refinement two-pass. The dialog only offers it for a stills-with-cell run + // (Rugnux no-ops it otherwise), so honour it whenever set; unset leaves the pass off. + if (spec.refine_geometry) + config.refine_geometry = spec.refine_geometry_frames; } return config; } diff --git a/viewer/windows/JFJochProcessingJobsWindow.h b/viewer/windows/JFJochProcessingJobsWindow.h index 8554a981..1fe5cf5e 100644 --- a/viewer/windows/JFJochProcessingJobsWindow.h +++ b/viewer/windows/JFJochProcessingJobsWindow.h @@ -81,6 +81,8 @@ private: bool rotation = false; int rotation_images = 30; // images used to find the rotation lattice (first pass) bool scaling = false; + bool refine_geometry = false; // stills-only global geometry bundle-adjust (needs a known cell) + int refine_geometry_frames = 200; // strong indexed frames fed to that bundle adjustment }; // Returns 0 = cancel, 1 = run locally, 2 = copy command line; fills spec from the dialog. diff --git a/writer/HDF5NXmx.cpp b/writer/HDF5NXmx.cpp index 44ecfeea..c631f167 100644 --- a/writer/HDF5NXmx.cpp +++ b/writer/HDF5NXmx.cpp @@ -455,8 +455,8 @@ void NXmx::MX(const StartMessage &start) { case GeomRefinementAlgorithmEnum::BeamCenter: hdf5_file->SaveScalar("/entry/MX/geom_refinement_algorithm", "beam_center"); break; - case GeomRefinementAlgorithmEnum::Multi: - hdf5_file->SaveScalar("/entry/MX/geom_refinement_algorithm", "multi"); + case GeomRefinementAlgorithmEnum::Flex: + hdf5_file->SaveScalar("/entry/MX/geom_refinement_algorithm", "flex"); break; default: break;