v1.0.0-rc.41
This commit is contained in:
@@ -7,10 +7,14 @@
|
||||
#include "RawToConvertedGeometry.h"
|
||||
|
||||
Coord DiffractionGeometry::LabCoord(float x, float y) const {
|
||||
// Assumes planar detector, 90 deg towards beam
|
||||
return {(x - beam_x_pxl) * pixel_size_mm ,
|
||||
(y - beam_y_pxl) * pixel_size_mm ,
|
||||
det_distance_mm};
|
||||
Coord detectorCoord = {(x - beam_x_pxl) * pixel_size_mm ,
|
||||
(y - beam_y_pxl) * pixel_size_mm ,
|
||||
det_distance_mm};
|
||||
return poni_rot * detectorCoord;
|
||||
}
|
||||
|
||||
std::pair<float, float> DiffractionGeometry::GetDirectBeam_pxl() const {
|
||||
return RecipToDector({0,0,0});
|
||||
}
|
||||
|
||||
Coord DiffractionGeometry::GetScatteringVector() const {
|
||||
@@ -22,36 +26,37 @@ Coord DiffractionGeometry::DetectorToRecip(float x, float y) const {
|
||||
}
|
||||
|
||||
std::pair<float, float> DiffractionGeometry::RecipToDector(const Coord &recip) const {
|
||||
auto S = recip + GetScatteringVector();
|
||||
auto S_unrotated = recip + GetScatteringVector();
|
||||
auto S = poni_rot.transpose() * S_unrotated;
|
||||
|
||||
float coeff = det_distance_mm / (S.z * pixel_size_mm);
|
||||
float x = beam_x_pxl + S.x * coeff;
|
||||
float y = beam_y_pxl + S.y * coeff;
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
float DiffractionGeometry::CosTwoTheta(float x, float y) const {
|
||||
float DiffractionGeometry::TwoTheta(float x, float y) const {
|
||||
auto lab = LabCoord(x, y);
|
||||
return det_distance_mm / lab.Length();
|
||||
|
||||
float r = sqrtf(lab.x * lab.x + lab.y * lab.y);
|
||||
return atan2f(r, lab.z);
|
||||
}
|
||||
|
||||
float DiffractionGeometry::Phi(float x, float y) const {
|
||||
auto lab = LabCoord(x, y);
|
||||
return atan2f(lab.y, lab.x);
|
||||
auto v = atan2f(-lab.y, lab.x);
|
||||
if (v < 0)
|
||||
v += 2.0f * M_PI;
|
||||
return v;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::PxlToRes(float x, float y) const {
|
||||
float cos_2theta = CosTwoTheta( 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 wavelength_A / (2 * sin_theta);
|
||||
float two_theta = TwoTheta(x, y);
|
||||
return wavelength_A / (2.0f * sinf(two_theta/2.0f));
|
||||
}
|
||||
|
||||
float DiffractionGeometry::PxlToRes(float dist_pxl) const {
|
||||
// This is agnostic to detector rotation!!!
|
||||
if (dist_pxl == 0)
|
||||
return INFINITY;
|
||||
float tan_2theta = dist_pxl * pixel_size_mm / det_distance_mm;
|
||||
@@ -83,13 +88,13 @@ float DiffractionGeometry::CalcAzIntSolidAngleCorr(float q) const {
|
||||
}
|
||||
|
||||
float DiffractionGeometry::CalcAzIntSolidAngleCorr(float x, float y) const {
|
||||
float cos_2theta = CosTwoTheta(x, y);
|
||||
float cos_2theta = cosf(TwoTheta(x, y));
|
||||
float cos_2theta_3 = cos_2theta * cos_2theta * cos_2theta;
|
||||
return cos_2theta_3;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::CalcAzIntPolarizationCorr(float x, float y, float coeff) const {
|
||||
auto cos_2theta = CosTwoTheta(x, y);
|
||||
auto cos_2theta = cosf(TwoTheta(x, y));
|
||||
float cos_2theta_2 = cos_2theta * cos_2theta;
|
||||
float cos_2phi = cosf(2.0f * Phi(x, y));
|
||||
return 0.5f * (1.0f + cos_2theta_2 - coeff * cos_2phi * (1.0f - cos_2theta_2));
|
||||
@@ -145,3 +150,63 @@ DiffractionGeometry &DiffractionGeometry::Wavelength_A(float input) {
|
||||
wavelength_A = input;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::AngleFromEwaldSphere(const Coord &p0) const {
|
||||
// https://journals.iucr.org/d/issues/2014/08/00/dz5332/index.html
|
||||
Coord S0 = GetScatteringVector();
|
||||
|
||||
const float epsilon = 1e-5f;
|
||||
|
||||
float S0_sq = S0 * S0;
|
||||
float p0_sq = p0 * p0;
|
||||
float S0_p0 = S0 * p0;
|
||||
|
||||
float val = S0_sq * p0_sq - S0_p0 * S0_p0;
|
||||
|
||||
if (fabsf(val) < epsilon)
|
||||
return NAN;
|
||||
|
||||
float A = std::sqrt((S0_sq - 1.0f/4.0f * p0_sq) * p0_sq / val);
|
||||
float B = (A * S0_p0 + p0_sq / 2.0f) / S0_sq;
|
||||
|
||||
Coord p_star = A * p0 - B * S0;
|
||||
|
||||
return angle_deg(p_star, p0);
|
||||
}
|
||||
|
||||
void DiffractionGeometry::UpdatePoniRotMatrix() {
|
||||
poni_rot = RotMatrix(-poni_rot_1, {0,1,0})
|
||||
* RotMatrix(poni_rot_2, {1,0,0})
|
||||
* RotMatrix(poni_rot_3, {0,0,1});
|
||||
}
|
||||
|
||||
DiffractionGeometry &DiffractionGeometry::PoniRot1_rad(float input) {
|
||||
poni_rot_1 = input;
|
||||
UpdatePoniRotMatrix();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiffractionGeometry &DiffractionGeometry::PoniRot2_rad(float input) {
|
||||
poni_rot_2 = input;
|
||||
UpdatePoniRotMatrix();
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiffractionGeometry &DiffractionGeometry::PoniRot3_rad(float input) {
|
||||
poni_rot_3 = input;
|
||||
UpdatePoniRotMatrix();
|
||||
return *this;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::GetPoniRot1_rad() const {
|
||||
return poni_rot_1;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::GetPoniRot2_rad() const {
|
||||
return poni_rot_2;
|
||||
}
|
||||
|
||||
float DiffractionGeometry::GetPoniRot3_rad() const {
|
||||
return poni_rot_3;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user