diff --git a/image_analysis/scale_merge/SearchSpaceGroup.cpp b/image_analysis/scale_merge/SearchSpaceGroup.cpp index 3b99f6e3e..59eb289eb 100644 --- a/image_analysis/scale_merge/SearchSpaceGroup.cpp +++ b/image_analysis/scale_merge/SearchSpaceGroup.cpp @@ -1900,9 +1900,14 @@ SearchSpaceGroupResult SearchSpaceGroup( // the point group is one only a non-reference setting carries (Stage A's second pass), since // otherwise there is no candidate at all and the group would be lost after being found. These are // alternative namings at the same order, so nothing here can promote the point group; what they - // add is a screw or a centering on the axis the data show it on. Two refusals bound them: a - // setting whose axes the cell does not have is not offered, and one predicting exactly the - // absences a candidate already offered predicts is the same hypothesis under another name. + // add is a screw or a centering on the axis the data show it on. One refusal bounds them: a setting + // predicting exactly the absences a candidate already offered predicts is the same hypothesis + // under another name. The cell is NOT asked again here: a setting of the chosen rotation set holds + // the very rotations the reference candidates hold, so it fits the cell exactly as well as they + // do - and they are offered without asking. Asking only the non-reference ones turned a free- + // refined cell a few tenths of a degree off 90 into a refusal of every setting but the reference + // one, leaving the group with the measured screws on a and c (P 2_1 2 2_1) unoffered and P2_12_12_1 + // the only candidate that covered both. if (opt.cell.has_value() && (opt.enumerate_all_settings || (opt.enumerate_all_rotation_sets && sg_cands.empty()))) { std::vector> signatures; @@ -1910,8 +1915,7 @@ SearchSpaceGroupResult SearchSpaceGroup( signatures.push_back(AbsenceSignature(*c)); for (const auto& sg : gemmi::spacegroup_tables::main) { if (!sg.is_sohncke() || sg.is_reference_setting() || - RotationSetOf(sg) != best_pg->rotation_set || - !CellHostsRotations(*opt.cell, sg.operations())) + RotationSetOf(sg) != best_pg->rotation_set) continue; auto sig = AbsenceSignature(sg); if (std::find(signatures.begin(), signatures.end(), sig) != signatures.end()) diff --git a/tests/SearchSpaceGroupTest.cpp b/tests/SearchSpaceGroupTest.cpp index 88123bdd3..59b912021 100644 --- a/tests/SearchSpaceGroupTest.cpp +++ b/tests/SearchSpaceGroupTest.cpp @@ -444,6 +444,17 @@ TEST_CASE("SearchSpaceGroup names an orthorhombic screw pair on the axes it lies REQUIRE(result.best_space_group.has_value()); CHECK(result.best_space_group->xhm() == "P 2 21 21"); } + + // A cell refined free after integration is a few tenths of a degree off 90. The reference + // candidates hold the same rotations and are offered on it, so the other settings must be too. + SECTION("a free cell a few tenths off 90 still offers it") { + opt.cell = gemmi::UnitCell(40.0, 50.0, 60.0, 90.32, 90.19, 90.19); + opt.enumerate_all_settings = true; + const auto result = SearchSpaceGroup(merged, opt); + INFO(SearchSpaceGroupResultToText(result)); + REQUIRE(result.best_space_group.has_value()); + CHECK(result.best_space_group->xhm() == "P 2 21 21"); + } } // A screw on a row the sweep never recorded is not a group the data refused, it is a question