Stills: the shell past the CC1/2 crossing is not written where only the detector corners record it
The automatic cut writes one shell past the CC1/2 crossing. Past the finest whole ring about the beam only the detector's corners record, and a reflection there is seen a few times at most, on whichever weak frames reach it, scaled up tens to hundreds of times: that shell is pure noise, and on several still runs its handful of reflections decided the plain overall CC1/2 and R_split. On stills the extension now stops at the finest whole ring, or at the crossing where that already lies in the corners - also where no cut was made because the extension ran past the measured edge. Rotation is unchanged. Open still battery, against the branch before both changes: plain CC1/2 and R_split recover on every set whose last shell was corner-only (e.g. 0.00 -> 0.99 / 5.5 % on one PAL set), the deposited-model R-free is within 0.005 or better on all eight sets checked, at a written d_min 0.05-0.13 A coarser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqN9qRD57vnShzTC37
This commit is contained in:
1 parent
1e2a83dbca
commit
314e502733
3 files changed
+42
-3
No files matched your search
@@ -244,6 +244,7 @@ ResolutionCutoffResult ComputeCCHalfLogisticCutoff(const std::vector<MergedRefle
|
||||
|
||||
// No cut if the fall-off is beyond the measured edge (CC1/2 still healthy at the highest s).
|
||||
if (s_final >= s_hi) {
|
||||
result.extension_past_edge = true;
|
||||
result.note = "CC1/2 does not fall off within the measured range";
|
||||
return result;
|
||||
}
|
||||
@@ -278,7 +279,8 @@ std::optional<double> ApplyResolutionCutoff(std::vector<MergedReflection> &merge
|
||||
double cc_target,
|
||||
bool for_search,
|
||||
Logger &logger,
|
||||
std::optional<double> *fit_limit_out) {
|
||||
std::optional<double> *fit_limit_out,
|
||||
std::optional<double> whole_ring_d) {
|
||||
std::optional<double> effective_d_min = manual_limit;
|
||||
if (!effective_d_min && !for_search && method == ResolutionCutoffMethod::CCHalfLogistic) {
|
||||
const auto rc = ComputeCCHalfLogisticCutoff(merged, cc_target, logger);
|
||||
@@ -295,6 +297,18 @@ std::optional<double> ApplyResolutionCutoff(std::vector<MergedReflection> &merge
|
||||
} else {
|
||||
logger.Info("Auto resolution cutoff: none ({}); keeping the full resolution range", rc.note);
|
||||
}
|
||||
// Past the finest whole ring the detector records only its corners, and there a reflection is seen
|
||||
// a few times at most, on whichever frames reach it: the shell written past the crossing is then
|
||||
// made of those reflections, and pure noise. So the extension stops at the whole ring, or at the
|
||||
// crossing where that is already in the corners - which is where established programs stop too
|
||||
// (the inscribed circle of XDS's default TRUSTED_REGION).
|
||||
if (rc.d_fit && whole_ring_d
|
||||
&& (rc.d_cut ? *rc.d_cut < *whole_ring_d : rc.extension_past_edge)) {
|
||||
effective_d_min = std::max(rc.d_cut.value_or(0.0), std::min(*rc.d_fit, *whole_ring_d));
|
||||
logger.Info("Auto resolution cutoff: {:.2f} A instead - past the detector's finest whole ring at {:.2f} A "
|
||||
"only its corners record, so the shell past the crossing is not written there",
|
||||
*effective_d_min, *whole_ring_d);
|
||||
}
|
||||
}
|
||||
if (effective_d_min)
|
||||
merged.erase(std::remove_if(merged.begin(), merged.end(),
|
||||
|
||||
@@ -31,6 +31,7 @@ struct ResolutionCutoffResult {
|
||||
// reflections are actually written to. This is the number to quote. Set whenever the fit produced
|
||||
// a crossing inside the measured range, even when no cut was applied.
|
||||
std::optional<double> d_fit;
|
||||
bool extension_past_edge = false; // no cut because the one-shell extension runs past the measured edge
|
||||
std::string note; // human-readable description of the decision (for logging)
|
||||
};
|
||||
|
||||
@@ -59,10 +60,13 @@ ResolutionCutoffResult ComputeCCHalfLogisticCutoff(const std::vector<MergedRefle
|
||||
// fit_limit_out, when given, receives ResolutionCutoffResult::d_fit - the CC1/2 crossing without the
|
||||
// one-shell extension, for reporting. Left untouched when no automatic fit ran (a manual limit, a
|
||||
// search merge, or the method turned off), so a caller can tell "not fitted" from "fitted".
|
||||
// whole_ring_d, when given, is the finest resolution the detector records on a whole ring: the one-shell
|
||||
// extension of an automatic cut then stops there, and where the crossing is already finer, at the crossing.
|
||||
std::optional<double> ApplyResolutionCutoff(std::vector<MergedReflection> &merged,
|
||||
std::optional<double> manual_limit,
|
||||
ResolutionCutoffMethod method,
|
||||
double cc_target,
|
||||
bool for_search,
|
||||
Logger &logger,
|
||||
std::optional<double> *fit_limit_out = nullptr);
|
||||
std::optional<double> *fit_limit_out = nullptr,
|
||||
std::optional<double> whole_ring_d = std::nullopt);
|
||||
@@ -83,6 +83,7 @@
|
||||
#include "../image_analysis/WriteReflections.h"
|
||||
#include "../image_analysis/bragg_integration/CalcISigma.h"
|
||||
#include "../common/Definitions.h"
|
||||
#include "../common/AssembleToPlane.h"
|
||||
#include "../common/CorrelationCoefficient.h"
|
||||
#include <array>
|
||||
#include <map>
|
||||
@@ -92,6 +93,25 @@
|
||||
using namespace rugnux_internal;
|
||||
|
||||
namespace {
|
||||
// The finest resolution the detector records on a whole ring about the beam: the coarsest along its edge.
|
||||
double WholeRingResolution_A(const DiffractionExperiment &x) {
|
||||
const DiffractionGeometry geom = x.GetDiffractionGeometry();
|
||||
const PlaneRaster raster = PlaneRasterOf(x.GetModules(), x.GetXPixelsNumConv(), x.GetYPixelsNumConv());
|
||||
double d = 0.0;
|
||||
const auto at = [&](int64_t i, int64_t j) {
|
||||
d = std::max<double>(d, geom.PxlToRes(static_cast<float>(raster.x0 + i), static_cast<float>(raster.y0 + j)));
|
||||
};
|
||||
for (int64_t i = 0; i < raster.width; i++) {
|
||||
at(i, 0);
|
||||
at(i, raster.height - 1);
|
||||
}
|
||||
for (int64_t j = 0; j < raster.height; j++) {
|
||||
at(0, j);
|
||||
at(raster.width - 1, j);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// Two groups of a given cell's frames whose mean volumes differ by less than this (relative) are one
|
||||
// crystal form (see the given-cell population below).
|
||||
constexpr double MIN_FORM_SEPARATION = 0.01;
|
||||
@@ -741,7 +761,8 @@ StillsMergeResult StillsScaleMerge(const DiffractionExperiment &experiment, std:
|
||||
// space-group search still sees the full range.
|
||||
const auto &cut_ss = experiment.GetScalingSettings();
|
||||
out.d_min = ApplyResolutionCutoff(out.merged, cut_ss.GetHighResolutionLimit_A(), cut_ss.GetResolutionCutoff(),
|
||||
cut_ss.GetResolutionCCTarget(), for_search, logger, &out.resolution_fit_A);
|
||||
cut_ss.GetResolutionCCTarget(), for_search, logger, &out.resolution_fit_A,
|
||||
WholeRingResolution_A(experiment));
|
||||
|
||||
phase("Computing statistics");
|
||||
TimingMark stats_mark(logger, "stills statistics");
|
||||
|
||||
Reference in new issue
Block a user