leonarski_fandClaude Opus 5.5 584777bfa2
Build Packages / Create release (push) Successful in 9s
Build Packages / build:portable:windows-x86_64:cuda (push) Successful in 32m21s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 33m58s
Build Packages / build:portable:macos-arm64:nocuda (push) Successful in 5m26s
Build Packages / build:portable:linux-x86_64:cuda (push) Successful in 20m0s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 9m33s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 29m20s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / build:portable:linux-x86_64:nocuda (push) Successful in 15m54s
Build Packages / Generate python client (push) Successful in 51s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 30m34s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 23m35s
Build Packages / build:portable:windows-x86_64:nocuda (push) Successful in 27m31s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 30m23s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 27m6s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 34m21s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 25m48s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 36m24s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 34m11s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 29m11s
Build Packages / Unit tests (push) Successful in 1h50m56s
Build Packages / Validation Battery (push) Successful in 44m43s
Writer: drop /entry/sample/input_unit_cell
It was only ever written in the branch where unit_cell is the start message's
cell, so wherever it appeared it repeated unit_cell. Nothing in the tree reads
it - not the reader, the viewer, rugnux or the tools.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
2026-11-11 10:07:14 +01:00
2026-11-02 12:05:20 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-10-16 15:34:43 +02:00
2026-10-16 15:34:43 +02:00
2026-11-02 12:05:20 +01:00
2026-11-10 22:06:51 +01:00
2026-11-04 11:13:33 +01:00
2026-11-02 12:05:20 +01:00
2026-11-10 22:06:51 +01:00
2026-10-21 11:20:01 +02:00
2026-10-21 11:20:01 +02:00
2026-03-26 20:50:33 +01:00
2026-06-23 20:29:49 +02:00
2026-11-02 12:05:20 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-10-16 15:34:43 +02:00
2026-06-23 20:29:49 +02:00
2026-10-27 13:18:42 +01:00
2024-11-22 21:25:20 +01:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2024-12-02 21:17:14 +01:00
2026-08-13 17:03:10 +02:00
2025-10-25 22:05:47 +02:00
2026-07-03 19:18:56 +02:00
2026-10-16 15:34:43 +02:00
2026-08-13 17:03:10 +02:00
2026-11-10 22:06:51 +01:00
2026-11-10 22:06:51 +01:00
2026-10-16 15:34:43 +02:00

Jungfraujoch and Rugnux

This repository is about doing macromolecular crystallography fast, at the edge and automatically. The data are processed where they are collected, next to the detector at the beamline, at the detector's frame rate and with nothing to set by hand, so that merged data and, with a model, a refined structure are available seconds after the measurement ends.

Repository: https://gitea.psi.ch/mx/jungfraujoch. Documentation: https://jungfraujoch.readthedocs.io.

The programs

  • Jungfraujoch (jfjoch_broker, jfjoch_writer) - data acquisition. The broker takes the detector's frames at the full frame rate, analyses the images on the fly and streams them to the writer, which writes NXmx HDF5. Linux servers only. See Jungfraujoch and Deployment.
  • Rugnux (rugnux) - offline processing of a stored dataset, rotation sweeps and serial stills. It takes the images to scaled and merged reflections and, with an atomic model, on to a refined structure with maps. The unit cell, space group and resolution are decided from the data. Linux, Windows and macOS. See Rugnux.
  • Jungfraujoch Viewer (jfjoch_viewer) - the Qt desktop application: shows the images with their spots and predictions, runs the Rugnux pipeline on the open dataset and follows a live collection. See Using the viewer.

All three are open-source software from the Paul Scherrer Institute. The names are explained in Naming. The instructions below are about Rugnux; the acquisition system needs a beamline and is covered by its own pages.

Requirements

Rugnux runs on Linux x86-64 and ARM (aarch64), Windows 11 and macOS 13 or newer on Apple Silicon. An NVIDIA GPU is optional and recommended: the demo below takes seconds on a GPU and minutes without one. The CUDA archive needs only the NVIDIA driver, no CUDA toolkit. The demo needs about 10 GB of host memory and 9 GB of GPU memory. Details in Installing Rugnux.

The acquisition system needs a server with AMD Alveo U55C FPGA cards for JUNGFRAU and the PSI EIGER; NVIDIA GPUs for live indexing and a 100G switch are optional (Hardware requirements). DECTRIS detectors are read through their detector control unit and need no FPGA.

