docs: the receiver of a run and Rugnux live stills on the DECTRIS stream
From rc1862feef4b02(JFJOCH_BROKER.md, IMAGE_STREAM.md), for what this branch has: the table of the receiver each run gets, the DECTRIS serial live mode (pre-pass, analysis, live merge, model step, CANCELLED after a cancel, a rotation run the buffer cannot hold getting the per-image analysis), no calibration forwarded from a DECTRIS stream, nothing on the preview and metadata streams for the DECTRIS mask sequence. Adapted: JFJochReceiverFPGA takes every PSI run, pedestal included, and still analyses serial runs live with rugnux on; a paragraph says how that differs (frames wait in half the image buffer, no model step). Left out: the broker_pipeline figure (it shows JFJochReceiverPedestal and the FPGA receiver without live stills), the internal-generator memory check (25542a9af, not ported) and docs/TESTS.md (the card mock, not ported). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
1 parent
8a7f46a4e2
commit
fa0c96a095
2 files changed
+90
-22
No files matched your search
+11
-2
@@ -11,6 +11,8 @@ These are:
|
||||
## Image stream
|
||||
Images (with metadata) are serialized as CBOR [image message](CBOR.md#image-message).
|
||||
The stream will also include CBOR [start message](CBOR.md#start-message), [calibration messages](CBOR.md#calibration-message) and [end message](CBOR.md#end-message) with run metadata.
|
||||
Calibration messages (the JUNGFRAU pedestal and pedestal RMS, with `save_calibration` on) come only from the
|
||||
FPGA workflow; a DECTRIS stream carries no calibration, so none is forwarded for it.
|
||||
|
||||
If `file_prefix` is not provided for a data collection, images won't be sent to image stream (or its HDF5/CBOR replacements).
|
||||
|
||||
@@ -239,12 +241,19 @@ For this reason it is also recommended to use the same option on receiver side.
|
||||
|
||||
Given PUB socket properties, it is possible to connect multiple viewers to a single socket --- all the viewers should receive all the images sent.
|
||||
|
||||
The dark frames of the mask sequence from a DECTRIS detector are no images for a viewer: nothing is sent on
|
||||
this stream for them, not even a start or end message.
|
||||
|
||||
## Metadata stream
|
||||
Jungfraujoch can also send pure metadata for the purpose of archiving such information.
|
||||
Metadata are serialized as CBOR [metadata message](CBOR.md#metadata-message).
|
||||
This is very similar to the image message, but excludes the image array, the spot list and the reflection list.
|
||||
As metadata are relatively small, to avoid large number of messages, Jungfraujoch bundles metadata of many images in one message.
|
||||
Order of images within bundle, as well as the size of the bundle, are not guaranteed.
|
||||
As metadata are relatively small, to avoid large number of messages, Jungfraujoch bundles metadata of many images in one message:
|
||||
a bundle is cut every `period_ms` of the `zeromq_metadata` configuration and holds the images analysed since the last one.
|
||||
Order of images within bundle, as well as the size of the bundle, are not guaranteed, and two bundles cut
|
||||
close together can leave in either order; the end message is always last.
|
||||
The stream will also include CBOR [start message](CBOR.md#start-message) and [end message](CBOR.md#end-message) with run metadata.
|
||||
A disabled metadata stream keeps nothing, and the dark frames of the mask sequence from a DECTRIS detector
|
||||
send nothing on it, as on the preview stream.
|
||||
|
||||
This is using PUB socket with watermark, so there is some queuing of messages with ZeroMQ. Multiple receivers can be connected.
|
||||
+79
-20
@@ -214,19 +214,42 @@ rugnux processed the data: by rugnux live mode (below) during the collection, or
|
||||
`rotation_indexing_angular_stride_deg` and `spot_finding_settings.quick_integration` are deprecated: accepted, ignored,
|
||||
and returned at their old defaults. `bragg_integration_settings` apply to rugnux live mode.
|
||||
|
||||
### The receiver of a run
|
||||
|
||||
Each run is taken by one receiver, chosen when it starts from the detector type, the detector mode, the
|
||||
goniometer and the rugnux live setting:
|
||||
|
||||
| Input | Run | Receiver | What it does |
|
||||
|---|---|---|---|
|
||||
| FPGA cards (PSI JUNGFRAU, PSI EIGER) | every run | `JFJochReceiverFPGA` | the card's converted pixels, spots, azimuthal and ROI sums into the image; summation on the host above what the card sums; indexing of each image; the calibration to the writer; pedestal runs into the pedestal and its RMS; with rugnux live on, a serial run analysed on the GPU after a rugnux pre-pass (see [Serial collections](#serial-collections-experimental)) |
|
||||
| DECTRIS stream | dark-mask sequence | `JFJochReceiverDarkMask` | the dark frames into the mask; nothing on any stream |
|
||||
| DECTRIS stream | rugnux live off, or a rotation run the image buffer cannot hold | `JFJochReceiverLite` | each image on the GPU: masking, azimuthal and ROI integration, spot finding, indexing |
|
||||
| DECTRIS stream | rugnux live on, rotation that fits the image buffer | `JFJochReceiverRugnuxRotation` | images forwarded as they come; rugnux reads the collection back from the image buffer and runs the whole pipeline |
|
||||
| DECTRIS stream | rugnux live on, serial | `JFJochReceiverRugnuxStills` | a rugnux pre-pass on the first frames, then every frame analysed and integrated on the GPU and merged live |
|
||||
|
||||
`receiver_threads` is the number of image threads. The Lite receiver uses at most 16 of them for a
|
||||
collection at 100 Hz or slower or of fewer than 256 images (each thread holds a GPU analysis of its
|
||||
own); the FPGA receiver takes four when it sums images on the host. The GPU FFT indexers and cuFFT
|
||||
plans the broker's own indexing uses are built once and kept for the life of the process, and the ones
|
||||
built for earlier indexing settings are released when the settings change. `azim_int.force_cpu`
|
||||
moves the azimuthal integration of the FPGA workflow from the card to the host, which a profile with
|
||||
more bins than the card holds needs.
|
||||
|
||||
## Rugnux live mode
|
||||
|
||||
With rugnux live mode on, rotation collections from a DECTRIS detector are processed by rugnux inside
|
||||
the broker while they arrive, and serial (stills) collections in the FPGA workflow are analysed on the GPU
|
||||
with the geometry and mask a rugnux pre-pass decided (see [Serial collections](#serial-collections-experimental)
|
||||
below). It is off by default; the configuration file switches it on with
|
||||
With rugnux live mode on, collections from a DECTRIS detector are processed inside the broker while they
|
||||
arrive: rotation collections by rugnux, and serial (stills) collections on the GPU with the geometry and mask a
|
||||
rugnux pre-pass decided (see [Serial collections](#serial-collections-experimental) below). In the FPGA workflow
|
||||
(PSI JUNGFRAU and EIGER) serial collections are analysed on the GPU after a pre-pass as well, with the differences
|
||||
given there; rotation collections run image by image, as with the mode off. It is off by default; the
|
||||
configuration file switches it on with
|
||||
`"rugnux": {"enable": true, "reserved_cpus": 4}`, where `reserved_cpus` is the number of CPU threads
|
||||
left to the receiver and the image pusher.
|
||||
|
||||
For a rotation collection, rugnux reads the images back from the broker's image buffer, so the buffer must hold the whole
|
||||
collection - one slot per image. Where it holds fewer, the collection is only forwarded to the writer,
|
||||
as with the mode off; the live status reports it as skipped and the collection's statistics carry a
|
||||
warning saying how many images the buffer holds against how many the collection has.
|
||||
collection - one slot per image. Where it holds fewer, the collection gets the per-image analysis of
|
||||
the mode off (spots, indexing, scan result); the live status reports it as skipped and the collection's
|
||||
statistics carry a warning saying how many images the buffer holds against how many the collection has.
|
||||
|
||||
The results - the merged data, the map coefficients and, with a model, the placed model and its
|
||||
refinement - travel to the writer in the end message, which writes them beside the master file as
|
||||
@@ -251,7 +274,8 @@ they prepare the next collection and expose nothing of the current one.
|
||||
The end message, and with it the end of the collection, waits for the analysis. `deadline_s` (default
|
||||
60 s; 0 for no cutoff) bounds that wait: this long after the last image the analysis is cut. `POST /cancel` is
|
||||
the other way to cut it: while images still arrive it cancels the collection as with the mode off,
|
||||
and the analysis with it; after the last image it ends only the analysis. A cut analysis gives what it
|
||||
and the analysis with it - the live status then ends with verdict `CANCELLED` and the images that came before
|
||||
the cancel; after the last image it ends only the analysis. A cut analysis gives what it
|
||||
has established: a pass that is past its images still merges and makes its outputs, the canonical pass
|
||||
cut among its images merges those it has read, only the placed model is left out, and
|
||||
any other pass cut short gives way to the last one that ran to its end. The end message goes out at
|
||||
@@ -277,9 +301,9 @@ estimate and background of every image in `GET /result/scan` and the master file
|
||||
### Serial collections (experimental)
|
||||
|
||||
Live processing of serial collections is **experimental**. With rugnux live mode on, a serial
|
||||
(non-rotation) collection in the FPGA workflow, in the standard detector mode, is analysed as frames from a
|
||||
DECTRIS detector are: the converted frames go to GPU spot finding, indexing and integration, with rugnux's
|
||||
stills spot finder (adaptive threshold, single-pixel spots kept). Before any frame is analysed, the first
|
||||
(non-rotation) collection from a DECTRIS detector, in the standard detector mode, is analysed frame by frame: the
|
||||
frames as the stream delivers them go to GPU spot finding, indexing and integration, with rugnux's stills spot
|
||||
finder (adaptive threshold, single-pixel spots kept). Before any frame is analysed, the first
|
||||
500 frames are run through rugnux, in memory, as `rugnux --no-merge` would run on them. That pre-pass
|
||||
decides the beam centre, refines the detector distance (where the dataset settings give a unit cell) and
|
||||
masks the beam-stop shadow and defective pixels; every frame of the collection is then analysed with that
|
||||
@@ -288,14 +312,15 @@ the centre and distance used (`refined_beam_center_x/y`, `refined_detector_dista
|
||||
[CBOR](CBOR.md)). The broker's own distance is taken as the beamline's: unlike offline rugnux, the pre-pass
|
||||
does not search the whole distance range. It refines the centre and distance for a detector square to the
|
||||
beam, as the frames are then analysed. At a serial hit rate the distance needs the 500 frames to be refined at
|
||||
all: on fewer, too few index for the geometry refinement to run, and the stated distance is kept. The image
|
||||
buffer has to hold them, and the frames that arrive while the pre-pass runs, in half its slots (for a JUNGFRAU
|
||||
8M, a slot is the size of an uncompressed frame); a smaller buffer starts the pre-pass on as many as it holds.
|
||||
all: on fewer, too few index for the geometry refinement to run, and the stated distance is kept. The pre-pass
|
||||
holds and fits on at most half the slots of the image buffer (a slot is the size of an uncompressed
|
||||
frame), so a smaller buffer starts it on as many as that.
|
||||
|
||||
Where a unit cell is given and those frames are too few for the geometry fit (200 indexed frames), frames go on
|
||||
being held and the pre-pass runs again on all of them each time they have doubled, until the fit has its frames, half
|
||||
the image buffer is full, or the collection ends. The analysis starts when the pre-pass ends and catches up from the
|
||||
frames held, so it starts later on a low hit rate; a frame finding the buffer full meanwhile is dropped as usual.
|
||||
the image buffer or 2000 frames are held, or the collection ends; frames arriving during a run do not make the next
|
||||
one larger than that, so the last run stays short. The analysis starts when the pre-pass ends and catches up from the
|
||||
frames waiting, so it starts later on a low hit rate.
|
||||
|
||||
The geometry is fixed when the pre-pass ends and does not change during the collection, so every frame is analysed
|
||||
and merged at it and the radial profile has one binning throughout. Where the pre-pass could not refine it (too few
|
||||
@@ -303,9 +328,10 @@ of its frames indexed, as with a small image buffer, a low hit rate or a chip wh
|
||||
cell given), the distance in the header is used for the whole run: this is a warning in the log and a note of the
|
||||
live status, and a wrong header distance then costs resolution and indexed frames.
|
||||
|
||||
Frames arriving during the pre-pass, or faster than the analysis, wait in the image buffer, in at most half of
|
||||
its slots; a frame that finds no free slot is dropped and counted as for a full image buffer, so analysis
|
||||
slower than the frame rate costs frames, not memory. A pre-pass that fails leaves the stated geometry and
|
||||
Frames arriving during the pre-pass, or faster than the analysis, wait in the image buffer, in all its slots but
|
||||
one per analysis thread, kept for sending; a frame that finds it full is dropped and counted as for a full image
|
||||
buffer, so analysis slower than the frame rate costs frames, not memory. Where the writer lags behind, the analysis
|
||||
waits for slots to come back. A pre-pass that fails leaves the stated geometry and
|
||||
mask in use. Where the start message cannot be sent after the pre-pass (no writer listening) or the analysis
|
||||
cannot be set up, the collection ends with that error, reported by `/status` and `/wait_till_done`, and the
|
||||
next `/start` runs as usual.
|
||||
@@ -323,11 +349,44 @@ JUNGFRAU 8M, against about half a minute for the same merge made from nothing. T
|
||||
writer in the end message, as for rotation (`<file_prefix>.mtz`), and the run's step "Merge" carries the
|
||||
final statistics.
|
||||
|
||||
`GET /rugnux/status` reports such a run as three steps (pre-pass, GPU analysis, merge) and a `stills` block: the
|
||||
With an uploaded model, the model step runs on every one of these merges, as `rugnux --mode scale --model`
|
||||
places a model and `rugnux --mode refine` refines it: the model is placed by its rigid body where it fits the
|
||||
data as given - its indexing ambiguity probed by R-free, and the merge put in the model's indexing - and by
|
||||
molecular replacement where it does not (or is a prediction); the 2mFo-DFc and mFo-DFc maps are made, and the
|
||||
placed model is refined, with the blobs of its difference map. Without a space group in the dataset settings
|
||||
the frames are merged in the model's own, where the model's cell is the consensus cell of the run on the same
|
||||
axes; otherwise the model is left out, with a warning in the live status saying why. The step on a provisional
|
||||
merge runs on a thread of its own, on 8 CPU threads and the GPU, beside the analysis and the merge, which do not
|
||||
wait for it: its result - the placed and the refined model, their maps, the scores - goes to the live status
|
||||
(`model`, `/rugnux/model.cif`, `/rugnux/map.ccp4`) as soon as it is made, so the density can be looked at while
|
||||
the collection goes on. A step still running when the next merge is made is cut (a refinement cut short keeps
|
||||
the weight trials it finished), and each step starts from the placement of the one before: the merge is put in
|
||||
the same indexing, and the model goes in where it was placed, with no null, indexing probe or search made again.
|
||||
After the last frame the step on the merge of the collection runs on every thread, and the end message waits
|
||||
for it until `deadline_s` after the last image; then it is cut as for rotation - the refinement first (cut
|
||||
short, or left out where it has not started), and a molecular replacement that has not started. The end message
|
||||
carries the merge in the model's indexing (`<file_prefix>.mtz`), the map coefficients, the placed and the
|
||||
refined model, the refined maps and the blobs, written as for rotation; one that would not fit the pushers'
|
||||
buffer goes without them. The GPU memory the analysis's indexers hold for the broker's life is counted against
|
||||
the card when the model step decides what goes on it. `POST /cancel` cuts it
|
||||
the same way, at any time (`cut` in `/rugnux/status`): the frames that came are still analysed and merged.
|
||||
|
||||
The frames wait in the image buffer compressed, and go on to the writer byte for byte, with their analysis. `efficiency` is the
|
||||
images received over the images expected; a stream has no module packets, so per-image collection
|
||||
efficiency, ADU histograms and pulse IDs are absent. The dark frames of the mask sequence stay outside this mode.
|
||||
|
||||
`GET /rugnux/status` reports such a run as three steps (pre-pass, GPU analysis, merge; with a model, the steps of
|
||||
the model on the merge of the collection after them) and a `stills` block: the
|
||||
pre-pass state and duration, the stated and decided beam centre and distance, the pixels masked, and the
|
||||
images analysed and indexed with the analysis rate. The "Rugnux live" page of the web frontend shows the
|
||||
same. `tools/jfjoch_stills_gpu_replay` replays a stored serial collection through the same analysis.
|
||||
|
||||
In the FPGA workflow (JUNGFRAU), a serial collection with rugnux live mode on is analysed by the receiver of the
|
||||
card (`JFJochReceiverFPGA`) with the pre-pass, the GPU analysis and the live merge described above, with three
|
||||
differences: the converted frames wait for the analysis in at most half of the image buffer's slots, a frame that
|
||||
finds them taken is dropped, and there is no model step - an uploaded model is not placed or refined on these
|
||||
merges. The end message carries the merged data, as for a DECTRIS stream.
|
||||
|
||||
## Setting up a local test for Jungfraujoch
|
||||
For development, it is possible to set up a local installation of Jungfraujoch.
|
||||
This will work without FPGA installed in the computer and allows testing the Jungfraujoch software layer, including
|
||||
|
||||
Reference in new issue
Block a user