None of this has a reader:
- ScalingSettings::scaling_regularize and its setter/getter
- ScaleOnTheFlyResult::succesful (never set) and ::time_s (set, never read),
with the timing that only fed the latter
- JFJochImage::last_fit_viewport_ (written twice, read nowhere) and the
comment claiming the retry uses it - the retry keys off initial_fit_done_
- JFJochDiffractionImage::ice_ring_width_Q_recipA, and a QtConcurrent include
in a file that uses none
- an unused gemmi::Op accumulator in the spindle-angle helper
- <random> in Merge.{h,cpp}, from before the half-set split became a hash
- an orphaned comment describing the Ceres B-factor residual deleted in
014e43a4c, and two trailing comments that had collided on one line
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
149 lines
8.3 KiB
C++
149 lines
8.3 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <optional>
|
|
#include "JFJochException.h"
|
|
|
|
// How the high-resolution cutoff for the written reflections and the reported shell table is chosen
|
|
// when no explicit --scaling-high-resolution is given. Off = keep the full (detector-edge) range;
|
|
// CCHalfLogistic = fit the CC1/2 fall-off and cut one shell past cc_target (DIALS-style, generous).
|
|
enum class ResolutionCutoffMethod { Off, CCHalfLogistic };
|
|
|
|
class ScalingSettings {
|
|
bool refine_wedge = false;
|
|
|
|
bool merge_friedel = true;
|
|
std::optional<double> high_resolution_limit_A;
|
|
std::optional<double> wedge_for_scaling;
|
|
std::optional<double> forced_mosaicity; // diagnostic: fix the scaling mosaicity (deg) instead of the per-image seed
|
|
double min_partiality = 0.02;
|
|
// Capture-aware systematic uncertainty for the rot3d combine: a full reconstructed from only
|
|
// a fraction f<1 of its rocking curve is extrapolated, and the unobserved (1-f) carries a
|
|
// systematic error ~coeff*(1-f)*I that plain counting sigma misses. 0 = off (baseline).
|
|
double capture_uncertainty_coeff = 0.0;
|
|
// Full-level captured-fraction floor for the rot3d combine: drop a reconstructed full whose rocking
|
|
// curve was only fractionally captured (sum of its partials' partiality < this). Distinct from
|
|
// min_partiality, which gates individual partials; this gates the assembled full. 0 = off (baseline).
|
|
double min_captured_fraction = 0.0;
|
|
double min_cc_for_image = 0.0;
|
|
|
|
// Exclude observations whose Lorentz geometry |zeta| falls below this from the DE-NOVO space-group
|
|
// search merge only (see RotationScaleMerge::search_min_zeta). 0 = off.
|
|
double search_min_zeta = 0.0;
|
|
double outlier_reject_nsigma = 0.0; // per-observation merge outlier rejection (XDS/DIALS-style); 0 = off, e.g. 6 enables
|
|
|
|
// Scale fulls: after the rotation 3D combine, refit a per-frame scale on the combined fulls (XDS
|
|
// order). Only used by the rotation path (RotationScaleMerge).
|
|
bool scale_fulls = false;
|
|
|
|
// Correction surfaces fitted on the rot3d fulls after scale-fulls: a decay (per-run Debye-Waller B)
|
|
// and an absorption surface (over the diffracted-beam direction in the goniometer frame). Both are
|
|
// cross-validated, so they no-op when their systematic is absent - hence ON by default (they only ever
|
|
// help or do nothing). No-op without rot3d. Set false to disable both.
|
|
bool correction_surfaces = true;
|
|
// Absorption-surface refinement iteration count (used when correction_surfaces is on).
|
|
int absorption_iter = 3;
|
|
|
|
// Physical partiality post-refinement for the STILLS merge (StillsPartialityRefine): refine a per-crystal
|
|
// orientation tilt against the running merge, recompute each reflection's partiality from the refined
|
|
// geometry (angular Ewald-proximity model), and re-scale/merge - the "full model" for stills. ON by
|
|
// default (helps mono stills, neutral on pink beam, tames weak data via a soft prior). rugnux
|
|
// --simple-stills turns it OFF, reverting to treating every reflection as a full (p = 1, single pass).
|
|
bool stills_partiality_refine = true;
|
|
|
|
// Expected-variance merge weighting for the STILLS merge (MergeOnTheFly). When combining a reflection's
|
|
// redundant observations by inverse variance, rebuild the Poisson signal part of each observation's
|
|
// variance at the reflection's EXPECTED <I> instead of the observation's own intensity. Weighting by an
|
|
// observation's own sigma^2 biases the inverse-variance mean low at <1 photon (an up-fluctuated
|
|
// observation gets a larger sigma and is over-downweighted). Default on - it mirrors the rotation combine
|
|
// (RotationScaleMerge::process_rawrun), which already does this, and is R-free-neutral on strong data and
|
|
// better on weak. --no-expected-variance-merge restores the old observed-sigma weighting.
|
|
bool expected_variance_merge = true;
|
|
|
|
// Smooth the per-frame scale G across frames (centered moving average of log G) before the rot3d
|
|
// combine, so a rocking event's partials share a consistent scale. Given as a ROTATION RANGE in
|
|
// degrees (like XDS DELPHI), converted to an odd frame window from the oscillation step; this keeps
|
|
// the smoothing physical (independent of frame slicing). 0 = off. A no-op without rot3d.
|
|
double smooth_g_deg = 0.0;
|
|
|
|
// Per-batch relative-B on the rot3d fulls (beyond the single global decay slope): bin frames into
|
|
// rotation-range batches of this width in degrees and refine one relative Debye-Waller B per batch, so
|
|
// NON-monotonic changes in scattering power across the run (absorption path, crystal slippage, dose
|
|
// bursts) are corrected the resolution-flat per-frame G and the single decay slope both miss. Cross-
|
|
// validated + zero-mean-anchored, so a no-op when absent. 0 = off. A no-op without rot3d.
|
|
double relative_b_deg = 0.0;
|
|
|
|
double rfree_fraction = 0.05;
|
|
|
|
// Automatic high-resolution cutoff for the written reflections + reported shells (not the scaling
|
|
// or the error model, and not the per-image _process.h5). Applied only when no explicit
|
|
// high_resolution_limit_A is set - that manual limit always wins and disables the auto-cut.
|
|
ResolutionCutoffMethod resolution_cutoff = ResolutionCutoffMethod::CCHalfLogistic;
|
|
double resolution_cc_target = 0.30; // CC1/2 value defining the fall-off limit before the +1 shell
|
|
int report_shell_count = 10; // number of resolution shells in the reported statistics table
|
|
|
|
public:
|
|
ScalingSettings& RefineRotationWedge(bool input);
|
|
ScalingSettings& RotationWedgeForScaling(std::optional<double> input);
|
|
ScalingSettings& MergeFriedel(bool input);
|
|
ScalingSettings& HighResolutionLimit_A(double limit);
|
|
ScalingSettings& HighResolutionLimit_A(std::optional<double> limit); // nullopt clears the limit
|
|
ScalingSettings& MinPartiality(double min_partiality);
|
|
ScalingSettings& ForcedMosaicity(std::optional<double> input);
|
|
ScalingSettings& CaptureUncertaintyCoeff(double input);
|
|
ScalingSettings& MinCapturedFraction(double input);
|
|
ScalingSettings& MinCCForImage(double min_cc_for_image);
|
|
ScalingSettings& SearchMinZeta(double search_min_zeta);
|
|
ScalingSettings& OutlierRejectNsigma(double input);
|
|
ScalingSettings& ScaleFulls(bool input);
|
|
ScalingSettings& AbsorptionIter(int input);
|
|
ScalingSettings& CorrectionSurfaces(bool input);
|
|
ScalingSettings& StillsPartialityRefine(bool input);
|
|
ScalingSettings& ExpectedVarianceMerge(bool input);
|
|
ScalingSettings& SmoothGDegrees(double input);
|
|
ScalingSettings& RelativeBDegrees(double input);
|
|
|
|
ScalingSettings& RfreeFraction(double input);
|
|
|
|
ScalingSettings& ResolutionCutoff(ResolutionCutoffMethod input);
|
|
ScalingSettings& ResolutionCCTarget(double input);
|
|
ScalingSettings& ReportShellCount(int input);
|
|
|
|
[[nodiscard]] bool GetRefineWedge() const;
|
|
|
|
[[nodiscard]] double GetMinMosaicity() const;
|
|
[[nodiscard]] double GetDefaultMosaicity() const;
|
|
[[nodiscard]] double GetMaxMosaicity() const;
|
|
|
|
[[nodiscard]] double GetMinWedge() const;
|
|
[[nodiscard]] std::optional<double> GetRotationWedgeForScaling() const;
|
|
[[nodiscard]] double GetMaxWedge() const;
|
|
|
|
[[nodiscard]] bool GetMergeFriedel() const;
|
|
|
|
[[nodiscard]] std::optional<double> GetHighResolutionLimit_A() const;
|
|
|
|
[[nodiscard]] double GetMinPartiality() const;
|
|
[[nodiscard]] std::optional<double> GetForcedMosaicity() const;
|
|
[[nodiscard]] double GetCaptureUncertaintyCoeff() const;
|
|
[[nodiscard]] double GetMinCapturedFraction() const;
|
|
[[nodiscard]] double GetMinCCForImage() const;
|
|
[[nodiscard]] double GetSearchMinZeta() const;
|
|
[[nodiscard]] double GetOutlierRejectNsigma() const;
|
|
[[nodiscard]] bool GetScaleFulls() const;
|
|
[[nodiscard]] int GetAbsorptionIter() const;
|
|
[[nodiscard]] bool GetCorrectionSurfaces() const;
|
|
[[nodiscard]] bool GetStillsPartialityRefine() const;
|
|
[[nodiscard]] bool GetExpectedVarianceMerge() const;
|
|
[[nodiscard]] double GetSmoothGDegrees() const;
|
|
[[nodiscard]] double GetRelativeBDegrees() const;
|
|
|
|
[[nodiscard]] double GetRfreeFraction() const;
|
|
|
|
[[nodiscard]] ResolutionCutoffMethod GetResolutionCutoff() const;
|
|
[[nodiscard]] double GetResolutionCCTarget() const;
|
|
[[nodiscard]] int GetReportShellCount() const;
|
|
};
|