rugnux stills: mask the pixels holding the detector's error value (and dead pixels) in the pre-scan
The defective-pixel finder ran only on scanning rotation data. On stills, a pixel that holds the detector's error value on every frame but is missing from the file's static mask is read by the integrator as a per-frame unreadable pixel, so every reflection whose signal disk touches it is flagged overloaded and the merge drops it. On a SwissFEL JUNGFRAU stills run, 14k such pixels made 3.9% of all integrated reflections "overloaded" (mostly finer than 1.6 A, where they are scarcest) and raised a false OVERLOADS warning; with them masked, 0.05% remain flagged and the profile fit keeps the reflections whose disk stays at least MINPK readable. On stills only the error-value and dead rules apply: the hot-pixel rule counts a reflection's stay on a pixel in rotation, so spacing is passed as 0 there, which HotPixelFinder already treats as "no hot-pixel test". Rotation is unchanged (same gate, same oscillation and spacing). Result-changing for stills; merged-statistics A/B on full runs and the battery ci check still to do. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -190,10 +190,12 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru
|
||||
// radius the first one measured rather than re-reading the frames.
|
||||
const bool want_width = config_.adaptive_integration_radius && !spot_width_measured_;
|
||||
// Defective pixels, for the same reason on the same pass: each pixel is compared against its
|
||||
// resolution ring. Only under rotation, where a reflection moves off a pixel and a defect does not.
|
||||
// resolution ring. Only under rotation, where a reflection moves off a pixel and a defect does not -
|
||||
// except for the pixels holding the detector's error value and the dead ones, which need no
|
||||
// rotation and are measured on stills too (MaskDefectivePixels).
|
||||
const auto goniometer = experiment_.GetGoniometer();
|
||||
const bool want_hot = !hot_pixels_measured_
|
||||
&& experiment_.IsRotationIndexing() && goniometer && goniometer->IsScanning();
|
||||
&& (!experiment_.IsRotationIndexing() || (goniometer && goniometer->IsScanning()));
|
||||
// The background noise per unit level of a CCD, read off the same frames (BackgroundGain.h).
|
||||
const bool want_gain = config_.counts_in_adu && !background_gain_measured_;
|
||||
if (!want_shadow && !want_width && !want_hot && !want_gain)
|
||||
@@ -1193,9 +1195,11 @@ void Rugnux::MaskDefectivePixels(int start_image, const std::vector<int> &sample
|
||||
}
|
||||
});
|
||||
|
||||
// On stills there is no rotation to count a reflection's stay on a pixel in, so spacing stays 0 and
|
||||
// the hot-pixel rule is not applied (HotPixelFinder::GetMask); the error-value and dead pixels are.
|
||||
const auto goniometer = experiment_.GetGoniometer();
|
||||
const double oscillation = std::abs(goniometer->GetIncrement_deg());
|
||||
const double spacing = sample.size() > 1
|
||||
const double oscillation = goniometer ? std::abs(goniometer->GetIncrement_deg()) : 0.0;
|
||||
const double spacing = goniometer && sample.size() > 1
|
||||
? oscillation * (sample.back() - sample.front()) / static_cast<double>(sample.size() - 1)
|
||||
: 0.0;
|
||||
const auto hot = finder.GetMask(oscillation, spacing, nthreads);
|
||||
|
||||
Reference in New Issue
Block a user