// Copyright (2019-2023) Paul Scherrer Institute #include "AzimuthalIntegrationProfile.h" #include "../common/JFJochException.h" inline float sum_to_count(float sum, uint64_t count) { if (count == 0) return 0.0f; else return sum / (static_cast(count)); } AzimuthalIntegrationProfile::AzimuthalIntegrationProfile(const AzimuthalIntegrationMapping &mapping) : bin_to_q(mapping.GetBinToQ()), sum(mapping.GetBinNumber(), 0), count(mapping.GetBinNumber(), 0){} AzimuthalIntegrationProfile::AzimuthalIntegrationProfile(const AzimuthalIntegrationProfile &other) : bin_to_q(other.bin_to_q), sum(other.sum), count(other.count) {} AzimuthalIntegrationProfile::AzimuthalIntegrationProfile(AzimuthalIntegrationProfile &&other) noexcept { bin_to_q = std::move(other.bin_to_q); sum = std::move(other.sum); count = std::move(other.count); } AzimuthalIntegrationProfile &AzimuthalIntegrationProfile::operator=(const AzimuthalIntegrationProfile &other) { bin_to_q = other.bin_to_q; sum = other.sum; count = other.count; return *this; } void AzimuthalIntegrationProfile::Add(const std::vector &in_sum, const std::vector &in_count) { std::unique_lock ul(m); if ((in_sum.size() == sum.size()) && (in_count.size() == count.size())) { for (int i = 0; i < sum.size(); i++) { sum[i] += in_sum[i]; count[i] += in_count[i]; } } else if (!in_sum.empty() && !in_count.empty()) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in size of sum/count datasets"); } std::vector AzimuthalIntegrationProfile::GetResult() const { std::vector rad_int_profile(sum.size(), 0); for (int i = 0; i < sum.size(); i++) rad_int_profile[i] = sum_to_count(sum[i], count[i]); return rad_int_profile; } void AzimuthalIntegrationProfile::SetTitle(const std::string &input) { title = input; } MultiLinePlot AzimuthalIntegrationProfile::GetPlot() const { std::unique_lock ul(m); MultiLinePlot ret(1); ret[0].x = bin_to_q; ret[0].y = GetResult(); ret[0].title = title; return ret; } float AzimuthalIntegrationProfile::GetMeanValueOfBins(uint16_t min_bin, uint16_t max_bin) const { std::unique_lock ul(m); float ret_sum = 0; uint64_t ret_count = 0; for (int i = std::min((uint16_t)sum.size(),min_bin); i <= std::min((uint16_t)(sum.size()-1),max_bin); i++) { ret_sum += sum[i]; ret_count += count[i]; } return sum_to_count(ret_sum, ret_count); } AzimuthalIntegrationProfile &AzimuthalIntegrationProfile::operator+=(const AzimuthalIntegrationProfile &other) { std::unique_lock ul(m); // It is expected that "other" has exclusive access if ((other.bin_to_q != bin_to_q) || (sum.size() != other.sum.size())) { throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Error combining two radial integration profiles"); } for (int i = 0; i < sum.size(); i++) { sum[i] += other.sum[i]; count[i] += other.count[i]; } return *this; } void AzimuthalIntegrationProfile::Add(const DeviceOutput &result) { std::unique_lock ul(m); if (sum.size() > FPGA_INTEGRATION_BIN_COUNT ) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Error in getting result from FPGA"); for (int i = 0; i < sum.size(); i++) { sum[i] += result.integration_result[i].sum; count[i] += result.integration_result[i].count; } }