Stills keep an overloaded observation as a lower bound instead of dropping it

The stills merge dropped every observation with a saturated pixel. On a still the saturated
observations are the fully recorded ones of the strongest low-resolution reflections, so what
survived were their partial observations, whose partiality correction then set the merged
intensity: on clipped CCD stills the merged low-resolution intensities came out at 0.4-0.6x of
the deposited ones, a ramp no Wilson B absorbs, invisible to CC1/2 and R_split.

The pixels are really clipped (flat-topped plateaus a few per mille wide, a pile-up in the
pixel-value histogram from the per-pixel ADC limit), so the auto ceiling is right; the drop was
the defect. A still now keeps the observation: the box sum with every saturated pixel counted at
the saturation limit, unflagged and marked clipped, counted in BraggIntegrationCounts and
reported as OVERLOADED_REFLECTIONS_KEPT. Rotation data (IsRotationIndexing) are unchanged and
keep the flag for the rocking-event drop.

Measured on a clipped-CCD stills subset (dimple R-free, deposited free set): dropped 0.247,
lower bound 0.230 (same as switching saturation off). A Kabsch fit to the unsaturated wings read
lower than the lower bound (0.237), and inflating the lower bound's sigma lost (0.255).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-10-22 10:36:33 +02:00
1 parent 987e812e23
commit 72cc542d78
15 files changed
+152 -20

No files matched your search

+3 -2
View File
@@ -204,9 +204,10 @@ double CompareCpuVsGpu(IntegratorMode mode, std::optional<float> bandwidth_fwhm,
const auto out_clean = clean_cpu.Run(clean_image, clean_scene.predicted,
clean_scene.predicted.size(), 5);
// An unreadable pixel the (empty) mask does not explain reads as an overload, which keeps the
// reflection, flagged - so the cost shows in the measured ones.
// reflection - flagged, or on a still as a lower bound, clipped either way - so the cost shows
// in the complete ones.
const auto measured = std::count_if(out_cpu.begin(), out_cpu.end(),
[](const Reflection &r) { return !r.overloaded; });
[](const Reflection &r) { return !r.clipped; });
CHECK(static_cast<size_t>(measured) < out_clean.size());
}
for (size_t i = 0; i < out_cpu.size(); ++i) {