Build Packages / build:windows:nocuda (push) Failing after 1m40s
Build Packages / build:windows:cuda (push) Failing after 1m39s
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m50s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m45s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m12s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m43s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m54s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m3s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m3s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m50s
Build Packages / build:rpm (rocky8) (push) Successful in 12m1s
Build Packages / XDS test (durin plugin) (push) Successful in 8m9s
Build Packages / Generate python client (push) Successful in 34s
Build Packages / Build documentation (push) Successful in 1m3s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m31s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m58s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 13m19s
Build Packages / DIALS test (push) Successful in 14m25s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m45s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m22s
Build Packages / Unit tests (push) Successful in 58m49s
The local Bragg background is the mean over the r2..r3 ring. That mean reads high because the contaminants that survive the signal-disk mask - neighbour- spot wings, tails, zingers - are one-sided (positive), so it over-subtracts. Since a weak intensity is a small difference of large numbers (I = S - nS*b), a per-pixel background bias is fractionally largest at the resolution edge, exactly where it hurts most. Replace the ring mean with a symmetric trimmed mean (sort the ring, drop the lowest and highest fraction f, average the rest), controlled by a new BraggIntegrationSettings field and the rugnux `--background-trim <f>` option (default f=0.10; 0 restores the plain mean). Default on for monochromatic (rotation) data; broadband (stills) keep their tuned high-side sigma-clip, so the base engine forces the trim to 0 there. Implemented in both the CPU engine and the GPU kernel (shared-memory bitonic sort per block, flat-mean fallback above BKG_TRIM_MAX ring pixels); the two agree. 25-crystal rotation battery (fixed SG/cell): <I/sigma> improved on every crystal (median +50%), ISa on 20/22, resolution-edge R_meas fell several-fold (e.g. lyso_ref 1.0 A 108%->43%). Last-shell CC1/2 is rescued where the plain mean had collapsed to noise (Thau_9 at ~2.0 A 3.8%->64%, ~0.5 A of resolution regained; cytC_10 0.2%->10%) at a small cost (1-3%) in already-clean shells - it flattens the CC1/2 fall-off rather than shifting it. Stills unchanged. Documented in CPU_DATA_ANALYSIS.md section 9.2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
53 lines
2.6 KiB
C++
53 lines
2.6 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
#include <optional>
|
|
|
|
// Spot-intensity extraction method used by the Bragg integration engine. ProfileGaussian (default)
|
|
// profile-fits with a measured-width Gaussian (Kabsch-style) - more accurate intensities than the
|
|
// classical uniform BoxSum; validated on anomalous data (stronger S/Cl peaks vs box-sum). BoxSum is
|
|
// the simpler, faster fallback. ProfileEmpirical learns the profile per resolution shell from strong
|
|
// spots - see docs/CPU_DATA_ANALYSIS.md (Bragg integration).
|
|
enum class IntegratorMode { BoxSum, ProfileGaussian, ProfileEmpirical };
|
|
|
|
class BraggIntegrationSettings {
|
|
IntegratorMode integrator_mode = IntegratorMode::ProfileGaussian;
|
|
float r_1 = 4;
|
|
float r_2 = 6;
|
|
float r_3 = 10;
|
|
float d_min_limit_A = 1.0;
|
|
std::optional<float> fixed_profile_radius;
|
|
float minimum_sigma_in_regards_to_i = 0.02;
|
|
bool still_partiality = false; // experimental stills excitation-error partiality (rugnux --still-partiality)
|
|
// Symmetric trimmed-mean fraction for the r2..r3 background ring: drop the lowest and highest this
|
|
// fraction of ring pixels before averaging. Resists the high-side contamination (neighbour-spot
|
|
// wings, tails, zingers) that biases the plain ring mean up and makes it over-subtract weak
|
|
// high-angle reflections. Applied to monochromatic (rotation) data; the integration engine keeps
|
|
// the tuned high-side sigma-clip for stills instead. 0 = plain ring mean (rugnux --background-trim).
|
|
float bkg_trim_fraction = 0.10f;
|
|
|
|
public:
|
|
BraggIntegrationSettings& R1(float input);
|
|
BraggIntegrationSettings& R2(float input);
|
|
BraggIntegrationSettings& R3(float input);
|
|
BraggIntegrationSettings& DMinLimit_A(float input);
|
|
BraggIntegrationSettings& FixedProfileRadius_recipA(std::optional<float> input);
|
|
BraggIntegrationSettings& Integrator(IntegratorMode input);
|
|
BraggIntegrationSettings& StillPartiality(bool input);
|
|
BraggIntegrationSettings& BackgroundTrimFraction(float input);
|
|
|
|
|
|
[[nodiscard]] IntegratorMode GetIntegrator() const;
|
|
[[nodiscard]] float GetR1() const;
|
|
[[nodiscard]] float GetR2() const;
|
|
[[nodiscard]] float GetR3() const;
|
|
[[nodiscard]] std::optional<float> GetFixedProfileRadius_recipA() const;
|
|
[[nodiscard]] float GetDMinLimit_A() const;
|
|
|
|
[[nodiscard]] float GetMinimumSigmaInRegardsToI() const;
|
|
[[nodiscard]] bool GetStillPartiality() const;
|
|
[[nodiscard]] float GetBackgroundTrimFraction() const;
|
|
};
|