Bragg integration: a ring the neighbours starved is taken whole, not dropped
The r2..r3 background ring excludes every pixel inside any predicted reflection's r2 region, and a reflection whose ring kept five or fewer clean pixels was dropped. The mask marks every prediction in the +-4 sigma rocking window, most of which put a few percent of their flux on the frame. On a finely sliced, dense pattern (0.05 deg frames, sigma_M 0.067 deg, 0.35 A, 7200 frames) they fill every ring: ~9400 predictions per frame but only ~900 with partiality above 0.2, and 88.9% of all partials were dropped at the fixed radius - including the peak frames. The merge was 17.9% complete. Such a ring now falls back on all its readable pixels; the existing high-side clip removes the neighbour cores that are really there. The starvation counts are unchanged, so the adaptive-radius guard reads the same numbers. Detector-starved rings are still dropped. On that set (fixed radius, no --model): 7.4M -> 67M partials ingested, completeness 17.9 -> 79.7% (88% to 0.65 A), d_min 0.69 -> 0.61 A, ISa 12.8 -> 14.3, reflections in common with the deposition 60k -> 252k, rank CC vs |Fc|^2 minus the depositor's, outer shells -0.10 -> +0.07. A dense 360-frame set: 14.9M -> 17.6M partials, dCC outer -0.116 -> -0.096. myob_x10sa MTZ byte-identical. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C
This commit is contained in:
@@ -140,7 +140,8 @@ DiffractionExperiment MakeExperiment(IntegratorMode mode, std::optional<float> b
|
||||
return experiment;
|
||||
}
|
||||
|
||||
void CompareCpuVsGpu(IntegratorMode mode, std::optional<float> bandwidth_fwhm,
|
||||
// Returns the fraction of the predicted reflections the engines kept.
|
||||
double CompareCpuVsGpu(IntegratorMode mode, std::optional<float> bandwidth_fwhm,
|
||||
float clip_nsigma = 4.0f, bool radial = false, int spacing = 60,
|
||||
float stencil_k = 0.0f,
|
||||
float r1 = 0.0f, float r2 = 0.0f, float r3 = 0.0f,
|
||||
@@ -200,6 +201,7 @@ void CompareCpuVsGpu(IntegratorMode mode, std::optional<float> bandwidth_fwhm,
|
||||
CHECK(out_gpu[i].I == Catch::Approx(out_cpu[i].I).epsilon(0.03).margin(2.0));
|
||||
CHECK(out_gpu[i].sigma == Catch::Approx(out_cpu[i].sigma).epsilon(0.03).margin(0.5));
|
||||
}
|
||||
return static_cast<double>(out_cpu.size()) / static_cast<double>(scene.predicted.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -269,6 +271,12 @@ TEST_CASE("BraggIntegrationEngineGPU_MatchesCPU") {
|
||||
CompareCpuVsGpu(IntegratorMode::ProfileGaussian, std::nullopt, 4.0f, false, 60, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, OverlapMode::Exclude);
|
||||
}
|
||||
// Spots 8 px apart: the neighbours' r2 regions cover every background ring, so only the edge of
|
||||
// the grid keeps a clean ring pixel. Both engines have to fall back to the whole ring and keep the
|
||||
// reflections rather than drop them for want of a background.
|
||||
SECTION("ProfileGaussian neighbour-starved rings") {
|
||||
CHECK(CompareCpuVsGpu(IntegratorMode::ProfileGaussian, std::nullopt, 4.0f, false, 8) > 0.95);
|
||||
}
|
||||
SECTION("ProfileGaussian mono trim") { CompareCpuVsGpu(IntegratorMode::ProfileGaussian, std::nullopt, 0.0f); }
|
||||
// Unreadable pixels inside the signal disks themselves: the MINPK rescue keeps the reflection and
|
||||
// fits it over what is left, and the peak-loss rule throws back the ones that lost the profile's
|
||||
|
||||
Reference in New Issue
Block a user