Report: a stretch removed whole is named as the frames to process on their own
The SWEEP_GAPS warning of a rejected range that the merge removed whole and took out of the data (RotationScaleMerge::TakenOut) now says what the frames may be - another crystal, radiation-damaged or dead data - and gives them as the -s / -e range that processes them on their own: file images, the end exclusive, through the run's own -s and stride (ProcessResult::first_image, image_stride). Stretches removed one after the other can overlap; the range is all of them the warning's range touches. Processed alone, such stretches range from dead frames to valid data of another crystal; the user is the one who can tell which is wanted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqXYdL4qBGYRiSXSGXfCLu
This commit is contained in:
1 parent
d04f91fd74
commit
48dcf8218a
5 files changed
+45
-1
No files matched your search
@@ -622,7 +622,9 @@ the correction surfaces and the error model it was judged on were all fitted wit
|
||||
merge that may be written and removes one takes its frames' reflections out — they are in no later merge
|
||||
and in no file written from the integrated reflections — and makes itself again from the start without
|
||||
them; the run's own batches are then judged again on what is left, which can remove more. The stretch
|
||||
stays in this table at the scale, CC and ΔCC1/2 it was removed on.
|
||||
stays in this table at the scale, CC and ΔCC1/2 it was removed on. Its warning names it as the frames to process
|
||||
on their own (`-s <first> -e <last + 1>`, file images): it may be another crystal, radiation-damaged or
|
||||
dead data.
|
||||
|
||||
**What ΔCC1/2 cannot do**, because the report must not imply otherwise:
|
||||
|
||||
|
||||
@@ -2700,6 +2700,20 @@ ReportDocument BuildReportDocument(const std::string &output_prefix,
|
||||
cost = fmt::format(" - kept at their own reduced weight; removing them would change "
|
||||
"CC1/2 by {:+.4f} +/- {:.4f} over the reflections they touch",
|
||||
-r.delta_cc_half, r.delta_cc_half_se);
|
||||
// A stretch the merge removed whole (RotationScaleMerge::TakenOut) is out of the data, and
|
||||
// may still be data of its own: named as the frames to process alone. Stretches removed one
|
||||
// after the other can overlap; the range is all of them that this one touches.
|
||||
int s0 = r.last_image + 1, s1 = r.first_image - 1;
|
||||
for (const auto &[f0, f1] : sq.removed_stretches)
|
||||
if (rejected && f0 <= r.last_image && r.first_image <= f1) {
|
||||
s0 = std::min(s0, f0);
|
||||
s1 = std::max(s1, f1);
|
||||
}
|
||||
if (s0 <= s1)
|
||||
cost += fmt::format(". The stretch removed whole may be another crystal, radiation-damaged "
|
||||
"or dead data; -s {} -e {} processes it on its own",
|
||||
result.first_image + s0 * result.image_stride,
|
||||
result.first_image + s1 * result.image_stride + 1);
|
||||
Warn(doc, PathologyCode::SWEEP_GAPS, fmt::format(
|
||||
"Frames {}-{} {} ({:.1f} deg, scale {:.2f} and CC {:.2f} of the run, {:.0f}% scaled){}",
|
||||
r.first_image, r.last_image, SweepQualityReasonText(r.reason),
|
||||
|
||||
@@ -565,6 +565,9 @@ struct RugnuxOutputs {
|
||||
struct ProcessResult {
|
||||
bool cancelled = false;
|
||||
uint64_t images_processed = 0;
|
||||
// The file image of processed-image ordinal f is first_image + f * image_stride (-s, --stride).
|
||||
int first_image = 0;
|
||||
int image_stride = 1;
|
||||
double processing_time_s = 0.0;
|
||||
// Wall time of the per-image loop alone; processing_time_s additionally covers the first-pass
|
||||
// indexing and the scaling/merging around it, which no per-stage timer sees.
|
||||
|
||||
@@ -482,6 +482,8 @@ void Rugnux::ImagePass(PipelineLocals &p) {
|
||||
std::chrono::steady_clock::now() - image_loop_start).count();
|
||||
|
||||
result.images_processed = finished_count.load();
|
||||
result.first_image = start_image;
|
||||
result.image_stride = config_.stride;
|
||||
// fast_live: a cut inside the canonical pass's image loop ends its sweep at the images read so far, and
|
||||
// the pass merges those, a partial sweep, as a pre-pass merges its share. Any other pass a cut stops.
|
||||
const bool partial_sweep = config_.fast_live && cancelled_ && p.write_output && !geometry_prepass
|
||||
|
||||
@@ -163,6 +163,29 @@ TEST_CASE("ResultReport_Render", "[Diagnostics]") {
|
||||
!= std::string::npos);
|
||||
}
|
||||
|
||||
// A rejected range the merge removed whole (RotationScaleMerge::TakenOut) names the frames to process on
|
||||
// their own, as -s / -e give them: file images, the end exclusive, through the run's own -s and stride.
|
||||
TEST_CASE("ResultReport_RemovedStretchFramesToProcessAlone", "[Diagnostics]") {
|
||||
DiffractionExperiment x(DetJF(1));
|
||||
x.ImagesPerTrigger(1210);
|
||||
ProcessResult result;
|
||||
result.images_processed = 600;
|
||||
result.first_image = 10;
|
||||
result.image_stride = 2;
|
||||
result.consensus_cell = UnitCell{.a = 79.0f, .b = 79.0f, .c = 38.0f,
|
||||
.alpha = 90.0f, .beta = 90.0f, .gamma = 90.0f};
|
||||
result.space_group = *gemmi::find_spacegroup_by_number(96);
|
||||
result.has_merge_statistics = true;
|
||||
result.merge_statistics.sweep_quality = TestSweepQuality();
|
||||
CHECK(RenderResultReport("prefix", "in.h5", x, result).find("processes it on its own") == std::string::npos);
|
||||
|
||||
// Removed one after the other, the two overlap: the range is both.
|
||||
result.merge_statistics.sweep_quality.removed_stretches = {{120, 149}, {100, 130}};
|
||||
const auto text = RenderResultReport("prefix", "in.h5", x, result);
|
||||
CHECK(text.find("over the reflections they touch. The stretch removed whole may be another crystal, "
|
||||
"radiation-damaged or dead data; -s 210 -e 309 processes it on its own") != std::string::npos);
|
||||
}
|
||||
|
||||
// The reference-range table: REFRES_* keys beside the run's own, the shells past the run's own limit
|
||||
// reported as not merged rather than as zeros, and no REFRES_ key at all when no range was given.
|
||||
TEST_CASE("ResultReport_ReferenceRangeTable", "[Diagnostics]") {
|
||||
|
||||
Reference in new issue
Block a user