This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use. * rugnux: Add `--model model.pdb` - score the merged data against an atomic model and compute initial maps. It reports R-work/R-free (scaling the model to the observed amplitudes with an overall scale, an anisotropic B and a flat bulk solvent - the standard few-parameter model, so a batch of maps stays directly comparable) and writes 2Fo-Fc / Fo-Fc electron-density maps (CCP4) plus a map-coefficient MTZ. The structure itself is not refined; the model is only re-fractionalised into the data cell. * rugnux: The merged reflection output now carries French-Wilson amplitudes (|F| and its sigma) next to the intensities - MTZ `F`/`SIGF`, mmCIF `_refln.F_meas_au`, and the text HKL - computed with the correct centric/acentric Wilson prior and epsilon multiplicity, so a downstream program (e.g. phenix.refine) can refine against amplitudes. The intensity columns are unchanged. * rugnux: R-free test-set flags are now assigned deterministically and consistently across symmetry - a Bijvoet pair I(+)/I(-) is never split between the work and free sets, and the assignment is a reproducible per-hkl hash that depends only on the reflection index, so every dataset of one crystal form gets the same ~5% free set (what a multi-dataset campaign such as PanDDA needs). On small data the fraction is floored so the test set stays large enough for a stable R-free (~500 reflections, capped at 10%); it stays flat at 5% on ordinary data. When a reference MTZ carries a `FreeR_flag` column its test set is imported instead, letting a whole campaign inherit one shared free set. * rugnux: A reference MTZ (`--reference-mtz`) can now fix the space group and cell for rotation data too (previously rejected), without being used to scale - the rotation merge stays self-consistent. When the crystal has an indexing (merohedral) ambiguity - a lattice symmetry higher than its Laue symmetry, e.g. P3/P4/P6/C2 - the reference also resolves it: each candidate reindexing (identity plus the twin-law cosets of the metric symmetry) is scored by its intensity correlation against the reference and the data are re-merged in the best-correlating one. This is a metric-preserving relabelling of hkl (the cell is unchanged) and a no-op for a holohedral crystal such as lysozyme. * rugnux: `--model` validation now aligns the data to the model before scoring - the observed reflections are reindexed into the model's enantiomorph when the two differ only by hand (indistinguishable from merged intensities). A merohedral indexing ambiguity is resolved against the reference MTZ when one is given (so a whole campaign shares one indexing convention); only with a model and no reference does validation fall back to fitting each candidate reindexing and keeping the lowest R-free. * rugnux: De-novo symmetry - recover a genuine high-symmetry group whose data are imperfectly scaled. Such a merge's within-orbit chi² lands just past the self-consistency bound (each real symmetry step adds a little systematic scatter), right where a merohedral twin also lands, so the chi² ratio alone cannot separate them. The candidate is now rescued when the extra intensity-proportional systematic error it invokes stays small relative to the confirmed subgroup - a genuine symmetry step gains multiplicity without inflating the merge error model's b, whereas a twin forces non-equivalent reflections together and b balloons. Fixes cubic insulin (I23 instead of I222) with no change to any other crystal in the test battery, including the twins that must stay in their lower symmetry. * Docs: Document the French-Wilson amplitude estimation, R-free flagging, reference-based space-group/ambiguity resolution, and model-based validation/maps in CPU_DATA_ANALYSIS.md. * Frontend: The status-bar pill now shows a progress bar during detector calibration (previously only during measurement), and the calibration state and its button are labelled "Calibration"/"CALIBRATE" (the internal `Pedestal` state name is unchanged for back-compatibility).Reviewed-on: #70 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
62 KiB
CPU-side crystallographic data analysis (Jungfraujoch)
This document describes the crystallographic algorithms implemented in Jungfraujoch for CPU- and GPU-side real‑time and near‑real‑time data analysis.
Scope. The pipeline covered here comprises:
- geometry mapping and corrections,
- azimuthal integration (powder/radial profiles),
- Bragg spot finding (strong pixels → connected components → spot descriptors),
- indexing (still and rotation modes),
- Bravais lattice / centering inference,
- geometry and lattice refinement,
- reflection prediction (still and rotation),
- Bragg integration by either 2D box summation or profile fitting (Kabsch, reference-free),
- scaling and merging,
- merge-level error modelling and outlier rejection,
- auxiliary statistics (Wilson plot, ⟨I/σ(I)⟩, CC1/2, CCref),
- amplitude estimation (French–Wilson) and R-free test-set flagging,
- optional model-based validation: R-free against a supplied model and 2Fo−Fc / Fo−Fc electron-density maps.
References
The methods are inspired and reuising solutions implemented in:
- W. Kabsch, “XDS”, Acta Cryst. D66 (2010), 125–132 and related XDS papers (rotation geometry, partiality, scaling concepts).
- W. Kabsch, “Integration, scaling, space-group assignment and post-refinement”, Acta Cryst. D66 (2010), 133–144 (mosaicity/partiality likelihood treatment; notation such as ζ and rotation factors).
- T. A. White et al., CrystFEL method papers (spot finding, three‑ring integration, serial/still diffraction processing concepts).
- J. Kieffer & J. P. Wright, "PyFAI: a Python library for high performance azimuthal integration on GPU", Powder Diffraction 28 (2013), S339-S350 (detector geometry definition, azimuthal integration)
- H. Powell, "The Rossmann Fourier autoindexing algorithm in MOSFLM", Acta Cryst. D55 (1999), 1690-1695 (FFT indexing)
- S. French & K. Wilson, "On the treatment of negative intensity observations", Acta Cryst. A34 (1978), 517-525 (Bayesian amplitude estimation from intensities).
- A. T. Brünger, "Free R value: a novel statistical quantity for assessing the accuracy of crystal structures", Nature 355 (1992), 472-475 (R-free cross-validation).
- M. Wojdyr, "GEMMI: A library for structural biology", J. Open Source Softw. 7 (2022), 4200 (model / structure-factor / map machinery used in §14). (list is not exhaustive)
1. Geometry, reciprocal-space mapping, and basic quantities
1.1 Coordinate conventions
For a pixel coordinate (x,y) (in pixels), Jungfraujoch converts to a laboratory direction vector via:
- shift by direct-beam position
(x_\mathrm{beam}, y_\mathrm{beam}), - scale by pixel size
p(mm), - set detector distance
D(mm), - apply detector orientation rotation
R_\mathrm{det}(PyFAI-like parameterization).
The unnormalized detector coordinate (mm) is: $ \mathbf{r}\mathrm{det}(x,y) = \begin{pmatrix} (x-x\mathrm{beam})p\ (y-y_\mathrm{beam})p\ D \end{pmatrix}. $
The lab-frame vector is: $ \mathbf{r}\mathrm{lab} = R\mathrm{det},\mathbf{r}_\mathrm{det}. $
Let the incident wavevector magnitude be k = 1/\lambda in Å^{-1}, and define:
$
\mathbf{S}_0 = (0,0,k).
$
The reciprocal-space scattering vector associated with pixel (x,y) is:
$
\mathbf{s}(x,y) = k,\frac{\mathbf{r}\mathrm{lab}}{\lVert \mathbf{r}\mathrm{lab}\rVert} - \mathbf{S}_0.
$
This \mathbf{s} is the fundamental quantity used for spot finding (resolution filters), indexing, and refinement.
1.2 Two-theta, azimuth, resolution and q
The scattering angle 2\theta is computed from \mathbf{r}_\mathrm{lab} via:
$
2\theta = \arctan!\left(\frac{\sqrt{x_\mathrm{lab}^2 + y_\mathrm{lab}^2}}{z_\mathrm{lab}}\right).
$
Resolution (Å) at a pixel is: $ d = \frac{\lambda}{2\sin(\theta)} = \frac{\lambda}{2\sin(2\theta/2)}. $
The magnitude q = 2\pi/d is used for radial binning and ice-ring handling.
1.3 Distance from the Ewald sphere
For a reciprocal lattice point \mathbf{p} (Å^{-1}), define:
$
\Delta_\mathrm{Ewald}(\mathbf{p}) = \lVert \mathbf{p} + \mathbf{S}_0\rVert - k.
$
Jungfraujoch uses |\Delta_\mathrm{Ewald}| as an operational proxy for excitation error. This appears in:
- still prediction (accept if
|\Delta_\mathrm{Ewald}|\le \Delta_\mathrm{cut}), - profile radius estimation (see §11.1),
- still partiality option in scaling/merging (§10.2).
2. Azimuthal integration (radial profiles)
Azimuthal integration produces a radial profile I(q) or I(d) by histogramming pixels into radial bins. Pixels are not split across bins; each pixel contributes wholly to a single bin. By default the profile is purely radial (a single azimuthal bin), but the azimuth can optionally be split into up to 512 \phi sectors (azim_bins, --azim-phi-bins), giving a 2D q\times\phi profile that exposes azimuthal anisotropy such as detector shadowing or sample texture.
2.1 Histogram estimator
Let bin index b(x,y) be precomputed from q(x,y) (or equivalently from d(x,y)) and, when \phi sectors are enabled, the azimuth \phi(x,y) — so b = b_q + b_\phi B_q. For each bin b:
- accumulate corrected intensity and its square: $ S_b = \sum_{(x,y):,b(x,y)=b} I(x,y),C(x,y),\qquad S^{(2)}_b = \sum I(x,y)^2,C(x,y)^2, $
- and count: $ N_b = #{(x,y):,b(x,y)=b \text{ and pixel is valid}}. $
The profile reports both the mean \bar{I}_b = S_b / N_b (when N_b>0) and a per-bin sample standard deviation \sigma_b = \sqrt{(S^{(2)}_b - S_b^2/N_b)/(N_b-1)} (a spread/error estimate for each radial point). Invalid pixels (masked, saturated, detector error codes) are excluded.
2.2 Corrections applied
Two standard corrections are available:
(i) Solid angle / geometric correction. A flat pixel's solid angle falls off with the incidence angle \alpha between the scattered ray and the detector normal. With the in-plane detector offsets u=(x-x_\mathrm{beam})p and v=(y-y_\mathrm{beam})p (§1.1) and detector distance D,
$
\cos\alpha = \frac{D}{\sqrt{u^2+v^2+D^2}},\qquad
C_\Omega = \cos^3\alpha,
$
applied — like the polarization term below — as a divisor (intensities are scaled by 1/\cos^3\alpha), so pixels at oblique incidence, which subtend a smaller solid angle, are boosted. Because \alpha is evaluated in the detector's own frame it is invariant under detector tilt (\mathrm{rot1}/\mathrm{rot2}/\mathrm{rot3}), matching PyFAI's solidAngleArray and MAX IV azint. It reduces to the commonly quoted \cos^3(2\theta) form only for an untilted detector, where the incidence angle coincides with the scattering angle.
(ii) Polarization correction. With polarization coefficient P (beamline dependent) and azimuth \phi:
$
C_\mathrm{pol}(2\theta,\phi) =
\frac{1}{2}\left(1+\cos^2(2\theta) - P\cos(2\phi)\left(1-\cos^2(2\theta)\right)\right),
$
applied as a divisor to intensities (i.e. scale by 1/C_\mathrm{pol}) when enabled.
2.3 Background estimate for profiles
A background estimate is derived from the profile as its mean intensity over a fixed low-to-mid Q window (default 2\pi/5 to 2\pi/3 Å^{-1}). This background is used for monitoring and diagnostics; it is not the same as the local Bragg-spot background used in summation integration (§9.2).
3. Spot finding (strong pixels → Bragg spots)
Spot finding is a two-stage process:
- Strong-pixel selection using intensity and/or local signal-to-noise criteria.
- Connected-component labeling (CCL) to group strong pixels into candidate spots, followed by spot-level filtering and feature extraction.
3.1 Strong-pixel detection by local statistics
For each pixel i with value v_i, consider a square window (nominally 31\times 31 pixels) around it. Let the window contain n valid pixels (excluding masked/bad/saturated), and define:
$
\Sigma = \sum v,\qquad \Sigma_2 = \sum v^2.
$
To avoid biasing the local statistics by the test pixel itself, Jungfraujoch evaluates the pixel against the window with the pixel removed: $ \Sigma' = \Sigma - v_i,\quad \Sigma_2' = \Sigma_2 - v_i^2,\quad n' = n-1. $
A variance-like quantity proportional to n'^2 is formed:
$
V = n'\Sigma_2' - (\Sigma')^2,
$
and the deviation-from-mean quantity:
$
\Delta = v_i n' - \Sigma'.
$
A pixel is considered strong if:
- it is above a photon/count threshold, and
- its window contains enough valid neighbours (more than 100), so the local statistics are meaningful, and
\Delta>0, and- the squared deviation exceeds a scaled variance:
$
\Delta^2 > V\cdot T^2,
$
where
Tis the configured signal-to-noise threshold.
This is equivalent to a local z-score criterion but implemented in integer arithmetic to be robust and fast.
Special cases:
- saturated pixels can be forced to “strong” (useful for detecting overloaded Bragg spots),
- invalid pixels are never strong.
3.2 Resolution and ice-ring handling
Spot finding can be restricted to a resolution range [d_\mathrm{high}, d_\mathrm{low}] by masking pixels outside the range. Optionally, spots in identified ice-ring regions can be tagged so that subsequent indexing/refinement may include or exclude them (see §4 and §6).
A single per-image ice-ring score is derived from the azimuthally-integrated radial profile: for each hexagonal-ice powder ring (positions d from Moreau et al., Acta Cryst D77, 2021), the profile intensity at the ring is divided by a smooth background estimated from the whole profile — a running median of the non-ice bins, interpolated under each ring — and the strongest ring's ratio is reported (1 = no ice, >1 = ice above background). A whole-profile background is used rather than a couple of adjacent shoulder bins so the estimate is robust to the radial binning: at a coarse Q-spacing a local shoulder can be only ~1 bin and would double-count the ring's own edge (offline processing defaults to a fine 0.01 1/Å spacing, --azim-q-spacing, so the rings are well resolved). (A significance/z-score was considered but is uninformative here: with many photons any real ice ring is highly significant, so the discriminating quantity is the ice magnitude, i.e. this ratio.) It is stored per image (ice_ring_score, HDF5 /entry/MX/iceRingScore) as a monitoring quantity, distinct from the merge-time ice masking, which is data-driven from the per-ring merged CC1/2.
A further optional safeguard removes isolated high-resolution “spur” spots by detecting large gaps in 1/d (or q) space and discarding spots beyond the gap. This is intended for macromolecular diffraction where edge-of-detector backgrounds can be extremely low.
3.3 Connected-component labeling (CCL)
Strong pixels are grouped into connected components (adjacent strong pixels) using a CCL algorithm. Each component yields a candidate spot with:
- centroid
(x,y)(often intensity-weighted), - pixel count (spot size),
- integrated spot intensity proxy (sum of pixel values),
- resolution
dat the centroid (or mean over pixels), - and quality flags (e.g. ice-ring classification).
Spot-level filters include minimum/maximum pixel count and resolution limits.
4. Indexing overview
Indexing maps observed reciprocal-space vectors \mathbf{s}_i to a lattice such that:
$
\mathbf{s}_i \approx h_i\mathbf{a}^* + k_i\mathbf{b}^* + l_i\mathbf{c}^*,
$
with integer (h_i,k_i,l_i).
Jungfraujoch supports two complementary indexing strategies:
- FFT-based indexing (Rossmann-type): does not require an a priori unit cell; suitable for unknown samples.
- Fast-feedback indexing (TORO-like): requires an approximate unit cell; optimized for speed and feedback.
Both feed into a common robust refinement/selection stage which maximizes the number of inliers under an indexing tolerance, and which can return more than one lattice per image (multi-lattice indexing; see §5.4).
4.1 Indexed-spot decision (inlier test)
Given a trial lattice with direct basis vectors \mathbf{a},\mathbf{b},\mathbf{c} (used here as reciprocal-space dot-test vectors), fractional indices are estimated by:
$
h_f = \mathbf{s}\cdot\mathbf{a},\quad
k_f = \mathbf{s}\cdot\mathbf{b},\quad
l_f = \mathbf{s}\cdot\mathbf{c}.
$
Let (h,k,l)=(\mathrm{round}(h_f),\mathrm{round}(k_f),\mathrm{round}(l_f)) and define the fractional residual:
$
\delta^2 = (h_f-h)^2 + (k_f-k)^2 + (l_f-l)^2.
$
A spot is indexed if \delta^2 < \tau^2, where \tau is the configured tolerance.
For indexed spots, the reciprocal lattice point \mathbf{p} = h\mathbf{a}^*+k\mathbf{b}^*+l\mathbf{c}^* is used to compute \Delta_\mathrm{Ewald}(\mathbf{p}) (stored as a diagnostic and later used in profile-radius estimation).
5. FFT indexing (unknown unit cell)
FFT indexing follows a classical approach: detect dominant periodicities by projecting reciprocal-space points onto many directions and Fourier transforming the resulting 1D histograms.
5.1 Directional projections and histograms
Choose a set of unit vectors \{\mathbf{u}_d\} on a half-sphere (a near-uniform distribution generated via a golden-angle construction). For each direction d, form a histogram in the scalar projection:
$
t_{id} = \left|\mathbf{u}_d\cdot \mathbf{s}_i\right|.
$
Bin width is chosen approximately as:
$
\Delta t \approx \frac{1}{2 L_\mathrm{max}},
$
where L_\mathrm{max} is the maximum expected real-space unit-cell edge (Å). The histogram extent is tied to the maximum q used (set by a high-resolution cutoff for indexing).
5.2 FFT peak picking and candidate vectors
For each direction, the FFT magnitude spectrum is computed; peaks correspond to periodicities along \mathbf{u}_d. Each direction yields a candidate real-space length L chosen not by raw magnitude but by maximum prominence above a running-mean local background (subtracting the broad low-frequency envelope that otherwise dominates on weak or pink-beam frames), subject to L\ge L_\mathrm{min}.
Candidate vectors are \mathbf{v}_d = L_d\,\mathbf{u}_d.
A collinearity filter removes nearly parallel vectors (e.g. within 5°) and attempts to resolve harmonic ambiguity: shorter “fundamental” vectors may be preferred over longer harmonics if their peak magnitude is sufficiently strong relative to the dominant peak.
5.3 Lattice reduction and cell candidates
Triples of candidate vectors are combined to form candidate bases (\mathbf{A},\mathbf{B},\mathbf{C}), each reduced to its Niggli-reduced cell (Gruber-vector reduction) before comparison, and filtered by allowed length and angle ranges. Two passes are run: a standard pass forms shortest-vector triples from the ~30 strongest filtered directions; if the best cell then indexes fewer than half the spots, a widened fallback anchors the two shortest axes and lets the third range over up to ~60 candidate vectors (deduplicated by Niggli cell), catching large, elongated or superstructure cells the first pass misses.
5.4 Robust refinement and best-cell selection
Candidate bases are refined against observed spots using an iterative inlier‑focused least‑squares procedure (trimmed/contracting threshold). Candidates are then ranked:
- more indexed spots wins — unless two candidates index within ~10 % of each other, in which case
- the smaller-volume cell is preferred (when the volumes differ by more than ~5 %), avoiding a doubled supercell, then
- the smaller refinement score, then the spot count again.
Selection is not limited to a single lattice: after the best cell is accepted, further lattices are added as separate crystals provided fewer than ~40 % of their indexed spots overlap an already-accepted lattice (up to two extra by default), so split or multi-lattice crystals are indexed rather than discarded.
An optional reference unit cell (if supplied) restricts acceptance to cells within a relative distance tolerance in edge lengths (permutation-invariant).
6. Bravais lattice / centering inference (“lattice search”)
If the space group is supplied by the user, its lattice constraints are assumed for refinement and subsequent processing.
If not, Jungfraujoch attempts to infer the most plausible Bravais lattice type from the metric tensor after Niggli reduction:
- Niggli reduction is performed to obtain a reduced cell in
G^6representation (Gruber vector). - The reduced cell is compared against a list of Niggli classes corresponding to Bravais lattices and centerings.
- The highest-symmetry class that matches within tolerances is selected (relative metric tolerance and angular tolerance).
The output includes:
- a conventional cell,
- crystal system (triclinic, monoclinic, …),
- centering symbol (one of
P, C, I, F, R; theA/Bvariants are not emitted here — they are handled only later as prediction absences, §8.4).
This stage provides centering information used for systematic absences in prediction (§8.4) and for reporting.
Note. In ambiguous or special cases, forcing space group to P1 (no symmetry assumptions) is recommended.
7. Geometry and lattice refinement
Refinement adjusts experimental geometry and crystal parameters to minimize discrepancies between observed spot reciprocal vectors and those predicted by a lattice model with integer indices.
7.1 Parameterization
The refinement jointly optimizes, depending on mode and constraints:
- beam center
(x_\mathrm{beam}, y_\mathrm{beam}), - detector distance
D, - detector tilt angles (two-angle model; third rotation often held at 0),
- rotation axis direction (for rotation datasets),
- crystal orientation (a global rotation),
- unit-cell parameters, with constraints determined by inferred crystal system.
By default only the beam center, unit cell and crystal orientation are refined; the detector distance, tilt angles and rotation-axis direction are held fixed unless explicitly enabled. A lighter orientation-only mode refines just the crystal orientation (with a weak small-rotation prior on the poorly-determined out-of-plane component), for stills whose geometry is already trusted.
For higher symmetries, constraints are enforced, e.g.
- cubic:
a=b=c,\ \alpha=\beta=\gamma=90^\circ, - tetragonal:
a=b, - hexagonal:
a=b,\ \gamma=120^\circ, - monoclinic (unique axis
b):\alpha=\gamma=90^\circ,\betarefined.
7.2 Residuals and objective
For each indexed spot assigned integer (h,k,l), compute:
- observed reciprocal vector
\mathbf{s}_\mathrm{obs}from its detector position and current geometry, - predicted reciprocal vector
\mathbf{s}_\mathrm{pred}(h,k,l;\ \text{lattice params}).
Residual is: $ \mathbf{r} = \mathbf{s}\mathrm{obs} - \mathbf{s}\mathrm{pred}. $
A non-linear least squares solver minimizes \sum \|\mathbf{r}\|^2 over all selected inlier spots.
7.3 Rotation datasets: bringing observations to a common reference frame
For oscillation/rotation data, each image corresponds to a rotation angle \phi about an axis \mathbf{m}_2. Observed reciprocal vectors are rotated “back to start” so that all images are refined in a single reference crystal frame:
$
\mathbf{s}\mathrm{obs,ref} = R(\phi),\mathbf{s}\mathrm{obs},
$
with R(\phi) constructed from the axis-angle representation of the goniometer model. The angle \phi is taken at the centre of each frame's oscillation (the frame angle plus half the oscillation width).
7.4 Multi-stage tightening of inlier tolerance
Refinement is performed in stages with decreasing acceptance tolerance for including reflections (three stages, indexing tolerance 0.3\to0.2\to0.1), which stabilizes convergence when starting from imperfect indexing and approximate geometry.
7.5 Rotation geometry post-refinement (two-pass)
The refinement above (§7.2) runs per image against that image's spots. For rotation data an additional post-refinement (on by default; --rotation-no-postrefine disables it) improves the detector distance, beam centre and crystal cell/axis using all frames at once, then re-integrates:
- Pass 1 integrates, scales and merges at the header geometry.
- Against the merged fulls, the shared detector distance and beam centre and the crystal cell / goniometer-axis are refined jointly over all frames (Ceres, robust loss). The fit is cross-validated on a deterministic frame split — refined on one half, gated on the held-out half — and the geometry is committed only for a small move (a distance/beam shift under ~1 %); a larger move is treated as a fit instability and rejected. The beam centre is gauge-weak in a rotation series (it trades off against the crystal orientation), so it is restrained toward the header value.
- Pass 2 re-indexes de novo and re-integrates at the committed geometry, reusing pass-1's space group for the merge only.
The refined pass is written as the canonical <prefix>_* output; the pass-1 (header-geometry) result is kept alongside as <prefix>_01_* for comparison.
8. Reflection prediction
Jungfraujoch predicts reflection positions for integration by enumerating Miller indices within a resolution cutoff and accepting those that satisfy a diffraction condition model.
8.1 Enumerating reciprocal lattice points
For a maximum resolution d_\mathrm{min}, accept (h,k,l) such that:
$
\lVert \mathbf{p}(h,k,l)\rVert^2 = \lVert h\mathbf{a}^* + k\mathbf{b}^* + l\mathbf{c}^*\rVert^2 \le \left(\frac{1}{d_\mathrm{min}}\right)^2.
$
8.2 Still prediction (excitation-error cutoff)
For still images, the diffracting condition is approximated by an excitation-error cutoff:
$
\left|\Delta_\mathrm{Ewald}(\mathbf{p})\right| \le \Delta_\mathrm{cut}.
$
Accepted reflections are projected to the detector by intersecting the diffracted direction \mathbf{S}=\mathbf{S}_0+\mathbf{p} with the detector plane, using the current geometry.
When the beam has a finite energy bandwidth, this window is broadened radially per reflection: the cutoff is combined in quadrature with a bandwidth smear, \sqrt{\Delta_\mathrm{cut}^2 + (3\,\sigma_\mathrm{bw})^2}, where \sigma_\mathrm{bw}\propto|p_z| (the reciprocal-space depth along the beam, growing as \sim 1/d^2). This keeps high-resolution reflections — smeared by the bandwidth into radial streaks — from being clipped. The same \sigma_\mathrm{bw} is deconvolved from the measured profile radius (§11.1), so it is not double-counted.
8.3 Rotation prediction (Laue equation + partiality model)
For rotation/oscillation datasets, Jungfraujoch solves for rotation angles \phi where the rotated reciprocal lattice point satisfies the Ewald-sphere condition. In an XDS-like notation, define:
- rotation axis unit vector
\mathbf{m}_2, \mathbf{S}_0incident vector,\mathbf{S}(\phi)=\mathbf{S}_0+\mathbf{p}(\phi).
A key quantity is: $ \zeta = \left|\mathbf{m}_2\cdot \mathbf{e}_1\right|,\quad \mathbf{e}_1 = \frac{\mathbf{S}\times \mathbf{S}_0}{\lVert \mathbf{S}\times \mathbf{S}_0\rVert}, $ which also appears in XDS as the Lorentz component linked to the rotation axis.
A Gaussian mosaicity model yields a partiality fraction over an oscillation width \Delta\phi:
P(\phi;\sigma_M,\zeta,\Delta\phi) = \frac{1}{2}\left[\mathrm{erf}\!\left(\frac{\phi+\Delta\phi/2}{\sqrt{2}\,\sigma_M/\zeta}\right) - \mathrm{erf}\!\left(\frac{\phi-\Delta\phi/2}{\sqrt{2}\,\sigma_M/\zeta}\right)\right],
with mosaicity \sigma_M in radians.
Reflections are predicted if they meet minimum \zeta and mosaicity-window criteria, and their predicted detector coordinates fall on the active detector area.
8.4 Systematic absences (centering)
Systematic absences are applied at least at the centering level (prior to full space-group symmetry). For centering symbol C:
I: absent ifh+k+lodd,A: absent ifk+lodd,B: absent ifh+lodd,C: absent ifh+kodd,F: absent if any ofh+k, h+l, k+lis odd,R: absent if(-h+k+l)\bmod 3 \ne 0,P: no centering absences.
9. 2D Bragg integration (profile fitting over a three-ring ROI)
Jungfraujoch integrates each predicted reflection in the detector plane over a CrystFEL-inspired “three-ring” region of interest (§9.1). The default extraction is profile fitting (Kabsch; §9.3), which weights each pixel by a fitted spot profile and so recovers weak reflections far better than plain summation; plain box summation (§9.2) is retained as the seed for the profile and as a fallback. Both methods share the same ROI and background model, and emit the same per-reflection (I,\sigma,\text{partiality},d), so scaling, the rotation combine (§10.6) and merging consume either unchanged.
9.1 Regions of interest
For each predicted reflection at (x_p,y_p), define three radii:
r_1: inner signal radius,r_2: inner background radius,r_3: outer background radius.
Pixels are classified by their squared distance r^2=(x-x_p)^2+(y-y_p)^2:
- signal region:
r^2 < r_1^2, - background annulus:
r_2^2 \le r^2 < r_3^2.
Invalid pixels (masked/bad/saturated) are excluded from both sums. In addition, pixels lying inside the signal disk (r<r_2) of any other predicted reflection are removed from this reflection's background annulus, so a neighbouring spot cannot leak into the background estimate.
9.2 Box summation (seed and fallback)
Let:
S = \sum I(x,y)over signal pixels,n_S= number of valid signal pixels,B = \sum I(x,y)over background pixels,n_B= number of valid background pixels.
Background per pixel and integrated intensity:
$
\hat{b} = \frac{B}{n_B},\qquad
\hat{I} = S - n_S \hat{b},
$
with a Poisson-like uncertainty \sigma(\hat{I})=\max\!\big(1,\ r_\sigma\hat{I},\ \sqrt{S}\big), i.e. \sqrt{S} floored both at 1 and at a small fraction r_\sigma of the intensity. A reflection is accepted as “observed” only if all signal pixels were valid and n_B exceeds a minimum. This box sum is the classical estimator; it is used directly with --integrator boxsum, and otherwise seeds the profile fit below.
Trimmed-mean background (monochromatic, default on). On monochromatic data — rotation and still (the discriminator is the beam, not the acquisition mode) — the ring mean \hat{b} is by default replaced with a symmetric trimmed mean: the ring pixels are sorted, the lowest and highest fraction f are dropped, and the central (1-2f) are averaged (f=0.10 by default, --background-trim; f=0 restores the plain mean). Because \hat{I}=S-n_S\hat{b} is a small difference of large numbers for weak reflections, a per-pixel background bias \delta\hat{b} becomes a fractional intensity bias \approx n_S\,\delta\hat{b}/\hat{I} that grows as \hat{I} shrinks — worst at the resolution edge. The plain mean reads high there because neighbour-spot wings that survive the signal-disk mask, tails and zingers are one-sided (positive) contaminants; dropping the extreme ring pixels removes that bias while a clean Poisson ring is essentially unchanged. In practice this lowers the resolution-edge R_\text{meas} several-fold, raises \langle I/\sigma\rangle, and rescues the high-resolution CC${1/2}$ on data where the plain mean had collapsed it (at a small CC${1/2}$ cost in already-clean shells, from the slightly higher variance of the trimmed estimate). It is applied to the shared background used by both the box sum and the profile fit.
For the profile-fit path on broadband (non-zero bandwidth: pink-beam / DMM) data, the trimmed mean is not used; instead the background mean is computed with a single high-outlier reject (drop ring pixels above \hat{b}+3\sqrt{\hat{b}}, then recompute): a bandwidth-streaked high-resolution spot or a close neighbour can leak into the ring and bias the mean high, over-subtracting and driving weak high-resolution intensities negative. A clean Poisson background is essentially unchanged by the cut. Neither robustification is applied to plain box summation (--integrator boxsum).
9.3 Profile-fitted extraction (default)
A fixed signal disk captures a width-dependent fraction of each spot, which puts a multiplicative floor on the per-observation precision of strong reflections and weights weak reflections poorly. Profile fitting removes this by extracting each intensity against a fitted spot shape, without needing reference intensities. Per frame:
-
Seed. Box-sum every reflection (§9.2) to get a rough intensity and observed centroid, and select strong spots (significance
\ge 5). -
Build the profile. For
gaussian(the default) the width is taken per resolution shell from the measured second moment of the strong spots (shell-dependent because spot size grows with resolution); the intrinsic spot is essentially round in the detector plane (per-detector-region and crystal-anisotropy profiles were evaluated and add nothing — the real crystal anisotropy lives in the discarded rocking direction). Forempiricalthe profile is instead the averaged, centroid-aligned, background-subtracted pixel grid of the shell's strong spots. Either way the profile is then rebuilt for each reflection, centred on its sub-pixel predicted position (the noise-free geometric centre, not the observed centroid) and, where needed, elongated only along the radial direction (away from the beam centre) — because two effects stretch a spot radially but not tangentially:- a finite energy bandwidth smears each spot by
\sigma_\mathrm{bw}=\text{bandwidth}\cdot R_\mathrm{px}(R_\mathrm{px}= distance from the beam centre, large at high resolution), and - sensor parallax — the depth over which a photon converts in a thick Si/CdTe sensor — adds a term
\propto\tan^2(2\theta)(material- and energy-dependent), plus, on the monochromatic path, a small fixed weak-spot capture term.
These combine as
\sigma^2_\mathrm{radial}=\sigma^2_\mathrm{intrinsic}+\sigma_\mathrm{bw}^2+c_\mathrm{par}\tan^2(2\theta)(tangential unchanged), on a grid grown to hold the streak — capturing it without the tangential background an isotropic widening would add. - a finite energy bandwidth smears each spot by
-
Fit (Kabsch). With profile
P, backgroundBand the shell variance model, the intensity and its uncertainty are $ I = \frac{\sum P,(c-B)/v}{\sum P^2/v},\qquad \sigma = \sqrt{\frac{1}{\sum P^2/v}},\qquad v = B + \max(I,0),P, $ wherecis the pixel value and the de-biased variancev(background plus model signal, rather than the down-fluctuating observed count) is iterated (a few passes). As a guard, if the profile intensity runs away from the box-sum seed (by more than ~10 box-sum\sigma) it falls back to the seed, and the variance floors the background at1/12(the integer-binning pixel-variance floor). The rotation/excitation partiality is carried exactly as in the box-sum path.
The integrator is selected by --integrator boxsum|gaussian|empirical (default gaussian).
9.4 Lorentz–polarization factor handling
For integrated reflections, polarization correction can be applied as a multiplicative correction to the reflection scale via the geometry-based polarization term (§2.2). A Lorentz-like factor is carried as rlp in predictions, and used during scaling/merging (§10).
10. Scaling and merging
After per-image integration, Jungfraujoch scales observations and merges them into unique reflections. The design is intentionally compatible with XDS/XSCALE concepts, and handles both still and rotation data.
10.1 Observation model
For an observation j of a unique reflection h on image (or image group) i, the predicted measured intensity is modeled as:
$
I_{ij} \approx G_i , L_{ij}, P_{ij}, I_h,
$
where:
G_iis the image scale factor,L_{ij}is a Lorentz-like / geometry factor (stored asrlpor derived),P_{ij}is a partiality term (model-dependent),I_his the merged (true) intensity parameter for that unique reflection.
A least-squares objective is minimized: $ \sum_{ij} \left(\frac{I_{ij}^{\mathrm{pred}} - I_{ij}^{\mathrm{obs}}}{\sigma_{ij}}\right)^2 $ solved by robust (Cauchy) weighted least squares, with optional post-fit smoothing of the per-frame scales for rotation series (§10.3).
10.2 Partiality models
The partiality applied is fixed by the data type and scaling stage, not chosen from a user menu:
-
Rotation partiality (XDS-like; see §8.3), used for the per-frame scaling of rotation partials: $ P_{ij} = \frac{1}{2}\left[ \mathrm{erf}!\left(\frac{\Delta\phi_{ij}+\Delta\phi/2}{\sqrt{2},\sigma_{M,i}/\zeta_{ij}}\right) - \mathrm{erf}!\left(\frac{\Delta\phi_{ij}-\Delta\phi/2}{\sqrt{2},\sigma_{M,i}/\zeta_{ij}}\right) \right]. $ The mosaicity
\sigma_{M,i}is measured once per image at indexing (MLE, §11.2) and held fixed during scaling — only smoothed in frame order (§10.3), never re-refined (it is degenerate with the scaleG; §11.2). -
Unity (
P_{ij}=1): used for the scale-on-fulls refit (§10.6), where each observation is already a complete reflection. -
Fixed: use the per-reflection partiality carried from prediction. Still/serial images are predicted with
P=1by default, so their scaling is effectively unity/fixed. An optional excitation-error still-partiality model (--still-partiality) instead weights each stills reflection by a Gaussian\exp(-\Delta_\mathrm{Ewald}^2/2\sigma^2)in its distance from the Ewald sphere, with a companion merge term (--partiality-uncertainty) that adds an intensity- and $(1-P)$-proportional sigma to down-weight the least-complete reflections.
Reflections below a minimum partiality can be rejected from merging to avoid unstable corrections.
10.3 Smoothing of per-frame scales
The per-frame scales G_i are fit by robust (Cauchy) inverse-variance-weighted ratios; there is no explicit G\approx1 prior. For rotation datasets, optional smoothing enforces the expectation that scale and mosaicity vary slowly across a sweep: after the per-frame fit, \log G_i (and the mosaicity) are replaced by a centred moving average over a window spanning a configurable rotation range (XDS DELPHI-like; --smooth-g, default 5° for rot3d, off otherwise). It is a post-fit smoothing pass, not a curvature penalty inside the least-squares objective.
10.4 Merging estimator
After refinement, corrected observations are formed: $ I^{\mathrm{corr}}{ij} = \frac{I^{\mathrm{obs}}{ij}}{G_i L_{ij} P_{ij}},\qquad \sigma^{\mathrm{corr}}{ij} = \frac{\sigma^{\mathrm{obs}}{ij}}{G_i L_{ij} P_{ij}}. $
Unique intensities are merged by inverse-variance weighted mean: $ I_h = \frac{\sum_j w_j I^{\mathrm{corr}}{ij}}{\sum_j w_j},\qquad w_j = \frac{1}{(\sigma^{\mathrm{corr}}{ij})^2}. $
An internal-consistency term can inflate uncertainties when multiple observations are present, in the spirit of XSCALE.
10.5 Merging statistics
Per-shell and overall merging statistics are computed on corrected intensities, including:
- number of observations and of unique reflections, and multiplicity,
- mean
I/\sigma(I), R_\mathrm{meas}(the redundancy-independent Diederichs–Karplus form) from within‑HKL deviations,\mathrm{CC}_{1/2}(half-set correlation) and, when a reference dataset is supplied,\mathrm{CC}_\mathrm{ref},- completeness against the enumerated reflections for the cell and symmetry,
- the anomalous signal-to-noise
\mathrm{SigAno}(below).
The error model is refined as \sigma_\mathrm{corr}^2 = a\,\sigma^2 + (b\,\langle I\rangle)^2, with a set by the scatter of weak (counting-limited) reflections and b the intensity-proportional systematic scatter of the strong ones. ISa is the asymptotic (I\to\infty) signal-to-noise — by definition the reproducibility limit of the strongest reflections (Diederichs, Acta Cryst. D66 (2010) 733) — and is read directly from the strong symmetry equivalents as the counting-subtracted fractional scatter of well-measured reflection groups (a robust median over strong groups; the I/\sigma threshold is relaxed on weak or radiation-damaged data that has few strong reflections), rather than as 1/b of the whole-range fit, whose b is raised slightly by an intermediate-intensity excess and so understates the limit. The reported ISa and the merged-intensity systematic floor \sigma \ge b_\mathrm{ISa}\,|I| both use this asymptotic value, so a high-multiplicity merged I/\sigma approaches ISa; the per-observation \sigma_\mathrm{corr} (the merge weights) uses the whole-range a,b and is unchanged.
Anomalous signal-to-noise (SigAno). The strength of the anomalous signal is reported per shell and overall as \mathrm{SigAno}=\langle|\Delta I|\rangle / \langle\sigma(\Delta I)\rangle, where \Delta I = I(+)-I(-) over acentric reflections measured in both Bijvoet hands and \sigma(\Delta I)=\sqrt{\sigma_+^2+\sigma_-^2}. It is computed from the full-multiplicity inverse-variance I(+)/I(-) split (the same one written to the output), i.e. from all observations rather than a half-set. For pure noise \mathrm{SigAno} approaches the half-normal value \sqrt{2/\pi}\approx0.8, and it rises above 1 once a real anomalous difference is present. A half-set anomalous correlation ("$\mathrm{CC}_\mathrm{anom}$") is deliberately not used: its two half estimates \Delta I_0,\Delta I_1 are complementary partitions of one observation pool (\Delta I_0+\Delta I_1=2\,\Delta I_\mathrm{full}), so subtracting the two Bijvoet hands cancels the large common intensity that keeps \mathrm{CC}_{1/2} non-negative and leaves only the small anomalous signal against the per-half split noise; once the anomalous signal-to-noise per half drops below 1 that correlation is driven towards -1 rather than 0, misrepresenting a weak-but-real signal, whereas \mathrm{SigAno} has no such floor. It is emitted only when an anomalous split was made, using the standard PDBx items _reflns.pdbx_absDiff_over_sigma_anomalous (overall) and _reflns_shell.pdbx_absDiff_over_sigma_anomalous (per shell), and appears as the SigAno column of the printed merge-statistics table.
10.6 Rotation datasets: combining partials into fulls (3D integration)
In a rotation scan a reflection is recorded as a series of partials spread across the frames its rocking curve crosses. Merging those partials directly would force the merge error model to absorb the rocking-curve slicing as if it were measurement noise, capping the achievable I/\sigma. For rotation data Jungfraujoch instead combines each reflection's partials into a single full intensity first, then scales and merges the fulls — a 3D integration over the rocking curve.
The combine groups each reflection's partials into rocking events (contiguous runs of frames) and reduces each event to one full:
- De-biased weighted sum. Partials are combined by inverse-variance weighting, where each partial's variance is its background-noise component plus the model signal shared across the event (Kabsch profile-fit form). Using the shared model signal rather than the individual down-fluctuating intensity stops weak partials from being over-weighted, which would otherwise inflate the merged error model. The weights depend on the full, so the estimate is iterated.
- Captured fraction. The partiality summed over the event,
f=\min(1,\sum_j p_j), measures how completely the rocking curve was sampled. A full whose curve was captured below a threshold (--min-captured-fraction, default 0.7 for rotation) is dropped — an event seen over only a small fraction of its curve is unreliable however many frames it spans. (The per-partial minimum-partiality cut of §10.2 still applies upstream, in the per-frame scaling.) - Capture-aware uncertainty. A full captured incompletely (
f<1) is extrapolated and biased high. The unobserved fraction is charged as an extra systematic uncertainty,\sigma^2 \leftarrow \sigma^2 + \big(c\,(1-f)\,I\big)^2, so the merge down-weights these extrapolated fulls and the error model treats their scatter as expected. It is enabled by default for the rotation path.
The fulls are then re-scaled in the XDS sense — a per-image scale refit directly on the complete reflections under the unity partiality model — and merged (§10.4). Because every merged observation is now a counting-statistics-limited full rather than a partiality-divided slice, the error model reaches a far higher asymptotic I/\sigma.
After scale-fulls, three correction surfaces are fitted on the combined fulls (rotation path, on by default; disable all with --no-scaling-corrections), each an alternating multiplicative refinement of the per-full scale against the merged reference:
- Decay. Radiation damage weakens later frames more at higher resolution — a resolution×time (Debye–Waller) systematic the resolution-flat per-image scale cannot capture. A single global relative-
Brate is fitted,\ln(I_\mathrm{ref}/I_\mathrm{obs}) = 2\,(\mathrm{d}B/\mathrm{d}n)\,(n-\bar n)\,s^2(framen,s^2 = 1/4d^2), and folded into the scale. It engages only when the total relative-Bover the run exceeds a physical floor (2 Ų); below that the decay is negligible and "correcting" it only spreads symmetry equivalents (sames^2, different frames). An optional per-batch relative-$B$ (--relative-b[=deg], off unless requested; 10°-of-rotation batches by default) extends the single global rate to a smoothB(n)curve — the same $s^2$-weighted decay fit solved independently over short frame batches, curvature-penalized so it cannot over-fit and cross-validated like the surfaces below — for crystals whose decay is non-linear in dose. - Absorption. A smooth multiplicative factor over the diffracted-beam direction expressed in the goniometer (crystal) frame: each full's predicted detector position gives the lab diffracted direction, de-rotated by the spindle so a fixed crystal-frame direction is sampled at many rotation angles and its grid cell is well-determined. Negligible at hard X-rays / thin crystals; it matters at low photon energy.
- Modulation (detector-plane flat-field). A smooth multiplicative factor over where each reflection lands on the detector (predicted
x,y): symmetry-equivalents land at different positions as the crystal rotates, over-determining the surface. It absorbs detector-response and geometric systematics that inflateR_\mathrm{meas}. The same 16×16 detector-frame surface is available for the stills path (--stills-modulation, off by default), where serial data repeatedly hammers the same detector regions.
Each surface is cross-validated: fitted on even-numbered frames and kept only if it improves the held-out odd-frame agreement by a clear margin (and vice versa), scored by a σ-independent, $R_\mathrm{meas}$-like fractional agreement \sum|I_s-I_\mathrm{ref}|/\sum|I_\mathrm{ref}| rather than a studentized \chi^2 — so a surface cannot "pass" by reshaping the sigmas instead of tightening the intensities. A surface fitted to noise where its systematic is absent does not generalize and is discarded — a correction never adds scatter.
Radiation-damage report (rotation, report-only). Independently of whether any decay correction is applied, rugnux measures and reports the relative Debye–Waller B across the sweep: the per-image scale's correlation to the merge and the per-image mosaicity versus frame (dose), together with a per-batch relative-B curve whose first→last change is a single headline number (measured before any decay correction, against the least-damaged early wedge). It is written to the log and to the merged mmCIF as a data-quality-vs-dose diagnostic and never alters the merged intensities — distinct from the decay correction above, which does fold into the scale.
10.7 R-free test-set flags
A fraction of the unique reflections (rfree_fraction, default 0.05) is flagged as a free (test) set, written to the output (MTZ FreeR_flag, mmCIF _refln.status_free, a text-HKL column) for model validation (§14) and for downstream refinement. The flag is a pure function of the reflection's Friedel-merged (Laue) ASU index, which gives three properties:
- all symmetry- and Friedel-equivalent reflections share one flag — in particular a Bijvoet pair
I(+)/I(-), kept as two separate merged rows in anomalous mode, is never split across the work and free sets (which would bias R-free); - the free/work decision is a deterministic hash of that key, so the same reflection always lands in the same set — reproducible run-to-run and independent of the order in which observations were merged;
- the hash depends only on the reflection index, not on this dataset's resolution range or which reflections it happens to contain, so a uniform draw takes ~
rfree_fractionof the distinct reflections free and — crucially — every dataset of one crystal form gets the same free set. That cross-dataset consistency is what a multi-dataset campaign (ensemble refinement, PanDDA) requires; a per-shell stratification tied to each dataset's ownd_\mathrm{min}would break it.
On small data, where rfree_fraction (default 0.05) would give too few test reflections for a statistically stable R-free (Brünger's ~500–2000 rule), the fraction is floored so at least ~500 distinct reflections are free — capped at 10 % so a large test set never steals working data. For ordinary data this floor is inactive and the fraction stays flat at rfree_fraction, preserving the cross-dataset-identical property above; it only lifts the fraction on genuinely small datasets, where per-dataset R-free stability outweighs cross-dataset identity (and a shared reference set is the way to keep exact identity there).
When a reference MTZ (--reference-mtz) carries a FreeR_flag column, its test set is imported instead: every merged reflection whose Laue-ASU index matches the reference takes the reference's flag (reflections absent from the reference keep the hash flag). This lets a whole fragment-screening campaign inherit one shared free set from the apo/reference dataset. The CCP4/refmac convention (test set = flag 0, including the historical 0–19 form) is assumed, with the complement taken automatically if flag 0 would be the majority (a phenix-style file where 1 marks free).
10.8 French–Wilson amplitudes
The last step of the merge estimates a Bayesian structure-factor amplitude |F| for each unique reflection from its intensity I and error \sigma, so the output carries amplitudes alongside intensities (a naïve \sqrt{\max(I,0)} turns every weak or negative measurement into a biased — or zero — amplitude). With the Wilson prior for the true intensity J\ge 0 at that resolution,
$ P_\mathrm{acentric}(J) \propto e^{-J/\Sigma},\qquad P_\mathrm{centric}(J) \propto J^{-1/2},e^{-J/2\Sigma}, $
and a Gaussian likelihood \mathcal{N}(I;J,\sigma^2), the posterior mean amplitude and its uncertainty are
$ \langle |F|\rangle = \frac{\int_0^\infty \sqrt{J},\mathcal{N}(I;J,\sigma^2),P(J),\mathrm{d}J}{\int_0^\infty \mathcal{N}(I;J,\sigma^2),P(J),\mathrm{d}J},\qquad \sigma_F = \sqrt{\langle J\rangle - \langle|F|\rangle^2}. $
The prior mean is \Sigma = \varepsilon\,\langle I/\varepsilon\rangle_\mathrm{shell}, where \varepsilon is the reflection's epsilon (symmetry-enhancement) multiplicity and \langle I/\varepsilon\rangle is the Wilson mean in its resolution shell (so reflections on symmetry elements, and each shell, are treated correctly). Strong reflections (I>4\sigma) short-circuit to |F|=\sqrt{I}, where the French–Wilson bias is negligible; a reflection with an unusable I/\sigma falls back to \sqrt{\max(I,0)}. The integral is evaluated numerically with a log-shift for stability.
Amplitudes are written as MTZ F/SIGF, mmCIF _refln.F_meas_au/F_meas_sigma_au, and appended to the text HKL, alongside the intensity columns. The same |F| feed the model-validation step (§14), so the reflection file and the maps use one consistent set of amplitudes.
10.9 Reference data: fixing the space group and resolving the indexing ambiguity
A reference dataset (--reference-mtz) supplies known intensities for the same crystal form, and is used in two ways.
Fix the space group and cell. Unless overridden on the command line (-S for the space group, -C for the cell), the reference's space group is adopted and its cell is used as the soft reference cell — indexing may still drift the cell within tolerance, so a small mismatch between reference and data is absorbed rather than rejected. This applies to both stills and rotation data.
Resolve the indexing (merohedral) ambiguity. When the lattice symmetry is higher than the crystal's Laue symmetry (e.g. P3, P4, P6, C2), more than one indexing of the same lattice is geometrically valid, and the two solutions produce different merged intensities that a self-consistent scale cannot tell apart — only an external reference can. The candidate reindexings are the identity together with the twin-law cosets of the metric symmetry (from the unit-cell metric and the Laue group); each is scored by the intensity correlation \mathrm{CC}_\mathrm{ref} of the reindexed merge against the reference, and the data are re-merged in the best-correlating indexing. The reindex is metric-preserving — only the hkl labels change, the cell is unchanged — and it is a no-op for a holohedral crystal, which has no twin laws (the lattice and Laue symmetry coincide). For rotation data this is done once, after the space group is determined; the reference is not used to scale the rotation merge, which stays self-consistent (its \mathrm{ISa} comes from the data alone). For stills the reference is the per-image scale target of the on-the-fly scaling (§10.2).
11. Mosaicity and “profile radius” monitoring
11.1 Profile radius (intrinsic excitation-error width)
The “profile radius” is the intrinsic angular width of a reflection — crystal mosaicity plus beam divergence — estimated from the spread of \Delta_\mathrm{Ewald} over indexed spots,
$
R \approx \sqrt{\tfrac{1}{N}\sum_i \Delta_{\mathrm{Ewald},i}^2}.
$
When the beam has a finite energy bandwidth, that bandwidth smears each reflection radially by \sigma_\mathrm{bw}\approx \mathrm{bandwidth}\cdot\lambda/2d^2 (largest at high resolution), which also broadens the measured \Delta_\mathrm{Ewald} spread. Since prediction re-applies the bandwidth term per reflection (§8.2), this contribution is deconvolved from the estimate — R^2 = \langle\Delta_\mathrm{Ewald}^2\rangle - \langle\sigma_\mathrm{bw}^2\rangle — so that R is the intrinsic width and bandwidth is not double-counted. Still predictions use an excitation-error cutoff proportional to R.
11.2 Mosaicity from rotation data
For rotation data the mosaicity \sigma_M is estimated by maximum likelihood from the rocking offsets \tau of indexed spots, using the XDS reflection-fraction model R(\tau;\sigma_M/\zeta) (Kabsch 2010): each spot's exact Bragg angle is located near its frame, \zeta (the rotation-axis Lorentz component) is computed, and \sigma_M is chosen to maximize \sum_i \log R(\tau_i;\sigma_M/\zeta_i).
The \phi search window for the Bragg angle is set wider than the oscillation, so that reflections recorded at large rocking offset are included. These tail reflections carry most of the information about the mosaic width; a window limited to the oscillation range would truncate the \tau distribution and bias \sigma_M low.
The estimated mosaicity feeds the rotation prediction (how many frames each reflection spans, §8.3) and the rotation partiality (§10.2). It is held fixed during scaling: in the per-image scale fit the mosaicity is degenerate with the scale G (both rescale the predicted intensity), so refining it there is unstable. A correct mosaicity matters because it controls both how much of each rocking curve is captured and the partiality used to form fulls (§10.6); too small a value truncates the captured curve and over-peaks the partiality, degrading the combined fulls.
12. Auxiliary statistics: ⟨I/σ(I)⟩ and Wilson plot
12.1 Per-shell ⟨I/σ(I)⟩
For monitoring integration quality, Jungfraujoch reports mean \langle I/\sigma(I)\rangle in a fixed number of resolution shells. Shelling is performed in 1/d^2 space (typical of crystallographic practice).
12.2 Wilson plot (B-factor proxy)
A Wilson-type analysis is computed by binning intensities by resolution and fitting:
$
\langle I\rangle \propto \exp!\left(-\frac{B}{2}\frac{1}{d^2}\right),
$
i.e.
$
\log \langle I\rangle = \mathrm{const} - \frac{B}{2}\left(\frac{1}{d^2}\right).
$
A linear regression of \log\langle I\rangle vs 1/d^2 provides an estimate of B, subject to basic quality checks (e.g. R^2 threshold).
A dataset-wide Wilson B is also estimated over the merged reflections — restricted to the meaningful resolution range (skipping the low-resolution non-linear region below ~4 Å and shells past the signal limit \langle I/\sigma\rangle < 1, so it is insensitive to how far the merged data extend) — and written to the merged mmCIF as _reflns.B_iso_Wilson_estimate, the analogue of XDS's Wilson-line B. It is diagnostic only and is not fed back into scaling. The per-image estimate (used for the live radiation-damage plot) is accepted only when the fit is well-correlated and physically plausible (0 < B < 200 Ų); on a bad frame (an indexing glitch, too few reflections) the Wilson line runs wildly steep, so an implausible B is reported as NaN rather than a spurious hundreds-of-Ų value.
13. Practical notes and limitations
- Bragg integration is profile-fitted by default (per-shell Gaussian profile, Kabsch extraction; §9.3), with plain box summation available as a fallback (
--integrator boxsum). The profiles are built per frame from that frame's strong spots, which suits fast-feedback and serial/streaming use; a profile shared across many frames (as in full offline workflows) is not currently formed. - Space-group symmetry beyond centering absences is not necessarily enforced during prediction/integration unless the space group is supplied and used downstream.
- Resolution masking and ice rings are controllable; including ice-ring spots in indexing can improve robustness for some samples but may bias refinement in others.
- Rotation vs still modes differ substantially in prediction and scaling: partiality is angle-driven in rotation data, while stills are predicted (within an excitation-error window) and scaled with unit partiality.
- Space-group determination. When no space group is supplied, a POINTLESS-like search scores Laue-group symmetry (CC of
I(h)vsI(Rh)plus merge self-consistency) and detects screw/centering absences from the $P1$-merged intensities. The self-consistency test is calibrated so a merohedral twin — whose twin law forces non-equivalent reflections together and inflates the merged\chi^2— stays in its true lower symmetry rather than being over-promoted to the holohedral group. Because a partial twin's within-orbit\chi^2can nonetheless look self-consistent, a chi²-passing promotion is additionally vetoed when merging its extra operator balloons the error-modelb(the intensity-proportional systematic) relative to the confirmed subgroup: a genuine symmetry step gains multiplicity without inflatingb, whereas a twin forces non-equivalent reflections together andbballoons. Centering is accepted when the systematically-absent class is weak relative to the present one by either of two floor-independent tests — its mean signedI/\sigmawell below the present mean, or its rate of individually-significant reflections well below the present class's own significant rate. The second test matters on weak / low-energy data, where a positive intensity floor (background/profile leakage) lifts the absent class's meanI/\sigmato $\sim1.5$–2.3instead of\sim0and, when the present class is itself weak, inflates the plain mean ratio past its bound and hides a real centering (an $I$-centred cubic recorded at 5 keV was otherwise kept primitive); a false centering fails both tests because its absent class is as strong as the present one. When several centerings pass, they are ranked by their net systematic absences (absent minus violating), not the gross absent count, so a super-centering (e.g.Fover a trueC) whose extra, only-half-populated absent class merely dilutes the strength ratio does not out-rank the correct lower centering. - Twinning check. A Padilla–Yeates $L$-test (
\langle|L|\rangle,\langle L^2\rangle) and the second moment\langle I^2\rangle/\langle I\rangle^2(taken per resolution shell with noise-only shells skipped and Wilson outliers rejected, so a single strong reflection in a collapsed-mean shell cannot skew it) are written to the merged mmCIF as a twinning diagnostic. Twinning is only flagged in Laue classes where a merohedral twin law can exist; the holohedral high-symmetry classes (4/mmm,6/mmm,m\bar{3}m, and\bar{3}mon a rhombohedral lattice) are exempt, so a low\langle|L|\ranglethere is reported as a statistical artefact rather than twinning. - Outlier rejection. Merging applies an optional per-observation median-based
N\sigmacut (default 6σ forrot3d) and an optional per-crystal\Delta\mathrm{CC}_{1/2}image rejection (--reject-delta-cchalf, CrystFEL-style, off by default). The sameN\sigmacut is fed back into the error model: after an initiala,bfit the parameters are re-fit once on the reflections that survive rejection (dropping any whose squared deviation exceedsN\sigma^2\,[a\,\sigma^2 + (b\,\langle I\rangle)^2]), so the calibrated errors describe the reflections that actually enter the merge rather than the pre-rejection pool. - Automatic resolution cutoff. By default the reported/written high-resolution limit is trimmed where
\mathrm{CC}_{1/2}falls off (logistic, target 0.30);--scaling-high-resolutionoverrides it and--resolution-cutoff offdisables it. - Amplitudes and intensities. The merged output carries both intensities (mmCIF
intensity_meas, MTZIMEAN/SIGIMEAN) and French–Wilson amplitudes (mmCIFF_meas_au, MTZF/SIGF; §10.8), so a downstream program can refine against either.
14. Model-based validation: R-free against a model and electron-density maps
Offline (rugnux --model model.pdb) the merged data can be scored against a supplied atomic model and initial electron-density maps computed — enough to confirm that a model fits the data and to inspect the density, not a substitute for refinement. The structure itself is not refined; the model is only re-fractionalized into the data unit cell (a rigid cell adjustment, so a deposited model with a slightly different cell still lines up), and the observed amplitudes are the French–Wilson |F| from §10.8, so the R-free and the maps use exactly the same amplitudes as the written reflection file. The model, structure-factor, bulk-solvent and FFT machinery is provided by GEMMI.
14.1 Model structure factors
The model electron density is sampled on a grid (IT92 X-ray form factors, with a Refmac-compatible Gaussian blur chosen for the grid spacing) and Fourier-transformed to structure factors F_\mathrm{calc}(hkl) up to the data resolution.
14.2 Bulk solvent and scaling
A flat bulk-solvent mask around the model is transformed to F_\mathrm{mask}, and the model is scaled to the observed amplitudes by an overall least-squares fit of a scale k, an anisotropic B, and the flat-solvent parameters k_\mathrm{sol}, B_\mathrm{sol}:
$ F_\mathrm{model} = k,e^{-\mathbf{h}^\top \mathbf{B},\mathbf{h}/4}\left(F_\mathrm{calc} + k_\mathrm{sol},e^{-B_\mathrm{sol},s^2},F_\mathrm{mask}\right),\quad s^2 = 1/4d^2. $
This is the standard, few-parameter scaling model used by refinement programs. A dataset-specific free-form per-resolution-shell rescale would lower this dataset's R a little, but it reshapes each map's radial amplitude profile differently, so a batch of maps would no longer be directly comparable — for a fragment-screening / PanDDA campaign, comparable maps across datasets matter more than the last bit of per-dataset R, so it is deliberately not applied.
14.3 R-work and R-free
Crystallographic R-factors are reported over the work and free sets (the §10.7 flags):
$ R = \frac{\sum \big|,|F_o| - |F_\mathrm{model}|,\big|}{\sum |F_o|}, $
with R-free the same sum restricted to the free set — an unbiased measure of how well the model explains data it was not scaled against.
14.4 Electron-density maps
Two maps are formed with the model phases \varphi_\mathrm{model}: a 2F_o-F_c map, coefficients (2|F_o|-|F_\mathrm{model}|)\,e^{i\varphi_\mathrm{model}}, and an F_o-F_c difference map, (|F_o|-|F_\mathrm{model}|)\,e^{i\varphi_\mathrm{model}}, each inverse-Fourier-transformed to a real-space CCP4 map (<prefix>_2fofc.ccp4, <prefix>_fofc.ccp4). A map-coefficient MTZ (<prefix>_maps.mtz: FP, FC, PHIC, FWT/PHWT, DELFWT/PHDELWT, FREE) is written alongside so the maps can be reopened or rebuilt in Coot / PyMOL. These are unweighted difference coefficients (no \sigma_A / figure-of-merit weighting), which is why they are described as initial maps.
14.5 Aligning the data to the model: enantiomorph and indexing ambiguity
The model fixes a definite hand and indexing, but the merged data need not share them, so before comparison the observed reflections are brought into the model's frame.
- Enantiomorph / screw. When the data space group is the enantiomorph of the model's (e.g. data
P4_12_12, modelP4_32_12; orP3_1/P3_2), the two are indistinguishable from merged intensities —|F_\mathrm{calc}|is invariant under the change of hand, so R-free cannot choose between them and probing would be meaningless. The hand is therefore taken from the model: the observed reflections are reindexed by the change-of-hand operator into the model's enantiomorph. Only the map phases (the density's hand) depend on this choice. - Indexing (merohedral) ambiguity. When the crystal has a merohedral ambiguity (§10.9), the observed intensities do differ between indexings, and the right one is chosen against the best available reference. If a reference MTZ was supplied, the data were already reindexed to agree with it (§10.9 — by the reference-intensity correlation, at the merge stage for rotation data or per image in stills scaling), and model validation keeps that authoritative choice. Only with a model and no reference does validation resolve the ambiguity itself, as a fallback: the scaled model is fit to each reindexing of the data (identity plus the twin-law cosets) and the one giving the lowest R-free is kept. This matters for a multi-dataset campaign — a single shared reference fixes one indexing convention for every dataset, whereas an independent per-dataset lowest-R-free choice could send borderline datasets to different conventions. A no-op either way for a holohedral crystal (no twin laws).