The 1274-line page becomes a landing page (quick start, the page map, where it fits) plus seven pages a reader can answer one question from: installing, what rugnux reads, running it, integration with other programs, the results report, advanced usage, and powder calibration. Content is moved, not rewritten - only the connective sentences at each page top are new. Every internal anchor is remapped to its new page and every inbound link (DEPLOYMENT, TOOLS, HDF5, CPU_DATA_ANALYSIS) updated; the built site has zero Sphinx warnings and an anchor check over the rendered HTML finds no dead link. index.rst leads with the rugnux group, then acquisition, FPGA, reference and project. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
4.5 KiB
Detector calibration from powder rings (rugnux --mode calibration)
The calibration mode determines the detector geometry — PONI x/y, the two tilts
rot1/rot2 and the distance — from the powder rings of a calibrant, and writes it as a
pyFAI <prefix>.poni file and a machine-readable <prefix>.json, alongside a printed
report of how far each parameter moved from the header. Bragg data pin the beam centre worst (it is gauge-coupled to the crystal orientation);
a powder ring has no orientation to be coupled to, so this is the measurement that fixes it.
rugnux --mode calibration --calibrant lab6 -o det LaB6_master.h5
What it writes
<prefix>.poni is for pyFAI and the tools that read its format. <prefix>.json is for everything
else, and has two members:
-
dataset_settings— the geometry under the property namesdataset_settingsgives them injfjoch_broker's OpenAPI schema, and nothing else. It is a validdataset_settingsbody as it stands, so it can be POSTed or merged into one without translating a field:curl -X POST -H 'Content-Type: application/json' \ -d "$(jq -c .dataset_settings det.json)" http://broker:5232/startbeam_x_pxl/beam_y_pxlis the PONI, as everywhere in this system — on a tilted detector it is not where the direct beam lands. The threeponi_rot*_radare written whenever any of them is non-zero, and left out when all are zero: a body that omits them states a flat detector, so they travel together or not at all. -
calibration— what the run knows about that geometry: the residual, the fit's own sigmas and the correlation between the tilt and the beam centre, whether the tilt cleared its significance test or was declined and pinned, where the direct beam lands, and where the spots independently put the beam. A calibration that has gone wrong looks exactly like one that has not until those are read.
--calibrant takes lab6, agbh (silver behenate), ceo2, si or ice, case-insensitively.
ice calibrates a real experiment against its own ice rings — no calibrant exposure needed —
and is the reason a calibrant is a list of ring positions rather than a unit cell: hexagonal ice
is P63/mmc, so rings enumerated from its cell would include systematically absent ones.
--calibration picks how the rings are measured, and both use the whole dataset — -s/-e/-t
select which images:
rings(default) sums the (q × azimuth) azimuthal profile over every processed image into one map and fits the ring arcs in it. A powder ring is an arc, not a set of spots, and the summed profile measures it at every azimuth with all the run's counts behind it. It needs the profile to be binned in azimuth, so this mode defaults--azim-phi-binsto 32.spotspools the found spots of every processed image and fits those. It determines the centre from scratch (a Hough circle vote, which quantises it to a whole pixel) and then refines.
Both routes read the ring position out of a binned profile or a spot centroid, so the radial
sampling matters: at a long detector distance the default 0.01 Å⁻¹ q bin is several pixels wide
and quantises the rings route accordingly — pass a finer --azim-q-spacing there (the total
q × azimuth bin count must stay under 65534).
The report prints the fitted geometry, the scatter of the ring points about the fitted rings and the standard error that implies on the centre. That error is formal: it measures the scatter of the points, not whether the rings themselves are trustworthy, so it stays small when a fit goes wrong for a structural reason — one visible ring, or ice that is textured rather than smooth.
--no-refine-tilt holds rot1/rot2 where the header put them and fits only the centre and the
distance. The tilt is real and worth measuring, but a program that has nowhere to put one — XDS
takes a detector normal to the beam — is better given a geometry that was measured with the tilt
pinned than one that was measured tilted and then flattened, because in the tilted fit the centre
and the distance have already absorbed the tilt.
Both the PONI (the point of normal incidence, which is what a .poni file stores) and the direct
beam (where the beam lands, which is what most other programs call the beam centre) are printed.
They differ by distance × tan(rot) once the detector is tilted, which on a 0.3° tilt at 300 mm is
several pixels — enough to look like a disagreement with another program when there is none.