1d6d50c162
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>
56 lines
2.0 KiB
C++
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;
|
|
}; |