diff --git a/image_analysis/rotation_indexer/RotationIndexer.cpp b/image_analysis/rotation_indexer/RotationIndexer.cpp index 67998e27..f01c8f60 100644 --- a/image_analysis/rotation_indexer/RotationIndexer.cpp +++ b/image_analysis/rotation_indexer/RotationIndexer.cpp @@ -34,7 +34,7 @@ namespace { // crystal here separated the true cell from a spurious 5x supercell by 0.003, little enough // that the build's -march flags settled it, and the supercell merged to an R-free of 0.58 // (i.e. noise). A real superstructure's satellite rows are a large share of its spots and - // clear this ratio comfortably. + // clear this ratio comfortably - but see the limitation noted at the comparison itself. constexpr float ROT_SUPERCELL_FRAC_RATIO = 1.5f; // How far from a whole number the volume ratio may sit and still count as an axis multiple. constexpr double ROT_SUPERCELL_INTEGER_TOL = 0.15; @@ -337,6 +337,20 @@ void RotationIndexer::RunIndexing() { const double vol_nearest = std::round(vol_ratio); const bool integer_supercell = vol_nearest >= 2.0 && std::abs(vol_ratio - vol_nearest) < ROT_SUPERCELL_INTEGER_TOL; + // NOTE, and it is a real limitation: `frac > RATIO * best_frac` cannot be satisfied at + // all once best_frac exceeds 1/RATIO - above 0.667 for a ratio of 1.5, which is ordinary + // for good rotation data. So on data that indexes well these two guards do not merely + // raise the bar, they close the branch: no axis multiple and no lower-symmetry setting + // can displace the incumbent however much better it fits. A genuine superstructure whose + // satellite rows the sub-cell misses is therefore kept as its sub-cell, silently. + // + // Restating the bar on the fraction left UNINDEXED - the candidate must account for + // 1/RATIO of what the incumbent missed - is well defined over the whole range and looks + // like the obvious repair. It was tried and it REGRESSED the 37-crystal battery from + // 34/37 to 32/37 correct space groups: one C2 lattice fell to P1, and a P2 case went to + // C222 keeping 2923 of 22440 reflections. The indexed fraction is too noisy a statistic + // to carry a looser test, so the unreachable-but-safe form stays until the selection is + // decided on something better than it. const bool clearly_more = frac > best_frac + 0.05f && frac > 0.15f && (!lower_symmetry_setting || frac > ROT_SUBGROUP_FRAC_RATIO * best_frac) && (!integer_supercell || frac > ROT_SUPERCELL_FRAC_RATIO * best_frac);