IndexAndRefine: conventionalise de-novo lattice when cell+SG are given
Providing both a unit cell (-C) and space group (-S) silently broke the de-novo indexers (FFT/FFTW) -> 0% indexing, while each flag alone worked. Root cause: the `sg && GetUnitCell()` branch fed the indexer's raw lattice straight into symmetry-constrained refinement. FFBIDX returns the lattice already in the reference setting, but FFT/FFTW return an arbitrarily-oriented Niggli-primitive cell; enforcing the crystal system on its mis-assigned axes rejects every frame. Fix: for de-novo indexers only, reduce the lattice to the conventional setting (LatticeSearch) before refinement. FFBIDX keeps using its raw lattice as-is, so it is byte-identical to before (no regression). niggli_class stays unassigned (0) in this branch - it is a property of the primitive cell incl. centering, which LatticeSearch cannot recover from a user-supplied (possibly centered, e.g. C2) cell. A proper primitive-cell indexing path (CrystFEL-style) is deferred. Validation (lyso, -C79,79,38 -S96): crystal 2 FFT : 0% -> 94.9% (CC1/2 95.8, CCref 92.7) = de-novo quality crystal 2 FFBIDX: 71.4% (CC1/2 94.6) - byte-identical jet FFBIDX: 27.2% (CC1/2 91.9) - byte-identical (Jet FFT stays 0% - that is a separate, still-open issue: de-novo finds no consensus on the weak serial-still frames, 0% even without -S; to investigate.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -101,16 +101,27 @@ IndexAndRefine::IndexingOutcome IndexAndRefine::DetermineLatticeAndSymmetry(Data
|
||||
auto latt = indexer_result.lattice[0];
|
||||
if (latt.CalcVolume() > 1.0) {
|
||||
auto sg = experiment.GetGemmiSpaceGroup();
|
||||
const auto algorithm = experiment.GetIndexingAlgorithm();
|
||||
const bool de_novo = (algorithm == IndexingAlgorithmEnum::FFT
|
||||
|| algorithm == IndexingAlgorithmEnum::FFTW);
|
||||
|
||||
// If space group and cell provided => always enforce symmetry in refinement
|
||||
// If space group not provided => guess symmetry
|
||||
// If space group and cell provided => enforce that symmetry in refinement.
|
||||
// If not => detect the symmetry from the lattice.
|
||||
if (sg && experiment.GetUnitCell()) {
|
||||
// FFBIDX returns the lattice already in the reference setting, so use it
|
||||
// as-is. De-novo indexers (FFT/FFTW) return an arbitrarily-oriented primitive
|
||||
// cell that must first be reduced to the conventional setting, else enforcing
|
||||
// the crystal system on mis-assigned axes rejects every frame. Centering is
|
||||
// taken from the user's space group; niggli_class is left unassigned (0) - it
|
||||
// is a property of the primitive cell incl. centering, which LatticeSearch
|
||||
// cannot recover from a cell the user may have given centered (e.g. C2). A
|
||||
// proper primitive-cell indexing path (CrystFEL-style) is deferred.
|
||||
outcome.symmetry = LatticeMessage{
|
||||
.centering = sg->centring_type(),
|
||||
.niggli_class = 0,
|
||||
.crystal_system = sg->crystal_system()
|
||||
};
|
||||
outcome.lattice_candidate = latt;
|
||||
outcome.lattice_candidate = de_novo ? LatticeSearch(latt).conventional : latt;
|
||||
} else {
|
||||
auto sym_result = LatticeSearch(latt);
|
||||
outcome.symmetry = LatticeMessage{
|
||||
|
||||
Reference in New Issue
Block a user