Files
Jungfraujoch/common/ModuleSummation.cpp
T
leonarski_f bb9f5c715f
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m55s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m28s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m56s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m47s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m7s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m31s
Build Packages / build:rpm (rocky8) (push) Successful in 12m59s
Build Packages / build:rpm (rocky9) (push) Successful in 14m5s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 15m30s
Build Packages / Generate python client (push) Successful in 1m18s
Build Packages / Build documentation (push) Successful in 1m3s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m8s
Build Packages / XDS test (durin plugin) (push) Successful in 9m16s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m59s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m12s
Build Packages / DIALS test (push) Successful in 11m44s
Build Packages / Unit tests (push) Successful in 1h23m8s
v1.0.0-rc.135 (#44)
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* Multiple small bug fixes scattered across the whole code base. (detected with GPT-5.4)
* jfjoch_viewer: Improve image render performance

Reviewed-on: #44
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-04-16 11:59:59 +02:00

127 lines
4.9 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "ModuleSummation.h"
#include "JFJochException.h"
ModuleSummation::ModuleSummation(bool in_pixel_signed, uint32_t in_fpga_depth_bytes) {
pixel_signed = in_pixel_signed;
first = true;
is_empty = false;
output_depth_bytes = 4;
fpga_depth_bytes = in_fpga_depth_bytes;
if ((fpga_depth_bytes != 4)
&& (fpga_depth_bytes != 2)
&& (fpga_depth_bytes != 1))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "FPGA byte depth can be only 1, 2 or 4");
output = std::make_unique<DeviceOutput>();
memset(output.get(), 0, sizeof(DeviceOutput));
}
ModuleSummation::ModuleSummation(const DiffractionExperiment &experiment) : ModuleSummation(
experiment.IsPixelSigned(), experiment.GetByteDepthFPGA()) {
if (!experiment.IsCPUSummation())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"CPU summation not turned on");
if (experiment.GetByteDepthImage() != 4)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"CPU summation works only for 32-bit output");
}
const DeviceOutput &ModuleSummation::GetOutput() const {
return *output;
}
DeviceOutput &ModuleSummation::GetOutput() {
return *output;
}
template<class Tdst, class Tsrc>
void Add(DeviceOutput &output, const DeviceOutput &input) {
auto in_pixel = reinterpret_cast<const Tsrc *>(input.pixels);
auto out_pixel = reinterpret_cast<Tdst *>(output.pixels);
Tdst err_val_dst = std::is_signed_v<Tdst> ? std::numeric_limits<Tdst>::min() : std::numeric_limits<Tdst>::max();
Tsrc err_val_src = std::is_signed_v<Tsrc> ? std::numeric_limits<Tsrc>::min() : std::numeric_limits<Tsrc>::max();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
if ((in_pixel[i] == err_val_src) || (out_pixel[i] == err_val_dst))
out_pixel[i] = err_val_dst;
else if ((in_pixel[i] == std::numeric_limits<Tsrc>::max())
|| (out_pixel[i] == std::numeric_limits<Tdst>::max())
|| (static_cast<int64_t>(out_pixel[i]) + static_cast<int64_t>(in_pixel[i]) >= std::numeric_limits<
Tdst>::max()))
out_pixel[i] = std::numeric_limits<Tdst>::max();
else
out_pixel[i] = out_pixel[i] + in_pixel[i];
}
}
void ModuleSummation::AddFPGAOutput(const DeviceOutput &input, const std::optional<uint32_t> &in_fpga_depth_bytes) {
std::unique_lock ul(module_summation_mutex);
if (first) {
output->module_statistics = input.module_statistics;
first = false;
} else {
output->module_statistics.err_pixels += input.module_statistics.err_pixels;
output->module_statistics.saturated_pixels += input.module_statistics.saturated_pixels;
output->module_statistics.packet_count += input.module_statistics.packet_count;
}
// The only function not handled is spot finding
switch (in_fpga_depth_bytes.value_or(fpga_depth_bytes)) {
case 2:
if (pixel_signed)
Add<int32_t, int16_t>(*output, input);
else
Add<uint32_t, uint16_t>(*output, input);
break;
case 4:
if (pixel_signed)
Add<int32_t, int32_t>(*output, input);
else
Add<uint32_t, uint32_t>(*output, input);
break;
case 1:
if (pixel_signed)
Add<int32_t, int8_t>(*output, input);
else
Add<uint32_t, uint8_t>(*output, input);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Unknown bit depth");
}
for (int i = 0; i < FPGA_INTEGRATION_BIN_COUNT; i++) {
output->integration_result[i].count += input.integration_result[i].count;
output->integration_result[i].sum += input.integration_result[i].sum;
}
for (int i = 0; i < ADU_HISTO_BIN_COUNT; i++)
output->adu_histogram[i] += input.adu_histogram[i];
for (int i = 0; i < FPGA_ROI_COUNT; i++) {
output->roi_counts[i].sum += input.roi_counts[i].sum;
output->roi_counts[i].sum2 += input.roi_counts[i].sum2;
output->roi_counts[i].good_pixels += input.roi_counts[i].good_pixels;
output->roi_counts[i].sum_x_weighted += input.roi_counts[i].sum_x_weighted;
output->roi_counts[i].sum_y_weighted += input.roi_counts[i].sum_y_weighted;
if (output->roi_counts[i].max_value < input.roi_counts[i].max_value)
output->roi_counts[i].max_value = input.roi_counts[i].max_value;
}
}
void ModuleSummation::AddEmptyOutput() {
std::unique_lock ul(module_summation_mutex);
is_empty = true;
}
bool ModuleSummation::empty() const {
std::unique_lock ul(module_summation_mutex);
return is_empty;
}