Report the strongest index-2 superstructure class and the cell it doubles to

The report-only supercell probe now reaches the results report: SUPERCELL_CLASS (parity of the
primitive indices), its occupancy and Bragg-like (rocking) part against the lattice's own reflections,
its <I/sigma>, and SUPERCELL_DOUBLED_CELL, the Niggli-reduced cell to give with -C. No decision is
taken on it: correct cells whose half-integer class is diffuse, and cells whose depositor kept the
sub-cell, cannot be told from a real doubling by the data alone. On a crystal with a real doubled
axis the reported cell matched the deposited one, and processing on it with -C brought R_free
against the deposited model from 0.60 to 0.29.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-09-25 08:57:28 +02:00
1 parent 9e510816e0
commit 6c9205a670
7 files changed
+96

No files matched your search

+1
View File
@@ -9,6 +9,7 @@
* Rugnux accepts a detector-modulation or absorption correction surface when held-out data support it on Fisher's z, and fits them in the order modulation, time, goniometer frame; this recovers corrections that were wrongly refused.
* Rugnux settles a disagreement between the file's and the measured beam centre over an axis harmonic in either direction, so a file centre off along the spindle no longer leaves the run on a doubled axis.
* Rugnux commits a post-refined geometry only when the held-out residual falls by more than its own noise, instead of by a fixed 2 %.
* Rugnux reports the strongest index-2 superstructure class of a rotation run (`SUPERCELL_CLASS` and related keys), with the doubled cell to give with `-C`; it does not change the lattice.
* Rugnux also reports `R_MEAS_WEIGHTED`, the R_meas with each observation weighted as the merge weights it, so weak frames kept in the merge at low weight can be told from real disagreement; `R_MEAS` is unchanged.
* Rugnux no longer stops per-frame scaling as unsettled because of a single frame that is about to be dropped as blank.
* `rugnux --polarization` is documented as the polarization degree (XDS `FRACTION_OF_POLARIZATION` = (1 + p)/2); the default 0.99 suits undulators.
+19
View File
@@ -415,6 +415,25 @@ Rings are detected far more often than they are excluded: exclusion happens only
found no usable lattice. The measurement is described in
[CPU/GPU data analysis ▸ Resolution and ice-ring handling](CPU_DATA_ANALYSIS_IMAGE.md#33-resolution-and-ice-ring-handling).
## Index-2 superstructure
On rotation data, section 4 reports whether the lattice the run adopted has intensity at half-integer
positions it does not index. On 60 frames spread over the sweep, after each frame's own integration, the
lattice is predicted doubled along all three primitive axes and integrated to 3 Å; the reflections split
into eight parity classes of h, k and l, of which `0 0 0` is the lattice itself and each of the other
seven is one index-2 superstructure. Nothing is decided on it: whether a superstructure belongs in the
cell is as much the depositor's call as the data's, and several crystals whose accepted cell is the
sub-cell carry one.
**`SUPERCELL_CLASS=`** is the parity class with the most intensity over 20–3 Å.
**`SUPERCELL_OCCUPANCY_PCT=`** is its mean intensity against the lattice's own reflections on the same
frames, and **`SUPERCELL_ROCK_PCT=`** (± **`SUPERCELL_ROCK_SE_PCT=`**) the part of it that follows the
partiality the way a Bragg reflection does, from a fit I = a + b p over the class, on the same scale.
**`SUPERCELL_I_OVER_SIGMA=`** is its mean I/σ. A class near zero on both is empty. One that is occupied
and rocks is a superstructure whose reflections this run did not integrate; **`SUPERCELL_DOUBLED_CELL=`**
is the Niggli-reduced cell the lattice would double to, to give with `-C` to process on it. One that is
occupied but hardly rocks is diffuse or disordered intensity rather than Bragg reflections.
## Translational pseudo-symmetry
Two copies of the contents of the asymmetric unit related by a pure translation that is not a lattice
+7
View File
@@ -640,6 +640,7 @@ void IndexAndRefine::ProbeSupercell(std::vector<int64_t> image_numbers) {
std::sort(image_numbers.begin(), image_numbers.end());
supercell_probe_frames_ = std::move(image_numbers);
supercell_probe_ = {};
supercell_probe_primitive_.reset();
}
SupercellProbe IndexAndRefine::GetSupercellProbe() {
@@ -647,6 +648,11 @@ SupercellProbe IndexAndRefine::GetSupercellProbe() {
return supercell_probe_;
}
std::optional<CrystalLattice> IndexAndRefine::GetSupercellProbePrimitive() {
const std::unique_lock ul(supercell_probe_mutex_);
return supercell_probe_primitive_;
}
void IndexAndRefine::ProbeSupercellFrame(const DataMessage &msg, BraggPrediction &prediction,
const BraggIntegrateFn &integrate, const IndexingOutcome &outcome,
const BraggPredictionSettings &settings) {
@@ -684,6 +690,7 @@ void IndexAndRefine::ProbeSupercellFrame(const DataMessage &msg, BraggPrediction
for (int i = 0; i < 8; i++)
for (int j = 0; j < 2; j++)
supercell_probe_[i][j] += frame[i][j];
supercell_probe_primitive_ = prim;
}
std::optional<IndexAndRefine::IndexingOutcome>
+4
View File
@@ -123,6 +123,7 @@ class IndexAndRefine {
// Supercell probe: the image numbers it reads, and what it has read (see ProbeSupercell).
std::vector<int64_t> supercell_probe_frames_;
SupercellProbe supercell_probe_{};
std::optional<CrystalLattice> supercell_probe_primitive_;
std::mutex supercell_probe_mutex_;
void ProbeSupercellFrame(const DataMessage &msg, BraggPrediction &prediction,
const BraggIntegrateFn &integrate, const IndexingOutcome &outcome,
@@ -189,6 +190,9 @@ public:
// The probe's integrations are the caller's to keep out of anything else it counts.
void ProbeSupercell(std::vector<int64_t> image_numbers);
[[nodiscard]] SupercellProbe GetSupercellProbe();
// The primitive lattice the parity classes are indexed in (the last probed frame's; only its metric
// is meant to be read), so a class can be turned into the cell it would double to.
[[nodiscard]] std::optional<CrystalLattice> GetSupercellProbePrimitive();
// Index a single frame (no integration) with the current forced rotation lattice; used to score
// first-pass sampling schemes on the real per-image path. Returns whether the frame indexed.
bool IndexFrameOnly(DataMessage &msg, const SpotFindingSettings &settings);
+26
View File
@@ -1075,6 +1075,32 @@ ReportDocument BuildReportDocument(const std::string &output_prefix,
}
}
// ---- index-2 superstructure
// Report only, like the harmonic above: on 60 frames the probe integrates the lattice doubled
// along all three primitive axes and reads the seven half-integer parity classes. Whether a
// class that is there belongs in the cell is the depositor's call as much as the data's -
// several crystals whose accepted cell is the sub-cell carry one - so no verdict is printed.
if (result.supercell) {
const auto &sc = *result.supercell;
Add(s, KeyText("SUPERCELL_CLASS", fmt::format("{} {} {}", sc.h, sc.k, sc.l)));
Add(s, KeyReal("SUPERCELL_OCCUPANCY_PCT", sc.occupancy_pct, "{:.1f}"));
Add(s, KeyReal("SUPERCELL_ROCK_PCT", sc.rock_pct, "{:.1f}"));
Add(s, KeyReal("SUPERCELL_ROCK_SE_PCT", sc.rock_se_pct, "{:.1f}"));
Add(s, KeyReal("SUPERCELL_I_OVER_SIGMA", sc.i_over_sigma, "{:.2f}"));
Add(s, KeyText("SUPERCELL_DOUBLED_CELL", CellString(sc.doubled_cell)));
Add(s, Blank());
Add(s, Prose(
" SUPERCELL_CLASS is the half-integer class (parity of h, k, l in the primitive cell of the\n"
" lattice) with the most intensity over 20-3 A, read on 60 frames. OCCUPANCY is its mean\n"
" intensity against the lattice's own reflections; ROCK is the part of it that follows the\n"
" partiality the way a Bragg reflection does, on the same scale. A class near zero on both is\n"
" empty. One that is occupied and rocks is an index-2 superstructure the lattice does not\n"
" index: its reflections are not integrated. To process on the doubled lattice, give\n"
" SUPERCELL_DOUBLED_CELL with -C. An occupied class that does not rock is diffuse or\n"
" disordered intensity rather than Bragg reflections."));
Add(s, Blank());
}
// ---- powder contamination
// A crystalline phase other than the crystal, diffracting as rings among its reflections.
// Measured in the pre-scan on every run, from the spots found there for the width and the
+29
View File
@@ -5312,6 +5312,35 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b
}
logger.Info("Supercell probe (the eight parity classes of the doubled primitive cell; <I/sigma>, "
"mean intensity, and the fit I = a + b p against the lattice's own):{}", table);
// The class with the most intensity over 20-3 A goes into the report, with the cell it would
// double the lattice to: the vectors t of the primitive lattice with (h,k,l).t even - twice
// one axis the class is odd on, and each other axis plus that one where the class is odd
// on it too - Niggli-reduced.
const auto band = [&](int c) { SupercellProbeClass x = probe[c][0]; x += probe[c][1]; return x; };
const SupercellProbeFit f0 = FitSupercellProbe(band(0));
const auto prim = indexer->GetSupercellProbePrimitive();
int best = 0;
for (int c = 1; c < 8; c++)
if (best == 0 || FitSupercellProbe(band(c)).mean_i > FitSupercellProbe(band(best)).mean_i)
best = c;
if (prim && f0.mean_i > 0.0 && f0.b != 0.0) {
const SupercellProbeFit f = FitSupercellProbe(band(best));
const int p[3] = {(best >> 2) & 1, (best >> 1) & 1, best & 1};
const Coord v[3] = {prim->Vec0(), prim->Vec1(), prim->Vec2()};
const int i = p[0] ? 0 : p[1] ? 1 : 2;
Coord t[3];
for (int j = 0; j < 3; j++)
t[j] = j == i ? v[i] * 2.0f : v[j] + v[i] * static_cast<float>(p[j]);
ProcessResult::SupercellClass sc;
sc.h = p[0]; sc.k = p[1]; sc.l = p[2];
sc.occupancy_pct = 100.0 * f.mean_i / f0.mean_i;
sc.rock_pct = 100.0 * f.b / f0.b;
sc.rock_se_pct = 100.0 * f.b_se / f0.b;
sc.i_over_sigma = f.mean_i_over_sigma;
sc.doubled_cell = CrystalLattice(t[0], t[1], t[2]).NiggliReduce().GetUnitCell();
result.supercell = sc;
}
}
}
+10
View File
@@ -362,6 +362,16 @@ struct ProcessResult {
// Higher-order contamination of the beam, read off the spots the lattice did not take. Measured
// on the images themselves, so it is there whether or not anything merged.
HarmonicContaminationResult harmonic;
// The strongest index-2 superstructure class the supercell probe read (20-3 A, 60 frames): which
// parity class of the primitive cell, its mean intensity and the part that rocks like a Bragg
// reflection, both against the lattice's own, and the cell the lattice would double to were it
// real. Report only - nothing decides on it.
struct SupercellClass {
int h = 0, k = 0, l = 0; // parity of the primitive indices
double occupancy_pct = 0.0, rock_pct = 0.0, rock_se_pct = 0.0, i_over_sigma = 0.0;
UnitCell doubled_cell{};
};
std::optional<SupercellClass> supercell;
// Powder contamination measured in the pre-scan: a crystalline phase other than the crystal,
// diffracting as rings among its reflections. Measured and reported on every run.
PowderRings powder;