Files
Jungfraujoch/docs/RELEASE_CONTENTS.md
leonarski_f 749db470ca
Build Packages / build:rpm (rocky9) (push) Successful in 19m56s
Build Packages / Unit tests (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 16m57s
Build Packages / build:windows:cuda (push) Successful in 19m18s
Build Packages / build:viewer-tgz:cpu (push) Successful in 14m48s
Build Packages / build:viewer-tgz:cuda (push) Successful in 16m18s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 14m19s
Build Packages / build:rugnux:windows (push) Successful in 10m34s
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 8m49s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 20m55s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 17m4s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 20m48s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 19m15s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 24m26s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 20m32s
Build Packages / build:rpm (rocky8) (push) Successful in 23m39s
Build Packages / Generate python client (push) Successful in 46s
Build Packages / Build documentation (push) Successful in 1m45s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (durin plugin) (push) Successful in 11m3s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 11m30s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 20m10s
Build Packages / XDS test (neggia plugin) (push) Successful in 10m17s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 23m12s
Build Packages / DIALS test (push) Successful in 20m12s
v1.0.0-rc.164 (#74)
* rugnux now tells you whether a crystal diffracts anisotropically and how far it reaches in each direction, without a second program: a new `9. DIFFRACTION ANISOTROPY` section in `<prefix>_report.txt` and matching `_reflns.pdbx_aniso_B_tensor_*` / `_reflns.jfjoch_aniso_*` items in the merged mmCIF report the anisotropic deltaB, the diffraction limit along each principal direction, and a `NOT DETECTED` / `DETECTED` / `CANNOT DETERMINE` verdict measured against the data set's own systematic error. It is a description only - no intensity is corrected, no reflection is removed, and the merged data do not depend on direction.
* rugnux can hand its integrated observations to another scaling program: `--export-unmerged` writes `<prefix>_unmerged.mtz`, an unmerged MTZ readable by aimless, pointless, careless and `iotbx.merging_statistics`, in `--mode mx` and `--mode scale` alike. Each rotation reflection's partials are summed into one full; `--export-unmerged-partials` writes one row per image instead. Intensities carry the Lorentz-polarization factor and nothing else, since those programs scale the data themselves. Lattice-centring absences are not written; screw and glide absences are.
* rugnux integrates crystals with broad spots better - where it changes anything, per-shell mean I/sigma improves by up to 31% and R_meas by up to 24% - because on rotation data the integration signal radius is now taken from the crystal's own measured spot width instead of a fixed 4 px. `--adaptive-integration-radius=off` restores the fixed radius and an explicit `--integration-radius` still overrides both. The widened radius applies to the final integration pass only, and a pattern too dense for it is re-integrated at 4 px with a note in the log.
* rugnux discards fewer stills reflections for want of a background ring, improving per-shell R_meas over most of the signal-bearing range: the stills background ring now runs to 14 px instead of 12. The gain reverses in shells below a mean I/sigma of about 4.
* rugnux determines the space group with thresholds that mean the same thing on a weak crystal as on a strong one: symmetry operators are scored on resolution-normalised intensities (E squared) instead of raw merged intensities, and a reflection counts as genuinely present on its counting significance instead of on the merged I/sigma, which saturates at the merge's own ISa. The search resolution cut is no longer able to move the answer, and the twin-law H bound moves from 1.70 to 1.85, which stops one class of correct high-symmetry assignment being refused as twinning.
* rugnux says what the space-group search tested and what it could not: the twin-law disagreement H is printed for every operator together with the adopted point group's H ratio and its bound; alternatives that are not on the reported lattice are named with how their cell differs; and a lattice centring the data could not test - the crystal having been integrated on the primitive sub-cell, so the reflections it extinguishes were never measured - is marked `UNTESTED` and warned about where it is adopted, as coming from the lattice metric rather than from the intensities.
* rugnux `--mode scale` re-merges a `_process.h5` in the right symmetry without being told it: the file now records the space group on every run - a two-pass rotation run wrote none before, so re-merging defaulted to P1 - together with the change of basis under `/entry/MX/reindexMatrix` where the lattice was re-seated, and `--mode scale` also reports the Wilson B-factor estimate instead of `WILSON_B= nan`. A file written before this stops with a message naming the two cells and the override to use, instead of failing inside the merge. A third-party reader of a `_process.h5` must apply `reindexMatrix` where it is present.
* rugnux installs on its own, as a package called `rugnux` - `dnf install rugnux` or `apt install rugnux` - instead of arriving inside `jfjoch-viewer`. It pulls in none of the acquisition stack, so a machine that only processes data no longer has to carry the broker, the detector libraries or Qt to get it. Installing it over a `jfjoch-viewer` from rc.163 or earlier, which still owns `/usr/bin/rugnux`, upgrades cleanly rather than failing on the duplicate file.
* rugnux is also a standalone download, built for arm64 as well as x86_64: `rugnux-<version>-linux-{x86_64|aarch64}-cuda<major>.tgz` and `rugnux-<version>-win64-cuda<major>.zip` on the release page, for machines that are not managed by a package manager. The aarch64 build targets GH200 and DGX Spark, and is untested on hardware.
* Every portable Linux binary is now a single self-contained file: cuFFT is linked statically instead of being shipped beside the executable and found through an rpath, so `rugnux` and `jfjoch_viewer` need nothing but an NVIDIA driver, and only to use the GPU. The `.rpm`/`.deb` continue to take cuFFT from the distribution. The developer utilities `jfjoch_extract_hkl` and `jfjoch_recompress` are no longer packaged anywhere.
* Jungfraujoch needs six fewer shared libraries on the machine - libopenblas and libmetis, and libgfortran, libquadmath, libgomp and libz behind them - because the Ceres LAPACK, METIS and SuiteSparse back-ends are no longer built. Nothing in the code ever selected them, and results are unchanged.
* The PCIe driver DKMS package builds for the kernel it is being installed for instead of the running one, so a module built while a kernel update is being applied loads after the reboot.
* The PCIe driver builds on RHEL 9.5 and later, and on their CentOS Stream, Rocky and AlmaLinux equivalents, where the `vm_flags` kernel interface was backported into the 5.14 kernel.
* A data collection started with `async_start` that fails to start - a writer refusing to overwrite an existing file, for instance - is reported as an error by `/wait_until_running` and `/wait_till_done` instead of as a timeout and a successful collection respectively. The error message is the one the writer gave.
* A calibration that is cancelled or that fails to collect its pedestals is no longer reported as a successful one. The broker goes to `Inactive` with an error message and has to be initialized again, instead of sitting in `Idle` looking ready to measure while holding partial pedestals - data collected in that state was silently mis-converted.
* A failed `/initialize` is reported to `/wait_until_running` and `/wait_till_done` as soon as it happens, instead of when their timeout expires.
* `space_group_number` accepts space groups up to 230 in the API schema, so cubic space groups can be recorded. The broker always accepted them; the generated clients rejected them before the request was sent.
* The results report's `REPORT_VERSION` is 3, two sections having been added. Existing key names and table columns are unchanged.
* The merged statistics table has **9** resolution shells instead of 10, which is what XDS reports. The bins were already XDS's - equal steps in 1/d^2 between the lowest- and the highest-resolution reflection the merge kept - so at the same resolution limits the two tables now have the same shell boundaries and can be read row for row. `--resolution-shells` sets a different count.
* `rugnux --model` now settles the frame the merged reflections are written in, not only the frame the R-factors and the maps are computed in: the `.mtz`/`.cif`/`.hkl` come out in the model's indexing, and where the data were merged in the model's enantiomorph they take the model's hand and space group - which on anomalous data puts I(+) and I(-) the right way round. The indexing choice is logged with the winning R-free and the runner-up, so a decision made within noise is visible.
* `rugnux --model` can resolve the indexing ambiguity of a **serial stills** run, which a model could not do before: structure factors computed from the model become the per-image reference, the same role a reference MTZ plays. It needs the cell and space group up front (`-C` / `-S`). Without one or the other, a merohedral serial run still merges both hands together and says so.
* The rugnux documentation opens with a quick start - the default run, and runs with a reference MTZ, with a model, or with the space group and cell pinned - and explains the indexing ambiguity: what it costs on rotation and on serial data, and which of `-z` / `--model` resolves it in each case. The long reference pages now carry a table of contents.

Reviewed-on: #74
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-08-26 22:47:00 +02:00

11 KiB

Release contents

This page describes what a Jungfraujoch release ships and what each artefact needs on the target machine — which CPU instruction set the binaries were compiled for, which CUDA toolkit they were built against, and which runtime libraries are bundled rather than expected from the host.

The artefacts in the table below are built and published by the continuous-integration pipeline (.gitea/workflows/build_and_test.yml) when a tag is pushed. For how to install and configure the result see Deployment; for the package-repository URLs see Linux package repositories.

Artefacts

Artefact Distributed via Contains
.rpm / .deb packages package repositories The full server stack: jfjoch (broker, frontend, FPGA and detector tools), jfjoch-writer, jfjoch-viewer (incl. the XDS plugin), jfjoch-driver-dkms, and rugnux (offline analysis, independent of the rest)
jfjoch_viewer-<version>-linux-cuda<major>.tgz, ...-linux-cpu.tgz Gitea release page Portable Linux viewer: jfjoch_viewer, its desktop entry, icon and D-Bus service, and the license notices
jfjoch-viewer-<version>-win64-cuda<major>.exe, ...-win64-cpu.exe Gitea release page Windows installer for jfjoch_viewer, plus the Qt runtime
rugnux-<version>-linux-x86_64-cuda<major>.tgz Gitea release page Portable Linux rugnux, the offline analysis CLI, and the license notices. One executable
rugnux-<version>-linux-aarch64-cuda<major>.tgz Gitea release page The same, cross-built for 64-bit Arm — NVIDIA GH200 and DGX Spark
rugnux-<version>-win64-cuda<major>.zip Gitea release page The same for Windows, plus the cuFFT DLL
jfjoch-writer .rpm / .deb Gitea release page The writer alone, for a file-writing machine without the rest of the stack
libjfjoch_xds_plugin.so.<version> Gitea release page XDS HDF5 read plugin (built on RHEL 8); see Integration with MX software
jfjoch-client PyPI and the Gitea PyPI index Generated Python OpenAPI client
Documentation Read the Docs and the gitea-pages branch This documentation set

The FPGA firmware (.mcs) images are attached to the release as well. The firmware is stable and is carried from version to version, and is rebuilt with Vivado (see FPGA smartNIC) when it needs to change — so a card keeps its image across a software upgrade unless the release notes say otherwise.

CPU instruction set

The architecture flags live in the CI configuration rather than in CMakeLists.txt, so a site building from source picks its own (x86-64-v4 on an AVX-512 cluster, -march=native, or the plain baseline the compiler defaults to). The released binaries are compiled to a fixed floor:

Release Flags Minimum CPU
Linux (all packages, and the portable .tgz) -march=x86-64-v3 -flto=auto AVX2 + FMA + BMI2 — Intel Haswell (2013) / AMD Zen (2017) and newer
Windows installer /arch:AVX AVX — Intel Sandy Bridge (2011) / AMD Bulldozer and newer

The Windows floor is lower because MSVC has no spelling for the x86-64-v2 level; /arch:AVX is the nearest one and implies SSE4.1/4.2, which is what actually matters — without it Eigen has no vectorised round and falls back to a libm call per element. Link-time optimisation is applied on Linux only.

A binary will fault with an illegal instruction on a CPU below its floor. If you must run on older hardware, build from source without the flags.

Operating-system floor

The .rpm / .deb packages are built per distribution (RHEL/Rocky 8 and 9, Ubuntu 22.04 and 24.04) and are tied to it. The portable viewer .tgz and the x86_64 rugnux .tgz are built on RHEL 8, the oldest supported distribution, so their glibc floor is low enough to run on any newer Linux — that is what they are for, and why they replace the per-distro packaging of those programs on the release page. The aarch64 rugnux .tgz is the exception: it is cross-built against Ubuntu 24.04, so it needs glibc 2.39 or newer (which DGX OS 7 and any current Arm server distribution have). The Windows installer is built and verified on Windows 11.

The portable archives have no top-level directory. They unpack straight into bin/ and share/, so always extract them into a directory of their own (tar xzf … -C /opt/rugnux-<version>) rather than into a working directory.

CUDA and non-CUDA builds

Every binary artefact is released in two variants, cuda<major> and cpu. The CUDA variant adds the GPU fast-feedback indexer (ffbidx), the GPU FFT indexer and GPU image processing; the CPU-only variant runs the same pipeline on the CPU with the FFTW indexer, at much lower throughput.

The CUDA toolkit used is the one on the corresponding build machine: CUDA 12 for the RHEL 8 packages, CUDA 13 for RHEL 9, Ubuntu and Windows. The major version is part of the artefact and repository name, so a download is self-identifying. Building from source needs CUDA 12.8 or newer.

A CUDA build does not require a CUDA machine. Jungfraujoch asks how many CUDA devices are present at start-up and treats "none" (including "no driver installed") as zero GPUs, falling back to the CPU path. So a CUDA build starts and runs correctly on a machine with no NVIDIA GPU at all. What each artefact has to find at run time differs:

  • Portable Linux .tgz — nothing. The CUDA runtime, the fast-feedback indexer and cuFFT are all linked statically, so each archive is a single executable that depends on nothing but the C and C++ runtimes. On a GPU machine the NVIDIA driver is the only NVIDIA component needed.
  • Windows installer and .zip — the CUDA toolkit ships no static cuFFT for Windows, so the cuFFT DLL is part of the distribution, next to the executable. No CUDA toolkit is needed.
  • .rpm / .deb — these deliberately keep cuFFT dynamic, so that one dependency is managed centrally with the rest of CUDA. Install the cuFFT package alongside, or use the nocuda repositories on a machine where CUDA is not wanted.

Static CUDA linkage makes the Linux CUDA artefacts substantially bigger than the CPU ones, and the Windows cuFFT DLL is ~256 MB — which is the other reason for shipping both variants.

On a machine with an NVIDIA GPU, take the CUDA variant: only that one uses the GPU.

GPU generations and the NVIDIA driver

A CUDA variant carries compiled device code for a fixed set of GPU generations, and which generations those are follows from the CUDA toolkit it was built with. The CUDA runtime is linked statically, so the only NVIDIA component the target machine has to supply is the driver — there is no CUDA-toolkit version requirement on the host.

Artefact CUDA toolkit GPU generations Minimum driver
RHEL 8 packages, portable viewer .tgz, x86_64 rugnux .tgz 12.9 Volta (V100) through Blackwell: sm_70, 75, 80, 86, 89, 90, 100, 120, 121 525.60.13
RHEL 9 and Ubuntu packages, Windows installer, Windows rugnux .zip 13.x Turing (T4) through Blackwell: the same list without sm_70 580.65.06 (Linux), R580 (Windows)
aarch64 rugnux .tgz 13.x sm_90 (GH200) and sm_121 (DGX Spark) only 580.65.06
any cpu / nocuda variant none

The aarch64 build is cross-compiled and verified in CI to be Arm, self-contained and to carry both GPU targets, but it is not exercised on hardware — CI has no GH200 or Spark runner.

A V100 needs the CUDA 12 build. CUDA 13 dropped offline compilation for Volta, and the PTX a fatbin also carries only ever JIT-compiles forwards, so a CUDA 13 artefact contains nothing a V100 can execute: every kernel launch fails with no kernel image is available for execution on the device. On a V100 host take the RHEL 8 packages or the portable Linux .tgz. Nothing older than Volta is supported.

Newer GPUs never need a newer build — the highest generation in the list ships PTX as well as SASS, which the driver JIT-compiles for a GPU that came out after the release.

The minimum driver above is the floor for the whole CUDA major version, which is what applies here because the CUDA runtime is statically linked (CUDA minor version compatibility). Newer drivers are always fine; they are backward compatible. A driver from the same release as the build toolkit (575.57.08 for the CUDA 12.9 build, 610.43.02 for a CUDA 13.3 one) additionally rules out the single caveat of minor version compatibility — a call into a driver API newer than the installed driver, which fails with cudaErrorCallRequiresNewerDriver.

Windows installer

The Windows artefacts are the jfjoch_viewer installer and the separate rugnux .zip; the rest of Jungfraujoch (broker, receiver, FPGA host, detector control) is Linux-only.

The toolchain bounds of the released installer are:

  • Visual Studio 2026 with the C++ (MSVC) toolset. MSVC is not optional — CUDA on Windows builds through it — and it is what the release is compiled with.
  • CUDA Toolkit 13.3 for the cuda13 variant.
  • Qt 6.11 for MSVC (msvc2022_64), including Qt Charts.
  • Ninja as the generator; zlib and Eigen 3.4 supplied from a build prefix.

The installer is generated with NSIS and bundles the Qt runtime (via windeployqt) and, on the CUDA variant, the cuFFT DLL — so the end user installs neither Qt nor a CUDA toolkit. The two variants share an install directory and Start Menu group and replace each other (CUDA is a strict superset); they are told apart by the installer filename and the Add/Remove Programs entry:

Build Installer file Add/Remove Programs
CUDA (default) jfjoch-viewer-<version>-win64-cuda<major>.exe Jungfraujoch (CUDA)
CPU-only jfjoch-viewer-<version>-win64-cpu.exe Jungfraujoch (CPU)

To build the viewer yourself on Windows, see jfjoch_viewer ▸ Building from source on Windows.

Licenses

Every package variant carries the project license, the third-party manifest and the verbatim license texts of the bundled dependencies, each package under a directory of its own — share/doc/jfjoch_broker, jfjoch_writer, jfjoch_viewer, jfjoch_rugnux, jfjoch_driver_dkms — so that no two packages claim the same path and they can be upgraded independently. See Third-party software notices.