// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include "AzimuthalIntegrationSettings.h" #include "JFJochException.h" #define check_max(param, val, max) if ((val) > (max)) throw JFJochException(JFJochExceptionCategory::InputParameterAboveMax, param) #define check_min(param, val, min) if ((val) < (min)) throw JFJochException(JFJochExceptionCategory::InputParameterBelowMin, param) #define check_finite(param, val) if (!std::isfinite(val)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, param) AzimuthalIntegrationSettings::AzimuthalIntegrationSettings() { UpdateBinCount(); } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::SolidAngleCorrection(bool input) { solid_angle_correction = input; return *this; } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::QRange_recipA(float low, float high) { check_finite("Low Q for azimuthal integration", low); check_finite("High Q for azimuthal integration", high); check_max("High Q for azimuthal integration", high, 10.0); check_min("Low Q for azimuthal integration", low, 0.001); if (high <= low) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "High Q must be higher than low Q"); high_q_recipA = high; low_q_recipA = low; UpdateBinCount(); return *this; } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::QSpacing_recipA(float input) { check_finite("Q spacing for azimuthal integration", input); check_min("Q spacing for azimuthal integration", input, 0.00999); q_spacing = input; UpdateBinCount(); return *this; } bool AzimuthalIntegrationSettings::IsSolidAngleCorrection() const { return solid_angle_correction; } float AzimuthalIntegrationSettings::GetHighQ_recipA() const { return high_q_recipA; } float AzimuthalIntegrationSettings::GetLowQ_recipA() const { return low_q_recipA; } float AzimuthalIntegrationSettings::GetQSpacing_recipA() const { return q_spacing; } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::BkgEstimateQRange_recipA(float low, float high) { check_finite("Low Q for azimuthal integration", low); check_finite("High Q for azimuthal integration", high); check_max("High Q for azimuthal integration", high, 10.0); check_min("Low Q for azimuthal integration", low, 0.001); if (high <= low) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "High Q must be higher than low Q"); bkg_estimate_low_q_recipA = low; bkg_estimate_high_q_recipA = high; return *this; } float AzimuthalIntegrationSettings::GetBkgEstimateLowQ_recipA() const { return bkg_estimate_low_q_recipA; } float AzimuthalIntegrationSettings::GetBkgEstimateHighQ_recipA() const { return bkg_estimate_high_q_recipA; } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::PolarizationCorrection(bool input) { polarization_correction = input; return *this; } bool AzimuthalIntegrationSettings::IsPolarizationCorrection() const { return polarization_correction; } AzimuthalIntegrationSettings &AzimuthalIntegrationSettings::AzimuthalBinCount(int32_t input) { check_min("Azimuthal bin count", input, 1); check_max("Azimuthal bin count", input, 512); azim_bins = input; UpdateBinCount(); return *this; } int32_t AzimuthalIntegrationSettings::GetQBinCount() const { return q_bins; } int32_t AzimuthalIntegrationSettings::GetAzimuthalBinCount() const { return azim_bins; } int32_t AzimuthalIntegrationSettings::GetBinCount() const { return total_bins; } uint16_t AzimuthalIntegrationSettings::QToBin(float q) const { return std::min(GetBinCount() - 1, std::floor(std::max(0.0f, (q - GetLowQ_recipA()) / GetQSpacing_recipA()))); } uint16_t AzimuthalIntegrationSettings::GetBin(float q, float phi_deg) const { if (q < low_q_recipA || q >= high_q_recipA) return UINT16_MAX; if (phi_deg < 0.0 || phi_deg >= 360) return UINT16_MAX; int16_t q_bin = std::floor((q - low_q_recipA) / q_spacing); int16_t phi_bin = std::floor(phi_deg / 360.0f * azim_bins); return q_bin + phi_bin * GetQBinCount(); } void AzimuthalIntegrationSettings::UpdateBinCount() { q_bins = std::ceil((high_q_recipA - low_q_recipA) / q_spacing); total_bins = q_bins * azim_bins; }