Files
Jungfraujoch/image_analysis/azint/AzIntEngineCPU.h
T
leonarski_f 1d6d50c162 AzIntEngineCPU: Skip masked/saturated pixels
The GPU kernels exclude sentinel pixels (saturated/masked), but the
CPU path summed them blindly, corrupting the azimuthal integration
result and diverging from the GPU output. Skip them on the CPU too,
deriving the sentinels from the pixel type via std::numeric_limits:
the max value (saturated) for any type, plus the min value
(masked/bad) for signed types.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:54:48 +02:00

56 lines
2.0 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <limits>
#include <type_traits>
#include "AzIntEngine.h"
class AzIntEngineCPU : public AzIntEngine {
public:
// image is anything that can be referenced with operator[]
template <class T>
void RunAzint(const T &image, AzimuthalIntegrationProfile &profile) {
for (int i = 0; i < azint_count.size(); i++) {
azint_sum[i] = 0.0f;
azint_sum2[i] = 0.0f;
azint_count[i] = 0;
}
if (image.size() != npixel)
throw std::runtime_error("ImageSpotFinder::AzimIntegration: Mismatch in size");
const uint16_t *pixel_to_bin = integration.GetPixelToBin().data();
const float *corrections = integration.Corrections().data();
using pixel_t = std::remove_cv_t<std::remove_reference_t<decltype(image[0])>>;
for (int i = 0; i < image.size(); i++) {
const pixel_t v = image[i];
// saturated pixels use the type's max value; for signed types
// masked/bad pixels additionally use the min value
if (v == std::numeric_limits<pixel_t>::max())
continue;
if constexpr (std::is_signed_v<pixel_t>) {
if (v == std::numeric_limits<pixel_t>::min())
continue;
}
const float val = static_cast<float>(v) * corrections[i];
const float val_sq = val * val;
const uint16_t bin = pixel_to_bin[i];
if (bin < azint_bins) {
azint_sum[bin] += val;
azint_sum2[bin] += val_sq;
++azint_count[bin];
}
}
profile.Clear(integration);
profile.Add(azint_sum, azint_sum2, azint_count);
}
AzIntEngineCPU(const AzimuthalIntegrationMapping& integration);
void Run(const ImagePreprocessorBuffer &image, AzimuthalIntegrationProfile &profile) override;
};