rugnux: background clip scaled by the CCD gain measured in the pre-scan
The background ring's high-side clip, mean + 4*sqrt(mean), assumes counted photons. A CCD reports ADU: on a Rigaku Saturn a background pixel scatters 4-5x its mean, so the clip sat at ~2 sigma, cut the upper tail of every ring and added a positive offset to every reflection, compressing the intensity statistics (a false 422 on one twinned I41 crystal). No header carries a usable gain (SMV states none, every marCCD file the writer default of 1 ADU per photon), so it is measured: background_gain::MeasureFrame takes the variance per unit mean of the difference of pixels two columns apart, per level, clipped, on every fourth row of up to 16 of the pre-scan's frames; Gain is the pair-weighted median over the levels. The clip becomes mean + n*sqrt(max(g,1)*mean) (BraggIntegrationSettings::bkg_pixel_gain, CPU and GPU engines). Only for SMV/marCCD input (ProcessConfig::counts_in_adu, set from the file format); HDF5 and CBF keep g = 1, the identity. One log line reports the value. No new option. Measured g: Saturn 944+ 4.7-5.2, Saturn 944 2.7, A200 0.68, ADSC ~0.3, marCCD ~0.3 - so the ADSC/marCCD/A200 sets keep the photon clip exactly. Checks (reflection data via gemmi and p.hkl, against the rc175 battery outputs / base build): identical on 11if, 7qis, 8a1a, myob_x10sa, cytc_x10sa (photon counting), 4bwl, 5epe (ADSC, marCCD) and 6cee (A200). Saturn sets, battery baseline -> this change: 3r6o I4122 R_meas 19.3% ISa 4.4 <|L|> .321 -> I41 (correct) 12.1% 8.1 .384 3mc4 R_meas 10.2 -> 9.8 %, ISa 12.1 -> 12.7, d_min 1.79 -> 1.75 A, <|L|> .360 -> .391 5uth 12.6 -> 11.8 %, ISa 10.4 -> 10.1, <|L|> .426 -> .483, offset vs |Fc|^2 0.21 -> 0.00 5vml 10.2 -> 9.6 %, ISa 11.0 -> 11.6, <|L|> .426 -> .475, offset 0.15 -> 0.05 5cc8 8.1 -> 7.9 %, ISa 10.8 -> 11.2, <|L|> .469 -> .494 3meb 14.5 -> 14.6 %, ISa 13.2 -> 13.2, <|L|> .442 -> .457 Space groups unchanged except 3r6o. Pre-scan cost: +0.5 s on a 9 Mpx ADSC sweep, within noise on a 15 Mpx marCCD sweep, nothing on HDF5/CBF. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SVmAWnzCmRKAXVUCdc4iNi
This commit is contained in:
@@ -311,8 +311,10 @@ std::vector<Reflection> BraggIntegrationEngineCPU::RunImpl(const Sampler &img,
|
||||
}
|
||||
} else if (do_clip) {
|
||||
// One high-outlier sigma-clip pass on the background ring: reject pixels above
|
||||
// mean + n*sqrt(mean) to strip a neighbour core or a zinger that biases the mean.
|
||||
const double thr = out.bkg + bkg_clip_nsigma * std::sqrt(std::max(out.bkg, 1.0));
|
||||
// mean + n*sqrt(gain*mean) to strip a neighbour core or a zinger that biases the mean.
|
||||
// The gain is 1 for counted photons, so this is then exactly the Poisson clip.
|
||||
const double thr = out.bkg + bkg_clip_nsigma * std::sqrt(static_cast<double>(bkg_pixel_gain)
|
||||
* std::max(out.bkg, 1.0));
|
||||
double s = 0.0;
|
||||
int n = 0;
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
|
||||
Reference in New Issue
Block a user