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

@@ -281,6 +281,8 @@ std::vector<Reflection> BraggIntegrationEngineCPU::RunImpl(const Sampler &img,
if (px == INT32_MAX
|| (px == INT32_MIN && on && !static_masked(static_cast<size_t>(y) * W + x)))
s.overloaded = 1;
if (px == INT32_MAX)
++s.n_saturated;
if (!valid(px)) continue;
s.I_sum += px;
s.I_sum_x += static_cast<int64_t>(x) * px;
@@ -368,6 +370,7 @@ void BraggIntegrationEngineCPU::FinishPassA(PassA &a, size_t i, const Reflection
out.r_bin = std::clamp(static_cast<int>(std::lround(st.r0)), 0, a.n_rad - 1);
out.k_bin = BraggStencilKernelIndex(st, n_kern);
out.overloaded = s.overloaded != 0;
out.saturated = s.n_saturated;
if (overlap != OverlapMode::Off && s.n_own < s.n_disk) {
++counts.overlapped;
@@ -635,7 +638,7 @@ std::vector<Reflection> BraggIntegrationEngineCPU::ProfilePasses(const Sampler &
if (overlap == OverlapMode::Reject && rh.n_own < overlap_min_peak * rh.n_disk) continue;
results[i] = {static_cast<float>(rh.I), static_cast<float>(rh.sigma), static_cast<float>(rh.bkg),
static_cast<float>(rh.obs_x), static_cast<float>(rh.obs_y),
static_cast<float>(rh.var_bkg), true, rh.has_obs, rh.overloaded};
static_cast<float>(rh.var_bkg), true, rh.has_obs, rh.overloaded, rh.saturated};
}
return Finalize(predicted, npredicted, panels, results, image_number);
}
@@ -751,13 +754,14 @@ std::vector<Reflection> BraggIntegrationEngineCPU::ProfilePasses(const Sampler &
fs = {};
if (!rh.ok) continue;
// An overloaded reflection is not measured by any fit - its brightest pixels are what is
// missing. It is passed on with its box sum and the flag, for the merge to drop its rocking
// event (Reflection::overloaded); the missing-peak cut below would otherwise drop just this
// frame and leave the event to be extrapolated from its flanks.
// missing. It is passed on with its box sum and the flag, for a rotation merge to drop its
// rocking event (Reflection::overloaded) and for a still to be kept as a lower bound
// (Finalize); the missing-peak cut below would otherwise drop just this frame and leave the
// event to be extrapolated from its flanks.
if (rh.overloaded) {
results[i] = {static_cast<float>(rh.I), static_cast<float>(rh.sigma), static_cast<float>(rh.bkg),
static_cast<float>(rh.obs_x), static_cast<float>(rh.obs_y),
static_cast<float>(rh.var_bkg), true, false, true};
static_cast<float>(rh.var_bkg), true, false, true, rh.saturated};
continue;
}
const int sh = rh.shell < 0 ? 0 : rh.shell;
@@ -866,7 +870,7 @@ std::vector<Reflection> BraggIntegrationEngineCPU::ProfilePasses(const Sampler &
results[i] = {static_cast<float>(I), static_cast<float>(sigma),
static_cast<float>(rh.bkg),
static_cast<float>(rh.obs_x), static_cast<float>(rh.obs_y),
static_cast<float>(var_bkg), true, rh.has_obs, rh.overloaded};
static_cast<float>(var_bkg), true, rh.has_obs, rh.overloaded, rh.saturated};
}
return Finalize(predicted, npredicted, panels, results, image_number);