Files
Jungfraujoch/common/DiffractionGeometry.h
2024-03-14 20:26:03 +01:00

100 lines
4.3 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#ifndef JUNGFRAUJOCH_DIFFRACTIONGEOMETRY_H
#define JUNGFRAUJOCH_DIFFRACTIONGEOMETRY_H
#include "DiffractionExperiment.h"
#include <cmath>
#include "RawToConvertedGeometry.h"
#include "JFJochException.h"
inline Coord DetectorToRecip(const DiffractionExperiment &experiment, float x, float y) {
return experiment.LabCoord(x, y).Normalize() / experiment.GetWavelength_A() - experiment.GetScatteringVector();
}
inline std::pair<float, float> RecipToDector(const DiffractionExperiment &experiment, const Coord &recip) {
auto S = recip + experiment.GetScatteringVector();
float coeff = experiment.GetDetectorDistance_mm() / (S.z * experiment.GetPixelSize_mm());
float x = experiment.GetBeamX_pxl() + S.x * coeff;
float y = experiment.GetBeamY_pxl() + S.y * coeff;
return {x, y};
}
inline float CosTwoTheta(const DiffractionExperiment& experiment, float x, float y) {
auto lab = experiment.LabCoord(x, y);
return experiment.GetDetectorDistance_mm() / lab.Length();
}
inline float Phi(const DiffractionExperiment& experiment, float x, float y) {
auto lab = experiment.LabCoord(x, y);
return atan2f(lab.y, lab.x);
}
inline float PxlToRes(const DiffractionExperiment& experiment, float x, float y) {
float cos_2theta = CosTwoTheta(experiment, x, y);
if (cos_2theta == 1.0f)
return std::numeric_limits<float>::infinity();
// cos(2theta) = cos(theta)^2 - sin(theta)^2
// cos(2theta) = 1 - 2*sin(theta)^2
// Technically two solutions for two theta, but it makes sense only to take positive one in this case
float sin_theta = sqrtf((1 - cos_2theta)/2);
return experiment.GetWavelength_A() / (2 * sin_theta);
}
inline float ResToPxl(const DiffractionExperiment& experiment, float d) {
if (d == 0)
return INFINITY;
float sin_theta = experiment.GetWavelength_A() / (2 * d);
float theta = asinf(sin_theta);
float tan_2theta = tanf(2 * theta);
return tan_2theta * experiment.GetDetectorDistance_mm() / experiment.GetPixelSize_mm();
}
inline float DistFromEwaldSphere(const DiffractionExperiment& experiment, const Coord& recip) {
auto S = recip + experiment.GetScatteringVector();
return fabsf(S.Length() - (1.0f/experiment.GetWavelength_A()));
}
inline float CalcAzIntSolidAngleCorr(const DiffractionExperiment& experiment, float q) {
float sin_theta = q * experiment.GetWavelength_A() / (4 * static_cast<float>(M_PI));
float cos_2theta = 1.0f - 2.0f * sin_theta * sin_theta; // cos(2*alpha) = 1 - 2 * sin(alpha)^2
float cos_2theta_3 = cos_2theta * cos_2theta * cos_2theta;
return cos_2theta_3;
}
inline float CalcAzIntSolidAngleCorr(const DiffractionExperiment& experiment, float x, float y) {
float cos_2theta = CosTwoTheta(experiment, x, y);
float cos_2theta_3 = cos_2theta * cos_2theta * cos_2theta;
return cos_2theta_3;
}
inline float CalcAzIntPolarizationCorr(const DiffractionExperiment& experiment, float x, float y) {
auto cos_2theta = CosTwoTheta(experiment, x, y);
float cos_2theta_2 = cos_2theta * cos_2theta;
float cos_2phi = cosf(2.0f * Phi(experiment, x, y));
return 0.5f * (1.0f + cos_2theta_2 - experiment.GetPolarizationFactor() * cos_2phi * (1.0f - cos_2theta_2));
}
inline void CalcAzIntCorrRawCoord(float *output, const DiffractionExperiment& experiment, size_t module_number) {
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
auto [x,y] = RawToConvertedCoordinate(experiment, module_number, i);
if (experiment.GetApplySolidAngleCorr())
output[i] /= CalcAzIntSolidAngleCorr(experiment, static_cast<float>(x), static_cast<float>(y));
if (experiment.GetApplyPolarizationCorr())
output[i] /= CalcAzIntPolarizationCorr(experiment, static_cast<float>(x), static_cast<float>(y));
}
}
inline void CalcSpotFinderResolutionMap(float *data, const DiffractionExperiment& experiment, size_t module_number) {
if (module_number >= experiment.GetModulesNum())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong module number");
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
auto [x,y] = RawToConvertedCoordinate(experiment, module_number, i);
data[i] = PxlToRes(experiment, static_cast<float>(x), static_cast<float>(y));
}
}
#endif //JUNGFRAUJOCH_DIFFRACTIONGEOMETRY_H