Stills: kept overloads go back to the drop where they are not concentrated at low resolution
Saturation clips the strongest spots, and those are at low resolution. On a Rayonix stills set the saturated pixels sat almost entirely past 4 A (0.002% of the reflections coarser than 4 A against 0.59% overall) - flagged or hot pixels, not clipped spots - and keeping those observations as lower bounds put the saturation limit into high-resolution intensities: R_split 0.12 -> 0.93, CC1/2 0.99 -> 0.33. The run now keeps overloads only where their share coarser than 4 A is at least 1.5x their overall share; otherwise they are flagged and dropped as before, with a log line saying so. On clipped CCD stills the share coarser than 4 A is 2.6-5.9x the overall one and nothing changes (R_split and R_free identical); on the Rayonix set R_split returns to 0.12. A pragmatic gate until saturation is told from bad pixels per spot. Rotation never keeps overloads and is unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
This commit is contained in:
1 parent
5f8c739358
commit
0cf62452cd
3 files changed
+43
No files matched your search
@@ -62,6 +62,9 @@ struct Reflection {
|
||||
// intensity at all - its brightest pixels are missing - and a rotation merge drops the whole
|
||||
// rocking event it belongs to, as XDS does with an overloaded reflection.
|
||||
bool overloaded = false;
|
||||
// A still's overloaded reflection kept as a lower bound instead (BraggIntegrationEngine::Finalize);
|
||||
// the run may still hand it back to the overload drop (RugnuxScaleMerge).
|
||||
bool overload_kept = false;
|
||||
};
|
||||
|
||||
// One full reflection of a rotation sweep as the merge used it - its partials summed into one
|
||||
|
||||
@@ -288,6 +288,7 @@ std::vector<Reflection> BraggIntegrationEngine::Finalize(const std::vector<Refle
|
||||
refl.I = fr.I + static_cast<float>(fr.saturated * (saturation_limit - fr.bkg));
|
||||
refl.sigma = std::sqrt(fr.var_bkg + std::max(refl.I, 1.0f));
|
||||
refl.overloaded = false;
|
||||
refl.overload_kept = true;
|
||||
++counts.overloads_kept;
|
||||
}
|
||||
refl.observed = true;
|
||||
|
||||
@@ -549,6 +549,45 @@ bool Rugnux::ScaleMergeAndSymmetry(PipelineLocals &p) {
|
||||
size_t ice_flagged = 0, ice_total = 0;
|
||||
{
|
||||
auto &outcomes = indexer->GetIntegrationOutcome();
|
||||
// Saturation clips the strongest spots, and those are at low resolution: kept overloads of a
|
||||
// still are a measurement only where they concentrate there. Where they do not, the saturated
|
||||
// pixels are something else (hot or flagged pixels across the pattern), and an observation
|
||||
// with such a pixel set to the saturation limit is not a lower bound but an outlier - so they
|
||||
// go back to the overload drop. A pragmatic gate until saturation is told from bad pixels per
|
||||
// spot.
|
||||
{
|
||||
std::atomic<int64_t> k_all{0}, k_low{0}, n_all{0}, n_low{0};
|
||||
ParallelFor(static_cast<int>(outcomes.size()), config_.nthreads, [&](int o) {
|
||||
int64_t all = 0, low = 0, kept = 0, kept_low = 0;
|
||||
for (const auto &r : outcomes[o].reflections) {
|
||||
const bool low_res = r.d >= OVERLOAD_LOW_RES_A;
|
||||
++all;
|
||||
low += low_res;
|
||||
if (r.overload_kept) {
|
||||
++kept;
|
||||
kept_low += low_res;
|
||||
}
|
||||
}
|
||||
n_all += all; n_low += low; k_all += kept; k_low += kept_low;
|
||||
});
|
||||
if (k_all > 0 && n_low > 0) {
|
||||
const double frac_all = static_cast<double>(k_all) / static_cast<double>(n_all);
|
||||
const double frac_low = static_cast<double>(k_low) / static_cast<double>(n_low);
|
||||
if (frac_low < 1.5 * frac_all) {
|
||||
for (auto &oc : outcomes)
|
||||
for (auto &r : oc.reflections)
|
||||
if (r.overload_kept) {
|
||||
r.overloaded = true;
|
||||
r.overload_kept = false;
|
||||
}
|
||||
result.overloads_kept = 0;
|
||||
logger.Info("Overloads: the {} kept as a lower bound are not concentrated at low resolution "
|
||||
"({:.3f}% of the reflections coarser than {:.0f} A, {:.3f}% of all) - not "
|
||||
"saturated spots, so they are dropped as overloads",
|
||||
k_all.load(), 100.0 * frac_low, OVERLOAD_LOW_RES_A, 100.0 * frac_all);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::atomic<int64_t> n_all{0}, n_low{0}, n_over{0}, n_over_low{0}, n_ice{0};
|
||||
ParallelFor(static_cast<int>(outcomes.size()), config_.nthreads, [&](int o) {
|
||||
int64_t all = 0, low = 0, over = 0, over_low = 0, on_ice = 0;
|
||||
|
||||
Reference in new issue
Block a user