docs: correct the FPGA analysis limits and the square-root coefficient
The azimuthal bin limit is FPGA_INTEGRATION_BIN_COUNT = 2048, not 1024. There are 16 ROIs, not 64, and the map is a 16-bit per-pixel mask, so a pixel belongs to any subset of them rather than to exactly one. The lossy transform is round(sqrt(N*N*X)) = round(N*sqrt(X)): the HLS squares the sqrtmult register before multiplying. The doc said sqrt(N*X), which is off by sqrt(N), and the register comment claimed the value was "minus one" and "should be square of the coeff" - both wrong, the host writes N and the FPGA squares it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ To implement azimuthal integration, FPGA is able to sum pixels based on a provid
|
||||
This way Jungfraujoch implements azimuthal integration with solid angle and polarization corrections.
|
||||
Corrections were implemented according to formulas developed by [Jensen et al. (J. Synchr. Rad., 29, 1420-1428, 2022)](https://journals.iucr.org/s/issues/2022/06/00/fv5148/).
|
||||
|
||||
Given FPGA limitations, split-pixels cannot be implemented and number of bins is limited as 1024 per detector module.
|
||||
Given FPGA limitations, split-pixels cannot be implemented and number of bins is limited as 2048 per detector module.
|
||||
This way 2D azimuthal integration, as needed for example by SAS-TT, cannot be currently implemented with the FPGA card and needs to be done on a CPU.
|
||||
One needs to be careful with per-pixel corrections - their acceptable range is constrained by 16-bit pixed point integer implementation
|
||||
and is tuned for standard SAXS/WAXS range.
|
||||
@@ -58,7 +58,7 @@ In vertical direction the area is flexible - it is 15 lines above and below of t
|
||||
Given very large box size, approximation are made, for example that `N ≈ N-1` in calculating standard deviation.
|
||||
|
||||
## Region-of-interest (ROI) integration
|
||||
Each pixel in a module can be assigned to one of 64 ROIs. For each ROIs, sum, sum of squares, max count, and number of valid pixels will be calculated.
|
||||
There are 16 ROIs, and the ROI map holds a 16-bit mask per pixel, so a pixel can belong to any subset of them (including none). For each ROI, sum, sum of squares, max count, and number of valid pixels will be calculated.
|
||||
Jungfraujoch also calculates X and Y values weighted by pixel values, though this feature is not properly tested at the moment and not integrated in downstream analysis.
|
||||
|
||||
ROIs are not specific to the FPGA path. The same ROI definitions — box, circle, and azimuthal
|
||||
@@ -79,4 +79,5 @@ Valid pixels are not masked, not saturated, not error pixels.
|
||||
## Square root compression
|
||||
Jungfraujoch FPGA includes lossy compression preserving counting statistic properties of X-ray image, while reducing bit width of an image.
|
||||
Scheme was described in [Wakonig et al., J. Appl. Cryst., 53, 574-586, 2020](https://doi.org/10.1107/S1600576720001776).
|
||||
Pixel value `X` is replaced with `sqrt(N*X)`, where `N` is integer constant in range 1 to 16.
|
||||
Pixel value `X` is replaced with `round(sqrt(N*N*X))`, i.e. `round(N*sqrt(X))`, where `N` is integer constant in range 1 to 16.
|
||||
`N` is what the host writes to the `sqrtmult` register; the FPGA squares it before multiplying the pixel value.
|
||||
|
||||
@@ -106,7 +106,7 @@ struct DataCollectionConfig {
|
||||
uint32_t nframes; // Number of frames for data collection
|
||||
uint32_t nstorage_cells; // Number of storage cells minus one (0 = 1SC, 1 = 2SC, ..., 15 = 16SC)
|
||||
uint32_t nsummation; // Summation of frames minus one (0 = no summation, 1 = 2 frames, 2 = 3 frames, ..., 255 = 256 frames)
|
||||
uint32_t sqrtmult; // Multiplication factor (minus one) of pixel value BEFORE taking square root function - should be square of the coeff used in other work
|
||||
uint32_t sqrtmult; // Coefficient N of the lossy square-root transform, range 1 to 16. The FPGA squares it, so the pixel value becomes round(sqrt(N*N*X)) = round(N*sqrt(X)). Write N here, not N*N.
|
||||
int32_t pxlthreshold_min; // pixels with values lower than threshold are set to zero (after conversion to photons; before summation)
|
||||
int32_t pxlthreshold_max; // pixels with values higher than threshold are set as overload (after conversion to photons; before summation)
|
||||
int32_t data_stream; // number of the data stream (checked against upper 8-bit of UDP destination port)
|
||||
|
||||
Reference in New Issue
Block a user