BraggIntegrationEngineCPU: background clip reads the ring pixels pass A gathered, output unchanged
The one-pass sigma clip of the background ring walked the reflection's whole box a second time, recomputing every pixel's stencil distances and neighbour mask. Pass A now keeps the ring pixels the clip reads (readable, not a neighbour's flux), with their radial offset, in pixel order, and the clip sums those - the same values in the same order. Measured on cytochrome C (CPU-only, Apple M6): the clip loop was 8.4% of CPU; the run is 4-5% faster with this and the ring-histogram change together. Merged reflections and maps byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
93958cfdc7
commit
1c748ba41e
1 file changed
+17
-17
@@ -208,6 +208,10 @@ std::vector<Reflection> BraggIntegrationEngineCPU::RunImpl(const Sampler &img,
|
||||
std::vector<Rough> rough(npredicted);
|
||||
double inv_d2_min = std::numeric_limits<double>::max(), inv_d2_max = 0.0;
|
||||
std::vector<int32_t> bkg_vals; // reused per reflection for the trimmed-mean background (idea 1)
|
||||
// The ring pixels the background clip below reads, with their radial offsets, gathered while pass
|
||||
// A walks the box anyway - in the order the clip sums them, so it sums the same values.
|
||||
struct ClipPixel { int32_t px; float rad; };
|
||||
std::vector<ClipPixel> clip_ring;
|
||||
|
||||
// Radial background curve, accumulated from the annulus pixels this pass already reads. A pixel's
|
||||
// radius is the reflection's radius plus the pixel's projection on the beam->reflection direction,
|
||||
@@ -266,10 +270,13 @@ std::vector<Reflection> BraggIntegrationEngineCPU::RunImpl(const Sampler &img,
|
||||
// separable from what the detector took.
|
||||
int n_ring = 0, n_clean = 0;
|
||||
bkg_vals.clear();
|
||||
clip_ring.clear();
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
for (int x = x0; x <= x1; ++x) {
|
||||
const auto d = BraggStencilDistances(st, x - r.predicted_x, y - r.predicted_y);
|
||||
const int32_t px = img[y * W + x];
|
||||
if (do_clip && d.inner >= r2_sq && d.outer < r3_sq && valid(px) && refl_mask.Get(x, y) != MASK_FLUX)
|
||||
clip_ring.push_back({px, d.rad});
|
||||
if (BraggStencilInSignal(st, x - r.predicted_x, y - r.predicted_y, d.signal, r1_sq)) {
|
||||
// A pixel a nearer neighbour owns carries that neighbour's flux, so in Exclude
|
||||
// mode it leaves the disk entirely - the sum, the pixel count the background is
|
||||
@@ -353,23 +360,16 @@ std::vector<Reflection> BraggIntegrationEngineCPU::RunImpl(const Sampler &img,
|
||||
* std::max(out.bkg, 1.0));
|
||||
double s = 0.0;
|
||||
int n = 0;
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
for (int x = x0; x <= x1; ++x) {
|
||||
const auto d = BraggStencilDistances(st, x - r.predicted_x, y - r.predicted_y);
|
||||
if (!(d.inner >= r2_sq && d.outer < r3_sq)) continue;
|
||||
if (refl_mask.Get(x, y) == MASK_FLUX) continue;
|
||||
const int32_t px = img[y * W + x];
|
||||
if (!valid(px)) continue;
|
||||
if (static_cast<double>(px) <= thr) {
|
||||
s += px;
|
||||
++n;
|
||||
if (bkg_radial) {
|
||||
// The radial curve is binned on the TRUE detector radius, so the
|
||||
// offset here is the unshrunk radial projection.
|
||||
const int b = std::clamp(static_cast<int>(std::lround(st.r0 + d.rad)), 0, n_rad - 1);
|
||||
rad_sum[b] += static_cast<double>(px);
|
||||
++rad_cnt[b];
|
||||
}
|
||||
for (const auto &[px, rad] : clip_ring)
|
||||
if (static_cast<double>(px) <= thr) {
|
||||
s += px;
|
||||
++n;
|
||||
if (bkg_radial) {
|
||||
// The radial curve is binned on the TRUE detector radius, so the
|
||||
// offset here is the unshrunk radial projection.
|
||||
const int b = std::clamp(static_cast<int>(std::lround(st.r0 + rad)), 0, n_rad - 1);
|
||||
rad_sum[b] += static_cast<double>(px);
|
||||
++rad_cnt[b];
|
||||
}
|
||||
}
|
||||
if (n > 5) { out.bkg = s / n; n_bkg_used = n; }
|
||||
|
||||
Reference in new issue
Block a user