|
FZGPUModules 2.0
GPU-accelerated modular compression pipelines
|
Header: modules/structural/roibin_split/roibin_split_stage.h Class: fz::ROIBinSplitStage<TData> — TData is float or double Category: Structural
Common instantiation:
Splits a detector field into two independently compressible streams plus the metadata that ties them back together:
| direction | ports |
|---|---|
forward (1 → 3) | field → roi, bg, peaks |
inverse (3 → 1) | roi, bg, peaks → field |
(2*hw+1)^2 box around every peak, concatenated in peak order, at full resolution and the field's element type.bin_factor within each z-slice: ceil(nx/b) * ceil(ny/b) * nz values. b = 1 copies the field through.8 * npeaks bytes (UINT8).On the inverse, the background is un-binned first and the ROI boxes are then pasted over it, so the tight-bound values win wherever the two overlap.
Serial-crystallography frames are almost all background; the science lives in a few hundred Bragg peaks covering a small percentage of the pixels. A single-bound compressor must apply the tight ROI bound to the entire frame, and pays for the other 99% at that bound.
This stage turns that into a graph problem. Because it is 1 → 3, the two data streams become two DAG branches, and each branch can carry its own Quantizer at its own error bound and its own coder chain:
There is no way to say "compress this part tightly and that part loosely" to a monolithic compressor; expressing it is the point. The design follows ROIBIN-SZ (Underwood et al.).
It is not derived from the data. It is the output of the experiment's own peak finder, which in a real light-source pipeline has already run upstream — the same assumption ROIBIN-SZ makes. At compress time setPeaksFile() reads it; the stage validates every record against the field bounds and throws if the file's nx/ny/nz disagree with the pipeline's dimensions, because a silent mismatch would relocate every ROI box and still produce output that round-trips.
The table is then re-emitted on the peaks port, so it lands inside the archive and is counted in the compressed size. The decompressor never needs the .roi file. At 8 B/peak this is ≈0.01 % of a frame.
bin_factor = b > 1 replaces each b x b block with its mean. This is a resolution reduction, not an error bound. The background reconstruction error is the binning error plus the quantization error, and it is not bounded by the background branch's error bound.
bin_factor | background guarantee | how to report background fidelity |
|---|---|---|
1 | satisfies its stated bound pixel-wise | max abs error and PSNR; the bound gate is meaningful |
> 1 | no bound | PSNR only; never claim a satisfied error bound |
The stage emits a getRunNotes() warning whenever bin_factor > 1 so this cannot be lost between the run and the write-up. The ROI branch satisfies its bound in both cases — that is the invariant the science depends on.
| setter | TOML key | default | meaning |
|---|---|---|---|
setRoiHalfWidth(hw) | roi_half_width | 4 | box is (2*hw+1)^2 |
setBinFactor(b) | bin_factor | 1 | background binning; 1 disables |
setPeaksFile(path) | peaks_file | — | compress-side peak list |
| — | data_type | float32 | float32 or float64 |
Downstream stages connect to the named ports:
If a downstream predictor is dimension-aware and bin_factor > 1, give it an explicit
dim_x/dim_y/dim_zoverride. The binned background is not the pipeline's input shape, andfinalize()re-pushes the global dims over anything set at construction — the predictor would then use the wrong row stride and still round-trip, silently costing ratio. See TiledLorenzoStage.
22 bytes. Peak values travel on the peaks port, not here — the 128-byte stage config slot cannot hold a few thousand records.
The separation of supplied Bragg-peak regions from a spatially binned background follows ROIBIN-SZ:
Robert Underwood, Chun Hong Yoon, Ali Murat Gok, Sheng Di, and Franck Cappello. ROIBIN-SZ: Fast and Science-Preserving Compression for Serial Crystallography. Synchrotron Radiation News 36(4), 17–22, 2023. https://doi.org/10.1080/08940886.2023.2245722
The public ROIBIN-SZ integration and examples are distributed with SZ2. This stage is an independent GPU/DAG implementation: no SZ2 or LibPressio source was copied. Its CUDA kernels, FZROI1 peak-table format, fixed-output geometry, three named ports, archive integration, and inverse scatter are FZGPUModules code. See THIRD_PARTY.md for the provenance and license record.