Files
Jungfraujoch/common/BraggIntegrationSettings.cpp
leonarski_f a395f358ef
Build Packages / Create release (push) Successful in 17s
Build Packages / build:viewer:macos-arm64:nocuda (push) Successful in 3m22s
Build Packages / build:rugnux:macos-arm64:nocuda (push) Successful in 2m37s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 9m33s
Build Packages / build:rugnux:linux-x86_64:cuda (push) Successful in 10m39s
Build Packages / build:viewer:linux-x86_64:nocuda (push) Successful in 11m4s
Build Packages / build:viewer:linux-x86_64:cuda (push) Successful in 13m19s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 17m37s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 18m49s
Build Packages / build:viewer:windows-x86_64:nocuda (push) Successful in 19m10s
Build Packages / build:viewer:windows-x86_64:cuda (push) Successful in 24m26s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 25m31s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 18m54s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 20m45s
Build Packages / Generate python client (push) Successful in 37s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 20m20s
Build Packages / Build documentation (push) Successful in 1m32s
Build Packages / build:rugnux:windows-x86_64:cuda (push) Successful in 14m37s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 21m6s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 19m49s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 20m29s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 17m2s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 14m27s
Build Packages / Unit tests (push) Successful in 1h18m12s
1.0.0-rc.174 (#84)
* Rugnux: Performance improvements on GPU and CPU (more of the pre-scan and of scaling on the GPU, faster CPU spot finding and crystal refinement), with unchanged results.
* Rugnux: More robust processing - patches of persistently hot pixels are masked, an inconsistent merge triggers a retry at the measured beam centre, and builds targeting different CPU levels give the same results.
* Rugnux: Improved scaling and merging - reflections with an overloaded pixel are dropped, as in XDS, sparse rotation sweeps are scaled more reliably, and French-Wilson amplitudes use an anisotropic Wilson prior.
* Rugnux: Improved space-group determination - glide planes in groups without a centre of symmetry, screw axes from short or weak axial rows kept when a higher group is adopted, and more reliable decisions on twinned and pseudo-symmetric crystals.
* Rugnux: Improved small-molecule processing - spots that grow wider than the integration disk and split spots are integrated over their measured footprint, sparse lattices are integrated on every frame, and the `.hkl` file holds unmerged scaled reflections (SHELX HKLF 4).
* Rugnux: Reads Rigaku d*TREK SMV images (Saturn CCD), including detector 2theta and encoded pixel overflows; home-source (rotating-anode) datasets were added to the validation battery.
* jfjoch_viewer: Fixed processing failing at the end with "Wrong JPEG library version" on Linux; the merge window shows the space group with proper subscripts and a checklist of crystal pathologies.

Reviewed-on: #84
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-10-06 14:03:18 +02:00

220 lines
7.3 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <cmath>
#include "BraggIntegrationSettings.h"
#include "JFJochException.h"
#define check_max(param, val, max) if ((val) > (max)) throw JFJochException(JFJochExceptionCategory::InputParameterAboveMax, param)
#define check_min(param, val, min) if ((val) < (min)) throw JFJochException(JFJochExceptionCategory::InputParameterBelowMin, param)
#define check_finite(param, val) if (!std::isfinite(val)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, param)
BraggIntegrationSettings &BraggIntegrationSettings::R1(float input) {
check_finite("Integration radius R1", input);
check_min("Integration radius R1", input, 0.1);
check_max("Integration radius R1", input, 20.0);
r_1 = input;
return *this;
}
BraggIntegrationSettings &BraggIntegrationSettings::R2(float input) {
check_finite("Background inner radius R2", input);
check_min("Background inner radius R2", input, 0.1);
check_max("Background inner radius R2", input, 30.0);
if (input <= r_1)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Background inner radius (R2) must be larger than integration radius (R1)");
r_2 = input;
return *this;
}
BraggIntegrationSettings &BraggIntegrationSettings::R3(float input) {
check_finite("Background outer radius R3", input);
check_min("Background outer radius R3", input, 0.1);
check_max("Background outer radius R3", input, 40.0);
if (input <= r_2)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Background outer radius (R3) must be larger than background inner radius (R2)");
r_3 = input;
return *this;
}
BraggIntegrationSettings &BraggIntegrationSettings::StencilKSigma(float input) {
check_finite("Integration stencil elongation", input);
check_min("Integration stencil elongation", input, 0.0);
check_max("Integration stencil elongation", input, 10.0);
stencil_k_sigma = input;
return *this;
}
BraggIntegrationSettings &BraggIntegrationSettings::DMinLimit_A(std::optional<float> input) {
if (input) {
check_finite("Minimum d-spacing", *input);
check_min("Minimum d-spacing", *input, 0.5);
check_max("Minimum d-spacing", *input, 100.0);
}
d_min_limit_A = input;
return *this;
}
BraggIntegrationSettings & BraggIntegrationSettings::FixedProfileRadius_recipA(std::optional<float> input) {
if (input) {
check_finite("Profile radius", input.value());
check_min("Profile radius [A^-1]", input.value(), 0.000001);
check_max("Profile radius [A^-1]", input.value(), 0.01);
}
fixed_profile_radius = input;
return *this;
}
std::optional<float> BraggIntegrationSettings::GetFixedProfileRadius_recipA() const {
return fixed_profile_radius;
}
BraggIntegrationSettings & BraggIntegrationSettings::ForcedPredictionMosaicity_deg(std::optional<float> input) {
if (input) {
check_finite("Prediction mosaicity", input.value());
check_min("Prediction mosaicity [deg]", input.value(), 0.001);
check_max("Prediction mosaicity [deg]", input.value(), 10.0);
}
forced_prediction_mosaicity_deg = input;
return *this;
}
std::optional<float> BraggIntegrationSettings::GetForcedPredictionMosaicity_deg() const {
return forced_prediction_mosaicity_deg;
}
BraggIntegrationSettings &BraggIntegrationSettings::Integrator(IntegratorMode input) {
integrator_mode = input;
return *this;
}
IntegratorMode BraggIntegrationSettings::GetIntegrator() const {
return integrator_mode;
}
float BraggIntegrationSettings::GetR1() const {
return r_1;
}
float BraggIntegrationSettings::GetR2() const {
return r_2;
}
float BraggIntegrationSettings::GetR3() const {
return r_3;
}
float BraggIntegrationSettings::GetStencilKSigma() const {
return stencil_k_sigma;
}
std::optional<float> BraggIntegrationSettings::GetDMinLimit_A() const {
return d_min_limit_A;
}
float BraggIntegrationSettings::GetMinimumSigmaInRegardsToI() const {
return minimum_sigma_in_regards_to_i;
}
BraggIntegrationSettings &BraggIntegrationSettings::BackgroundTrimFraction(float input) {
check_finite("Background trim fraction", input);
check_min("Background trim fraction", input, 0.0);
check_max("Background trim fraction", input, 0.49); // must leave a central majority after trimming
bkg_trim_fraction = input;
if (input > 0.0f)
bkg_clip_nsigma = 0.0f; // the two ring estimators are alternatives, not a stack
return *this;
}
float BraggIntegrationSettings::GetBackgroundTrimFraction() const {
return bkg_trim_fraction;
}
BraggIntegrationSettings &BraggIntegrationSettings::MaxHKL(std::optional<int> input) {
if (input) {
check_min("Maximum hkl index", *input, 1);
// The GPU predictor launches one thread per candidate, so the cost is (2n+1)^3: 511 is 1.1e9
// candidates per frame, already far past the point where prediction dominates a run.
check_max("Maximum hkl index", *input, 511);
}
max_hkl = input;
return *this;
}
std::optional<int> BraggIntegrationSettings::GetMaxHKL() const {
return max_hkl;
}
BraggIntegrationSettings &BraggIntegrationSettings::BackgroundClipNSigma(float input) {
check_finite("Background clip nsigma", input);
check_min("Background clip nsigma", input, 0.0);
bkg_clip_nsigma = input;
if (input > 0.0f)
bkg_trim_fraction = 0.0f; // the two ring estimators are alternatives, not a stack
return *this;
}
float BraggIntegrationSettings::GetBackgroundClipNSigma() const {
return bkg_clip_nsigma;
}
BraggIntegrationSettings &BraggIntegrationSettings::BackgroundRadialCorrection(std::optional<bool> input) {
bkg_radial_correction = input;
return *this;
}
std::optional<bool> BraggIntegrationSettings::GetBackgroundRadialCorrection() const {
return bkg_radial_correction;
}
BraggIntegrationSettings &BraggIntegrationSettings::Overlap(OverlapMode input) {
overlap_mode = input;
return *this;
}
OverlapMode BraggIntegrationSettings::GetOverlap() const {
return overlap_mode;
}
BraggIntegrationSettings &BraggIntegrationSettings::OverlapMinPeak(float input) {
check_finite("Overlap minimum peak fraction", input);
check_min("Overlap minimum peak fraction", input, 0.0);
check_max("Overlap minimum peak fraction", input, 1.0);
overlap_min_peak = input;
return *this;
}
float BraggIntegrationSettings::GetOverlapMinPeak() const {
return overlap_min_peak;
}
BraggIntegrationSettings &BraggIntegrationSettings::FlightPath(FlightPathMedium input) {
flight_path = input;
return *this;
}
FlightPathMedium BraggIntegrationSettings::GetFlightPath() const {
return flight_path;
}
BraggIntegrationSettings &BraggIntegrationSettings::Footprint(const SpotFootprint &input) {
if (input.sigma_rad.size() != input.sigma_tan.size()
|| input.sigma_rad.size() > static_cast<size_t>(SpotFootprint::MAX_BINS)
|| (!input.empty() && !(input.bin_px > 0.0f)))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Invalid spot footprint table");
footprint = input;
return *this;
}
const SpotFootprint &BraggIntegrationSettings::GetFootprint() const {
return footprint;
}