Fix offset in ClusterFinding (#269)
All checks were successful
Build on RHEL8 / build (push) Successful in 2m20s
Build on RHEL9 / build (push) Successful in 2m31s
Run tests using data on local RHEL8 / build (push) Successful in 3m17s

Directly casting the values in the cluster finder would truncate the
resulting ADU value and create an offset when summing the cluster.

1. do pedestal subtraction and then round
2. static cast to result type only after rounding
3. if constexpr to avoid unnecessary rounding
This commit is contained in:
2026-01-26 14:10:25 +01:00
committed by GitHub
4 changed files with 26 additions and 8 deletions

View File

@@ -240,9 +240,7 @@ endif()
add_library(aare_compiler_flags INTERFACE) add_library(aare_compiler_flags INTERFACE)
target_compile_features(aare_compiler_flags INTERFACE cxx_std_17) target_compile_features(aare_compiler_flags INTERFACE cxx_std_17)
if(AARE_PYTHON_BINDINGS)
add_subdirectory(python)
endif()
################# #################
# MSVC specific # # MSVC specific #
@@ -308,6 +306,9 @@ target_compile_options(
endif() #GCC/Clang specific endif() #GCC/Clang specific
if(AARE_PYTHON_BINDINGS)
add_subdirectory(python)
endif()
if(AARE_ASAN) if(AARE_ASAN)
message(STATUS "AddressSanitizer enabled") message(STATUS "AddressSanitizer enabled")

View File

@@ -16,6 +16,7 @@
### Bugfixes: ### Bugfixes:
- multi threaded cluster finder doesnt drop frames if queues are full - multi threaded cluster finder doesnt drop frames if queues are full
- Round before casting in the cluster finder to avoid biasing clusters by truncating
### 2025.11.21 ### 2025.11.21

View File

@@ -148,12 +148,27 @@ class ClusterFinder {
for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) { for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) {
if (ix + ic >= 0 && ix + ic < frame.shape(1) && if (ix + ic >= 0 && ix + ic < frame.shape(1) &&
iy + ir >= 0 && iy + ir < frame.shape(0)) { iy + ir >= 0 && iy + ir < frame.shape(0)) {
CT tmp =
static_cast<CT>(frame(iy + ir, ix + ic)) - // If the cluster type is an integral type, and
static_cast<CT>( // the pedestal is a floating point type then we
// need to round the value before storing it
if constexpr (std::is_integral_v<CT> &&
std::is_floating_point_v<
PEDESTAL_TYPE>) {
auto tmp = std::lround(
frame(iy + ir, ix + ic) -
m_pedestal.mean(iy + ir, ix + ic)); m_pedestal.mean(iy + ir, ix + ic));
cluster.data[i] = cluster.data[i] = static_cast<CT>(tmp);
tmp; // Watch for out of bounds access }
// On the other hand if both are floating point
// or both are integral then we can just static
// cast directly
else {
auto tmp =
frame(iy + ir, ix + ic) -
m_pedestal.mean(iy + ir, ix + ic);
cluster.data[i] = static_cast<CT>(tmp);
}
} }
i++; i++;
} }

View File

@@ -28,6 +28,7 @@
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
#include <cstdlib> #include <cstdlib>
#include <cstddef>
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>