The times in this file were measured with release 1.0.0-rc.183 on a Rocky Linux 8 desktop with a 16-core CPU and an NVIDIA RTX 5080, the data on a local SSD.

Installation

Rugnux is one executable in an archive on the release page, https://gitea.psi.ch/mx/jungfraujoch/releases. The archive has no top-level directory, so unpack it into a directory of its own. On Linux x86-64, with or without an NVIDIA GPU:

VERSION=1.0.0-rc.184        # the newest release on the page
curl -L -O https://gitea.psi.ch/mx/jungfraujoch/releases/download/$VERSION/rugnux-$VERSION-linux-x86_64-cuda12.tgz
mkdir -p rugnux-$VERSION && tar xzf rugnux-$VERSION-linux-x86_64-cuda12.tgz -C rugnux-$VERSION
export PATH=$PWD/rugnux-$VERSION/bin:$PATH
rugnux            # prints the version and the usage

The same page has the CPU-only, ARM (aarch64), Windows and macOS archives, the viewer and the XDS plugin. On RHEL / Rocky and Ubuntu, Rugnux is also a package (dnf install rugnux, apt install rugnux; package repositories).

Demo on public data

The demo is the 9ZLO dataset (PDB 9ZLO): 3600 EIGER images of Proteus mirabilis UreE collected at the Australian Synchrotron, 10.8 GB in 19 files on Zenodo (10.5281/zenodo.18652652, CC-BY 4.0). Cite the record if you use the data.

mkdir -p demo/9zlo && cd demo
for f in ASP0887_09_0114_master.h5 ASP0887_09_0114_data_0000{01..18}.h5; do curl -L -C - -o 9zlo/$f "https://zenodo.org/records/18652652/files/$f?download=1"; done
rugnux -o 9zlo 9zlo/ASP0887_09_0114_master.h5

-o 9zlo is the prefix of every output file; the last argument is the dataset's HDF5 master file (for a CBF, marCCD, SMV or SFRM sequence, any one of its images). No other option is needed: Rugnux tells rotation data from serial data by the associated metadata (goniometer axis), determines the unit cell, space group and resolution cutoff from the data, and scales and merges by default.

Terminal output

The run prints numbered steps and takes 17 s on the GPU (minutes on the CPU). It ends with

 Result        OK: Merged to 1.56 A in P 21 21 21. No warnings.
 Space group   P 21 21 21
 Unit cell     38.363 89.746 106.871 90.000 90.000 90.000
 Resolution    1.56 A written; the CC1/2 fall-off is fitted at 1.64 A
 Completeness  100.0 % to 1.66 A; 99.7 % over the full written range
 Signal        I/sigma 11.6 R_meas 12.0 % CC1/2 0.999 ISa 23.6 (23.1-24.0)
 Anomalous     no usable signal (CC_anom -0.16)
 Files         9zlo.cif 9zlo.hkl 9zlo.ins 9zlo.mtz 9zlo_detector.jpg
               9zlo_log.txt 9zlo_plot.txt 9zlo_report.txt 9zlo_unmerged.mtz
 Wall time     17.30 s

Another run, GPU or CPU, gives the same space group, the cell to 0.1 % and the resolution to one shell. The last digit of a statistic can differ. The deposited structure has the same space group, a cell within 0.5 % of this one and 2.0 A as its resolution.

Output files

  • 9zlo.mtz - merged intensities and amplitudes, for CCP4 and Phenix.
  • 9zlo.cif - the same as mmCIF, for deposition.
  • 9zlo.hkl, 9zlo.ins - for SHELX.
  • 9zlo_unmerged.mtz - the scaled observations, for POINTLESS and AIMLESS.
  • 9zlo_report.txt - the statistics and decisions. Read this one first; every value is also a KEY= value line (grep '^R_MEAS= ' 9zlo_report.txt).
  • 9zlo_plot.txt - one row per image, for plotting how the crystal behaved over the sweep.
  • 9zlo_detector.jpg - the detector with the pixel mask and the beam-stop shadow drawn on it.
  • 9zlo_log.txt - the full log of the run, to send with any question about it.

With a model

With a model the run goes on to place and refine it. The AlphaFold prediction of the protein is in this repository with its predicted-aligned-error file, which is read when it sits beside the model:

curl -L -O https://gitea.psi.ch/mx/jungfraujoch/raw/branch/main/tools/battery/models/AF-P17090-F1-model_v6.cif
curl -L -O https://gitea.psi.ch/mx/jungfraujoch/raw/branch/main/tools/battery/models/AF-P17090-F1-predicted_aligned_error_v6.json
rugnux -o 9zlo --model AF-P17090-F1-model_v6.cif 9zlo/ASP0887_09_0114_master.h5

