Docs: harmonic beam-centre disagreement decided both ways; geometry commit bar is the residual's noise
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:
@@ -7,6 +7,8 @@
|
||||
* Rugnux rejects single observations that Wilson statistics make implausible (typically a hot pixel, zinger or ice spot), including pairs and single measurements that the equivalents test cannot judge; the count is reported as `OBSERVATIONS_REJECTED_WILSON`.
|
||||
* Rugnux reports the X-ray bandwidth it measures from spot shapes (for multilayer and pink beams); the value is reported only and does not change processing.
|
||||
* 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 --polarization` is documented as the polarization degree (XDS `FRACTION_OF_POLARIZATION` = (1 + p)/2); the default 0.99 suits undulators.
|
||||
|
||||
### 1.0.0-rc.172
|
||||
|
||||
@@ -178,7 +178,11 @@ majority; where both work and
|
||||
disagree, both cells are reported and neither is chosen, because the only arbiter available at that
|
||||
stage is the indexed frame count and **it points the wrong way**: acceptance is a fractional-Miller
|
||||
test, so a cell twice as long must place every spot twice as accurately to score the same, and a
|
||||
halved axis can index *more* frames than the true cell. Where the two disagree only in Bravais class
|
||||
halved axis can index *more* frames than the true cell. The one disagreement that is decided is an
|
||||
axis harmonic — primitive volumes related by an integer factor 2 to 4 — and it is decided on the
|
||||
**pooled validation spots** instead, each cell scored against its own wrong-spindle null, in either
|
||||
direction: the measured centre is adopted when the lattice it gives, larger or smaller, carries
|
||||
materially more of the spots than the file's. Where the two disagree only in Bravais class
|
||||
at the same primitive volume, that is said separately from a volume ratio that is an axis harmonic,
|
||||
which is the one the centre decides.
|
||||
|
||||
|
||||
@@ -322,7 +322,7 @@ The refinement above (§7.2) runs per image against that image's spots. For rota
|
||||
|
||||
Free: the crystal orientation, the unit cell (every parameter the crystal system leaves free, not one overall scale), the goniometer-axis direction, the detector distance and the beam centre. The positional residual on its own *is* degenerate with the cell scale — that is why this used to be split into a cell-scale step and a distance step — but the excitation residual does not involve the detector at all, so it fixes the absolute size of the reciprocal lattice and breaks the degeneracy inside the same problem. Splitting it instead cost accuracy twice over: pass 1 frees the whole lattice against a frozen distance, so the distortion it absorbs is *anisotropic* and no single scale can undo it; and whatever bias is left in that scale goes straight into the distance, which is only ever determined relative to the cell.
|
||||
|
||||
The fit is **cross-validated** on a deterministic split of the *reflections* (an avalanche-mixed $hkl$ hash, not a frame split and not an $h+k+l$ parity, which would collide with a centering condition and leave the held-out half empty): fitted on one half, committed only if it lowers the held-out residual — both families of it, since the excitation residual is the only evidence of the cell scale and the positional values outnumber it about three to one — and the move stays inside its bounds: every free cell angle within 1° and the beam centre within 15 px of the nearest centre anything already believes.
|
||||
The fit is **cross-validated** on a deterministic split of the *reflections* (an avalanche-mixed $hkl$ hash, not a frame split and not an $h+k+l$ parity, which would collide with a centering condition and leave the held-out half empty): fitted on one half, committed only if it lowers the held-out residual by more than that residual's own noise (the standard errors of the two held-out means combined, the bar a round of the geometry walk has to clear) and lowers both families of it, since the excitation residual is the only evidence of the cell scale and the positional values outnumber it about three to one — and the move stays inside its bounds: every free cell angle within 1° and the beam centre within 15 px of the nearest centre anything already believes.
|
||||
|
||||
The **distance and the cell lengths are bounded one step at a time, not as a whole**. One per cent was once a cap on the entire move, and as a cap it was the opposite of its job — a header is most worth correcting when it is most wrong, and a geometry genuinely several per cent out could never be reached (measured: a refused fit of 310.000 → 305.692 mm whose cell landed within 0.06 % of the deposited one). It is a **trust region** instead. The first solve is asked in the wide box around nominal exactly as before, so a fit that settles within one step commits unchanged; a fit that wants more is re-fitted as a *walk* of one-per-cent steps, each seeded where the last arrived and each required to lower the held-out residual, stopping where a step stops paying. A walk that uses every step it is allowed has not settled — it stopped because it ran out of steps, not because it arrived — and is refused, which is the runaway the cap stood in for, tested where it can be seen. A move of more than one step is additionally **ratified by re-indexing at where it arrived**: that is what separates the failure the cap was really aimed at (a second lattice, whose spots bias every cross-validation fold identically) from a wrong header, since a second lattice does not index better at the new geometry and a real distance error does.
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ Geometry:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--beam-center-check[=off]` | Measure the beam centre from the isotropy of the scattered background on **every** run, report how far the file's value is from it — against how right this particular geometry needs it to be — and index a **second first pass** at the measured centre to see whether the two centres give the same lattice. The fit reads the projection `--detect-beam-stop` already builds, so it costs no extra frames. **On by default**; `=off` disables. On a run that indexes, the measured centre is adopted in two cases only: where the file's centre indexes nothing and the measured one indexes a majority, and where the two cells are related by an integer volume factor, the measured centre's is the **larger** one, and it carries materially more of the pooled validation spots than the file's does (each cell scored against its own wrong-spindle null, so a denser lattice is not credited for accidental hits). That one direction is the axis harmonic a centre error along the spindle produces, and nothing downstream repairs it; every other disagreement is reported with both cells and left undecided |
|
||||
| `--beam-center-check[=off]` | Measure the beam centre from the isotropy of the scattered background on **every** run, report how far the file's value is from it — against how right this particular geometry needs it to be — and index a **second first pass** at the measured centre to see whether the two centres give the same lattice. The fit reads the projection `--detect-beam-stop` already builds, so it costs no extra frames. **On by default**; `=off` disables. On a run that indexes, the measured centre is adopted in two cases only: where the file's centre indexes nothing and the measured one indexes a majority, and where the two cells are related by an integer volume factor (2 to 4) and the measured centre's cell, larger or smaller, carries materially more of the pooled validation spots than the file's does (each cell scored against its own wrong-spindle null, so a denser lattice is not credited for accidental hits). That is the axis harmonic a centre error along the spindle produces; every other disagreement is reported with both cells and left undecided |
|
||||
| `--beam-center-search[=N\|off]` | After a first pass that indexes fewer than half the validation frames, step the centre a pixel at a time out to N px along **each** detector axis and keep the first rung that indexes a majority. **On by default** (12 px); `=off` disables. It runs only after a pass that has already failed, and spot finding is not repeated, so a run that indexes never pays for it. Both detector directions are searched: a centre error *across* the spindle collapses the indexed fraction and announces itself, while one *along* it holds the frame count up and quietly returns an axis harmonic |
|
||||
| `--estimate-beam-center` | Measure the direct beam before indexing, from the symmetry of the spots where the sweep reaches at least half a turn and from the radial background profile where it does not; the value in the file is kept where neither can measure it. Off by default |
|
||||
| `--no-fit-spindle` | With the above, keep the rotation axis given in the file instead of fitting its skew about the beam |
|
||||
|
||||
Reference in New Issue
Block a user