101 lines
3.8 KiB
C++
101 lines
3.8 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <cmath>
|
|
|
|
#include "AzimuthalIntegrationMapping.h"
|
|
#include "../common/JFJochException.h"
|
|
#include "../common/DiffractionGeometry.h"
|
|
#include "../common/RawToConvertedGeometry.h"
|
|
|
|
AzimuthalIntegrationMapping::AzimuthalIntegrationMapping(const AzimuthalIntegrationSettings &settings) :
|
|
low_q(settings.GetLowQ_recipA()),
|
|
high_q(settings.GetHighQ_recipA()),
|
|
q_spacing(settings.GetQSpacing_recipA()),
|
|
max_bin_number(0) {
|
|
|
|
if (q_spacing < 0.0)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Q-spacing has to be >= 0.0");
|
|
|
|
if (low_q >= high_q)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Low-Q must be smaller than high-Q");
|
|
|
|
if (low_q <= 0)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Low-Q must be > 0");
|
|
|
|
if (std::ceil((high_q-low_q) / q_spacing ) >= UINT16_MAX)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Cannot accommodate more than 65536 rings");
|
|
|
|
}
|
|
|
|
AzimuthalIntegrationMapping::AzimuthalIntegrationMapping(const DiffractionExperiment& experiment)
|
|
: AzimuthalIntegrationMapping(experiment.GetAzimuthalIntegrationSettings())
|
|
{
|
|
pixel_to_bin.resize(experiment.GetModulesNum() * RAW_MODULE_SIZE);
|
|
|
|
DiffractionGeometry geom = experiment.GetDiffractionGeometry();
|
|
|
|
for (int m = 0; m < experiment.GetModulesNum(); m++) {
|
|
for (int pxl = 0; pxl < RAW_MODULE_SIZE; pxl++) {
|
|
auto [x,y] = RawToConvertedCoordinate(experiment, m, pxl);
|
|
float pixel_q = 2 * M_PI / geom.PxlToRes(x, y);
|
|
if ((pixel_q < low_q) || (pixel_q >= high_q))
|
|
pixel_to_bin[m * RAW_MODULE_SIZE + pxl] = UINT16_MAX;
|
|
else
|
|
pixel_to_bin[m * RAW_MODULE_SIZE + pxl] = std::floor((pixel_q - low_q) / q_spacing);
|
|
}
|
|
}
|
|
|
|
Setup();
|
|
}
|
|
|
|
AzimuthalIntegrationMapping::AzimuthalIntegrationMapping(const DiffractionGeometry &geom, int64_t width, int64_t height,
|
|
const AzimuthalIntegrationSettings &settings)
|
|
: AzimuthalIntegrationMapping(settings) {
|
|
pixel_to_bin.resize(width * height);
|
|
for (int row = 0; row < height; row++) {
|
|
for (int col = 0; col < width; col++) {
|
|
float pixel_q = 2 * M_PI / geom.PxlToRes(col, row);
|
|
if ((pixel_q < low_q) || (pixel_q >= high_q))
|
|
pixel_to_bin[row * width + col] = UINT16_MAX;
|
|
else
|
|
pixel_to_bin[row * width + col] = std::floor((pixel_q - low_q) / q_spacing);
|
|
|
|
}
|
|
}
|
|
Setup();
|
|
}
|
|
|
|
void AzimuthalIntegrationMapping::Setup() {
|
|
// In principle max bin number is equal to std::floor((high_q - low_q) / q_spacing), but it might be lower than this
|
|
// depending on detector distance and beam center position
|
|
for (const auto &i: pixel_to_bin) {
|
|
if ((i != UINT16_MAX) && (i > max_bin_number))
|
|
max_bin_number = i;
|
|
}
|
|
|
|
bin_to_q.resize(max_bin_number + 1);
|
|
for (int i = 0; i < max_bin_number + 1; i++)
|
|
bin_to_q[i] = static_cast<float>(q_spacing * (i + 0.5) + low_q);
|
|
}
|
|
|
|
uint16_t AzimuthalIntegrationMapping::GetBinNumber() const {
|
|
return max_bin_number + 1;
|
|
}
|
|
|
|
const std::vector<uint16_t> &AzimuthalIntegrationMapping::GetPixelToBin() const {
|
|
return pixel_to_bin;
|
|
}
|
|
|
|
const std::vector<float> &AzimuthalIntegrationMapping::GetBinToQ() const {
|
|
return bin_to_q;
|
|
}
|
|
|
|
float AzimuthalIntegrationMapping::QToBin(float q) const {
|
|
return std::min(static_cast<float>(max_bin_number), std::max(0.0f, (q - low_q) / q_spacing));
|
|
}
|