From e40eb08a3b84d42b1bcdc3d2a5145cfb6f0fddaf Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 4 Nov 2026 14:30:48 +0100 Subject: [PATCH] Stills with a cell but no space group: keep the cell's angles and setting With -C and no -S, two things broke a cell whose angles are not all 90 deg: - DiffractionExperiment::GetCrystalSystem() returned Monoclinic when no space group was set, and the stills geometry bundle adjustment (and the tilt trial) parametrise the cell by that system, so a hexagonal cell was refined with alpha = gamma = 90 deg. The refined cell then fed FFBIDX for the whole run: on a trigonal crystal 5.9% of the frames indexed instead of 16.4%. Without a space group the system is now Triclinic. - IndexAndRefine replaced the lattice FFBIDX returned on the given cell's axes with LatticeSearch's conventional setting, chosen frame by frame, so frames of one crystal form landed in different settings (89% of an R-centred hexagonal run reported as a second crystal form). The FFBIDX lattice is now kept, refined with every angle free. Runs with -S take the other branch and are unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UqXYdL4qBGYRiSXSGXfCLu --- common/DiffractionExperiment.cpp | 4 +++- image_analysis/IndexAndRefine.cpp | 13 +++++++++++++ tests/DiffractionExperimentTest.cpp | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/common/DiffractionExperiment.cpp b/common/DiffractionExperiment.cpp index 3ade2d095..639d3399d 100644 --- a/common/DiffractionExperiment.cpp +++ b/common/DiffractionExperiment.cpp @@ -1843,9 +1843,11 @@ DiffractionExperiment &DiffractionExperiment::GeomRefinementAlgorithm(GeomRefine } gemmi::CrystalSystem DiffractionExperiment::GetCrystalSystem() const { + // Without a space group nothing is known of the cell's symmetry: triclinic leaves every angle of + // the given cell free, where any other system would hold some of them at 90 degrees. auto sg = GetGemmiSpaceGroup(); if (!sg) - return gemmi::CrystalSystem::Monoclinic; + return gemmi::CrystalSystem::Triclinic; return sg->crystal_system(); } diff --git a/image_analysis/IndexAndRefine.cpp b/image_analysis/IndexAndRefine.cpp index b814fbcf0..c741d0c32 100644 --- a/image_analysis/IndexAndRefine.cpp +++ b/image_analysis/IndexAndRefine.cpp @@ -380,6 +380,19 @@ IndexAndRefine::IndexingOutcome IndexAndRefine::DetermineLatticeAndSymmetry(Data else if (!de_novo) outcome.lattice_candidate = latt; // else: de-novo + symmetry mismatch -> leave unset, frame is not indexed + } else if (!de_novo && experiment.GetUnitCell() + && latt.GetUnitCell().is_close(*experiment.GetUnitCell(), + experiment.GetIndexingSettings().GetUnitCellDistTolerance(), + experiment.GetIndexingSettings().GetUnitCellAngleTolerance_deg())) { + // A cell with no space group: FFBIDX returned the lattice on the given cell's axes, and + // it stays on them, so that every frame is in one setting. Nothing is known of the + // symmetry, so it is refined with every angle free. + outcome.symmetry = LatticeMessage{ + .centering = 'P', + .niggli_class = 0, + .crystal_system = gemmi::CrystalSystem::Triclinic + }; + outcome.lattice_candidate = latt; } else { auto sym_result = LatticeSearch(latt); outcome.symmetry = LatticeMessage{ diff --git a/tests/DiffractionExperimentTest.cpp b/tests/DiffractionExperimentTest.cpp index 930bc9ad1..e5db38e08 100644 --- a/tests/DiffractionExperimentTest.cpp +++ b/tests/DiffractionExperimentTest.cpp @@ -354,7 +354,7 @@ TEST_CASE("DiffractionExperiment_ZMQPreview", "[DiffractionExperiment]") { TEST_CASE("DiffractionExperiment_SpaceGroup", "[DiffractionExperiment]") { DiffractionExperiment x; REQUIRE(!x.GetGemmiSpaceGroup()); - REQUIRE(x.GetCrystalSystem() == gemmi::CrystalSystem::Monoclinic); + REQUIRE(x.GetCrystalSystem() == gemmi::CrystalSystem::Triclinic); REQUIRE_THROWS(x.SpaceGroupNumber(-1)); REQUIRE_THROWS(x.SpaceGroupNumber(500)); REQUIRE_NOTHROW(x.SpaceGroupNumber(96));