The model does not change the processing: the intensities, the cell and the resolution are those of the run without it. It can settle the hand of the space group, which the intensities cannot, and a different space group it prefers is written beside the answer as 9zlo_mr.mtz, never into it. Molecular replacement places the two copies (MR_DECISION= AGREES in the report), refinement brings them to R-work / R-free 0.27 / 0.30, and the run takes 22 s. It adds these files:

  • 9zlo_model.cif, 9zlo_model.pdb, 9zlo_maps.mtz - the model as placed, with its maps.
  • 9zlo_refined_model.cif, 9zlo_refined_model.pdb, 9zlo_refined_maps.mtz - the refined model, with map coefficients that Coot opens.
  • 9zlo_blobs.json - difference density the model does not explain.

The same walk-through is in the documentation: Quick start and A first run in detail.

Further examples

The paper's timing benchmark runs 9ZLO and the three rotation sets below; the last row is the serial set of the next section. All are public. A rotation set is run as 9ZLO is, with the master file of its archive (any one frame for 4NWV) and its model. The AlphaFold predictions for 9S02 and 9GJX are in tools/battery/models/; the 4NWV model is the deposited structure (https://files.rcsb.org/download/4NWV.cif).

Set Source (cite this) Data Run time with a model
9S02 MX-RDR 10.60884/NRNGS4 EIGER2 X 16M, NXmx HDF5, 11.7 GB 45 s
9GJX IRRMC 10.18430/M39GJX EIGER 16M, HDF5, 20.2 GB archive 43 s
4NWV SBGrid Data Bank 10.15785/sbgrid/9 marCCD frames, 16.8 GB; a 400 A cell 390 s
9V3D CXIDB 236, 10.11577/3014306 MPCCD, Cheetah-SACLA HDF5, 10.1 GB 35 s

Serial stills: lysozyme at SACLA

Serial data go through the same program: a dataset without a goniometer axis is taken as stills. The example is three hit files of one run of a tape-drive experiment at SACLA BL2 (CXIDB 236). The command gives the known cell and space group. The files carry the detector's panel layout, so no geometry file is needed.

mkdir -p sacla236
for f in run157084-0 run157084-1 run157084-2; do
  curl -L -C - -o sacla236/$f.h5 https://cxidb.org/data/236/Data/lyso01-apo-bigXtal/$f.h5
done
curl -L -O https://files.rcsb.org/download/9V3D.pdb
rugnux -o sacla236 -C 79.45,79.45,38.15,90,90,90 -S P43212 --model 9V3D.pdb sacla236/run157084-*.h5

It takes about 35 s and ends with

 Result        WARNINGS: Merged to 1.69 A in P 43 21 2. 2 conditions need
               attention: MODEL_FREE_SET, OVERLOADS.
 Space group   P 43 21 2
 Unit cell     79.343 79.343 38.121 90.000 90.000 90.000
 Resolution    1.69 A written; the CC1/2 fall-off is fitted at 1.72 A
 Completeness  100.0 % to 1.79 A; 98.4 % over the full written range
 Signal        I/sigma 12.8   CC1/2 0.978
 Files         sacla236.cif sacla236.hkl sacla236.ins sacla236.mtz
               sacla236_blobs.json sacla236_log.txt sacla236_maps.mtz
               sacla236_model.cif sacla236_model.pdb
               sacla236_module_placement.json sacla236_modules.h5
               sacla236_plot.txt sacla236_refined_maps.mtz
               sacla236_refined_model.cif sacla236_refined_model.pdb
               sacla236_report.txt sacla236_unmerged.mtz
 Wall time     34.64 s

Both warnings are expected here. The deposited model was refined against these reflections, so the free set drawn by this run is not truly free. A few percent of the reflections hold a saturated pixel. About 95 % of the 2424 frames are indexed and the refined model has an R-free of about 0.17. For serial data sacla236_report.txt gives R_SPLIT and CC_HALF_SPLIT (one half of the frames against the other) in place of R_meas. sacla236_module_placement.json holds the refined panel positions.

Your own data

rugnux -o myrun dataset_master.h5                                   # rotation: cell, space group, resolution from the data
rugnux -o myrun --model model.cif dataset_master.h5                 # with a model: placement, refinement, maps
rugnux -o serial -C 184.0,184.0,184.0,90,90,90 -S F432 run*.h5      # serial stills with the known cell and space group (here a cubic apoferritin)

