Stills: background clip follows the radial curve; signal disk from the lattice spacing

Two stills-only changes to the integration stencil.

1. Where the whole-frame radial curve is in use (the correction on), the ring's high-side clip
   follows it: a ring pixel is clipped against the threshold plus the curve's rise from the
   reflection's radius to its own (BraggIntegrationEngine::RadialClipOffset, rounded to whole counts
   so CPU, CUDA and Metal keep the same pixels). On a background falling steeply away from the beam
   the flat mean + 4 sqrt(mean) threshold cut the beam-side half of the ring as outliers, so the
   background read low and reflections near the beam stop read 3-150x too strong. The empty-aperture
   test's corrected column clips the same way, so the per-run correction decision sees it.
   Measured with r1 6 (dimple R_free, battery arguments, all frames):
     lcls222 0.196 -> 0.1856, pal86 0.216 -> 0.1997, sacla236 0.2559 -> 0.2559, alvra213_int16 0.1986 -> 0.1986.

2. The signal disk is taken from the lattice: it must not reach into the next node's spot. The
   closest two nodes can come on the detector is the shortest reciprocal-lattice vector the centring
   allows, s = F_px tan(2 asin(lambda / 2 d_max)), and a spot reaches 2 r80 (measured in the
   pre-scan); r1 = the largest of 4, 5, 6 px not above s - 2 r80, never below 4, never above the
   disk the run starts with (6). The empty apertures are measured for each candidate disk and the
   ring is chosen on the chosen disk's tally. Pixel detectors keep 6 (sacla236 s 22 px, alvra213
   20 px); the binned CCDs with a long axis shrink to 4 (lcls222 5.4 px, pal86 6.7 px), which the
   radius scans there measured as the optimum; pal90 (s 21 px) and lcls242_s (15.5 px) keep 6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-10-22 09:20:52 +02:00
1 parent 29000dd3d6
commit 61def00a1a
13 files changed
+228 -50

No files matched your search

+4 -3
View File
@@ -424,7 +424,9 @@ TEST_CASE("BraggIntegrationEngineGPU_RadialCurveFromRingsMatchesCPU", "[Integrat
DiffractionExperiment experiment(DetJF(2));
experiment.DetectorDistance_mm(100.0f).IncidentEnergy_keV(WVL_1A_IN_KEV).BeamX_pxl(400.0f).BeamY_pxl(400.0f);
const float bx = 400.0f, by = 400.0f;
const auto background = [](double r) { return 50.0 + 0.05 * (r - 300.0) * (r - 300.0); };
// Curved, plus a slope steep enough that the ring's flat clip would cut its beam-side half: the
// GPU must follow the curve in the clip as the CPU does (RadialClipOffset).
const auto background = [](double r) { return 40000.0 - 100.0 * r + 0.05 * (r - 300.0) * (r - 300.0); };
const size_t width = experiment.GetXPixelsNum(), npixel = experiment.GetPixelsNum();
ImagePreprocessorBuffer cpu_image(npixel);
ImagePreprocessorBufferGPU gpu_image(npixel);
@@ -462,8 +464,7 @@ TEST_CASE("BraggIntegrationEngineGPU_RadialCurveFromRingsMatchesCPU", "[Integrat
for (size_t i = 0; i < out_cpu.size(); ++i) {
INFO("mode " << static_cast<int>(mode) << " reflection " << i);
CHECK(out_gpu[i].bkg == Catch::Approx(out_cpu[i].bkg).epsilon(0.001).margin(0.05));
CHECK(std::fabs(out_gpu[i].I) < 10.0f);
CHECK(std::fabs(out_cpu[i].I) < 10.0f);
CHECK(out_gpu[i].I == Catch::Approx(out_cpu[i].I).epsilon(0.01).margin(2.0));
}
}
}