Merge cli-help into rc181: a short usage per mode, RUGNUX_CLI.md with every option, the HTML documentation in the rugnux archives and the Windows/macOS packages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqN9qRD57vnShzTC37
This commit is contained in:
commit
facf262360
8 files changed
+509
-449
No files matched your search
@@ -49,6 +49,68 @@ on:
|
||||
default: 'manual'
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
name: Build documentation
|
||||
# Uploads to the release, so it waits for the job that creates it. First in the file, so that
|
||||
# it is handed out ahead of the long Linux builds: build-windows and build-macos wait for it.
|
||||
needs: create-release
|
||||
runs-on: jfjoch_rocky8
|
||||
container:
|
||||
image: gitea.psi.ch/leonarski_f/jfjoch_rocky8:2609
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build documentation
|
||||
shell: bash
|
||||
run: bash make_doc.sh
|
||||
# Built once here for the Windows and macOS rugnux packages too (the Windows runner has no
|
||||
# Python new enough for Sphinx). The sphinx-build doctree cache in public/.doctrees is not shipped.
|
||||
- name: Upload the HTML for the Windows and macOS packages
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docs-html
|
||||
path: |
|
||||
public/
|
||||
!public/.doctrees/
|
||||
# The Rugnux pages site is the gitea-pages branch of rugnux/gitea-pages, updated with a release.
|
||||
# The HTML is pushed from a copy, so the checkout the release upload below works on is left as it was.
|
||||
- name: Upload documentation to rugnux/gitea-pages
|
||||
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true)
|
||||
shell: bash
|
||||
env:
|
||||
PAGES_TOKEN: ${{ secrets.RUGNUX_PAGES_TOKEN || secrets.PIP_REPOSITORY_API_TOKEN }}
|
||||
PAGES_TOKEN_NAME: ${{ secrets.RUGNUX_PAGES_TOKEN && 'RUGNUX_PAGES_TOKEN' || 'PIP_REPOSITORY_API_TOKEN' }}
|
||||
run: |
|
||||
echo "Pushing with secret ${PAGES_TOKEN_NAME}"
|
||||
rm -rf /tmp/rugnux-pages
|
||||
mkdir /tmp/rugnux-pages
|
||||
cp -a public/. /tmp/rugnux-pages/
|
||||
cd /tmp/rugnux-pages
|
||||
git init -q
|
||||
git checkout -q -b gitea-pages
|
||||
git config user.email "filip.leonarski@psi.ch"
|
||||
git config user.name "Filip Leonarski (Gitea)"
|
||||
git add .
|
||||
git commit -q -m "Deploy site from ${GITHUB_REF_NAME} ${GITHUB_SHA::9}"
|
||||
git push -f "https://${PAGES_TOKEN}@gitea.psi.ch/rugnux/gitea-pages.git" gitea-pages
|
||||
- name: Upload documentation
|
||||
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true)
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global user.email "filip.leonarski@psi.ch"
|
||||
git config --global user.name "Filip Leonarski (Gitea)"
|
||||
git checkout --orphan gitea-pages
|
||||
git reset --hard
|
||||
# Remove everything except .git and public
|
||||
git clean -fdx -e public -e .git
|
||||
|
||||
# Move public contents to root and remove the now-empty public dir
|
||||
shopt -s dotglob nullglob
|
||||
mv public/* .
|
||||
rm -rf public
|
||||
git add .
|
||||
git commit -m "Deploy site"
|
||||
git push -f https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git gitea-pages
|
||||
|
||||
# ---- Portable Linux artifacts: viewer, rugnux, XDS plugin -----------------------------------------
|
||||
# One viewer-only build per variant packs three tarballs, one program each (see CPack in
|
||||
# CMakeLists.txt): the viewer build compiles everything rugnux and the plugin need anyway.
|
||||
@@ -92,6 +154,7 @@ jobs:
|
||||
run: |
|
||||
cd build
|
||||
ninja -j16
|
||||
ninja rugnux_docs # the HTML documentation, shipped in the rugnux tarball
|
||||
cpack
|
||||
- name: Verify one libjpeg in the viewer
|
||||
shell: bash
|
||||
@@ -112,6 +175,7 @@ jobs:
|
||||
rm -rf /tmp/rgx && mkdir -p /tmp/rgx
|
||||
tar xf build/rugnux-*.tar.gz -C /tmp/rgx
|
||||
bin=$(find /tmp/rgx -name rugnux -type f)
|
||||
test -f "$(dirname "$bin")/../share/doc/jfjoch_rugnux/html/RUGNUX_CLI.html"
|
||||
# Each producer writes to a file and the greps read files, rather than piping into
|
||||
# `grep -q`: grep exits at the first match, the producer then dies of SIGPIPE, and under
|
||||
# `set -o pipefail` that becomes the pipeline's status -- which a leading `!` would turn
|
||||
@@ -164,7 +228,7 @@ jobs:
|
||||
build-windows:
|
||||
name: build:portable:windows-x86_64:${{ matrix.variant }}
|
||||
# Uploads to the release, so it waits for the job that creates it.
|
||||
needs: create-release
|
||||
needs: [create-release, documentation]
|
||||
runs-on: windows-11-cuda-qt
|
||||
timeout-minutes: 120
|
||||
strategy:
|
||||
@@ -202,6 +266,14 @@ jobs:
|
||||
run: |
|
||||
cd build\tests
|
||||
jfjoch_portable_test.exe "[portable]"
|
||||
# The HTML documentation for the rugnux package, built by the documentation job, where the
|
||||
# OPTIONAL install rule for rugnux_docs looks for it. download-artifact comes from the
|
||||
# mx/download-artifact mirror (the actions org has none); v4 refuses any server but github.com.
|
||||
- name: Download the HTML documentation
|
||||
uses: https://gitea.psi.ch/mx/download-artifact@v3
|
||||
with:
|
||||
name: docs-html
|
||||
path: build/docs_html
|
||||
- name: Build installer (NSIS) and rugnux zip
|
||||
shell: cmd
|
||||
run: |
|
||||
@@ -239,7 +311,7 @@ jobs:
|
||||
build-macos:
|
||||
name: build:portable:macos-arm64:nocuda
|
||||
# Uploads to the release, so it waits for the job that creates it.
|
||||
needs: create-release
|
||||
needs: [create-release, documentation]
|
||||
# A Mac mini running act_runner in host mode (no containers on macOS): the job runs as the runner's
|
||||
# user with that user's tools - Xcode command line tools, CMake.app and Qt under ~/Qt - so the
|
||||
# paths below are this machine's, like the Windows runner's C:/Qt.
|
||||
@@ -288,6 +360,14 @@ jobs:
|
||||
run: cd build-macos/tests && ./jfjoch_portable_test "[Metal]"
|
||||
# One build, two artifacts: the viewer .dmg and rugnux as .tar.gz (CPACK_PROJECT_CONFIG_FILE
|
||||
# in CMakeLists.txt gives each generator its components). The XDS plugin is Linux-only.
|
||||
# The HTML documentation for the rugnux package, built by the documentation job, where the
|
||||
# OPTIONAL install rule for rugnux_docs looks for it. download-artifact comes from the
|
||||
# mx/download-artifact mirror (the actions org has none); v4 refuses any server but github.com.
|
||||
- name: Download the HTML documentation
|
||||
uses: https://gitea.psi.ch/mx/download-artifact@v3
|
||||
with:
|
||||
name: docs-html
|
||||
path: build-macos/docs_html
|
||||
- name: Build viewer DMG and rugnux tgz
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -937,58 +1017,6 @@ jobs:
|
||||
twine upload -u __token__ -p ${{ secrets.CI_PYPI_TOKEN }} --skip-existing dist/*
|
||||
twine upload -u __token__ -p ${{ secrets.PIP_REPOSITORY_API_TOKEN }} --repository-url https://gitea.psi.ch/api/packages/mx/pypi dist/*
|
||||
|
||||
documentation:
|
||||
name: Build documentation
|
||||
# Uploads to the release, so it waits for the job that creates it.
|
||||
needs: create-release
|
||||
runs-on: jfjoch_rocky8
|
||||
container:
|
||||
image: gitea.psi.ch/leonarski_f/jfjoch_rocky8:2609
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build documentation
|
||||
shell: bash
|
||||
run: bash make_doc.sh
|
||||
# The Rugnux pages site is the gitea-pages branch of rugnux/gitea-pages, updated with a release.
|
||||
# The HTML is pushed from a copy, so the checkout the release upload below works on is left as it was.
|
||||
- name: Upload documentation to rugnux/gitea-pages
|
||||
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true)
|
||||
shell: bash
|
||||
env:
|
||||
PAGES_TOKEN: ${{ secrets.RUGNUX_PAGES_TOKEN || secrets.PIP_REPOSITORY_API_TOKEN }}
|
||||
PAGES_TOKEN_NAME: ${{ secrets.RUGNUX_PAGES_TOKEN && 'RUGNUX_PAGES_TOKEN' || 'PIP_REPOSITORY_API_TOKEN' }}
|
||||
run: |
|
||||
echo "Pushing with secret ${PAGES_TOKEN_NAME}"
|
||||
rm -rf /tmp/rugnux-pages
|
||||
mkdir /tmp/rugnux-pages
|
||||
cp -a public/. /tmp/rugnux-pages/
|
||||
cd /tmp/rugnux-pages
|
||||
git init -q
|
||||
git checkout -q -b gitea-pages
|
||||
git config user.email "filip.leonarski@psi.ch"
|
||||
git config user.name "Filip Leonarski (Gitea)"
|
||||
git add .
|
||||
git commit -q -m "Deploy site from ${GITHUB_REF_NAME} ${GITHUB_SHA::9}"
|
||||
git push -f "https://${PAGES_TOKEN}@gitea.psi.ch/rugnux/gitea-pages.git" gitea-pages
|
||||
- name: Upload documentation
|
||||
if: github.event_name == 'workflow_dispatch' && (github.event.inputs.create_release == 'true' || github.event.inputs.create_release == true)
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global user.email "filip.leonarski@psi.ch"
|
||||
git config --global user.name "Filip Leonarski (Gitea)"
|
||||
git checkout --orphan gitea-pages
|
||||
git reset --hard
|
||||
# Remove everything except .git and public
|
||||
git clean -fdx -e public -e .git
|
||||
|
||||
# Move public contents to root and remove the now-empty public dir
|
||||
shopt -s dotglob nullglob
|
||||
mv public/* .
|
||||
rm -rf public
|
||||
git add .
|
||||
git commit -m "Deploy site"
|
||||
git push -f https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git gitea-pages
|
||||
|
||||
# ---- Release -------------------------------------------------------------------------------------
|
||||
# Runs on every event, but only creates something when asked. Keeping it unconditional is what
|
||||
# lets every other job depend on it with a plain `needs:` -- a skipped dependency would otherwise
|
||||
|
||||
@@ -9,8 +9,9 @@ X-ray detectors. It receives detector data, runs it through an FPGA-accelerated
|
||||
(spot finding, azimuthal/ROI integration, compression), streams images out over ZeroMQ for
|
||||
writing to HDF5, and runs crystallographic analysis (indexing, integration, scaling/merging).
|
||||
Most authoritative documentation lives in `docs/` and on Read The Docs
|
||||
(https://jungfraujoch.readthedocs.io). When changing CLI behaviour, the program's own
|
||||
usage message is the source of truth, not the docs.
|
||||
(https://jungfraujoch.readthedocs.io). rugnux's options are all described in
|
||||
`docs/RUGNUX_CLI.md` (the program's own usage shows only the modes and the basic options): when
|
||||
changing CLI behaviour, update the parser, that page and, for a basic option, the usage together.
|
||||
|
||||
## Build
|
||||
|
||||
@@ -360,7 +361,8 @@ generated API model and internal types.
|
||||
- `jfjoch_viewer` — interactive Qt desktop (`viewer/`), results not persisted.
|
||||
- `rugnux` (`rugnux/rugnux_cli.cpp`, built on the `JFJochRugnux` library in the same directory) — offline
|
||||
batch over a stored HDF5, invoked as `rugnux {<options>} <input.h5>` (it has **no `--help`**; run
|
||||
it with no arguments to print the usage, which is the authority on its flags). Rotation vs stills
|
||||
it with no arguments to print a short usage: one section per mode and the basic options; every
|
||||
option is listed in `docs/RUGNUX_CLI.md`, which must be kept in step with the parser). Rotation vs stills
|
||||
is auto-detected from the goniometer axis. Merging is on by default (`--no-merge` to disable);
|
||||
merging writes `.mtz`/`.cif`/`.hkl` and skips the bulky `_process.h5` unless `--write-process-h5`,
|
||||
while `--no-merge` writes only `_process.h5`. `--mode` picks what a run does: `mx` (the full
|
||||
|
||||
@@ -944,6 +944,31 @@ else()
|
||||
endif()
|
||||
|
||||
|
||||
# The Sphinx HTML documentation, shipped with rugnux: its usage points at
|
||||
# share/doc/jfjoch_rugnux/html/RUGNUX_CLI.html in the release archive. Never part of the default
|
||||
# build - `make rugnux_docs` builds it in a venv of its own from docs/requirements.txt (so it needs
|
||||
# Python 3.10+ and pip's network, not an installed Sphinx), and the OPTIONAL install rule ships
|
||||
# whatever it left in the build tree; without it the packages are made as before, with no HTML.
|
||||
SET(JFJOCH_DOCS_HTML_DIR ${CMAKE_BINARY_DIR}/docs_html)
|
||||
FIND_PACKAGE(Python3 3.10 COMPONENTS Interpreter)
|
||||
IF (Python3_FOUND)
|
||||
IF (WIN32)
|
||||
SET(_docs_python ${CMAKE_BINARY_DIR}/docs_venv/Scripts/python.exe)
|
||||
ELSE()
|
||||
SET(_docs_python ${CMAKE_BINARY_DIR}/docs_venv/bin/python)
|
||||
ENDIF()
|
||||
ADD_CUSTOM_TARGET(rugnux_docs
|
||||
COMMAND ${Python3_EXECUTABLE} -m venv ${CMAKE_BINARY_DIR}/docs_venv
|
||||
COMMAND ${_docs_python} -m pip install -q -r ${CMAKE_SOURCE_DIR}/docs/requirements.txt
|
||||
COMMAND ${_docs_python} -m sphinx -q -b html -d ${CMAKE_BINARY_DIR}/docs_doctrees
|
||||
${CMAKE_SOURCE_DIR}/docs ${JFJOCH_DOCS_HTML_DIR}
|
||||
COMMENT "Building the HTML documentation into ${JFJOCH_DOCS_HTML_DIR}")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "No Python 3.10 or newer: no rugnux_docs target, rugnux is packaged without the HTML documentation")
|
||||
ENDIF()
|
||||
INSTALL(DIRECTORY ${JFJOCH_DOCS_HTML_DIR}/ DESTINATION share/doc/jfjoch_rugnux/html COMPONENT rugnux
|
||||
OPTIONAL PATTERN ".buildinfo" EXCLUDE)
|
||||
|
||||
# Ship the notices (top-level LICENSE, the third-party manifest, the verbatim license texts, and
|
||||
# the acknowledgements the programs refer a user to) with every package variant. Installed per
|
||||
# component so the files land in whichever component package(s) the current build mode produces.
|
||||
|
||||
+7
-5
@@ -39,8 +39,8 @@ the whole sweep gives. This is for rotation data and `--mode mx`; the collection
|
||||
is ignored.
|
||||
|
||||
> **Note.** `rugnux` is under very active development. This page describes the tool and
|
||||
> its options at a high level; the authoritative, always-current list of options is the program's
|
||||
> own usage message — run `rugnux` with no arguments.
|
||||
> its options at a high level. Run `rugnux` with no arguments for its usage - how to run each mode
|
||||
> and the basic options; every option is on [Command-line options](RUGNUX_CLI.md).
|
||||
|
||||
```{contents} On this page
|
||||
:local:
|
||||
@@ -56,7 +56,7 @@ the data, and scaling and merging run by default. `-o` names the output files (d
|
||||
|
||||
**We expect no need to tune anything else.** The defaults are meant to be the answer, and a run that
|
||||
needed a flag to do well is one we want to hear about. The other options exist for unusual cases and
|
||||
for diagnosis; they are listed under [Command-line options](RUGNUX_ADVANCED.md#command-line-options).
|
||||
for diagnosis; they are listed under [Command-line options](RUGNUX_CLI.md).
|
||||
|
||||
### Rotation data
|
||||
|
||||
@@ -249,7 +249,7 @@ A few things worth knowing before reaching for more flags:
|
||||
with `Killed` ran out of memory ([When host memory runs out](RUGNUX_INSTALL.md#when-host-memory-runs-out)).
|
||||
With any question about a run, send `myrun_report.txt` and `myrun_log.txt`.
|
||||
- Everything else is in [Running Rugnux](RUGNUX_TUTORIAL.md#running-rugnux) and the full
|
||||
[Command-line options](RUGNUX_ADVANCED.md#command-line-options).
|
||||
[Command-line options](RUGNUX_CLI.md).
|
||||
|
||||
|
||||
## The rest of the manual
|
||||
@@ -272,8 +272,10 @@ One page per job, so the answer needed is near the top of a short page:
|
||||
Phaser, SHELXC/D/E and, for small molecules, SHELXT / SHELXL.
|
||||
- [The results report](RUGNUX_REPORT.md) — the `KEY= value` interface, sweep quality and the
|
||||
anisotropy section.
|
||||
- [Command-line options](RUGNUX_CLI.md) — how to run each mode, and every option with what it
|
||||
does.
|
||||
- [Advanced usage](RUGNUX_ADVANCED.md) — reference data and the indexing ambiguity, model
|
||||
validation, re-merging, and the full command-line option tables.
|
||||
validation and re-merging.
|
||||
- [Models and reference data](RUGNUX_MODEL_AND_REFERENCE.md) — every model and reference option,
|
||||
and decision by decision what a model can and cannot change.
|
||||
- [Detector calibration](RUGNUX_CALIBRATION.md) — the geometry from a calibrant's powder rings
|
||||
|
||||
+2
-202
@@ -1,7 +1,7 @@
|
||||
# Advanced Rugnux
|
||||
|
||||
The machinery behind a run that needs more than the defaults: external reference data, model
|
||||
validation, re-merging without re-integration, and the full option tables.
|
||||
validation and re-merging without re-integration; the option tables are on [Command-line options](RUGNUX_CLI.md).
|
||||
|
||||
```{contents} On this page
|
||||
:local:
|
||||
@@ -338,204 +338,4 @@ the broker is not a file here, and has none.
|
||||
|
||||
## Command-line options
|
||||
|
||||
General:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `-o, --output-prefix <txt>` | Output file prefix (default: `output`) |
|
||||
| `-N, --threads <num>` | Number of worker threads (default, and for any value ≤ 0: every CPU the run may use - its affinity and cgroup quota). Some stages take fewer, because past a point more workers make them slower: the per-image loop of `--mode mx` uses at most 16 per GPU unless `-N` was given a positive value, and first-pass spot finding and the beam-stop pre-scan have ceilings of their own that `-N` does not lift. On a small card the two ceilings, and the per-image loop's 16 where `-N` was left at its default, come down to as many workers as keep their buffers (about 24 bytes per detector pixel each) within half of the card's total memory. Scaling, merging and the space-group search use the full count |
|
||||
| `-s, --start-image <num>` | First image to process (default: 0) |
|
||||
| `-e, --end-image <num>` | End image number, exclusive: `-s 0 -e 100` processes images 0-99 (default: all) |
|
||||
| `-t, --stride <num>` | Process every *n*-th image (default: 1) |
|
||||
| `-v, --verbose` | Show the whole log on the terminal in place of the steps; `<prefix>_log.txt` is written either way |
|
||||
| `--simulate-live <ms>` | Read a stored input as the collection it was while being written: image *i* becomes readable (*i*+1)·`ms` ms after the start (0: all at once). The run takes the live path a broker URL takes, with the same result; for testing the live workflow without a broker. `--mode mx` only |
|
||||
| `--fast-live` | With `--simulate-live` or a broker URL: run as the broker's rugnux live mode does — every decision stands where it was first taken, nothing is re-checked or run again once the sweep is in, the integration radius is fixed, and SIGINT cuts the run to what it has established. A difficult crystal can come out worse |
|
||||
| `--no-gpu` | Run on the CPU only, as on a machine without a GPU, even where one is present: CUDA is not touched (nor, on macOS, the Apple GPU that Bragg integration, the model density and the molecular-replacement rotation function otherwise run on) and every GPU step takes its CPU path (`-X FFT` indexes with FFTW and `-X FFBIDX` with its CPU implementation; `-X cuFFT` is refused) |
|
||||
|
||||
Mode — `--mode <name>` (default `mx`):
|
||||
|
||||
| Value | Description |
|
||||
| --- | --- |
|
||||
| `mx` | Full analysis — spot finding, indexing, integration and merging |
|
||||
| `azint` | Only azimuthal integration (no spot finding/indexing); writes `<prefix>_process.h5` |
|
||||
| `scale` | Only re-scale/merge the already-integrated reflections in the input `_process.h5` (no re-integration) |
|
||||
| `calibration` | Determine the detector geometry from powder rings; writes `<prefix>.poni` and `<prefix>.json` |
|
||||
| `refine` | Refine the `--model` against merged structure factors (an MTZ or a structure-factor mmCIF) and process nothing; see [Refining a model against structure factors](RUGNUX_MODEL_AND_REFERENCE.md#refining-a-model-against-structure-factors-rugnux---mode-refine) (`--refine-score-only`, `--refine-d-min`) |
|
||||
|
||||
Refinement (`--mode refine`): the columns are found, not named - amplitudes with their sigmas (F/SIGF,
|
||||
FP/SIGFP, ...) where the file has them, else intensities (IMEAN/SIGIMEAN, I/SIGI, ...) made into amplitudes by
|
||||
French-Wilson, else the mean of the anomalous pairs; the free set from a FreeR_flag-like column (0 the test set,
|
||||
or the minority value where 0 is the majority, as phenix writes it), drawn by rugnux where the file has none.
|
||||
The model is taken as placed in the data's cell, and refined in the data's space group.
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--refine-score-only` | Score the model as given and refine nothing: R-work/R-free, the scale, the bulk solvent, the likelihood and the geometry, each term under `REFINE_SCORE_` (`--developer` prints them all) |
|
||||
| `--refine-d-min <num>` | Leave out reflections finer than this (Å) |
|
||||
|
||||
Calibration (`--mode calibration`):
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--calibrant <name>` | Powder standard: `lab6` \| `agbh` \| `ceo2` \| `si` \| `ice` (default `lab6`, case-insensitive). A cell given with `-C` overrides it: that cell is the standard, its rings enumerated from the cell, with the absences of `-S` where given |
|
||||
| `--calibration <txt>` | How the rings are measured: `rings` \| `spots` (default `rings`; see above). `rings` defaults `--azim-phi-bins` to 32 |
|
||||
| `--no-refine-tilt` | Do not refine the detector tilt: hold rot1/rot2 at the header value and fit only the beam centre and the distance, for a calibration handed to a program that cannot express a tilted detector (XDS). On stills it holds the tilt in the geometry refinement too |
|
||||
|
||||
Detector mask:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--detect-beam-stop[=N\|off]` | Find the beam stop and its holder in a projection of N images and add them to the pixel mask as bit 9, so nothing shadowed by them is integrated. **On by default** (60 images); `=off` disables. A reflection whose signal disk reaches into the shadow is not integrated: the rest of such a disk lies in the stop's half-shadow and reads low. Pixels the finder reports that hold the detector's no-data mark (a PILATUS gap) are masked as dead instead |
|
||||
|
||||
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 geometry needs it to be), and on rotation data index a **second first pass** at the measured centre. The fit reads the projection `--detect-beam-stop` already builds, so it costs no extra frames. **On by default**; `=off` disables it, and with it the measured centre's part in the post-refinement bound. The measured centre is adopted where the file's centre indexes nothing and the measured one indexes a majority; where the two return cells 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 against its own chance level; and, on a two-pass run, where the first pass is run at both centres and the measured one merges better — done where the two give the same cell in different metric symmetries, where they agree only once less of each frame is read, and where they agree but lie further apart than the geometry absorbs and the file's centre merges inconsistently in the lowest-resolution shell. Otherwise the file's centre is kept. On stills, where there is no first pass, the file's centre, the measured one and the point-symmetry capture's are each indexed on a sample of frames and the one putting materially more spots on the lattice is taken; with `-C` the detector distance is searched too (30-3000 mm, the file's value one hypothesis). Still runs when `--beam-x`/`--beam-y` are given. See [§1.4](CPU_DATA_ANALYSIS_IMAGE.md) |
|
||||
|
||||
Spot finding:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--spot-sigma <num>` | Noise sigma level for spot finding (default: 4.0) |
|
||||
| `--spot-threshold <num>` | Photon-count threshold for spot finding (default: 10) |
|
||||
| `--adaptive-spots` | Self-calibrating detection (**default**, stills and rotation alike): the strong-pixel threshold comes from each image's own per-resolution-ring noise instead of the fixed `--spot-threshold`, so one setting adapts across datasets (no per-dataset `--spot-threshold`/`--spot-sigma` tuning) |
|
||||
| `--no-adaptive-spots` | Turn adaptive detection off and use the fixed `--spot-threshold` / `--spot-sigma` finder |
|
||||
| `--spot-false-pixels <num>` | Adaptive-detection operating point: expected noise pixels tolerated per frame (default: 100; implies `--adaptive-spots`) |
|
||||
| `--spot-high-resolution <num>` | High-resolution limit for spot finding, Å. Omitted (or 0): no resolution clipping — spot finding extends as far as the detector reaches, for rotation data as well as stills |
|
||||
| `--spot-low-resolution <num>` | Low-resolution limit for spot finding, Å (default: 50; lower it, e.g. 24, to exclude the direct-beam halo on weak serial data; 0 removes the limit) |
|
||||
| `--min-pix-per-spot <num>` | Minimum connected strong pixels per spot. **If omitted, min-pix is chosen per image** (stills indexing): the frame is scored at min-pix 2/3/1 (one lattice search per frame, refined on each list) and the one maximising indexed-spot count × indexed fraction is kept. Give an explicit value to force a fixed min-pix instead. |
|
||||
| `--max-spots <num>` | Maximum spots kept per image (the strongest ones) and handed to indexing. **If omitted, the budget is measured** on rotation data: the first pass reads how deep into an image's spot list its spots still lie on the lattice it found, and the run keeps that many (never more than 1000). Give a value to pin it. Stills always use the fixed 1000. |
|
||||
| `--detect-ice-rings[=on\|off]` | Flag ice-ring spots (de-prioritised in indexing) and exclude ice-ring reflections from scaling. Default: the master file's `detect_ice_rings`, or — where the file carries no such key — **on for rotation and off for stills** |
|
||||
|
||||
Azimuthal integration (the radial profile behind the per-image ice-ring score). Every *q* here is
|
||||
*q* = 2π/*d*, in Å⁻¹:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `-q, --azim-q-spacing <num>` | Q bin spacing, 1/Å (default: 0.01; finer resolves the narrow ice rings) |
|
||||
| `--azim-min-q <num>` | Minimum Q, 1/Å |
|
||||
| `--azim-max-q <num>` | Maximum Q, 1/Å. Omitted: integration extends to the highest Q the detector reaches. The adaptive spot finder shares these Q bins, so this also sets how far self-calibrating detection can see |
|
||||
| `--azim-phi-bins <num>` | Number of azimuthal (phi) bins (default: 1) |
|
||||
| `--polarization-correction <on\|off>` | Enable/disable the azimuthal polarization correction |
|
||||
| `--solid-angle-correction <on\|off>` | Enable/disable the azimuthal solid-angle correction |
|
||||
|
||||
Indexing:
|
||||
|
||||
A dataset with a **rotation goniometer axis** is processed as rotation data (two-pass rotation
|
||||
indexing) by default; a dataset without one is processed as independent stills. `--force-still`
|
||||
overrides the former; the `-R` / `--single-pass-rotation` / `--force-rotation-lattice` flags request
|
||||
rotation explicitly and pick the pass or lattice.
|
||||
|
||||
The FFT search looks for cell axes between 10 Å (`--fft-min-unit-cell`) and a default **longest
|
||||
axis of 500 Å**, which has no flag of its own — a reference cell (`-C`) moves both bounds to cover
|
||||
the cell it names. A de-novo rotation run also tries a second first-pass hypothesis with the short
|
||||
end lowered to 5 Å, so a small-molecule cell below the 10 Å floor is indexed on its true axes
|
||||
rather than as a supercell of them; the standard pass's answer stands unless that evidence takes it. An axis beyond the search's reach is **not refused**: the run returns a
|
||||
plausible shorter sub-cell or an axis harmonic and processes it happily, so a cell that comes out
|
||||
at a half or a third of the expected long axis should be read as this limit, not as the crystal.
|
||||
For very long axes the direction grid's angular resolution binds well below 500 Å — see the
|
||||
[analysis reference](CPU_DATA_ANALYSIS_INDEXING.md#5-fft-indexing-unknown-unit-cell) on FFT indexing.
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--force-still` | Treat a rotation (goniometer) dataset as independent stills instead of rotation |
|
||||
| `-X, --indexing-algorithm <txt>` | `Auto` (default) \| `FFT` \| `cuFFT` \| `FFTW` \| `FFBIDX` \| `None`, case-insensitive. `FFT` is the de-novo FFT search, on the GPU (cuFFT) where there is one and `--no-gpu` is not given, otherwise on the CPU (FFTW); `cuFFT` and `FFTW` name one implementation each; `cuFFT` needs a GPU and is refused without one. `FFBIDX` (known cell, `-C`) runs on the GPU where there is one and otherwise on the CPU. `Auto` takes `FFBIDX` on stills with a known cell, and `FFT` otherwise; rotation data always use the FFT search |
|
||||
| `-C, --unit-cell <cell>` | Reference unit cell `"a,b,c,alpha,beta,gamma"` (required by `ffbidx`). On rotation data it also widens the FFT search to cover the cell given, at both ends: the longest axis looked for is raised to reach it, and `--fft-min-unit-cell` is lowered to admit it |
|
||||
| `--fft-min-unit-cell <num>` | Shortest cell axis the FFT search accepts, Å (default: 10). A candidate with a shorter axis is discarded — but a de-novo rotation run also runs a **second first-pass hypothesis with the floor lowered to 5 Å by default**, adopted when the standing cell turns out to be an integer supercell of what it finds, so a small-molecule cell is indexed without this flag. `-C` lowers the floor on its own to cover the cell given (and the second hypothesis then stays out of the way). On stills, where neither applies, a crystal below the floor cannot be indexed unless this is lowered |
|
||||
| `--min-indexed-spots <num>` | Spots a frame must have on the lattice before it counts as indexed (default: 6, minimum 4). It sets the reported indexing rate and the count the rotation first pass ranks candidate lattices by; whether the run has a lattice at all is decided on the pooled spots instead ([§4.1](CPU_DATA_ANALYSIS_INDEXING.md#41-indexed-spot-decision-inlier-test)), and integration is not gated by it |
|
||||
| `-S, --space-group <num\|symbol>` | Space group number (`96`) or Hermann-Mauguin symbol (`P43212`) — for indexing and scaling. On serial stills whose group admits two indexings, it also lets the crystals be put on one from the data ([the indexing ambiguity](#the-indexing-ambiguity)) |
|
||||
| `-r, --geom-refine <txt>` | Geometry refinement: `none` \| `orientation` \| `beam_and_lattice` (default) \| `flex` (try all three per image, keep whichever indexes the most spots; alias `multi`) |
|
||||
| `-R, --two-pass-rotation[=num]` | Two-pass offline rotation indexing (default for goniometer data; optional first-pass image count, default 100) |
|
||||
| `--single-pass-rotation[=num]` | Online-like single-pass rotation indexing (optional min angular range, deg) |
|
||||
| `--force-rotation-lattice <vec>` | Force rotation lattice (9 floats, Å), skipping the first pass |
|
||||
| `--rotation-no-postrefine` | Rotation: disable the default-on two-pass geometry post-refine (see the rotation section) |
|
||||
| `--prepass-fraction <f>` | Rotation: the two-pass geometry pre-pass integrates the first fraction `f` of the sweep, but at least 120° of it (0.05-1, default **0.5**; `1` integrates the whole sweep twice). The second pass always integrates every frame. The pre-scan and the first-pass indexing sample the same part of the sweep |
|
||||
| `--refine-geometry[=N\|off]` | Stills: extra first pass that bundle-adjusts the shared beam/distance/cell from N strongly-indexed frames (default 200) then re-indexes; default ON for stills with a reference cell (`-C` / `-z`), a stationary goniometer axis counting as stills, `=off` disables |
|
||||
| `--index-ice-rings[=on\|off]` | Index on the spots flagged as sitting on an ice ring too, instead of setting them aside (default: **off**; no effect without `--detect-ice-rings`, which does the flagging) |
|
||||
|
||||
Indexer choice in brief: `ffbidx` (GPU or CPU) refines toward a **known cell** and is best for sparse
|
||||
serial stills; `fft` (GPU) / `fftw` (CPU) index **de novo** and suit strong rotation data. See the
|
||||
[CPU/GPU data-analysis reference](CPU_DATA_ANALYSIS_INDEXING.md) for the algorithms.
|
||||
|
||||
Scaling and merging:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--no-merge` | Skip scaling and merging, which are on by default; the per-image `_process.h5` is then written instead of the merged files (`_unmerged.mtz` and the results report are still written) |
|
||||
| `-A, --anomalous` | Anomalous mode: merge each Bijvoet hand as its own unique reflection, so multiplicity, completeness, ⟨I/σ⟩ and the error model are counted anomalously. A default rotation merge already writes `I(+)`/`I(-)` (see [Reflection-file conventions](RUGNUX_INTEGRATION.md#reflection-file-conventions)); `-A` changes the counting basis, not whether the anomalous signal is in the file |
|
||||
| `--scale-fulls` / `--no-scale-fulls` | rot3d: refit a per-frame scale on the combined fulls (XDS order, Unity model); on by default for rotation data, off for stills |
|
||||
| `--smooth-g[=deg]` | rot3d: smooth the per-frame scale *G* over a degree range before the 3D combine (XDS DELPHI-like; default 5° for rotation, 0 = off) |
|
||||
| `--no-scaling-corrections` | rot3d: disable the default-on decay + absorption + modulation correction surfaces fitted on the fulls after scale-fulls (see below) |
|
||||
| `--relative-b[=deg]` | rot3d: fit a per-batch relative-*B* beyond the single decay slope over deg-degree batches, cross-validated (default 10° when bare; off otherwise) |
|
||||
| `--simple-stills` | Stills: treat every reflection as a full (*p* = 1, single-pass scale/merge) — disables the default-on physical partiality post-refinement |
|
||||
| `--no-expected-variance-merge` | Stills: disable the default expected-variance merge weighting (which rebuilds each weak observation's signal variance at the reflection mean to de-bias the inverse-variance merge); restores observed-sigma weighting |
|
||||
| `--capture-uncertainty <num>` | Systematic sigma num·(1−captured fraction)·⟨I⟩: on rot3d fulls the share of the rocking curve not captured, on stills the share of each partial its partiality does not see (default: 1.0 for rotation, 0 otherwise) |
|
||||
| `--min-captured-fraction <num>` | rot3d: drop a combined full whose rocking curve was captured below this fraction — edge-of-sweep truncated fulls (default: 0.7 for rotation, 0 otherwise; 0 = off) |
|
||||
| `--scaling-high-resolution <num>` | High-resolution limit for scaling, Å — manual override (default: no limit; disables the automatic cutoff below) |
|
||||
| `--scaling-low-resolution <num>` | Low-resolution limit of the scale fit, Å (default: 50, which is also XDS's own default; 0 removes the limit). Reflections coarser than it are merged and written but kept out of every fit of the scale model: on a large cell a few dozen of them, measured on a background the beam stop depresses, bent the model enough to move the merged 10–50 Å intensities by tens of percent. Which of them are measured at all is the beam-stop mask's decision - a reflection whose signal disk reaches the shadow is not integrated (`--detect-beam-stop`) |
|
||||
| `--resolution-cutoff <txt>` | Automatic high-resolution cutoff for the written reflections and reported shells: `cc-logistic` \| `off` (default: `cc-logistic`; ignored when `--scaling-high-resolution` is set) |
|
||||
| `--resolution-cc-target <num>` | CC1/2 target defining the `cc-logistic` fall-off (default: 0.30) |
|
||||
| `--resolution-shells <num>` | Number of resolution shells in the reported statistics table (default: 9). The bins are equal steps in 1/d² between the lowest- and highest-resolution reflection merged, which is XDS's rule, and 9 is XDS's count — so at the same resolution limits the two tables have the same shells and can be read row for row |
|
||||
| `--report-resolution <dmin>[,<dmax>]` | Also report the merging statistics over this resolution range, Å (either order; `dmax` defaults to the run's own low-resolution limit), as a second table beside the run's own — the `REFRES_*` keys of the [results report](RUGNUX_REPORT.md#the-reference-range-table) — binned from the same merged reflections, so a run can be read against another program's table at that program's range. Report-only: the cut, the scaling, the error model and every decision stay the run's own, and shells finer than the run's own limit are reported as not merged rather than filled from data the run did not keep |
|
||||
| `--min-partiality <num>` | Minimum partiality to accept a reflection (default: 0.02 for rotation, 0.5 for stills) |
|
||||
| `--ice-min-score <num>` | Ice-presence gate: the measured per-run ice score (1 = no ice) a dataset must reach before **any** ice handling is applied — the flagging and the exclusion from scaling (default: 1.5; 0 = no gate). The fixed hexagonal bands cover 16–26 % of the unique reflections whether or not the crystal has ice, so handling ice on a clean crystal only costs completeness |
|
||||
| `--ice-min-spot-ratio <num>` | The second ice-presence channel: found **spots** on the hexagonal rings over the same q width of ice-free flanks beside them (1 = spots spread evenly). Ice in large crystallites diffracts as discrete spots and leaves the radial profile flat, so `--ice-min-score` alone is blind to it (default: 2.0; 0 disables this channel) |
|
||||
| `--reject-outliers <num>` | Per-observation outlier rejection, N σ from the per-reflection median (default: 6 for rotation, 10 for stills; 0 = off) |
|
||||
| `--min-image-cc <num>` | Per-image CC limit, percent (default: no limit) |
|
||||
| `--search-min-zeta <num>` | De-novo space-group search only: also search a merge of just the observations whose Lorentz geometry \|ζ\| reaches this, and report both answers (default: 0.85 for rotation, 0 = single search). Reflections crossing the Ewald sphere near-tangentially are measured worst and can make a real symmetry operator look like a twin law. Where the two searches disagree, the merge of all the observations decides — as it always has for the systematic absences |
|
||||
| `--mosaicity <num>` | Diagnostic: fix the scaling mosaicity (°) instead of using the per-image seed |
|
||||
| `--scaling-iterations <num>` | Cap on the per-frame scaling iterations; the loop stops earlier once the scales settle, and a merge that hits the cap is flagged `SCALING_NOT_CONVERGED` (default: 100) |
|
||||
| `-z, --reference <file>` | Reference data of the same crystal form — an MTZ or a PDB structure-factor mmCIF (`-sf.cif`), gzipped or not, recognised by content; `--reference-mtz` is the same option: fixes the space group, its setting and the cell, resolves the [indexing ambiguity](#the-indexing-ambiguity), hands over the R-free set and reports CC<sub>ref</sub>. Not a scale anchor |
|
||||
| `--reference-column <label>` | Reference column to use, by MTZ label — an mmCIF under the labels `gemmi cif2mtz` gives it (default: auto — F-model, else IMEAN/I/…, else FP/FOBS/F) |
|
||||
| `--model <file>` | Validate the merged intensities against this atomic model (PDB or mmCIF, gzipped or not; the format is taken from the file's content) — R-work / R-free and maps (see [Validating against a model](#validating-against-a-model-rugnux---model)). An experimental model is placed as a rigid body, and by molecular replacement where the rigid body does not place it; a prediction (AlphaFold or ModelCIF) goes to molecular replacement straight away (`MODEL_PLACEMENT=`). It also settles the frame the reflections are written in: the enantiomorph, and the [indexing ambiguity](#the-indexing-ambiguity) where no `-z` did; another space group or the twin hypothesis' subgroup it chooses is written beside the answer as `<prefix>_mr.mtz`/`.cif`. For serial stills given `-C` / `-S`, the model's structure factors become the per-image reference. A placed model is then [refined](RUGNUX_MODEL_AND_REFERENCE.md#refinement) against the merge it was placed on (`<prefix>_refined_model.cif`, `<prefix>_refined_maps.mtz`, `<prefix>_blobs.json`, `REFINE_` keys) - seconds on a GPU, typically 2-15 minutes on the CPU - which decides nothing about the processing |
|
||||
| `--mr <file>` | As `--model`, but placed by molecular replacement straight away, without trying the rigid body first. `--mode mx` only; not with `--model` |
|
||||
| `--no-refine` | Do not refine the placed model (for debugging): by default a model that `--model` or `--mr` places is refined |
|
||||
| `--write-process-h5` | Also write the (large) `_process.h5` when merging (default: only `.mtz`/`.cif`) |
|
||||
| `--developer` | Write the full `<prefix>_report.txt`: the pipeline-internal keys and the long explanations the default report leaves out. Nothing is computed differently — the same report, rendered in full (see [The results report](RUGNUX_REPORT.md#the-developer-report)) |
|
||||
| `--finalist-ledger` | Report the full-resolution evidence for each space group the search considered, not only the one it adopted, and the twin-immune zone evidence of the adopted group's 2-folds (report-only; the decision is unchanged). Both are read on a merge of the observations in P1 that only this option makes, so it costs one extra merge; rotation only, and not with a fixed centred `-S` |
|
||||
| `--export-unmerged` | Write `<prefix>_unmerged.mtz`, an unmerged MTZ (POINTLESS column layout) of the integrated observations, for aimless / pointless / careless. **On by default** whenever there is an output prefix. Rotation partials are summed into one full per reflection. Intensities carry the deterministic per-reflection corrections and nothing else — Lorentz and polarization in `LP`, sensor efficiency in `QE`, flight path in `FLIGHT` — while the partiality is not divided out and the per-image scale is not applied. Written in `--mode mx` and `--mode scale`, and with `--no-merge`. See [The unmerged export](RUGNUX_INTEGRATION.md#the-unmerged-export) |
|
||||
| `--no-export-unmerged` | Do not write `<prefix>_unmerged.mtz`. It is the largest file a run produces, so a run whose observations are not going to another scaling program can skip it |
|
||||
| `--export-unmerged-partials` | Write `<prefix>_unmerged_partials.mtz`, the same observations with each partial as its own row (one batch per image) for the reading program to sum. Off by default, and independent of `--export-unmerged` |
|
||||
|
||||
Integration:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--integrator <txt>` | Spot integrator: `gaussian` (profile-fit, default) \| `empirical` \| `boxsum` (classical fallback) |
|
||||
| `--integration-radius <r>` | Signal-box radius `r1`, or `r1,r2,r3` (px). One value ⇒ `r2=r1+2`, `r3=r1+4` |
|
||||
| `--adaptive-integration-radius[=on\|off]` | Set the signal radius `r1` from how wide this crystal's spots actually are (default: **on**). On stills it measures instead how far the background ring should reach: on empty apertures of the pre-scan frames, the `r3` (up to 14) whose ring best predicts the background under the signal disk. `r1` is not the integration domain — that is the profile-fit grid — but it *is* the aperture the profile **width** is learned over, and a second moment over a disk of radius `a` saturates at `a²/4`, so at the shipped `r1 = 4` the learned σ can never exceed 2 px and a broader spot is fitted with a profile the model cannot represent. The pre-scan reads `r80`, the radius holding 80 % of a spot's flux, off isolated strong spots over a fixed 14 px aperture that owes nothing to `r1`, fits it against `1/d` and evaluates it at 5 Å; then `r1 = clamp(round(2·r80), 4, 6)`, `r2 = r1 + 2`, and `r3` is taken so the `r2..r3` background ring keeps the area it has at the default `4,6,13`. The ceiling of 6 is pattern density: `r2` also drives the neighbour-ownership radius and the ring's inner edge, and past it a dense pattern starts losing reflections whose ring falls below six clean pixels. Ignored when `--integration-radius` is given. The widened radius applies to the **final** integration pass only — the two-pass geometry pre-pass keeps the radius the run started with, because the post-refinement fits the detector distance and beam to the observed reflection positions and those move with the signal disk (33 µm and 0.02 px between `r1 = 4` and `r1 = 6` on one crystal, enough for the second pass's de-novo lattice search to settle on a different lattice and index a fifth fewer frames). And where the widened radius leaves more than 1.1 % of the predicted reflections without a background ring — a pattern too dense for it — the final pass is re-integrated at the fixed 4 px radius, and the log says so. Over the rotation regression battery it moves 12 of 38 crystals and leaves the merged intensities of the other 26 unchanged; where it moves them, per-shell ⟨I/σ⟩ improves by up to 31 % and R_meas by up to 24 % |
|
||||
| `--integration-stencil <k>` | Push the `r2..r3` background ring out by `k` times the beam's radial streak `bandwidth·R_px`, per reflection (default `0` = the fixed circular ring). A fixed ring otherwise ends up on a streaked reflection's own tails at high resolution and measures them as background. Only the ring moves, and only radially — the `r1` signal box stays a circle — and the growth is capped at `2·r3`. The neighbour exclusion grows with it, so on a crowded pattern a few reflections can be left with too little background and dropped. On a monochromatic beam the streak is zero and this does nothing |
|
||||
| `--background-clip <n>` | High-side clip of the background ring at `mean + n·√mean` (default 4, whatever the bandwidth; 0 = off). The default background estimator — it rejects neighbour cores and zingers without the symmetric trim's Poisson skew bias. Ignored by `--integrator boxsum` |
|
||||
| `--background-trim <f>` | Use the old symmetric trimmed mean for the background ring instead of the clip, 0≤f<0.5 (`0.10` was the former default). Switches `--background-clip` off. A symmetric trim is biased low on Poisson data and adds ~5 counts to every partial, so this is for back compatibility only; `0` = plain ring mean. Rings holding more than 512 pixels fall back to the plain mean (the GPU sorts the ring in shared memory and the CPU now matches it), which the default radii never reach but wide ones do |
|
||||
| `--background-radial[=on\|off\|auto]` | Correct the background ring for the **curvature** of the radial background (default **auto**). Disk and ring are concentric, so a background linear in position cancels between them and only curvature survives — which on a smooth ice ring reaches +26 counts on a single reflection. `auto` decides per run in the pre-scan, on empty apertures of the pre-scan frames: on stills it is applied to every image where it makes the ring predict the background of empty apertures better at all; on rotation data to every image where it takes at least 10 % of that error away, and otherwise only to images whose ice score shows a *smooth* powder ring (ice made of discrete crystallite spots leaves no such ring, and the correction makes the bias worse). Ignored by `--integrator boxsum` (no clip pass to take the curve from) |
|
||||
| `--integration-high-resolution <num>` | High-resolution limit for prediction and integration. Omitted (or 0) means integration extends as far as the detector reaches — which is what the predictor can place on the detector anyway, since it rejects reflections that miss it. Set a value to integrate less than the detector offers |
|
||||
| `--max-hkl <n>` | Predict reflections with \|h\|,\|k\|,\|l\| ≤ `n` (max 511). By default this is derived per crystal from the refined cell as `ceil(max(a,b,c)/d_min) + 1`, which is the exact bound: the predictor keeps only \|q\| ≤ 1/d_min and `h = a·q`, so no reflection can lie outside it and no candidate inside it is wasted on a shorter axis. Set it only to override that |
|
||||
| `--bandwidth <num>` | Relative X-ray bandwidth FWHM (e.g. `0.01` for a 1% DMM). Default: the file's value; where the file states none, the one the pre-scan measures from how much longer strong spots are along their radius than across it, used where it is significant; otherwise 0 (monochromatic). `--bandwidth 0` forces a monochromatic beam |
|
||||
| `--overlap <txt>` | What to do where two predicted reflections share signal pixels: `off` \| `reject` \| `exclude` (default `exclude`). A shared pixel belongs to the nearer centre; without this a crowded reflection reads high on a dense pattern. `exclude` drops the shared pixels from the profile fit, which renormalises itself, and keeps the reflection; `reject` instead drops the whole reflection when too little of its profile is cleanly its own. `--integrator boxsum` has no profile to renormalise, so only `reject` acts there |
|
||||
| `--overlap-minpk <f>` | Least fraction of a reflection's expected profile that must be usable for it to be kept (default 0.75, XDS `MINPK`). Governs both the fraction that must be **readable** — not masked, untrusted, in a gap or overloaded — in every profile mode, and, under `--overlap reject`, the fraction that must be cleanly its own. Under `--integrator boxsum` any unreadable pixel discards the disk outright and the reject fraction goes by disk *area*, which cuts harder |
|
||||
| `--flight-path <txt>` | What the diffracted beam crosses between the sample and the detector: `air` (default) \| `helium` \| `vacuum`. A reflection arriving at angle α to the detector normal flies `D/cos α` instead of `D`, so it crosses more of the medium and reads low; the factor is `exp(D/L·(1/cos α − 1))`, with `L` the attenuation length of the medium from the NIST tabulation and `D` and λ as stated by the file — nothing in it is fitted. **Nothing in NXmx, and no field of any master file Rugnux reads, describes the medium**, so it cannot be auto-detected and is assumed; the report states which medium was assumed and what it was worth (`FLIGHT_PATH`, `FLIGHT_PATH_WILSON_B`). Nor can it be inferred from the implied transmission — in this corpus a confirmed helium station sits at 51 % implied air transmission and a confirmed air station at 63 %. In air the term is +1.5 % at α = 55° for 18 keV over 160 mm and several-fold below 5 keV, where stations use helium precisely because air is unusable; helium attenuates ~1/600 of air, and vacuum leaves intensities untouched |
|
||||
| `--prediction-mosaicity <num>` | Diagnostic: fix the rocking width (deg) the **prediction** window opens to, leaving partiality on the per-image σ_M. The two are one number by default, so a σ_M that moves takes the integrated reflection population with it |
|
||||
|
||||
Geometry overrides (defaults are taken from the input file; override them to reprocess with a corrected geometry):
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--beam-x <num>` | Beam centre X (pixel). `--beam-center-check` still runs and can adopt its measured centre ([§1.4](CPU_DATA_ANALYSIS_IMAGE.md)) |
|
||||
| `--beam-y <num>` | Beam centre Y (pixel). `--beam-center-check` still runs and can adopt its measured centre ([§1.4](CPU_DATA_ANALYSIS_IMAGE.md)) |
|
||||
| `--detector-distance <num>` | Detector distance (mm). On stills it is then held: neither searched nor refined. Without it, stills with a reference cell (`-C`) search the distance and refine it with the cell |
|
||||
| `--wavelength <num>` | Wavelength (Å) |
|
||||
| `--pixel-size <num>` | Pixel size (µm), for a file that does not state it (an XTC stream of an unknown camera) |
|
||||
| `--gain <num>` | Detector units per photon, for input in detector units (SACLA, CXI, XTC, SMV, marCCD and `--crystfel-geometry` input). Where the background resolves single photons (SACLA, CXI and `--crystfel-geometry` input) the frames are counted in whole photons as they are read; otherwise they are analysed in their own units and the gain enters where a photon count is assumed. The integrated intensities come out in photons either way. Default: measured on the background of a few frames ([Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)) |
|
||||
| `--saturation <num>` | Pixel value from which a pixel is overloaded, in the units the frames are read in. Replaces the file's limit and the one stills read off the frames |
|
||||
| `--crystfel-geometry <file>` | Place the panels of an HDF5/CXI input by a CrystFEL geometry file instead of the file's own metadata: module geometry, camera length, mask arrays and bad regions (optional; [Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)) |
|
||||
| `--module-geometry <file>` | Where the detector's modules are: an NXmx file with one NXdetector_module per module (what a run writes as `<prefix>_modules.h5`) or a CrystFEL geometry file whose panels are laid on the image. Overrides the input's own |
|
||||
| `--refine-modules[=on\|off\|diagnose]` | Stills: place each module as a rigid block in the geometry bundle adjustment, where that predicts held-out spots better (default: on). Used for a foreign multi-panel detector, measured and reported only for a JUNGFRAU; the placement is written to `<prefix>_modules.h5` |
|
||||
| `--mask-good [<file>:]<dataset>[@<bits>]` / `--mask-bad [<file>:]<dataset>[@<bits>]` | HDF5/CXI stills: a mask array in the frames' stored layout, in `<file>` or in each data file; usable only where non-zero (or with all `<bits>`) / unusable where non-zero (or with any `<bits>`). Repeatable ([Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)) |
|
||||
| `--rot1 <num>` | PONI detector rotation 1 (rad). On stills, `--rot1` or `--rot2` holds the tilt (not refined); without them stills refine the tilt where held-out frames agree |
|
||||
| `--rot2 <num>` | PONI detector rotation 2 (rad) |
|
||||
| `--rot3 <num>` | PONI detector rotation 3, about the beam (rad) — the one `rugnux --mode calibration` writes into its `.poni`, so a refined third rotation can be given straight back |
|
||||
| `--detector-mirror-y` | The stored image is mirrored in Y relative to the frame the PONI angles are stated in |
|
||||
| `--detector-quarter-turns <0-3>` | The stored image is turned by this many multiples of 90° about the beam relative to that same frame |
|
||||
| `--polarization <num>` | Degree of polarization *p* (XDS `FRACTION_OF_POLARIZATION` = (1+*p*)/2), signed: positive for a horizontally polarized source, negative for a vertically polarized one; where the beam-stop pre-scan finds the background clearly suppressed in the other plane, the degree is applied in that plane instead. Default: what a miniCBF `# Polarization` line or a d*TREK `SOURCE_POLARZ` states (a fraction *f*, read as *p* = 2*f* − 1, so a laboratory tube's 0.5 is unpolarized), and otherwise 0.99, an undulator value; bending-magnet and wiggler sources are typically lower (0.8–0.95), and neither ADSC SMV, marCCD nor NXmx files state it, so pass the beamline's known value here |
|
||||
| `--rotation-scale <k>` | Goniometer rotation scale: the stage turned `k` times the angle stored in the file (the commanded one). Applied to both passes, and overrides the scale Rugnux fits for itself |
|
||||
Every option, with what it does, is on its own page: [Command-line options](RUGNUX_CLI.md).
|
||||
@@ -0,0 +1,332 @@
|
||||
# Command-line options
|
||||
|
||||
`rugnux` run with no arguments prints a short usage: how to run each mode and the options most runs
|
||||
need. This page is the full reference behind it - every option the program accepts, with what it
|
||||
does. The program's own usage message is the authority on behaviour; this page is kept consistent
|
||||
with it.
|
||||
|
||||
The same pages ship with the release archive, as `share/doc/jfjoch_rugnux/html/` beside `bin/`, so
|
||||
they can be read without a network; this one is `share/doc/jfjoch_rugnux/html/RUGNUX_CLI.html`.
|
||||
|
||||
```
|
||||
rugnux [options] <input> [<input> ...] [<broker URL>]
|
||||
```
|
||||
|
||||
```{contents} On this page
|
||||
:local:
|
||||
:depth: 2
|
||||
```
|
||||
|
||||
## Running each mode
|
||||
|
||||
What a run does is chosen with `--mode` (default `mx`). Within `mx`, rotation and stills are not
|
||||
chosen by an option: a dataset whose goniometer axis turns is processed as a rotation sweep, one
|
||||
without a goniometer axis - or with an axis that stands still - as serial stills.
|
||||
|
||||
### Rotation data (`--mode mx`, the default)
|
||||
|
||||
```
|
||||
rugnux -o myrun dataset_master.h5 # NXmx / EIGER / Jungfraujoch master file
|
||||
rugnux -o myrun sweep_00001.cbf # CBF, marCCD or SMV sweep: name one frame
|
||||
rugnux -o myrun dataset_master.h5 model.cif # with a model (or --model model.cif)
|
||||
rugnux -o myrun x_master.h5 http://host:5232/ # follow a broker's collection while it is written
|
||||
```
|
||||
|
||||
Chosen when the file's goniometer axis turns. One sweep per run. A model is placed (rigid body, or
|
||||
molecular replacement), refined and validated after merging; it does not change the processing
|
||||
decisions ([Models and reference data](RUGNUX_MODEL_AND_REFERENCE.md)).
|
||||
|
||||
### Serial stills (`--mode mx`)
|
||||
|
||||
```
|
||||
rugnux -o serial *_master.h5 # several NXmx masters of one setup
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 run*.h5 # SACLA (Cheetah HDF5)
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 *.cxi # Cheetah CXI
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 *.xtc # LCLS-I XTC streams
|
||||
```
|
||||
|
||||
Chosen when there is no goniometer axis or it does not turn; `--force-still` processes a rotation
|
||||
sweep as stills. Giving the known cell (`-C`) and space group (`-S`) is recommended for stills. Several inputs are one dataset, read in the order given. Without `-C` the stills
|
||||
are indexed de novo; a model is given as for rotation data
|
||||
([Still / serial data](RUGNUX_TUTORIAL.md#still-serial-data)).
|
||||
|
||||
### Refinement (`--mode refine`)
|
||||
|
||||
```
|
||||
rugnux --mode refine -o refined data.mtz model.cif
|
||||
```
|
||||
|
||||
Refines a model against merged data that already exist - an MTZ or a structure-factor mmCIF - and
|
||||
reads no images. The model is required, given among the inputs or with `--model`
|
||||
([Refining a model against structure factors](RUGNUX_MODEL_AND_REFERENCE.md#refining-a-model-against-structure-factors-rugnux---mode-refine)).
|
||||
|
||||
### Detector calibration (`--mode calibration`)
|
||||
|
||||
```
|
||||
rugnux --mode calibration --calibrant lab6 -o det LaB6_master.h5
|
||||
```
|
||||
|
||||
The detector geometry from a powder standard's rings, written as `det.poni` (pyFAI) and `det.json`
|
||||
([Detector calibration](RUGNUX_CALIBRATION.md)).
|
||||
|
||||
### Azimuthal integration (`--mode azint`)
|
||||
|
||||
```
|
||||
rugnux --mode azint -o profiles dataset_master.h5
|
||||
```
|
||||
|
||||
Azimuthal integration only - no spot finding, indexing or merging; writes `profiles_process.h5`.
|
||||
The binning is set by the [azimuthal-integration options](#azimuthal-integration).
|
||||
|
||||
### Re-merging (`--mode scale`)
|
||||
|
||||
```
|
||||
rugnux -o myrun --write-process-h5 dataset_master.h5 # integrate and merge once
|
||||
rugnux --mode scale -o remerged -A myrun_process.h5 # re-merge, here anomalously
|
||||
```
|
||||
|
||||
Re-scales and merges the reflections already integrated into a `_process.h5`, without re-running
|
||||
spot finding or integration ([Re-scaling and re-merging](RUGNUX_ADVANCED.md#re-scaling-and-re-merging-rugnux---mode-scale)).
|
||||
|
||||
## Inputs
|
||||
|
||||
Inputs are files, never a directory, read in the order given (a shell glob gives them sorted by
|
||||
name). Several inputs are read together only as one stills dataset in `--mode mx`: all the files of
|
||||
one dataset - `rugnux run*.h5` (SACLA), `*.cxi`, `*.xtc` (LCLS) - or several Jungfraujoch/NXmx
|
||||
masters of stills, read as one run: their images one after another, merged together, with the
|
||||
indexing rate reported per master as well. Such masters must share the detector, wavelength,
|
||||
distance and beam centre. Several inputs must be one format; a rotation sweep (name one frame of a
|
||||
CBF/marCCD/SMV sweep), any `--mode` other than `mx`, and following a broker take one. What each
|
||||
format needs is in [What Rugnux reads](RUGNUX_FORMATS.md); serial XFEL stills are read without a
|
||||
geometry file where their own metadata places the detector
|
||||
([Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)).
|
||||
|
||||
An atomic model and a reference reflection file can be given among the inputs, in any order,
|
||||
instead of `--model` and `-z`. Each file is told by its contents, not its name: an MTZ (the MTZ
|
||||
magic) or an mmCIF with a `_refln` or `_diffrn_refln` loop is reflections (`-z`; the input itself in
|
||||
`--mode refine`), a PDB file or an mmCIF with an `_atom_site` loop is a model (`--model`), anything
|
||||
else is images. An mmCIF holding both coordinates and reflections has to be given with `--model` or
|
||||
`-z`. At most one of each, also counting `--model`/`--mr` and `-z`; gzipped or not.
|
||||
|
||||
With a broker URL (`http://host:port/`) as the last argument and no input on disk yet, rugnux
|
||||
follows the broker's current collection while it is written: the input must be the path its master
|
||||
file will have, the data files are read next to it as the broker reports them closed, and the run
|
||||
ends with the images the collection delivered. Rotation data, `--mode mx` only. The collection's
|
||||
token is read from the environment variable `JUNGFRAUJOCH_HTTP_TOKEN` and sent only to the broker.
|
||||
With the input already on disk, the URL is ignored.
|
||||
|
||||
## All options
|
||||
|
||||
|
||||
### General
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `-o, --output-prefix <txt>` | Output file prefix (default: `output`) |
|
||||
| `-N, --threads <num>` | Number of worker threads (default, and for any value ≤ 0: every CPU the run may use - its affinity and cgroup quota). Some stages take fewer, because past a point more workers make them slower: the per-image loop of `--mode mx` uses at most 16 per GPU unless `-N` was given a positive value, and first-pass spot finding and the beam-stop pre-scan have ceilings of their own that `-N` does not lift. On a small card the two ceilings, and the per-image loop's 16 where `-N` was left at its default, come down to as many workers as keep their buffers (about 24 bytes per detector pixel each) within half of the card's total memory. Scaling, merging and the space-group search use the full count |
|
||||
| `-s, --start-image <num>` | First image to process (default: 0) |
|
||||
| `-e, --end-image <num>` | End image number, exclusive: `-s 0 -e 100` processes images 0-99 (default: all) |
|
||||
| `-t, --stride <num>` | Process every *n*-th image (default: 1) |
|
||||
| `-v, --verbose` | Show the whole log on the terminal in place of the steps; `<prefix>_log.txt` is written either way |
|
||||
| `--simulate-live <ms>` | Read a stored input as the collection it was while being written: image *i* becomes readable (*i*+1)·`ms` ms after the start (0: all at once). The run takes the live path a broker URL takes, with the same result; for testing the live workflow without a broker. `--mode mx` only |
|
||||
| `--fast-live` | With `--simulate-live` or a broker URL: run as the broker's rugnux live mode does — every decision stands where it was first taken, nothing is re-checked or run again once the sweep is in, the integration radius is fixed, and SIGINT cuts the run to what it has established. A difficult crystal can come out worse |
|
||||
| `--no-gpu` | Run on the CPU only, as on a machine without a GPU, even where one is present: CUDA is not touched (nor, on macOS, the Apple GPU that Bragg integration, the model density and the molecular-replacement rotation function otherwise run on) and every GPU step takes its CPU path (`-X FFT` indexes with FFTW and `-X FFBIDX` with its CPU implementation; `-X cuFFT` is refused) |
|
||||
|
||||
### Mode
|
||||
|
||||
`--mode <name>` (default `mx`):
|
||||
|
||||
| Value | Description |
|
||||
| --- | --- |
|
||||
| `mx` | Full analysis — spot finding, indexing, integration and merging |
|
||||
| `azint` | Only azimuthal integration (no spot finding/indexing); writes `<prefix>_process.h5` |
|
||||
| `scale` | Only re-scale/merge the already-integrated reflections in the input `_process.h5` (no re-integration) |
|
||||
| `calibration` | Determine the detector geometry from powder rings; writes `<prefix>.poni` and `<prefix>.json` |
|
||||
| `refine` | Refine the `--model` against merged structure factors (an MTZ or a structure-factor mmCIF) and process nothing; see [Refining a model against structure factors](RUGNUX_MODEL_AND_REFERENCE.md#refining-a-model-against-structure-factors-rugnux---mode-refine) (`--refine-score-only`, `--refine-d-min`) |
|
||||
|
||||
### Refinement (`--mode refine`)
|
||||
|
||||
The columns are found, not named - amplitudes with their sigmas (F/SIGF,
|
||||
FP/SIGFP, ...) where the file has them, else intensities (IMEAN/SIGIMEAN, I/SIGI, ...) made into amplitudes by
|
||||
French-Wilson, else the mean of the anomalous pairs; the free set from a FreeR_flag-like column (0 the test set,
|
||||
or the minority value where 0 is the majority, as phenix writes it), drawn by rugnux where the file has none.
|
||||
The model is taken as placed in the data's cell, and refined in the data's space group.
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--refine-score-only` | Score the model as given and refine nothing: R-work/R-free, the scale, the bulk solvent, the likelihood and the geometry, each term under `REFINE_SCORE_` (`--developer` prints them all) |
|
||||
| `--refine-d-min <num>` | Leave out reflections finer than this (Å) |
|
||||
|
||||
### Calibration (`--mode calibration`)
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--calibrant <name>` | Powder standard: `lab6` \| `agbh` \| `ceo2` \| `si` \| `ice` (default `lab6`, case-insensitive). A cell given with `-C` overrides it: that cell is the standard, its rings enumerated from the cell, with the absences of `-S` where given |
|
||||
| `--calibration <txt>` | How the rings are measured: `rings` \| `spots` (default `rings`; see [Detector calibration](RUGNUX_CALIBRATION.md)). `rings` defaults `--azim-phi-bins` to 32 |
|
||||
| `--no-refine-tilt` | Do not refine the detector tilt: hold rot1/rot2 at the header value and fit only the beam centre and the distance, for a calibration handed to a program that cannot express a tilted detector (XDS). On stills it holds the tilt in the geometry refinement too |
|
||||
|
||||
### Detector mask
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--detect-beam-stop[=N\|off]` | Find the beam stop and its holder in a projection of N images and add them to the pixel mask as bit 9, so nothing shadowed by them is integrated. **On by default** (60 images); `=off` disables. A reflection whose signal disk reaches into the shadow is not integrated: the rest of such a disk lies in the stop's half-shadow and reads low. Pixels the finder reports that hold the detector's no-data mark (a PILATUS gap) are masked as dead instead |
|
||||
|
||||
### Beam centre
|
||||
|
||||
| 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 geometry needs it to be), and on rotation data index a **second first pass** at the measured centre. The fit reads the projection `--detect-beam-stop` already builds, so it costs no extra frames. **On by default**; `=off` disables it, and with it the measured centre's part in the post-refinement bound. The measured centre is adopted where the file's centre indexes nothing and the measured one indexes a majority; where the two return cells 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 against its own chance level; and, on a two-pass run, where the first pass is run at both centres and the measured one merges better — done where the two give the same cell in different metric symmetries, where they agree only once less of each frame is read, and where they agree but lie further apart than the geometry absorbs and the file's centre merges inconsistently in the lowest-resolution shell. Otherwise the file's centre is kept. On stills, where there is no first pass, the file's centre, the measured one and the point-symmetry capture's are each indexed on a sample of frames and the one putting materially more spots on the lattice is taken; with `-C` the detector distance is searched too (30-3000 mm, the file's value one hypothesis). Still runs when `--beam-x`/`--beam-y` are given. See [§1.4](CPU_DATA_ANALYSIS_IMAGE.md) |
|
||||
|
||||
### Spot finding
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--spot-sigma <num>` | Noise sigma level for spot finding (default: 4.0) |
|
||||
| `--spot-threshold <num>` | Photon-count threshold for spot finding (default: 10) |
|
||||
| `--adaptive-spots` | Self-calibrating detection (**default**, stills and rotation alike): the strong-pixel threshold comes from each image's own per-resolution-ring noise instead of the fixed `--spot-threshold`, so one setting adapts across datasets (no per-dataset `--spot-threshold`/`--spot-sigma` tuning) |
|
||||
| `--no-adaptive-spots` | Turn adaptive detection off and use the fixed `--spot-threshold` / `--spot-sigma` finder |
|
||||
| `--spot-false-pixels <num>` | Adaptive-detection operating point: expected noise pixels tolerated per frame (default: 100; implies `--adaptive-spots`) |
|
||||
| `--spot-high-resolution <num>` | High-resolution limit for spot finding, Å. Omitted (or 0): no resolution clipping — spot finding extends as far as the detector reaches, for rotation data as well as stills |
|
||||
| `--spot-low-resolution <num>` | Low-resolution limit for spot finding, Å (default: 50; lower it, e.g. 24, to exclude the direct-beam halo on weak serial data; 0 removes the limit) |
|
||||
| `--min-pix-per-spot <num>` | Minimum connected strong pixels per spot. **If omitted, min-pix is chosen per image** (stills indexing): the frame is scored at min-pix 2/3/1 (one lattice search per frame, refined on each list) and the one maximising indexed-spot count × indexed fraction is kept. Give an explicit value to force a fixed min-pix instead. |
|
||||
| `--max-spots <num>` | Maximum spots kept per image (the strongest ones) and handed to indexing. **If omitted, the budget is measured** on rotation data: the first pass reads how deep into an image's spot list its spots still lie on the lattice it found, and the run keeps that many (never more than 1000). Give a value to pin it. Stills always use the fixed 1000. |
|
||||
| `--detect-ice-rings[=on\|off]` | Flag ice-ring spots (de-prioritised in indexing) and exclude ice-ring reflections from scaling. Default: the master file's `detect_ice_rings`, or — where the file carries no such key — **on for rotation and off for stills** |
|
||||
|
||||
### Azimuthal integration
|
||||
|
||||
The radial profile behind the per-image ice-ring score, and what `--mode azint` writes. Every *q* here is
|
||||
*q* = 2π/*d*, in Å⁻¹:
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `-q, --azim-q-spacing <num>` | Q bin spacing, 1/Å (default: 0.01; finer resolves the narrow ice rings) |
|
||||
| `--azim-min-q <num>` | Minimum Q, 1/Å |
|
||||
| `--azim-max-q <num>` | Maximum Q, 1/Å. Omitted: integration extends to the highest Q the detector reaches. The adaptive spot finder shares these Q bins, so this also sets how far self-calibrating detection can see |
|
||||
| `--azim-phi-bins <num>` | Number of azimuthal (phi) bins (default: 1) |
|
||||
| `--polarization-correction <on\|off>` | Enable/disable the azimuthal polarization correction |
|
||||
| `--solid-angle-correction <on\|off>` | Enable/disable the azimuthal solid-angle correction |
|
||||
|
||||
### Indexing
|
||||
|
||||
A dataset with a **rotation goniometer axis** is processed as rotation data (two-pass rotation
|
||||
indexing) by default; a dataset without one is processed as independent stills. `--force-still`
|
||||
overrides the former; the `-R` / `--single-pass-rotation` / `--force-rotation-lattice` flags request
|
||||
rotation explicitly and pick the pass or lattice.
|
||||
|
||||
The FFT search looks for cell axes between 10 Å (`--fft-min-unit-cell`) and a default **longest
|
||||
axis of 500 Å**, which has no flag of its own — a reference cell (`-C`) moves both bounds to cover
|
||||
the cell it names. A de-novo rotation run also tries a second first-pass hypothesis with the short
|
||||
end lowered to 5 Å, so a small-molecule cell below the 10 Å floor is indexed on its true axes
|
||||
rather than as a supercell of them; the standard pass's answer stands unless that evidence takes it. An axis beyond the search's reach is **not refused**: the run returns a
|
||||
plausible shorter sub-cell or an axis harmonic and processes it happily, so a cell that comes out
|
||||
at a half or a third of the expected long axis should be read as this limit, not as the crystal.
|
||||
For very long axes the direction grid's angular resolution binds well below 500 Å — see the
|
||||
[analysis reference](CPU_DATA_ANALYSIS_INDEXING.md#5-fft-indexing-unknown-unit-cell) on FFT indexing.
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--force-still` | Treat a rotation (goniometer) dataset as independent stills instead of rotation |
|
||||
| `-X, --indexing-algorithm <txt>` | `Auto` (default) \| `FFT` \| `cuFFT` \| `FFTW` \| `FFBIDX` \| `None`, case-insensitive. `FFT` is the de-novo FFT search, on the GPU (cuFFT) where there is one and `--no-gpu` is not given, otherwise on the CPU (FFTW); `cuFFT` and `FFTW` name one implementation each; `cuFFT` needs a GPU and is refused without one. `FFBIDX` (known cell, `-C`) runs on the GPU where there is one and otherwise on the CPU. `Auto` takes `FFBIDX` on stills with a known cell, and `FFT` otherwise; rotation data always use the FFT search |
|
||||
| `-F` | Short for `-X FFT`, kept for old command lines |
|
||||
| `-C, --unit-cell <cell>` | Reference unit cell `"a,b,c,alpha,beta,gamma"` (required by `ffbidx`). On rotation data it also widens the FFT search to cover the cell given, at both ends: the longest axis looked for is raised to reach it, and `--fft-min-unit-cell` is lowered to admit it |
|
||||
| `--fft-min-unit-cell <num>` | Shortest cell axis the FFT search accepts, Å (default: 10). A candidate with a shorter axis is discarded — but a de-novo rotation run also runs a **second first-pass hypothesis with the floor lowered to 5 Å by default**, adopted when the standing cell turns out to be an integer supercell of what it finds, so a small-molecule cell is indexed without this flag. `-C` lowers the floor on its own to cover the cell given (and the second hypothesis then stays out of the way). On stills, where neither applies, a crystal below the floor cannot be indexed unless this is lowered |
|
||||
| `--min-indexed-spots <num>` | Spots a frame must have on the lattice before it counts as indexed (default: 6, minimum 4). It sets the reported indexing rate and the count the rotation first pass ranks candidate lattices by; whether the run has a lattice at all is decided on the pooled spots instead ([§4.1](CPU_DATA_ANALYSIS_INDEXING.md#41-indexed-spot-decision-inlier-test)), and integration is not gated by it |
|
||||
| `-S, --space-group <num\|symbol>` | Space group number (`96`) or Hermann-Mauguin symbol (`P43212`) — for indexing and scaling. On serial stills whose group admits two indexings, it also lets the crystals be put on one from the data ([the indexing ambiguity](RUGNUX_ADVANCED.md#the-indexing-ambiguity)) |
|
||||
| `-r, --geom-refine <txt>` | Geometry refinement: `none` \| `orientation` \| `beam_and_lattice` (default) \| `flex` (try all three per image, keep whichever indexes the most spots; alias `multi`) |
|
||||
| `-R, --two-pass-rotation[=num]` | Two-pass offline rotation indexing (default for goniometer data; optional first-pass image count, default 100) |
|
||||
| `--single-pass-rotation[=num]` | Online-like single-pass rotation indexing (optional min angular range, deg) |
|
||||
| `--force-rotation-lattice <vec>` | Force rotation lattice (9 floats, Å), skipping the first pass |
|
||||
| `--rotation-no-postrefine` | Rotation: disable the default-on two-pass geometry post-refine (see [Rotation data](RUGNUX_TUTORIAL.md#rotation-data)) |
|
||||
| `--prepass-fraction <f>` | Rotation: the two-pass geometry pre-pass integrates the first fraction `f` of the sweep, but at least 120° of it (0.05-1, default **0.5**; `1` integrates the whole sweep twice). The second pass always integrates every frame. The pre-scan and the first-pass indexing sample the same part of the sweep |
|
||||
| `--refine-geometry[=N\|off]` | Stills: extra first pass that bundle-adjusts the shared beam/distance/cell from N strongly-indexed frames (default 200) then re-indexes; default ON for stills with a reference cell (`-C` / `-z`), a stationary goniometer axis counting as stills, `=off` disables |
|
||||
| `--index-ice-rings[=on\|off]` | Index on the spots flagged as sitting on an ice ring too, instead of setting them aside (default: **off**; no effect without `--detect-ice-rings`, which does the flagging) |
|
||||
|
||||
Indexer choice in brief: `ffbidx` (GPU or CPU) refines toward a **known cell** and is best for sparse
|
||||
serial stills; `fft` (GPU) / `fftw` (CPU) index **de novo** and suit strong rotation data. See the
|
||||
[CPU/GPU data-analysis reference](CPU_DATA_ANALYSIS_INDEXING.md) for the algorithms.
|
||||
|
||||
### Scaling and merging
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--no-merge` | Skip scaling and merging, which are on by default; the per-image `_process.h5` is then written instead of the merged files (`_unmerged.mtz` and the results report are still written) |
|
||||
| `-A, --anomalous` | Anomalous mode: merge each Bijvoet hand as its own unique reflection, so multiplicity, completeness, ⟨I/σ⟩ and the error model are counted anomalously. A default rotation merge already writes `I(+)`/`I(-)` (see [Reflection-file conventions](RUGNUX_INTEGRATION.md#reflection-file-conventions)); `-A` changes the counting basis, not whether the anomalous signal is in the file |
|
||||
| `--scale-fulls` / `--no-scale-fulls` | rot3d: refit a per-frame scale on the combined fulls (XDS order, Unity model); on by default for rotation data, off for stills |
|
||||
| `--smooth-g[=deg]` | rot3d: smooth the per-frame scale *G* over a degree range before the 3D combine (XDS DELPHI-like; default 5° for rotation, 0 = off) |
|
||||
| `--no-scaling-corrections` | rot3d: disable the default-on decay + absorption + modulation correction surfaces fitted on the fulls after scale-fulls |
|
||||
| `--relative-b[=deg]` | rot3d: fit a per-batch relative-*B* beyond the single decay slope over deg-degree batches, cross-validated (default 10° when bare; off otherwise) |
|
||||
| `--simple-stills` | Stills: treat every reflection as a full (*p* = 1, single-pass scale/merge) — disables the default-on physical partiality post-refinement |
|
||||
| `--no-expected-variance-merge` | Stills: disable the default expected-variance merge weighting (which rebuilds each weak observation's signal variance at the reflection mean to de-bias the inverse-variance merge); restores observed-sigma weighting |
|
||||
| `--capture-uncertainty <num>` | Systematic sigma num·(1−captured fraction)·⟨I⟩: on rot3d fulls the share of the rocking curve not captured, on stills the share of each partial its partiality does not see (default: 1.0 for rotation, 0 otherwise) |
|
||||
| `--min-captured-fraction <num>` | rot3d: drop a combined full whose rocking curve was captured below this fraction — edge-of-sweep truncated fulls (default: 0.7 for rotation, 0 otherwise; 0 = off) |
|
||||
| `--scaling-high-resolution <num>` | High-resolution limit for scaling, Å — manual override (default: no limit; disables the automatic cutoff below) |
|
||||
| `--scaling-low-resolution <num>` | Low-resolution limit of the scale fit, Å (default: 50, which is also XDS's own default; 0 removes the limit). Reflections coarser than it are merged and written but kept out of every fit of the scale model: on a large cell a few dozen of them, measured on a background the beam stop depresses, bent the model enough to move the merged 10–50 Å intensities by tens of percent. Which of them are measured at all is the beam-stop mask's decision - a reflection whose signal disk reaches the shadow is not integrated (`--detect-beam-stop`) |
|
||||
| `--resolution-cutoff <txt>` | Automatic high-resolution cutoff for the written reflections and reported shells: `cc-logistic` \| `off` (default: `cc-logistic`; ignored when `--scaling-high-resolution` is set) |
|
||||
| `--resolution-cc-target <num>` | CC1/2 target defining the `cc-logistic` fall-off (default: 0.30) |
|
||||
| `--resolution-shells <num>` | Number of resolution shells in the reported statistics table (default: 9). The bins are equal steps in 1/d² between the lowest- and highest-resolution reflection merged, which is XDS's rule, and 9 is XDS's count — so at the same resolution limits the two tables have the same shells and can be read row for row |
|
||||
| `--report-resolution <dmin>[,<dmax>]` | Also report the merging statistics over this resolution range, Å (either order; `dmax` defaults to the run's own low-resolution limit), as a second table beside the run's own — the `REFRES_*` keys of the [results report](RUGNUX_REPORT.md#the-reference-range-table) — binned from the same merged reflections, so a run can be read against another program's table at that program's range. Report-only: the cut, the scaling, the error model and every decision stay the run's own, and shells finer than the run's own limit are reported as not merged rather than filled from data the run did not keep |
|
||||
| `--min-partiality <num>` | Minimum partiality to accept a reflection (default: 0.02 for rotation, 0.5 for stills) |
|
||||
| `--ice-min-score <num>` | Ice-presence gate: the measured per-run ice score (1 = no ice) a dataset must reach before **any** ice handling is applied — the flagging and the exclusion from scaling (default: 1.5; 0 = no gate). The fixed hexagonal bands cover 16–26 % of the unique reflections whether or not the crystal has ice, so handling ice on a clean crystal only costs completeness |
|
||||
| `--ice-min-spot-ratio <num>` | The second ice-presence channel: found **spots** on the hexagonal rings over the same q width of ice-free flanks beside them (1 = spots spread evenly). Ice in large crystallites diffracts as discrete spots and leaves the radial profile flat, so `--ice-min-score` alone is blind to it (default: 2.0; 0 disables this channel) |
|
||||
| `--reject-outliers <num>` | Per-observation outlier rejection, N σ from the per-reflection median (default: 6 for rotation, 10 for stills; 0 = off) |
|
||||
| `--min-image-cc <num>` | Per-image CC limit, percent (default: no limit) |
|
||||
| `--search-min-zeta <num>` | De-novo space-group search only: also search a merge of just the observations whose Lorentz geometry \|ζ\| reaches this, and report both answers (default: 0.85 for rotation, 0 = single search). Reflections crossing the Ewald sphere near-tangentially are measured worst and can make a real symmetry operator look like a twin law. Where the two searches disagree, the merge of all the observations decides — as it always has for the systematic absences |
|
||||
| `--mosaicity <num>` | Diagnostic: fix the scaling mosaicity (°) instead of using the per-image seed |
|
||||
| `--scaling-iterations <num>` | Cap on the per-frame scaling iterations; the loop stops earlier once the scales settle, and a merge that hits the cap is flagged `SCALING_NOT_CONVERGED` (default: 100) |
|
||||
| `-z, --reference <file>` | Reference data of the same crystal form — an MTZ or a PDB structure-factor mmCIF (`-sf.cif`), gzipped or not, recognised by content; `--reference-mtz` is the same option: fixes the space group, its setting and the cell, resolves the [indexing ambiguity](RUGNUX_ADVANCED.md#the-indexing-ambiguity), hands over the R-free set and reports CC<sub>ref</sub>. Not a scale anchor |
|
||||
| `--reference-column <label>` | Reference column to use, by MTZ label — an mmCIF under the labels `gemmi cif2mtz` gives it (default: auto — F-model, else IMEAN/I/…, else FP/FOBS/F) |
|
||||
| `--model <file>` | Validate the merged intensities against this atomic model (PDB or mmCIF, gzipped or not; the format is taken from the file's content) — R-work / R-free and maps (see [Validating against a model](RUGNUX_ADVANCED.md#validating-against-a-model-rugnux---model)). An experimental model is placed as a rigid body, and by molecular replacement where the rigid body does not place it; a prediction (AlphaFold or ModelCIF) goes to molecular replacement straight away (`MODEL_PLACEMENT=`). It also settles the frame the reflections are written in: the enantiomorph, and the [indexing ambiguity](RUGNUX_ADVANCED.md#the-indexing-ambiguity) where no `-z` did; another space group or the twin hypothesis' subgroup it chooses is written beside the answer as `<prefix>_mr.mtz`/`.cif`. For serial stills given `-C` / `-S`, the model's structure factors become the per-image reference. A placed model is then [refined](RUGNUX_MODEL_AND_REFERENCE.md#refinement) against the merge it was placed on (`<prefix>_refined_model.cif`, `<prefix>_refined_maps.mtz`, `<prefix>_blobs.json`, `REFINE_` keys) - seconds on a GPU, typically 2-15 minutes on the CPU - which decides nothing about the processing |
|
||||
| `--mr <file>` | As `--model`, but placed by molecular replacement straight away, without trying the rigid body first: as many copies as the cell holds, in every space group the merge cannot tell apart and in the twin hypothesis' subgroup. A prediction is trimmed to the residues of pLDDT 70 and above, and where the AlphaFold DB's predicted-aligned-error JSON sits beside it under its own name it is cut into rigid domains; any other PDB or mmCIF is taken as an experimental structure, its polymer only (no waters, ligands, hydrogens or alternative conformers). It may relabel the enantiomorph of the answer, and a different space group it chooses is written beside the answer as `<prefix>_mr.mtz`/`.cif` with the placed model `<prefix>_mr_model.pdb`. `--mode mx` only; not with `--model` |
|
||||
| `--no-refine` | Do not refine the placed model (for debugging): by default a model that `--model` or `--mr` places is refined |
|
||||
| `--no-refine-solvent` | Refine the placed model with its solvent as given: no waters built or removed, no ion relabelled (the solvent audit - the `REFINE_SOLVENT_` keys and `<prefix>_solvent.json` - is still made). Also with `--mode refine` |
|
||||
| `--write-process-h5` | Also write the (large) `_process.h5` when merging (default: only `.mtz`/`.cif`) |
|
||||
| `--developer` | Write the full `<prefix>_report.txt`: the pipeline-internal keys and the long explanations the default report leaves out. Nothing is computed differently — the same report, rendered in full (see [The results report](RUGNUX_REPORT.md#the-developer-report)) |
|
||||
| `--finalist-ledger` | Report the full-resolution evidence for each space group the search considered, not only the one it adopted, and the twin-immune zone evidence of the adopted group's 2-folds (report-only; the decision is unchanged). Both are read on a merge of the observations in P1 that only this option makes, so it costs one extra merge; rotation only, and not with a fixed centred `-S` |
|
||||
| `--export-unmerged` | Write `<prefix>_unmerged.mtz`, an unmerged MTZ (POINTLESS column layout) of the integrated observations, for aimless / pointless / careless. **On by default** whenever there is an output prefix. Rotation partials are summed into one full per reflection. Intensities carry the deterministic per-reflection corrections and nothing else — Lorentz and polarization in `LP`, sensor efficiency in `QE`, flight path in `FLIGHT` — while the partiality is not divided out and the per-image scale is not applied. Written in `--mode mx` and `--mode scale`, and with `--no-merge`. See [The unmerged export](RUGNUX_INTEGRATION.md#the-unmerged-export) |
|
||||
| `--no-export-unmerged` | Do not write `<prefix>_unmerged.mtz`. It is the largest file a run produces, so a run whose observations are not going to another scaling program can skip it |
|
||||
| `--export-unmerged-partials` | Write `<prefix>_unmerged_partials.mtz`, the same observations with each partial as its own row (one batch per image) for the reading program to sum. Off by default, and independent of `--export-unmerged` |
|
||||
| `--dump-observations <file>` | Diagnostic: write the unmerged fulls of every rotation 3D combine to `<file>` as text, for a comparison with XDS |
|
||||
|
||||
### Integration
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--integrator <txt>` | Spot integrator: `gaussian` (profile-fit, default) \| `empirical` \| `boxsum` (classical fallback) |
|
||||
| `--integration-radius <r>` | Signal-box radius `r1`, or `r1,r2,r3` (px). One value ⇒ `r2=r1+2`, `r3=r1+4` |
|
||||
| `--adaptive-integration-radius[=on\|off]` | Set the signal radius `r1` from how wide this crystal's spots actually are (default: **on**). On stills it measures instead how far the background ring should reach: on empty apertures of the pre-scan frames, the `r3` (up to 14) whose ring best predicts the background under the signal disk. `r1` is not the integration domain — that is the profile-fit grid — but it *is* the aperture the profile **width** is learned over, and a second moment over a disk of radius `a` saturates at `a²/4`, so at the shipped `r1 = 4` the learned σ can never exceed 2 px and a broader spot is fitted with a profile the model cannot represent. The pre-scan reads `r80`, the radius holding 80 % of a spot's flux, off isolated strong spots over a fixed 14 px aperture that owes nothing to `r1`, fits it against `1/d` and evaluates it at 5 Å; then `r1 = clamp(round(2·r80), 4, 6)`, `r2 = r1 + 2`, and `r3` is taken so the `r2..r3` background ring keeps the area it has at the default `4,6,13`. The ceiling of 6 is pattern density: `r2` also drives the neighbour-ownership radius and the ring's inner edge, and past it a dense pattern starts losing reflections whose ring falls below six clean pixels. Ignored when `--integration-radius` is given. The widened radius applies to the **final** integration pass only — the two-pass geometry pre-pass keeps the radius the run started with, because the post-refinement fits the detector distance and beam to the observed reflection positions and those move with the signal disk (33 µm and 0.02 px between `r1 = 4` and `r1 = 6` on one crystal, enough for the second pass's de-novo lattice search to settle on a different lattice and index a fifth fewer frames). And where the widened radius leaves more than 1.1 % of the predicted reflections without a background ring — a pattern too dense for it — the final pass is re-integrated at the fixed 4 px radius, and the log says so. Over the rotation regression battery it moves 12 of 38 crystals and leaves the merged intensities of the other 26 unchanged; where it moves them, per-shell ⟨I/σ⟩ improves by up to 31 % and R_meas by up to 24 % |
|
||||
| `--integration-stencil <k>` | Push the `r2..r3` background ring out by `k` times the beam's radial streak `bandwidth·R_px`, per reflection (default `0` = the fixed circular ring). A fixed ring otherwise ends up on a streaked reflection's own tails at high resolution and measures them as background. Only the ring moves, and only radially — the `r1` signal box stays a circle — and the growth is capped at `2·r3`. The neighbour exclusion grows with it, so on a crowded pattern a few reflections can be left with too little background and dropped. On a monochromatic beam the streak is zero and this does nothing |
|
||||
| `--background-clip <n>` | High-side clip of the background ring at `mean + n·√mean` (default 4, whatever the bandwidth; 0 = off). The default background estimator — it rejects neighbour cores and zingers without the symmetric trim's Poisson skew bias. Ignored by `--integrator boxsum` |
|
||||
| `--background-trim <f>` | Use the old symmetric trimmed mean for the background ring instead of the clip, 0≤f<0.5 (`0.10` was the former default). Switches `--background-clip` off. A symmetric trim is biased low on Poisson data and adds ~5 counts to every partial, so this is for back compatibility only; `0` = plain ring mean. Rings holding more than 512 pixels fall back to the plain mean (the GPU sorts the ring in shared memory and the CPU now matches it), which the default radii never reach but wide ones do |
|
||||
| `--background-radial[=on\|off\|auto]` | Correct the background ring for the **curvature** of the radial background (default **auto**). Disk and ring are concentric, so a background linear in position cancels between them and only curvature survives — which on a smooth ice ring reaches +26 counts on a single reflection. `auto` decides per run in the pre-scan, on empty apertures of the pre-scan frames: on stills it is applied to every image where it makes the ring predict the background of empty apertures better at all; on rotation data to every image where it takes at least 10 % of that error away, and otherwise only to images whose ice score shows a *smooth* powder ring (ice made of discrete crystallite spots leaves no such ring, and the correction makes the bias worse). Ignored by `--integrator boxsum` (no clip pass to take the curve from) |
|
||||
| `--integration-high-resolution <num>` | High-resolution limit for prediction and integration. Omitted (or 0) means integration extends as far as the detector reaches — which is what the predictor can place on the detector anyway, since it rejects reflections that miss it. Set a value to integrate less than the detector offers |
|
||||
| `--max-hkl <n>` | Predict reflections with \|h\|,\|k\|,\|l\| ≤ `n` (max 511). By default this is derived per crystal from the refined cell as `ceil(max(a,b,c)/d_min) + 1`, which is the exact bound: the predictor keeps only \|q\| ≤ 1/d_min and `h = a·q`, so no reflection can lie outside it and no candidate inside it is wasted on a shorter axis. Set it only to override that |
|
||||
| `--bandwidth <num>` | Relative X-ray bandwidth FWHM (e.g. `0.01` for a 1% DMM). Default: the file's value; where the file states none, the one the pre-scan measures from how much longer strong spots are along their radius than across it, used where it is significant; otherwise 0 (monochromatic). `--bandwidth 0` forces a monochromatic beam |
|
||||
| `--overlap <txt>` | What to do where two predicted reflections share signal pixels: `off` \| `reject` \| `exclude` (default `exclude`). A shared pixel belongs to the nearer centre; without this a crowded reflection reads high on a dense pattern. `exclude` drops the shared pixels from the profile fit, which renormalises itself, and keeps the reflection; `reject` instead drops the whole reflection when too little of its profile is cleanly its own. `--integrator boxsum` has no profile to renormalise, so only `reject` acts there |
|
||||
| `--overlap-minpk <f>` | Least fraction of a reflection's expected profile that must be usable for it to be kept (default 0.75, XDS `MINPK`). Governs both the fraction that must be **readable** — not masked, untrusted, in a gap or overloaded — in every profile mode, and, under `--overlap reject`, the fraction that must be cleanly its own. Under `--integrator boxsum` any unreadable pixel discards the disk outright and the reject fraction goes by disk *area*, which cuts harder |
|
||||
| `--flight-path <txt>` | What the diffracted beam crosses between the sample and the detector: `air` (default) \| `helium` \| `vacuum`. A reflection arriving at angle α to the detector normal flies `D/cos α` instead of `D`, so it crosses more of the medium and reads low; the factor is `exp(D/L·(1/cos α − 1))`, with `L` the attenuation length of the medium from the NIST tabulation and `D` and λ as stated by the file — nothing in it is fitted. **Nothing in NXmx, and no field of any master file Rugnux reads, describes the medium**, so it cannot be auto-detected and is assumed; the report states which medium was assumed and what it was worth (`FLIGHT_PATH`, `FLIGHT_PATH_WILSON_B`). Nor can it be inferred from the implied transmission — in this corpus a confirmed helium station sits at 51 % implied air transmission and a confirmed air station at 63 %. In air the term is +1.5 % at α = 55° for 18 keV over 160 mm and several-fold below 5 keV, where stations use helium precisely because air is unusable; helium attenuates ~1/600 of air, and vacuum leaves intensities untouched |
|
||||
| `--prediction-mosaicity <num>` | Diagnostic: fix the rocking width (deg) the **prediction** window opens to, leaving partiality on the per-image σ_M. The two are one number by default, so a σ_M that moves takes the integrated reflection population with it |
|
||||
|
||||
### Geometry overrides
|
||||
|
||||
Defaults are taken from the input file; override them to reprocess with a corrected geometry.
|
||||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `--beam-x <num>` | Beam centre X (pixel). `--beam-center-check` still runs and can adopt its measured centre ([§1.4](CPU_DATA_ANALYSIS_IMAGE.md)) |
|
||||
| `--beam-y <num>` | Beam centre Y (pixel). `--beam-center-check` still runs and can adopt its measured centre ([§1.4](CPU_DATA_ANALYSIS_IMAGE.md)) |
|
||||
| `--detector-distance <num>` | Detector distance (mm). On stills it is then held: neither searched nor refined. Without it, stills with a reference cell (`-C`) search the distance and refine it with the cell |
|
||||
| `--wavelength <num>` | Wavelength (Å) |
|
||||
| `--pixel-size <num>` | Pixel size (µm), for a file that does not state it (an XTC stream of an unknown camera) |
|
||||
| `--gain <num>` | Detector units per photon, for input in detector units (SACLA, CXI, XTC, SMV, marCCD and `--crystfel-geometry` input). Where the background resolves single photons (SACLA, CXI and `--crystfel-geometry` input) the frames are counted in whole photons as they are read; otherwise they are analysed in their own units and the gain enters where a photon count is assumed. The integrated intensities come out in photons either way. Default: measured on the background of a few frames ([Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)) |
|
||||
| `--saturation <num>` | Pixel value from which a pixel is overloaded, in the units the frames are read in. Replaces the file's limit and the one stills read off the frames |
|
||||
| `--crystfel-geometry <file>` | Place the panels of an HDF5/CXI input by a CrystFEL geometry file instead of the file's own metadata: module geometry, camera length, mask arrays and bad regions (optional; [Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)). Photon energy, camera length and - where the geometry names no mask array - the masks otherwise come from the data files (Cheetah CXI, SACLA) or the command line; gain and saturation are measured. Tilted panels, `dimN` layouts, per-panel data and detector shifts are refused |
|
||||
| `--module-geometry <file>` | Where the detector's modules are: an NXmx file with one NXdetector_module per module (what a run writes as `<prefix>_modules.h5`) or a CrystFEL geometry file whose panels are laid on the image. Overrides the input's own |
|
||||
| `--refine-modules[=on\|off\|diagnose]` | Stills: place each module as a rigid block in the geometry bundle adjustment, where that predicts held-out spots better (default: on). Used for a foreign multi-panel detector, measured and reported only for a JUNGFRAU; the placement is written to `<prefix>_modules.h5`. `=diagnose` also runs a set of tests on the placement and writes them to the log |
|
||||
| `--mask-good [<file>:]<dataset>[@<bits>]` / `--mask-bad [<file>:]<dataset>[@<bits>]` | HDF5/CXI stills: a mask array in the frames' stored layout, in `<file>` or in each data file; usable only where non-zero (or with all `<bits>`) / unusable where non-zero (or with any `<bits>`). Repeatable ([Serial XFEL inputs](RUGNUX_FORMATS.md#serial-xfel-inputs)) |
|
||||
| `--rot1 <num>` | PONI detector rotation 1 (rad). On stills, `--rot1` or `--rot2` holds the tilt (not refined); without them stills refine the tilt where held-out frames agree |
|
||||
| `--rot2 <num>` | PONI detector rotation 2 (rad) |
|
||||
| `--rot3 <num>` | PONI detector rotation 3, about the beam (rad) — the one `rugnux --mode calibration` writes into its `.poni`, so a refined third rotation can be given straight back |
|
||||
| `--detector-mirror-y` | The stored image is mirrored in Y relative to the frame the PONI angles are stated in |
|
||||
| `--detector-quarter-turns <0-3>` | The stored image is turned by this many multiples of 90° about the beam relative to that same frame |
|
||||
| `--polarization <num>` | Degree of polarization *p* (XDS `FRACTION_OF_POLARIZATION` = (1+*p*)/2), signed: positive for a horizontally polarized source, negative for a vertically polarized one; where the beam-stop pre-scan finds the background clearly suppressed in the other plane, the degree is applied in that plane instead. Default: what a miniCBF `# Polarization` line or a d*TREK `SOURCE_POLARZ` states (a fraction *f*, read as *p* = 2*f* − 1, so a laboratory tube's 0.5 is unpolarized), and otherwise 0.99, an undulator value; bending-magnet and wiggler sources are typically lower (0.8–0.95), and neither ADSC SMV, marCCD nor NXmx files state it, so pass the beamline's known value here |
|
||||
| `--rotation-scale <k>` | Goniometer rotation scale: the stage turned `k` times the angle stored in the file (the commanded one). Applied to both passes, and overrides the scale Rugnux fits for itself |
|
||||
@@ -89,6 +89,7 @@ are explained in :doc:`Naming <NAMING>`, the releases in the :doc:`changelog <CH
|
||||
RUGNUX_INSTALL
|
||||
RUGNUX_FORMATS
|
||||
RUGNUX_TUTORIAL
|
||||
RUGNUX_CLI
|
||||
RUGNUX_REPORT
|
||||
RUGNUX_INTEGRATION
|
||||
RUGNUX_ADVANCED
|
||||
|
||||
+55
-185
@@ -108,201 +108,71 @@ enum class RugnuxMode { MX, Azint, Scale, Calibration, Refine };
|
||||
// buys nothing and runs into the 65534-bin limit on q x azimuth, so 32 is the default.
|
||||
constexpr int CALIBRATION_AZIM_BINS_DEFAULT = 32;
|
||||
|
||||
// The usage is the quick start: one section per mode, then the options most runs need. Every
|
||||
// option, with what it does, is in docs/RUGNUX_CLI.md - keep the two consistent.
|
||||
void print_usage() {
|
||||
std::cout << "Usage rugnux {<options>} <input.h5> {<input.h5>} [<broker URL>]" << std::endl;
|
||||
std::cout << " Inputs are files, never a directory, read in the order given (a shell glob gives them sorted): "
|
||||
"all the files of one stills dataset - rugnux run*.h5 (SACLA), *.cxi, *.xtc (LCLS) - or several "
|
||||
"Jungfraujoch/NXmx masters of stills, read as one run: their images one after another, merged "
|
||||
"together, the indexing rate reported per master as well; these must share the detector, "
|
||||
"wavelength, distance and beam centre. Several inputs must be one format; rotation sweeps (name "
|
||||
"one frame of a CBF/marCCD/SMV sweep), --mode other than mx and following a broker take one" << std::endl;
|
||||
std::cout << " An atomic model and a reference reflection file can be given among the inputs, in any order, instead of "
|
||||
"--model and -z: each file is told by its contents, not its name - an MTZ (the MTZ magic) or an mmCIF "
|
||||
"with a _refln or _diffrn_refln loop is reflections (-z; the input itself in --mode refine), a PDB file "
|
||||
"or an mmCIF with an _atom_site loop is a model (--model), anything else is images. An mmCIF holding "
|
||||
"both coordinates and reflections has to be given with --model or -z. At most one of each, also "
|
||||
"counting --model/--mr and -z; gzipped or not. E.g. rugnux data_master.h5 model.cif" << std::endl;
|
||||
std::cout << " With a broker URL (http://host:port/) and no <input.h5> on disk yet, follows the broker's current "
|
||||
"collection while it is written: <input.h5> must be the path its master file will have, the data "
|
||||
"files are read next to it as the broker reports them closed, and the run ends with the images the "
|
||||
"collection delivered. Rotation data, --mode mx only. The collection's token is read from the "
|
||||
"environment variable JUNGFRAUJOCH_HTTP_TOKEN and sent only to the broker. With <input.h5> on disk, "
|
||||
"the URL is ignored" << std::endl;
|
||||
std::cout << " --simulate-live <ms> Read the stored <input.h5> as the collection it was while being written, "
|
||||
"the way a broker URL follows one: image i becomes readable (i+1)*<ms> ms after the run starts (0: all "
|
||||
"at once). The run then takes the live path - the first passes decide their near ties on the images in "
|
||||
"so far, re-checked once the last one is in, and the run is made again where one ends elsewhere - "
|
||||
"where on a stored sweep they decide on all of its images at once. Same result; for testing the "
|
||||
"live workflow without a broker. --mode mx only" << std::endl;
|
||||
std::cout << " --fast-live With --simulate-live or a broker URL: run as the broker's rugnux live "
|
||||
"mode does - every decision stands where it was first taken, nothing is checked or run again once the "
|
||||
"sweep is in (near-tie re-checks, geometry and rotation-scale walks, metric-symmetry arms, supercell and "
|
||||
"quality guards, doubled cell), the integration radius is fixed, and SIGINT cuts the run to what it has "
|
||||
"established. A difficult crystal can come out worse" << std::endl;
|
||||
std::cout << "Options:" << std::endl;
|
||||
std::cout << " -o, --output-prefix <txt> Output file prefix (default: output). mx and scale runs always write "
|
||||
"<prefix>_report.txt, the results report; every run writes <prefix>_log.txt, the full timestamped log "
|
||||
"(debug level); an empty prefix writes nothing at all" << std::endl;
|
||||
std::cout << " -N, --threads <num> Number of threads (default: every CPU the run may use - its affinity and cgroup quota - of which the "
|
||||
"per-image loop uses at most 16 per GPU; an explicit value is used as given)" << std::endl;
|
||||
std::cout << " --no-gpu Run on the CPU only, as on a machine without a GPU: CUDA is not "
|
||||
"touched and every GPU step takes its CPU path (FFT indexes with FFTW, FFBIDX with its CPU implementation)" << std::endl;
|
||||
std::cout << " -s, --start-image <num> Start image number (default: 0)" << std::endl;
|
||||
std::cout << " -e, --end-image <num> End image number, exclusive: -s 0 -e 100 processes images 0-99 (default: all)" << std::endl;
|
||||
std::cout << " -t, --stride <num> Image stride (default: 1)" << std::endl;
|
||||
std::cout << " -v, --verbose Show the whole log on the terminal in place of the steps "
|
||||
"(the log file is written either way)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << R"(Usage: rugnux [options] <input> [<input> ...] [<broker URL>]
|
||||
|
||||
std::cout << " Mode" << std::endl;
|
||||
std::cout << " --mode <name> What this run does (default: mx)" << std::endl;
|
||||
std::cout << " mx Full analysis - spot finding, indexing, integration and merging" << std::endl;
|
||||
std::cout << " azint Only azimuthal integration (no spot finding/indexing); writes <prefix>_process.h5" << std::endl;
|
||||
std::cout << " scale Only re-scale/merge the already-integrated reflections in <input> (no re-integration)" << std::endl;
|
||||
std::cout << " calibration Determine the detector geometry from powder rings; writes <prefix>.poni for pyFAI and <prefix>.json, whose dataset_settings member is a jfjoch_broker dataset_settings body as it stands" << std::endl;
|
||||
std::cout << " refine Refine the --model against merged structure factors: <input> is an MTZ or a structure-factor mmCIF (gzipped or not), nothing is processed. As a placed model is refined after a merge, and written alike: <prefix>_refined_model.cif, <prefix>_refined_maps.mtz, <prefix>_blobs.json and REFINE_ keys in <prefix>_report.txt" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Give rugnux the data and nothing else: the defaults are meant to be the answer. Inputs are files,
|
||||
never a directory; a model or reflection file among them is recognised by its contents.
|
||||
|
||||
std::cout << " Refinement (--mode refine)" << std::endl;
|
||||
std::cout << " The columns are found, not named: amplitudes with their sigmas (F/SIGF, FP/SIGFP, ...) where the file has them, else intensities (IMEAN/SIGIMEAN, I/SIGI, ...) made into amplitudes by French-Wilson, else the mean of the anomalous pairs; the free set from a FreeR_flag-like column (0 the test set, or the minority value where 0 is the majority, as phenix writes it), drawn here where the file has none. The model is taken as placed in the data's cell, and refined in the data's space group" << std::endl;
|
||||
std::cout << " --refine-score-only Score the model as given and refine nothing: R-work/R-free, the scale, the bulk solvent, the likelihood and the geometry, each term under REFINE_SCORE_ (--developer prints them all)" << std::endl;
|
||||
std::cout << " --refine-d-min <num> Leave out reflections finer than this (A)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Rotation data (--mode mx, the default; chosen when the file's goniometer axis turns)
|
||||
rugnux -o myrun dataset_master.h5 NXmx / EIGER / Jungfraujoch master file
|
||||
rugnux -o myrun sweep_00001.cbf CBF, marCCD or SMV sweep: name one frame
|
||||
rugnux -o myrun dataset_master.h5 model.cif with a model (or --model model.cif)
|
||||
rugnux -o myrun x_master.h5 http://host:5232/ follow a broker's collection while it is written
|
||||
A model is placed and refined after merging; it does not change the processing.
|
||||
|
||||
std::cout << " Calibration (--mode calibration)" << std::endl;
|
||||
std::cout << " --calibrant <name> Powder standard: lab6|agbh|ceo2|si|ice (default: lab6, case-insensitive). Overridden by -C: a unit cell given there IS the standard, with its rings enumerated from the cell and its absences from -S where that is given, or taken as primitive where it is not. -S supplies SYMMETRY absences only: a standard whose extinctions come from its atomic basis rather than from a symmetry element - silicon, whose 222 is absent in Fd-3m for that reason - is better named with --calibrant" << std::endl;
|
||||
std::cout << " --calibration <txt> How the rings are measured: rings|spots (default: rings). rings sums the (q x azimuth) azimuthal profile over every processed image and fits the ring arcs in it; spots pools the found spots and fits those. -s/-e/--stride select the images; rings defaults --azim-phi-bins to 32" << std::endl;
|
||||
std::cout << " --no-refine-tilt Do not refine the detector tilt: hold rot1/rot2 at the header value and fit only the beam centre and the distance. For a calibration handed to a program that cannot express a tilted detector, e.g. XDS. On stills it holds the tilt in the geometry refinement too" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Serial stills (--mode mx; chosen when there is no goniometer axis or it does not turn)
|
||||
rugnux -o serial *_master.h5 several NXmx masters of one setup, as one run
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 run*.h5 SACLA (Cheetah HDF5)
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 *.cxi Cheetah CXI
|
||||
rugnux -o serial -C 79,79,38,90,90,90 -S P43212 *.xtc LCLS-I XTC streams
|
||||
Giving the known cell (-C) and space group (-S) is recommended for stills. Several inputs are
|
||||
one dataset, read in the order given. --model works as for rotation data; --force-still
|
||||
processes a rotation sweep as stills.
|
||||
|
||||
std::cout << " Detector geometry" << std::endl;
|
||||
std::cout << " (Serial XFEL stills are read without a geometry file: SACLA Cheetah files are placed by their own /metadata; Cheetah CXI files of a single-panel detector (square frame) are one flat panel with the pixel size, photon energy and camera length they state; LCLS-I XTC streams of a Rayonix take the photon energy and pixel size from the XTC and need --detector-distance, or -C to have it searched. The beam centre is measured, the run is read at the mean photon energy, and frames that state no gain are counted in photons where their background resolves single photons, and otherwise analysed in the units they are stored in at the gain their background shows - see --gain)" << std::endl;
|
||||
std::cout << " --crystfel-geometry <file> Read the <input> HDF5/CXI files with their panels placed by this CrystFEL geometry file: the module geometry (panel ranges, fast/slow directions, corners, pixel size, coffset, the frames' data path), if stated the camera length, and the masks (mask arrays, bad regions, mask_edge_pixels, no_index) are taken from it; photon energy, camera length and - where the geometry names no mask array - masks otherwise come from the data files (Cheetah CXI, SACLA) or the command line, gain and saturation are measured. Tilted panels, dimN layouts, per-panel data and detector shifts are refused" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Refinement (--mode refine)
|
||||
rugnux --mode refine -o refined data.mtz model.cif
|
||||
Refines the model against merged data (MTZ or structure-factor mmCIF); no images are read.
|
||||
|
||||
std::cout << " Detector mask" << std::endl;
|
||||
std::cout << " --mask-good [<file>:]<dataset>[@<bits>] HDF5/CXI stills: a mask array in the frames' own layout (as stored, before the panels are placed) - in <file>, or without it in each data file (a per-frame mask stored beside the frames); a pixel is usable only where it is non-zero, or with <bits> only where it has all of them. May be given more than once" << std::endl;
|
||||
std::cout << " --mask-bad [<file>:]<dataset>[@<bits>] As --mask-good, but a pixel is unusable where the array is non-zero, or with <bits> where it has any of them (e.g. @0xfeff)" << std::endl;
|
||||
std::cout << " --detect-beam-stop[=N|off] Find the beam stop and its holder in a projection of N images and add them to the pixel mask (bit 9), so nothing shadowed by them is integrated. ON by default (60 images); =off disables. A reflection whose signal disk reaches into the shadow is not integrated: the rest of such a disk lies in the stop's half-shadow and reads low. Pixels the finder reports that hold the detector's no-data mark (a PILATUS gap) are masked as dead instead" << std::endl;
|
||||
std::cout << " --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, and index a second first pass with it 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 a run that indexes, the measured centre is adopted where the file's centre indexes nothing and the measured one indexes a majority, and where the two centres return cells related by an integer volume factor, in either direction, and the measured centre's lattice carries materially more of the pooled spots against its own chance level - the axis harmonic a centre error along the spindle produces, which nothing downstream repairs. Where the indexing cannot tell the two centres apart - the same cell with a different metric symmetry, or the same lattice found at both only by reading less of each frame - the first pass is run at both and the run keeps the one that merges better (on the same lattice: the one that measures more reflections at I/sigma >= 2). ON by default; =off disables On stills, where there is no first pass, the file's centre, the measured one and the point-symmetry capture's are each indexed on a sample of frames and the run takes the one that puts materially more spots on the lattice of their frame; with a reference cell (-C) the detector distance is searched too, over 30-3000 mm at every centre, the file's value being one hypothesis, before the stills geometry refinement" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Detector calibration (--mode calibration)
|
||||
rugnux --mode calibration --calibrant lab6 -o det LaB6_master.h5
|
||||
Geometry from a powder standard's rings (lab6|agbh|ceo2|si|ice): writes det.poni, det.json.
|
||||
|
||||
std::cout << " Spot finding" << std::endl;
|
||||
std::cout << " --spot-sigma <num> Noise sigma level for spot finding (default: 4.0)" << std::endl;
|
||||
std::cout << " --spot-threshold <num> Photon count threshold for spot finding (default: 10)" << std::endl;
|
||||
std::cout << " --min-pix-per-spot <num> Minimum connected strong pixels per spot. If omitted, min-pix is chosen PER IMAGE (stills indexing): the frame is scored at min-pix 2/3/1 (one lattice search per frame, refined on each list) and the one maximising indexed count x indexed fraction is kept. Give an explicit value to force a fixed min-pix instead." << std::endl;
|
||||
std::cout << " --adaptive-spots Self-calibrating detection (DEFAULT): the strong-pixel threshold comes from each image's own per-resolution-ring noise instead of the fixed --spot-threshold, so one setting adapts across datasets (no per-dataset --spot-threshold/--spot-sigma tuning)." << std::endl;
|
||||
std::cout << " --no-adaptive-spots Turn adaptive detection off and use the fixed --spot-threshold / --spot-sigma finder instead" << std::endl;
|
||||
std::cout << " --spot-false-pixels <num> Adaptive detection operating point: expected noise pixels tolerated per frame (default: 100; implies --adaptive-spots)" << std::endl;
|
||||
std::cout << " --spot-high-resolution <num> High resolution limit for spot finding. If omitted (or 0), spot finding is not clipped in resolution and extends as far as the detector reaches" << std::endl;
|
||||
std::cout << " --spot-low-resolution <num> Low resolution limit for spot finding, in A (default: 50; lower it, e.g. 24, to exclude the direct-beam halo on weakly-diffracting serial data; 0 removes the limit)" << std::endl;
|
||||
std::cout << " --max-spots <num> Max spot count per image, the strongest ones, handed to indexing. Default: measured from the data on rotation (as deep into each image's spot list as its spots still lie on the lattice), capped at 1000" << std::endl;
|
||||
std::cout << " --detect-ice-rings[=on|off] Flag ice-ring spots (de-prioritised in indexing) and exclude ice-ring reflections from scaling. Default: the master file's setting, or - where the file says nothing - on for rotation and off for stills" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Azimuthal integration (--mode azint)
|
||||
rugnux --mode azint -o profiles dataset_master.h5
|
||||
Azimuthal integration only, no spot finding or indexing: writes profiles_process.h5.
|
||||
|
||||
std::cout << " Indexing" << std::endl;
|
||||
std::cout << " (A dataset with a rotation goniometer axis is processed as rotation data by default; use --force-still to override)" << std::endl;
|
||||
std::cout << " --force-still Process a rotation (goniometer) dataset as independent stills (still indexing + per-image ScaleOnTheFly) instead of rotation" << std::endl;
|
||||
std::cout << " -R, --two-pass-rotation[=num] Two-pass offline rotation indexing (default for goniometer data; optional first-pass image count, default: 100)" << std::endl;
|
||||
std::cout << " --single-pass-rotation[=num] Use online-like single-pass rotation indexing (optional: min angular range deg)" << std::endl;
|
||||
std::cout << " --min-indexed-spots <num> Spots a frame must have on the lattice before it counts as indexed (default: 6, minimum 4). It sets the reported indexing rate and the count the rotation first pass ranks candidate lattices by; whether the run has a lattice at all is decided on the pooled spots instead, and integration is not gated by it" << std::endl;
|
||||
std::cout << " --force-rotation-lattice <vec> Force rotation indexer with external lattice (in Angstrom) : \"a0x,a0y,a0z,a1x,a1y,a1z,a2x,a2y,a2z\" (9 floats, skips first pass)" << std::endl;
|
||||
std::cout << " --rotation-scale <k> Goniometer rotation scale: the stage turned k times the angle stored in the file (the commanded one). Applied to both passes; overrides the fitted correction" << std::endl;
|
||||
std::cout << " --rotation-no-postrefine Disable the (default-on) two-pass rotation post-refine (post-refine detector distance/beam + cell/axis, then re-integrate; only the refined pass is written, as the canonical <prefix>_* output)" << std::endl;
|
||||
std::cout << " --prepass-fraction <f> Integrate the first fraction f of the sweep, but at least 120 deg of it, in the two-pass rotation geometry pre-pass (0.05-1, default 0.5; 1 = the whole sweep); pass 2 reads every frame. The pre-scan and the first-pass indexing sample the same part of the sweep" << std::endl;
|
||||
std::cout << " -X, --indexing-algorithm <txt> Indexing algorithm (Auto|FFT|cuFFT|FFTW|FFBIDX|None, default Auto). FFT is "
|
||||
"the de-novo FFT search, on the GPU (cuFFT) where there is one and --no-gpu is not given, otherwise on the "
|
||||
"CPU (FFTW); cuFFT and FFTW name one implementation each, and cuFFT needs a GPU. FFBIDX is the known-cell "
|
||||
"fast-feedback indexer for stills, likewise on the GPU where there is one and otherwise on the CPU; "
|
||||
"Auto picks it for stills whenever a cell is known" << std::endl;
|
||||
std::cout << " -S, --space-group <num|symbol> Space group number (96) or symbol (P43212) - for indexing and scaling; on serial stills where the space group admits two indexings, the crystals are put on one from the data (or from --model/-z when given)" << std::endl;
|
||||
std::cout << " -C, --unit-cell <cell> Fix reference unit cell: \"a,b,c,alpha,beta,gamma\"" << std::endl;
|
||||
std::cout << " --fft-min-unit-cell <num> Shortest cell axis the FFT search accepts, in A (default: 10). A candidate with a shorter axis is discarded, but a de-novo rotation run also tries a second first-pass hypothesis with the floor at 5 A, so a small-molecule cell is indexed without this flag; -C lowers it on its own to cover the cell given" << std::endl;
|
||||
std::cout << " -r, --geom-refine <txt> Geometry refinement algorithm (none|orientation|beam_and_lattice|flex); flex tries all three per image and keeps whichever indexes the most spots (alias: multi)" << std::endl;
|
||||
std::cout << " --refine-geometry[=N|off] Stills: extra first pass that bundle-adjusts the shared beam/distance/cell from N strongly-indexed frames (default: 200) then re-indexes (lifts weak-stills indexing). Default ON for stills when a reference cell is given (-C / reference MTZ); =off disables" << std::endl;
|
||||
std::cout << " --refine-modules[=on|off|diagnose] Stills, in that bundle adjustment: a detector of several modules (the input's own - NXdetector_module groups, SACLA sensors, geometry-file panels - or --module-geometry) has each placed as a rigid block - shift and in-plane turn - where that predicts the spots better on frames held out of the fit (default: on). Used from there on for the panels of a foreign detector (SACLA sensors, geometry-file panels); for a JUNGFRAU measured and reported only. The placement is written to <prefix>_modules.h5" << std::endl;
|
||||
std::cout << " --module-geometry <file> Where the detector's modules are: an NXmx file with one NXdetector_module group per module (module_0, module_1, ...; what a run writes as <prefix>_modules.h5), or a CrystFEL geometry file whose panels are laid on the image (fs = column, ss = row). Replaces the input's own modules" << std::endl;
|
||||
std::cout << " --index-ice-rings[=on|off] Index on the spots flagged as sitting on an ice ring too, instead of setting them aside (default: off; no effect without --detect-ice-rings)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Re-merging (--mode scale)
|
||||
rugnux --mode scale -o remerged -A myrun_process.h5
|
||||
Re-scales and merges the reflections of a _process.h5 written with --write-process-h5.
|
||||
|
||||
std::cout << " Scaling and merging (on by default)" << std::endl;
|
||||
std::cout << " --no-merge Skip scaling and merging; write only the per-image _process.h5" << std::endl;
|
||||
std::cout << " --scale-fulls rot3d: after the 3D combine, refit a per-frame scale on the fulls (XDS order, Unity model). Default ON for rot3d" << std::endl;
|
||||
std::cout << " --no-scale-fulls Disable the rot3d scale-fulls refit (it is on by default for rot3d)" << std::endl;
|
||||
std::cout << " --write-process-h5 Also write the (large) _process.h5 when merging (default: only .mtz/.cif when merging)" << std::endl;
|
||||
std::cout << " --finalist-ledger Report the full-resolution evidence for each space group the search considered, not only the one it adopted, and the twin-immune zone evidence of the adopted group's 2-folds (report-only; the decision is unchanged). Both are read on a merge of the observations in P1 that only this option makes, so it costs one extra merge" << std::endl;
|
||||
std::cout << " --developer Write the full <prefix>_report.txt: the pipeline-internal keys (the anisotropy gate, the space-group candidate and operator tables, the model-fit null, the sweep internals) and the long explanations, which the default report leaves out. Nothing is computed differently - the same report, rendered in full" << std::endl;
|
||||
std::cout << " --smooth-g[=deg] rot3d: smooth per-frame scale G over a deg-degree rotation range (XDS DELPHI-like) before the combine (default: 5 for rot3d; 0 = off)" << std::endl;
|
||||
std::cout << " --relative-b[=deg] rot3d: fit a per-batch relative-B (beyond the single decay slope) over deg-degree batches; cross-validated (default: 10 deg when bare; off otherwise)" << std::endl;
|
||||
std::cout << " --no-scaling-corrections rot3d: disable the (default-on) decay + absorption + modulation correction surfaces fitted on the fulls after scale-fulls" << std::endl;
|
||||
std::cout << " --no-expected-variance-merge stills: disable the default expected-variance merge weighting (which rebuilds each weak observation's signal variance at the reflection mean to de-bias the inverse-variance merge); restores observed-sigma weighting" << std::endl;
|
||||
std::cout << " -A, --anomalous Anomalous mode (don't merge Friedel pairs)" << std::endl;
|
||||
std::cout << " --scaling-high-resolution <num> High resolution limit for scaling/merging (manual override; default: no limit)" << std::endl;
|
||||
std::cout << " --scaling-low-resolution <num> Low resolution limit of the scale fit, in A (default: 50, also XDS's own default; 0 = no limit). Coarser reflections are merged and written, but kept out of the scale model, which a few of them on a large cell can bend" << std::endl;
|
||||
std::cout << " --resolution-cutoff <txt> Automatic high-resolution cutoff for the written reflections + reported shells: cc-logistic|off (default: cc-logistic; ignored when --scaling-high-resolution is set)" << std::endl;
|
||||
std::cout << " --resolution-cc-target <num> CC1/2 target defining the cc-logistic fall-off (default: 0.30)" << std::endl;
|
||||
std::cout << " --resolution-shells <num> Number of resolution shells in the reported statistics table (default: 9, as XDS)" << std::endl;
|
||||
std::cout << " --report-resolution <dmin>[,<dmax>] Also report the merging statistics over this resolution range (A, either order; dmax defaults to the run's own low-resolution limit) as a second table beside the run's own - the REFRES_* keys of the report - binned from the same merged reflections, so a run can be read against another program's table at that program's range. Report-only: the cut, the scaling, the error model and every decision stay the run's own, and shells finer than the run's own limit are empty rather than filled from data the run did not keep" << std::endl;
|
||||
std::cout << " --ice-min-score <num> Ice-presence gate: measured ice score (1 = no ice) a run must reach before ANY ice handling is applied - the flagging and the exclusion from scaling (default: 1.5). The eleven hexagonal bands cover 16-26% of the unique reflections whether or not the crystal has ice, so handling ice on a clean crystal is a pure loss. 0 = no gate (always handle ice)" << std::endl;
|
||||
std::cout << " --ice-min-spot-ratio <num> Second ice-presence channel: found spots on the hexagonal rings over the same q width of ice-free flanks beside them (1 = spots spread evenly). Ice in large crystallites diffracts as discrete spots and leaves the radial profile flat, so --ice-min-score alone is blind to it. Default 2.0; 0 disables this channel" << std::endl;
|
||||
std::cout << " --min-partiality <num> Minimum partiality to accept reflection (default: 0.02 for rotation, 0.5 for stills)" << std::endl;
|
||||
std::cout << " --capture-uncertainty <num> Systematic sigma num*(1-captured fraction)*<I>: on rot3d fulls, the share of the rocking curve not captured; on stills, the share of each partial its partiality does not see (default: 1.0 for rot3d, 0 otherwise)" << std::endl;
|
||||
std::cout << " --min-captured-fraction <num> rot3d: drop a combined full whose rocking curve was captured below this fraction (edge-of-sweep truncated fulls) (default: 0.7 for rotation, 0 otherwise; 0 = off)" << std::endl;
|
||||
std::cout << " --mosaicity <num> Diagnostic: fix the scaling mosaicity (deg) instead of the per-image seed" << std::endl;
|
||||
std::cout << " --prediction-mosaicity <num> Diagnostic: fix the rocking width the PREDICTION window opens to (deg), leaving the partiality on the per-image sigma_M. Prediction and partiality are one number by default, so a sigma_M that moves takes the integrated reflection population with it" << std::endl;
|
||||
std::cout << " --reject-outliers <num> Per-observation merge outlier rejection, N sigma from the per-reflection median, the systematic part of the band multiplicative on rotation and linear on stills (default: 6 for rotation, XDS/DIALS-style, and 10 for stills; 0 = off)" << std::endl;
|
||||
std::cout << " --search-min-zeta <num> De-novo space-group search only: also search a merge of just the observations whose Lorentz geometry |zeta| reaches this, and report both answers (default: 0.85 for rotation, 0 = single search). Reflections crossing the Ewald sphere near-tangentially are measured worst and can make a real symmetry operator look like a twin law; where the two searches disagree, the merge of ALL the observations decides" << std::endl;
|
||||
std::cout << " --min-image-cc <num> Per-image CC limit in percent (default: no limit)" << std::endl;
|
||||
std::cout << " --scaling-iterations <num> Cap on the per-frame scaling iterations; the loop stops earlier once the scales settle (default: 100)" << std::endl;
|
||||
std::cout << " -z, --reference <file> Reference data of the same crystal form: an MTZ, or a PDB structure-factor mmCIF (e.g. 1abc-sf.cif, first merged block with a usable column; R-free set from _refln.status f/o, else pdbx_r_free_flag). Gzipped or not, recognised by content. --reference-mtz is the same option" << std::endl;
|
||||
std::cout << " --reference-column <label> Reference column to use, by MTZ label; an mmCIF is read under the labels gemmi cif2mtz gives it (IMEAN, FP, I(+), FC, F-model, ...) (default: auto - F-model, else IMEAN/I, else FP/FOBS/F)" << std::endl;
|
||||
std::cout << " --model <file> After merging, validate vs this atomic model: R-free, sigma_A-weighted 2mFo-DFc/mFo-DFc maps, the model as placed (written beside them), and - where the merge kept the Bijvoet split - an anomalous difference map with the strongest anomalous scatterers named by the atom they sit on. PDB or mmCIF, gzipped or not, recognised by content rather than by extension. A prediction (AlphaFold or ModelCIF, pLDDT in the B column), or an experimental structure the rigid body does not place against its null, is placed by molecular replacement instead (see --mr). A model that is placed is then refined against the merge it was placed on - each chain as a rigid body and one B per residue, then every atom's position and B restrained by the dictionary carried in rugnux against a maximum-likelihood target, the X-ray weight chosen by R-free within geometry bounds, then its solvent rebuilt - waters added at difference-map peaks with a hydrogen-bond partner, removed from negative difference density, and waters and ions relabelled where their shell and density support another species (to 2.8 A, up to two rounds within the weight search, each kept where it lowers R-free; --no-refine-solvent keeps the solvent as given) - and the unexplained blobs of its difference map are listed: <prefix>_refined_model.cif, <prefix>_refined_maps.mtz, <prefix>_blobs.json, REFINE_ keys in the report. R_WORK, R_FREE and every other key stay those of the model as placed; the refinement decides nothing about the processing. It costs seconds on a GPU and typically 2-15 minutes on the CPU (no GPU, or --no-gpu); --no-refine skips it" << std::endl;
|
||||
std::cout << " --mr <file> As --model, but placed by molecular replacement straight away, without the rigid-body placement first: as many copies as the cell holds, in every space group the merge cannot tell apart and in the twin hypothesis' subgroup. A prediction is trimmed to the residues of pLDDT 70 and above, and where the AlphaFold DB's predicted-aligned-error JSON sits beside it under its own name it is cut into rigid domains; any other PDB or mmCIF is taken as an experimental structure, its polymer only (no waters, ligands, hydrogens or alternative conformers). Which of the two it is is read from the file. It may relabel the enantiomorph of the answer, and a different space group it chooses is written beside the answer as <prefix>_mr.mtz/.cif with the placed model <prefix>_mr_model.pdb. --mode mx only" << std::endl;
|
||||
std::cout << " --no-refine Do not refine the placed model (for debugging): by default a model that --model or --mr places is refined (see --model)" << std::endl;
|
||||
std::cout << " --no-refine-solvent Refine the placed model with its solvent as given: no waters built or removed, no ion relabelled (the solvent audit, REFINE_SOLVENT_ keys and <prefix>_solvent.json, is still made). Also with --mode refine" << std::endl;
|
||||
std::cout << " --export-unmerged Write <prefix>_unmerged.mtz, an unmerged MTZ (POINTLESS column layout) of the integrated observations, for aimless / pointless / careless. On by default, whenever there is an output prefix. On a rotation run the partials of each reflection are summed into one full, written at the batch its rocking curve is centred on, with the summed rocking-curve fraction in FRACTIONCALC; an event that caught less of its rocking curve than --min-captured-fraction (or --min-partiality) is not written, exactly as in the merge, since a full is what the reading program is told these rows are. Intensities carry the deterministic per-reflection corrections and nothing else - Lorentz and polarization in the LP column, the sensor's angle-dependent efficiency in QE and the flight path's attenuation in FLIGHT, so raw counts are I / LP * QE * FLIGHT - while the partiality is not divided out and the per-image scale is not applied at all, since those programs scale the data themselves. Written in --mode mx and --mode scale, and with --no-merge" << std::endl;
|
||||
std::cout << " --no-export-unmerged Do not write <prefix>_unmerged.mtz. It is the largest file a run produces, so a run whose observations are not going to another scaling program - a regression battery, say - can skip writing it" << std::endl;
|
||||
std::cout << " --export-unmerged-partials Write <prefix>_unmerged_partials.mtz, the same observations with each partial as its own row (one batch per image) flagged for the reading program to sum, instead of summed here. Off by default and independent of --export-unmerged; both can be written in one run" << std::endl;
|
||||
std::cout << std::endl;
|
||||
Basic options
|
||||
-o, --output-prefix <txt> Prefix of every output file (default: output)
|
||||
-C, --unit-cell <cell> Known unit cell a,b,c,alpha,beta,gamma (A, deg); helps stills
|
||||
-S, --space-group <sg> Known space group, number or symbol: 96 or P43212
|
||||
-A, --anomalous Merge Friedel pairs apart (anomalous statistics)
|
||||
--scaling-high-resolution <A> High-resolution limit (default: from the CC1/2 fall-off)
|
||||
--model <file> Atomic model (PDB/mmCIF) to place, refine and validate with
|
||||
--no-refine Place and score the model, but do not refine it
|
||||
-z, --reference <file> Reference reflections of the same crystal form (MTZ/mmCIF)
|
||||
-s, --start-image <num> First image (default: 0)
|
||||
-e, --end-image <num> End image, exclusive (default: all)
|
||||
--beam-x <px>, --beam-y <px> Beam centre, overriding the file
|
||||
--detector-distance <mm> Detector distance, overriding the file
|
||||
--wavelength <A> Wavelength, overriding the file
|
||||
-N, --threads <num> Limit the threads (default: every CPU the run may use)
|
||||
--no-gpu CPU only, even where a GPU is present
|
||||
--no-merge No scaling or merging; write the per-image _process.h5
|
||||
--write-process-h5 Also write the (large) _process.h5 when merging
|
||||
-v, --verbose Whole log on the terminal (it is always in <prefix>_log.txt)
|
||||
|
||||
std::cout << " Integration" << std::endl;
|
||||
std::cout << " --bandwidth <num> Relative X-ray bandwidth FWHM (e.g. 0.01 for 1% DMM). Default: the file's value, else measured in the pre-scan from the radial elongation of strong spots and used where significant, else 0; --bandwidth 0 forces a monochromatic beam" << std::endl;
|
||||
std::cout << " --integration-radius <r> Signal-box radius r1, or r1,r2,r3 (px). One value => r2=r1+2, r3=r1+4" << std::endl;
|
||||
std::cout << " --adaptive-integration-radius[=on|off] Set the signal radius r1 from how wide this crystal's spots actually are, measured in the pre-scan (default on). On stills it measures instead how far the background ring should reach: on empty apertures of the pre-scan frames, the r3 (up to 14) whose ring predicts the background under the signal disk best. r1 is the aperture the integrator learns the profile WIDTH over, and a second moment over a disk of radius a saturates at a^2/4, so at the shipped r1=4 the learned sigma can never exceed 2 px and a broader spot is fitted with a profile the model cannot represent. r80 - the radius holding 80% of a spot's flux, at a common resolution - is read off isolated strong spots over a fixed aperture that owes nothing to r1, and r1 = clamp(round(2*r80), 4, 6); the background ring keeps the area it has at the default 4,6,13. Ignored when --integration-radius is given" << std::endl;
|
||||
std::cout << " --integration-stencil <k> Push the r2..r3 background ring out by k times the beam's radial streak (bandwidth*Rpx), per reflection (default 0 = a fixed circular ring). A fixed ring otherwise ends up on a streaked reflection's own tails at high resolution and measures them as background. Only the ring moves, and only radially - the r1 signal box stays a circle. On a monochromatic beam the streak is zero and this does nothing" << std::endl;
|
||||
std::cout << " --integration-high-resolution <num> High resolution limit for prediction/integration. If omitted (or 0), integration extends as far as the detector reaches" << std::endl;
|
||||
std::cout << " --max-hkl <n> Predict reflections with |h|,|k|,|l| <= n. Default: derived per crystal from the refined cell (ceil(longest axis / d_min) + 1), which is the exact bound - set it only to override that" << std::endl;
|
||||
std::cout << " --background-clip <n> High-side clip of the background ring at mean + n*sqrt(mean) (default 4; 0 = off). This is the default background estimator - it rejects neighbour cores and zingers without the symmetric trim's Poisson skew bias. Ignored by --integrator boxsum" << std::endl;
|
||||
std::cout << " --background-radial[=on|off|auto] Correct the background ring for the CURVATURE of the radial background (default auto). The signal disk and the background ring are concentric, so a background linear in position cancels between them and only curvature survives - which on a smooth ice ring reaches +26 counts on a single reflection. Where it is on, the curve is the spot finder's peak-excluded background of the whole frame, and the ring's outlier clip follows it, so a background falling steeply from the beam is not cut as outliers. =auto decides it per run in the pre-scan, on empty apertures of the pre-scan frames: on stills it is applied to every image where it makes the background ring predict the background of empty apertures better at all (a smooth solvent or carrier hump curves the background as much as ice does); on rotation data it is applied to every image where it takes at least 10% of that error away, and otherwise only to the images whose ice score shows a smooth powder ring, with the curve from the reflections' own rings (ice made of discrete crystallite spots leaves no such ring, and the correction makes the bias worse). Costs one short dot product per reflection and no extra pixel reads" << std::endl;
|
||||
std::cout << " --background-trim <f> Use the old symmetric trimmed mean for the background ring instead of the clip (0<=f<0.5; 0.10 was the former default). Switches --background-clip off. A symmetric trim is biased low on Poisson data and adds ~5 counts to every partial, so this is for back compatibility only; 0 = plain ring mean" << std::endl;
|
||||
std::cout << " --overlap <txt> What to do where two predicted reflections share signal pixels: off|reject|exclude (default exclude). A pixel inside two signal disks belongs to the nearer centre; before this, nothing kept a neighbour's flux out of a reflection's own disk, so on a dense pattern a crowded reflection read high. exclude drops the shared PIXELS from the profile fit, which renormalises itself, so the reflection is kept; reject instead drops the whole reflection when less than --overlap-minpk of its expected profile is cleanly its own (what XDS calls MINPK). --integrator boxsum has no profile to renormalise with, so exclude does nothing there and only reject acts" << std::endl;
|
||||
std::cout << " --overlap-minpk <f> Least fraction of a reflection's expected profile that must be usable for the reflection to be kept (default 0.75, XDS MINPK). Governs both ways part of a profile is lost: the fraction that must be READABLE - not masked, untrusted, in a detector gap or overloaded - in every profile mode, and, under --overlap reject, the fraction that must be cleanly the reflection's own. --integrator boxsum has no profile to renormalise with, so there a signal disk with any unreadable pixel is still discarded outright and the reject fraction is by disk AREA, which cuts harder" << std::endl;
|
||||
std::cout << " --integrator <txt> Spot integrator boxsum|gaussian|empirical (default: gaussian profile-fit; boxsum is the classical fallback)" << std::endl;
|
||||
std::cout << " --simple-stills stills: treat every reflection as a full (p=1, single-pass scale/merge); disables the default physical partiality post-refinement" << std::endl;
|
||||
std::cout << " -q, --azim-q-spacing <num> Azimuthal-integration Q bin spacing (1/A) (default: 0.01)" << std::endl;
|
||||
std::cout << " --azim-min-q <num> Azimuthal-integration minimum Q (1/A)" << std::endl;
|
||||
std::cout << " --azim-max-q <num> Azimuthal-integration maximum Q (1/A). If omitted, integration extends to the highest Q the detector reaches." << std::endl;
|
||||
std::cout << " --azim-phi-bins <num> Number of azimuthal (phi) bins (default: 1)" << std::endl;
|
||||
std::cout << " --polarization-correction <on|off> Enable/disable azimuthal polarization correction" << std::endl;
|
||||
std::cout << " --solid-angle-correction <on|off> Enable/disable azimuthal solid angle correction" << std::endl;
|
||||
std::cout << " --flight-path <txt> What the diffracted beam crosses between the sample and the detector: air|helium|vacuum (default air). A reflection arriving at angle alpha to the detector normal flies D/cos(alpha) instead of D, so it crosses more of the medium and reads low; the factor is exp(D/L*(1/cos(alpha)-1)) from the NIST attenuation coefficient of the medium, the stated distance and the stated wavelength, and nothing in it is fitted. NOTHING IN ANY FILE STATES THE MEDIUM - no field of the NXmx application definition, and none of any master rugnux reads - so it cannot be detected and is assumed. Nor can it be inferred from the implied transmission: in this corpus a confirmed helium station sits at 51% implied air transmission and a confirmed air station at 63%. Air costs +1.5% at alpha = 55 deg for 18 keV over 160 mm and several-fold below 5 keV, where stations use helium precisely because air is unusable; helium attenuates about 1/600 of air, and vacuum leaves intensities untouched. The assumption and what it is worth are printed in the report" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << " Geometry overrides (defaults taken from the input file)" << std::endl;
|
||||
std::cout << " --beam-x <num> Beam center X (pixel)" << std::endl;
|
||||
std::cout << " --beam-y <num> Beam center Y (pixel)" << std::endl;
|
||||
std::cout << " --detector-distance <num> Detector distance (mm). On stills it is held: neither searched nor refined (the cell absorbs any error). Without it, stills with a reference cell (-C) search the distance and refine it together with the cell, the file's value being one hypothesis" << std::endl;
|
||||
std::cout << " --wavelength <num> Wavelength (A)" << std::endl;
|
||||
std::cout << " --pixel-size <num> Pixel size (um)" << std::endl;
|
||||
std::cout << " --gain <num> Detector units per photon, for input in detector units (SACLA, CXI, XTC, SMV, marCCD and --crystfel-geometry input). Default: measured on a few frames - the spacing of the photon peaks of the pixel values where they resolve single photons (for a JUNGFRAU file in keV, the photon energy), else the background's variance per unit mean. Where the background resolves single photons (SACLA, CXI and --crystfel-geometry input) the frames are counted in whole photons with it as they are read; otherwise they are analysed in their own units, and the gain enters where a photon count is assumed - the spot finder's threshold, the background clip, the spot-width and defective-pixel tests, and the integrated intensities' variances, which come out in photons. At or below 1 it is taken as 1. --gain replaces the value, not the kind: the background still says whether the photons are resolved" << std::endl;
|
||||
std::cout << " --saturation <num> Pixel value from which a pixel is overloaded, in the units the frames are read in (photons where they are converted). Replaces the file's limit and the one stills read off the frames" << std::endl;
|
||||
std::cout << " --rot1 <num> PONI rotation 1 (rad). On stills, --rot1 or --rot2 holds the tilt: it is not refined. Without them stills refine the tilt where frames the fit has not seen agree" << std::endl;
|
||||
std::cout << " --rot2 <num> PONI rotation 2 (rad)" << std::endl;
|
||||
std::cout << " --rot3 <num> PONI rotation 3, about the beam (rad)" << std::endl;
|
||||
std::cout << " --detector-mirror-y Stored image is mirrored in Y vs the detector" << std::endl;
|
||||
std::cout << " --detector-quarter-turns <0-3> Stored image is turned by this many 90 deg about the beam" << std::endl;
|
||||
std::cout << " --polarization <num> Degree of polarization p (XDS FRACTION_OF_POLARIZATION = (1+p)/2), signed: positive for a horizontally polarized source, negative for a vertically polarized one (the sign rotates the polarization plane by 90 degrees); where the beam-stop pre-scan finds the background clearly suppressed in the other plane, the degree is applied in that plane instead. Default: what a miniCBF \"# Polarization\" line or a d*TREK SOURCE_POLARZ states (a fraction f, read as p = 2f - 1, so 0.5 from a laboratory tube is unpolarized), and otherwise 0.99, an undulator value; bending-magnet and wiggler sources are typically lower (0.8-0.95), and neither ADSC SMV, marCCD nor NXmx files state it, so pass a known beamline value here" << std::endl;
|
||||
}
|
||||
All options (about 120, for unusual data and diagnosis), each with what it does:
|
||||
share/doc/jfjoch_rugnux/html/RUGNUX_CLI.html in the release archive, beside bin/
|
||||
https://jungfraujoch.readthedocs.io/en/latest/RUGNUX_CLI.html
|
||||
)";
|
||||
}
|
||||
|
||||
enum {
|
||||
OPT_SPOT_SIGMA = 1000,
|
||||
|
||||
Reference in new issue
Block a user