rugnux: the external reference MTZ is never a scale anchor (stills + rotation)
An external reference MTZ is a poor per-image scale reference: it is a different crystal/dataset, so scaling against it injects cross-dataset systematics rather than removing per-image scale error (measured: reference-scaled R-free 0.410 vs self-scaled 0.388 on OCP; 0.378 vs 0.350 on LOV). Its real value is fixing the cell/space group, breaking the merohedral indexing ambiguity, reporting CCref and providing the R-free test set - none of which need it to be a scale anchor. Make that consistent across both workflows: - Stills: the per-image pass (ScaleImage) now uses the reference ONLY to break the indexing ambiguity (once, for good), not to fit G. Scaling self-references at the post-measurement merge for every run, whether or not a reference is given (Rugnux + rugnux_cli --scale). - Rotation: ScaleImage no longer scales against the reference either (it was dead code - RotationScaleMerge recomputes the per-frame scale, so the reference never actually moved the result). Rotation resolves the ambiguity globally (ChooseReindex / ReferenceIntensityCC) and self-scales in RotationScaleMerge. - A reference-as-scale mode, if ever wanted, would be a dedicated later step, not this per-image pass. Validated: OCP CCref 56.5%->64.6%, R-free 0.400->0.393 (honest 2.36 A cutoff instead of a reference- propped 1.5 A); LOV CCref 88.3%->90.1%, R-free 0.336->0.331 with more reflections; rotation lyso_ref with the reference gives ISa 17.8 == de-novo 15.6 (same 15975 reflections, CC1/2 99.8%) - the reference demonstrably does not touch rotation scaling, only cell/SG + ambiguity + CCref. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -495,15 +495,19 @@ void IndexAndRefine::ScaleImage(DataMessage &msg, IntegrationOutcome& outcome) {
|
||||
if (!scaling_engine)
|
||||
return;
|
||||
|
||||
auto scaling_start_time = std::chrono::steady_clock::now();
|
||||
scaling_engine->Scale(outcome);
|
||||
auto scaling_end_time = std::chrono::steady_clock::now();
|
||||
// The external reference fixes the cell/space group, breaks the indexing ambiguity and reports CCref,
|
||||
// but is NEVER a scale anchor: scaling an image against a foreign dataset injects cross-dataset
|
||||
// systematics and is a worse reference than the data's own merge, so scaling self-references at the
|
||||
// post-measurement merge for both workflows. Rotation resolves the ambiguity globally and self-scales
|
||||
// in RotationScaleMerge (ChooseReindex / ReferenceIntensityCC), so there is nothing to do per image.
|
||||
// Stills resolve the merohedral ambiguity per image here (each crystal indexes in a random hand; pick
|
||||
// the hand best-correlated with the reference, once and for good).
|
||||
if (experiment.IsRotationIndexing())
|
||||
return;
|
||||
|
||||
scale_cc[msg.number] = outcome.image_scale_cc.value_or(NAN);
|
||||
msg.image_scale_b_factor = outcome.image_scale_b_factor_Ang2;
|
||||
msg.image_scale_factor = outcome.image_scale_g;
|
||||
msg.image_scale_mosaicity = outcome.mosaicity_deg;
|
||||
msg.image_scale_cc = outcome.image_scale_cc;
|
||||
auto scaling_start_time = std::chrono::steady_clock::now();
|
||||
scaling_engine->ResolveIndexingAmbiguity(outcome.reflections);
|
||||
auto scaling_end_time = std::chrono::steady_clock::now();
|
||||
msg.image_scale_time_s = std::chrono::duration<float>(scaling_end_time - scaling_start_time).count();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user