Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m24s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m32s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m40s
Build Packages / build:rpm (rocky8) (push) Successful in 15m8s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 15m12s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 15m25s
Build Packages / build:windows:nocuda (push) Successful in 15m47s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 15m50s
Build Packages / build:windows:cuda (push) Successful in 17m29s
Build Packages / XDS test (durin plugin) (push) Successful in 8m31s
Build Packages / Generate python client (push) Successful in 32s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m3s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (neggia plugin) (push) Successful in 8m31s
Build Packages / Build documentation (push) Successful in 1m6s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m23s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m16s
Build Packages / build:rpm (rocky9) (push) Successful in 12m56s
Build Packages / DIALS test (push) Successful in 12m42s
Build Packages / Unit tests (push) Successful in 1h34m10s
De-novo two-pass indexing failed on large-cell / superstructure / modulated crystals (EcwtAL500 0%, EcwtCQ034 0%) and mis-handled a pseudo-symmetric one (EcwtCQ066 14%). The common cause: the choice of unit cell was made too early, on the raw pre-refinement spot fraction, which is an unreliable discriminator (a correct hexagonal cell indexes only ~13% of the un-refined accumulated spots, while a wrong larger cell can index more). Move the decision to after geometry refinement, where it is reliable: - FFTIndexer now OFFERS widened candidate cells instead of deciding. ReduceResults gains a `widen` flag: the standard path (9 shortest vectors) is unchanged; the widened path anchors the two short axes and lets the third range over all filtered vectors (+dedup) to reach the long axis of an elongated cell. FilterFFTResults takes the peak count as a parameter (30 standard, 60 widened). RunInternal appends widened candidates only when its standard best indexes poorly, so compact crystals are untouched. - RotationIndexer fully refines the top few candidates and keeps the one that indexes the most spots under its own refined geometry (IndexedFraction). Each refine is length-bounded (1.2x the found cell) so a free triclinic refine cannot drift onto a pseudo-translation / modulation supercell (CQ034's satellites). The earlier (primary) candidate is preferred: a later one is adopted only if it indexes clearly more and reasonably well in absolute terms, so a twin's noisy near-tie cannot displace it. Extra/twin lattices are only searched when the chosen cell is the FFT primary (lattice[0]), since MultiLatticeSearch's rotations are derived from that primary. - The pseudo-symmetry guard (de-novo only - a user-fixed space group is always honored) is a ratio of refined fractions: refine the primitive as triclinic and drop to P only if the constrained cell indexes less than half of it. A false promotion indexes badly under its constraint (CQ066 ratio ~0.1) while genuine higher symmetry, including R-centred, indexes comparably (Ins_H R3 ratio ~0.7) and is kept. Validated on the full /data/rotation_test battery: AL500 0->89% (C2), CQ034 0->99%, CQ066 14->93% (ISa 7.2->13.7); the other 15 crystals keep their exact cell, space group, indexing rate and ISa (no regressions). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>