// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include "../../common/AzimuthalIntegrationMapping.h" #include "../../common/AzimuthalIntegrationProfile.h" #include "../image_preprocessing/ImagePreprocessorBuffer.h" class AzIntEngine { protected: const AzimuthalIntegrationMapping& integration; const uint16_t azint_bins; const size_t npixel; std::vector azint_sum; std::vector azint_sum2; std::vector azint_count; // Sigma clipping (AzimuthalIntegrationSettings::SigmaClip; 0 = off). Two clip passes follow the // plain one - the same one-plain-plus-two recipe the adaptive spot finder uses, where the second // matters because the first pass's standard deviation is itself inflated by the peaks being // removed, so one pass alone leaves a threshold that is still too generous. static constexpr int CLIP_PASSES = 2; const float clip_nsigma; std::vector clip_lo; std::vector clip_hi; // Per-bin accept range from the accumulators of the pass just finished. A bin with too few pixels // to have a meaningful spread is left unclipped rather than guessed at. void UpdateClipLimits(); [[nodiscard]] int PassCount() const { return clip_nsigma > 0.0f ? 1 + CLIP_PASSES : 1; } public: AzIntEngine(const AzimuthalIntegrationMapping& integration); virtual ~AzIntEngine() = default; virtual void Run(const ImagePreprocessorBuffer &image, AzimuthalIntegrationProfile &profile) = 0; };