Rugnux reads these without conversion (Input formats): NXmx HDF5 from Jungfraujoch, DECTRIS detectors or another toolchain, PILATUS miniCBF, marCCD, SMV and Bruker SFRM sequences, and the serial formats Cheetah-SACLA HDF5, Cheetah CXI and LCLS-I XTC.

Serial stills process much better with the cell and space group given (-C, -S); rotation data do not really need them. The anomalous signal needs no option: a rotation merge always keeps I(+) and I(-). Every option is listed in Command-line options. Running Rugnux is the manual, and Rugnux with other programs takes the files on to Phenix, REFMAC, SHELX and the CCP4 tools. The same datasets open in jfjoch_viewer.

Reproducing the paper's results

The results of the Rugnux paper come from the validation battery. The rotation datasets of External test data are scored against their depositions. The serial datasets of External test data: serial are scored against their deposited models. The timing benchmark runs the four rotation sets above. The results are on Zenodo: Rugnux: Results of synchrotron and XFEL tests, doi:10.5281/zenodo.23596195 (CC-BY-SA 4.0). The record holds every file the runs wrote, the manifests and scripts as used, and the source code of the versions used. The images come from the repositories listed on those two pages.

To rerun, copy the datasets under one data root with the paths of tools/battery/open.json and tools/battery/still_manifest.json, write a site config (tools/battery/site.example.json), and run

tools/battery/battery.py run --rugnux <binary>        # the battery (hours); --only <set> or --tier smoke for a subset
tools/battery/battery.py timing --rugnux <binary>     # the timing benchmark (minutes)
tools/battery/battery.py compare <run> <run>          # two runs side by side; the record's untarred synchrotron_result.tar can be one

The paper's times do not include the refinement; a current run's do. The protocol and the scoring rules are in tools/battery/README.md and Measuring Rugnux.

Building from source

Build from source for development or for a platform without a released binary. It needs CMake 3.26 or newer, a C++20 compiler (GCC 11 or newer, Clang 14 or newer, MSVC or Xcode), git-lfs for the FPGA bitstreams and the test data, and network access on the first configure, which downloads every third-party library. Optional: CUDA 12.8 or newer for the GPU path, Qt 6 for the viewer.

git clone https://gitea.psi.ch/mx/jungfraujoch.git && cd jungfraujoch
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc) --target rugnux            # build/rugnux/rugnux
cmake --build build -j$(nproc) --target jfjoch_broker     # the acquisition service

-DJFJOCH_RUGNUX_ONLY=ON builds only Rugnux, -DJFJOCH_USE_CUDA=OFF a CPU-only build. The options, the platform notes and the tests are in Installing Rugnux, Deployment and Tests.

Licence

The software is free software under the GNU General Public License v3.0 (LICENSE). It is free to use for industry and academia. If you modify this code and distribute it, you must do so under the same GNU General Public License. The FPGA design is released under the CERN Open Hardware Licence v2, strongly reciprocal (fpga/LICENSE). Third-party components bundled in the releases are listed in THIRD_PARTY_NOTICES.md.

Acknowledgements

Rugnux builds on many crystallographic methods published by others. We acknowledge their authors in docs/ACKNOWLEDGEMENT.md, which names each method and its paper.

How to cite

  • Jungfraujoch: F. Leonarski et al., "Jungfraujoch: hardware-accelerated data-acquisition system for kilohertz pixel-array X-ray detectors" (2023), J. Synchrotron Rad. 30, 227-234 doi:10.1107/S1600577522010268; for real-time serial crystallography also J. Duan et al., "Jungfraujoch: 38 GB s⁻¹ real-time serial crystallography – data acquisition and live indexing feedback" (2026), J. Appl. Cryst. 59, 1668-1677 doi:10.1107/S1600576726008083.
  • Rugnux: F. Leonarski and M. Wang, "Rugnux: from diffraction images to structure at synchrotrons and XFELs in one program" (2026), bioRxiv doi:10.64898/2026.10.24.761522.

The full list is in docs/PUBLICATIONS.md.

S
Description
Jungfraujoch Data Acquisition System, Rugnux Data Processing Application, and Diffraction Viewer
Readme GPL-3.0
3.1 GiB
2 Stars 3 Watchers 0 Forks
Languages
C++ 78.5%
HTML 5.5%
Cuda 4.2%
C 3.8%
TypeScript 3.3%
Other 4.6%