From a7adff181a2e2b13080a7296ccd9f8ff15c975c1 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Tue, 10 Nov 2026 18:07:38 +0100 Subject: [PATCH] rugnux: a fixed primitive space group on a lattice indexed as centred is merged as asked, with a warning The check that a user-fixed space group fits the indexed lattice refused every centring mismatch. A primitive group on a centred lattice is not a frame conflict: with a fixed group prediction runs in that group's centring, so the reflections the lattice centring would extinguish are integrated on the conventional cell and the merge in the group's frame is well defined. The group is the user's choice, so the run now warns - naming the centred lattice and cell the indexing found - and merges in it. A centred group on a lattice that does not carry it, and a cell the group's operators do not leave invariant, still stop the run: there the reflections are not in the group's frame (completeness above 100 % is the measured symptom). Measured: a monoclinic P crystal whose first pass was labelled C (without the indexer fix) now merges in P 1 21 1, 100 % complete; a genuinely C-centred monoclinic crystal run with -S P2 warns and merges in P2, 95 % complete. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK --- docs/RUGNUX_TUTORIAL.md | 4 +++- rugnux/RugnuxScaleMerge.cpp | 22 ++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/RUGNUX_TUTORIAL.md b/docs/RUGNUX_TUTORIAL.md index 56c6e0977..bfdb25d02 100644 --- a/docs/RUGNUX_TUTORIAL.md +++ b/docs/RUGNUX_TUTORIAL.md @@ -138,7 +138,9 @@ into the merged files. Run **fully de novo** (no `-C`/`-S`) for the best result — supplying a cell or space group up front tends to *degrade* low-symmetry cases. A `-S` group whose Bravais lattice the crystal turns out not to have stops the run and names the cell that was indexed, rather than merging in a frame the reflections -are not in; where the lattice does have that group's setting, the reflections are reindexed into it. `--scaling-high-resolution` (set it to your expected +are not in; where the lattice does have that group's setting, the reflections are reindexed into it. +A primitive `-S` group on a lattice indexed as centred is the exception: it is merged as asked, with a +warning. `--scaling-high-resolution` (set it to your expected resolution) sharpens both the space-group search and the error model. To tune the first pass use `--two-pass-rotation=100` (or `-R100` — the first-pass image count); to force the sweep to be treated as independent stills use `--force-still`. diff --git a/rugnux/RugnuxScaleMerge.cpp b/rugnux/RugnuxScaleMerge.cpp index 6478ebcd9..dbf89d206 100644 --- a/rugnux/RugnuxScaleMerge.cpp +++ b/rugnux/RugnuxScaleMerge.cpp @@ -1223,8 +1223,26 @@ bool Rugnux::ScaleMergeAndSymmetry(PipelineLocals &p) { // question that was not asked. Name the cell that WAS indexed so the user can act on it. if (user_fixed_sg_ && end_msg.rotation_lattice_type.has_value() && end_msg.unit_cell.has_value()) { const gemmi::SpaceGroup &fixed_sg = *user_fixed_sg_; - const bool centring_wrong = - end_msg.rotation_lattice_type->centering != fixed_sg.centring_type(); + // A PRIMITIVE group on a lattice indexed as centred is not that conflict: the reflections are + // integrated on the conventional cell, so the group's frame is theirs and its arithmetic holds; + // it only keeps the reflections the centring would extinguish. Whether those are absent is the + // data's to say, and the user chose the group - so warn, and merge in it. + const bool primitive_on_centred = fixed_sg.centring_type() == 'P' + && end_msg.rotation_lattice_type->centering != 'P'; + if (primitive_on_centred) { + const auto &uc = *end_msg.unit_cell; + logger.Warning("The space group {} was fixed for this run and is primitive, but the indexing " + "found a {}-centred {} lattice (a={:.3f} b={:.3f} c={:.3f} alpha={:.2f} " + "beta={:.2f} gamma={:.2f}): merging in {} as asked. If the centring is real, " + "the reflections it extinguishes merge to noise; if they are only weak, a " + "pseudo-translation is the likely reason. Without -S the space-group search " + "decides it from the intensities", + fixed_sg.xhm(), end_msg.rotation_lattice_type->centering, + gemmi::crystal_system_str(end_msg.rotation_lattice_type->crystal_system), + uc.a, uc.b, uc.c, uc.alpha, uc.beta, uc.gamma, fixed_sg.xhm()); + } + const bool centring_wrong = !primitive_on_centred + && end_msg.rotation_lattice_type->centering != fixed_sg.centring_type(); // The same two tests as the re-seating above, asked again now that it has had its chance. const double violation = MetricViolation(*end_msg.unit_cell, fixed_sg); if (centring_wrong || violation > MAX_METRIC_VIOLATION) {