// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "RugnuxDefaults.h" namespace { // Smoothing range for the per-frame scale G on rotation data (XDS DELPHI-like), in degrees. constexpr double SMOOTH_G_DEG = 5.0; // Per-observation outlier rejection for the rotation combine, in sigma. constexpr double REJECT_OUTLIERS_NSIGMA = 6.0; } void ApplyRugnuxExperimentDefaults(DiffractionExperiment &experiment) { // The Lp correction the integrator applies to every reflection. Without it the intensities carry an // azimuthal, intensity-proportional modulation (~1.3x at 2 A for a 1 A beam) that symmetry mates do // NOT share, because they sit at the same 2-theta but a different azimuth - which is exactly the // "unequal intensities forced together" signature the space-group search vetoes as pseudo-symmetry. experiment.PolarizationFactor(0.99); } void ClearStoredCrystal(DiffractionExperiment &experiment) { experiment.SpaceGroupNumber(std::nullopt); experiment.SetUnitCell(std::nullopt); } ScalingSettings RugnuxDefaultScalingSettings(bool rotation) { ScalingSettings s; // Refit the per-frame scale on the combined fulls. Rotation only - it is what lifts ISa there, and // there is no combine on the stills path. s.ScaleFulls(rotation); s.SmoothGDegrees(rotation ? SMOOTH_G_DEG : 0.0); // Drop edge-of-sweep fulls whose rocking curve was captured less than this. 0.7 rather than 0.5 also // strips the partiality-extrapolated fulls that dominate the intensity second moment on weakly // diffracting crystals, without which the de-novo space-group search is starved by the error-model // I/sigma floor and falls back to P1. s.MinCapturedFraction(rotation ? 0.7 : 0.0); // Capture-aware systematic sigma: down-weights the over-extrapolated under-captured fulls. s.CaptureUncertaintyCoeff(rotation ? 1.0 : 0.0); // A single un-rejected artifact wrecks the intensity-correlation and second-moment statistics the // space-group and twinning tests are built on. s.OutlierRejectNsigma(rotation ? REJECT_OUTLIERS_NSIGMA : 0.0); // Run the de-novo space-group search a second time on a merge of only the well-measured // observations and keep whichever found more symmetry. It cannot lose symmetry, so an imperfect cut // only means the second opinion contributes nothing. s.SearchMinZeta(rotation ? 0.85 : 0.0); return s; }