jungfrauandClaude Opus 5 f36cd88795
Build Packages / build:viewer-tgz:cpu (push) Successful in 17m25s
Build Packages / build:viewer-tgz:cuda (push) Successful in 19m19s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 20m8s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 21m53s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 24m17s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 24m27s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m3s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 22m47s
Build Packages / build:rpm (rocky9) (push) Successful in 21m2s
Build Packages / build:rpm (rocky8) (push) Successful in 24m29s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 21m39s
Build Packages / Generate python client (push) Successful in 32s
Build Packages / Build documentation (push) Successful in 1m16s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2204) (push) Successful in 25m3s
Build Packages / XDS test (durin plugin) (push) Successful in 9m45s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m2s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m24s
Build Packages / DIALS test (push) Successful in 14m28s
Build Packages / Unit tests (push) Successful in 1h18m40s
Build Packages / build:windows:nocuda (push) Canceled after 0s
Build Packages / build:windows:cuda (push) Canceled after 0s
Give a 16-bit image a saturation code when its limit is 65534
The narrow encoding picked NARROW_BAD as the saturation code whenever the saturation
limit was above UINT16_MAX - 2. That is one too strict. A real value is STRICTLY below
the limit, so a limit of UINT16_MAX - 1 still leaves UINT16_MAX - 1 free to be the
code; only a limit of the whole range has nothing to spare, and that is exactly the
case where no pixel can be saturated, because the "is error" test claims UINT16_MAX
first.

At a limit of exactly 65534 the old condition therefore stored a saturated pixel as
the masked code, and it widened back to INT32_MIN instead of INT32_MAX. Masked and
saturated are not interchangeable: the strong-pixel search flags a saturated pixel
unconditionally and a masked one never, so the overloaded core of the strongest spots
dropped out of the strong-pixel mask. Bragg integration treats the two alike and the
image statistics are taken from the raw value, so nothing downstream of those moved -
which is why a battery over 24 crystals showed nothing.

That value is not a corner case. GetByteDepthImage()-driven writing stores
saturation_value = GetSaturationLimit() - 1 and the readers take it back as-is, so a
16-bit acquisition whose detector cutoff is at or above the full range comes back with
a limit of exactly 65534. The one 16-bit dataset in the rotation test set declares
11963, which is safe, so it could not have caught this.

Found by review, not by testing, because nothing tested the narrow path at all: every
GPU test writes into the wide buffer directly and never asks for the narrow one, and
every preprocessor test copies the image back to the host, which forces the wide path.
So the test comes with the fix. It runs the wide and the narrow preprocessor over the
same synthetic frame - values around each boundary, masked on a stride coprime with
the value cycle so every value appears both masked and unmasked - across saturation
limits of none, 5000, 0xFFFD, 0xFFFE and 0xFFFF, on both the host-upload and the
device-decode entry point, and compares the statistics and every pixel. Against the
old condition it fails with 625860 differing pixels; against this one it passes.

Also makes the header self-contained: it uses __host__/__device__ and the CUDA vector
types and only compiled because every includer happened to pull in cuda_runtime.h
first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 18:41:53 -04:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-07-11 07:19:11 +02:00
2026-07-19 09:39:28 +02:00
2025-12-04 11:56:14 +01:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-07-13 13:54:03 +02:00
2026-07-12 19:42:29 +02:00
2026-08-13 17:03:10 +02:00
2026-03-26 20:50:33 +01:00
2026-06-23 20:29:49 +02:00
2026-08-13 17:03:10 +02:00
2026-07-19 09:39:28 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-07-19 09:39:28 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-06-13 21:27:41 +02:00
2026-06-23 20:29:49 +02:00
2026-08-13 17:03:10 +02:00
2024-11-22 21:25:20 +01:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02: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-06-23 20:29:49 +02:00
2026-08-13 17:03:10 +02:00
2024-12-02 21:17:14 +01:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00
2026-08-13 17:03:10 +02:00

Jungfraujoch

Application to receive data from the PSI JUNGFRAU and EIGER detectors.

All documentation is now placed in docs/ subdirectory and for the current version hosted on Jungfraujoch Read The Docs page.

S
Description
Jungfraujoch Data Acquisition System
Readme GPL-3.0
3 GiB
Languages
C++ 74.7%
HTML 8%
C 6.4%
TypeScript 4.4%
Tcl 2.3%
Other 4.1%