Newer
Older
continue; // Assume zero contribution if difference is small
// Average between two intersections for final position
std::transform(curIntSec.data(), curIntSec.data() + vmdDims - offset,
prevIntSec.data(), pos.begin(),
[](const double rhs, const double lhs) {
return static_cast<coord_t>(0.5 * (rhs + lhs));
});
// index of the current intersection
size_t k = static_cast<size_t>(std::distance(intersectionsBegin, it));
// signal = integral between two consecutive intersections
signal = (yValues[k] - yValues[k - 1]) * solid;
// transform kf to energy transfer
pos[3] = static_cast<coord_t>(m_Ei - pos[3] * pos[3] / energyToK);
// signal = energy distance between two consecutive intersections *solid
// angle *PC
}
m_transformation.multiplyPoint(pos, posNew);
size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data());
if (linIndex == size_t(-1))
continue;
Mantid::Kernel::AtomicOp(signalArray[linIndex], signal,
std::plus<signal_t>());
}
prog->report();
PARALLEL_END_INTERUPT_REGION
}
PARALLEL_CHECK_INTERUPT_REGION
if (m_accumulate) {
std::transform(
signalArray.cbegin(), signalArray.cend(), m_normWS->getSignalArray(),
m_normWS->getSignalArray(),
[](const std::atomic<signal_t> &a, const signal_t &b) { return a + b; });
} else {
std::copy(signalArray.cbegin(), signalArray.cend(),
m_normWS->getSignalArray());
}
/**
* Calculate the points of intersection for the given detector with cuboid
* surrounding the detector position in HKL
* @param intersections A list of intersections in HKL space
* @param theta Polar angle withd detector
* @param phi Azimuthal angle with detector
* @param transform Matrix to convert frm Q_lab to HKL (2Pi*R *UB*W*SO)^{-1}
* @param lowvalue The lowest momentum or energy transfer for the trajectory
* @param highvalue The highest momentum or energy transfer for the trajectory
*/
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
void MDNormalization::calculateIntersections(
std::vector<std::array<double, 4>> &intersections, const double theta,
const double phi, Kernel::DblMatrix transform, double lowvalue,
double highvalue) {
V3D qout(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)),
qin(0., 0., 1);
qout = transform * qout;
qin = transform * qin;
if (convention == "Crystallography") {
qout *= -1;
qin *= -1;
}
double kfmin, kfmax, kimin, kimax;
if (m_diffraction) {
kimin = lowvalue;
kimax = highvalue;
kfmin = kimin;
kfmax = kimax;
} else {
kimin = std::sqrt(energyToK * m_Ei);
kimax = kimin;
kfmin = std::sqrt(energyToK * (m_Ei - highvalue));
kfmax = std::sqrt(energyToK * (m_Ei - lowvalue));
}
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
double hStart = qin.X() * kimin - qout.X() * kfmin,
hEnd = qin.X() * kimax - qout.X() * kfmax;
double kStart = qin.Y() * kimin - qout.Y() * kfmin,
kEnd = qin.Y() * kimax - qout.Y() * kfmax;
double lStart = qin.Z() * kimin - qout.Z() * kfmin,
lEnd = qin.Z() * kimax - qout.Z() * kfmax;
double eps = 1e-10;
auto hNBins = m_hX.size();
auto kNBins = m_kX.size();
auto lNBins = m_lX.size();
auto eNBins = m_eX.size();
intersections.clear();
intersections.reserve(hNBins + kNBins + lNBins + eNBins + 2);
// calculate intersections with planes perpendicular to h
if (fabs(hStart - hEnd) > eps) {
double fmom = (kfmax - kfmin) / (hEnd - hStart);
double fk = (kEnd - kStart) / (hEnd - hStart);
double fl = (lEnd - lStart) / (hEnd - hStart);
for (size_t i = 0; i < hNBins; i++) {
double hi = m_hX[i];
if (((hStart - hi) * (hEnd - hi) < 0)) {
// if hi is between hStart and hEnd, then ki and li will be between
// kStart, kEnd and lStart, lEnd and momi will be between kfmin and
// kfmax
double ki = fk * (hi - hStart) + kStart;
double li = fl * (hi - hStart) + lStart;
if ((ki >= m_kX[0]) && (ki <= m_kX[kNBins - 1]) && (li >= m_lX[0]) &&
(li <= m_lX[lNBins - 1])) {
double momi = fmom * (hi - hStart) + kfmin;
intersections.push_back({{hi, ki, li, momi}});
}
// calculate intersections with planes perpendicular to k
if (fabs(kStart - kEnd) > eps) {
double fmom = (kfmax - kfmin) / (kEnd - kStart);
double fh = (hEnd - hStart) / (kEnd - kStart);
double fl = (lEnd - lStart) / (kEnd - kStart);
for (size_t i = 0; i < kNBins; i++) {
double ki = m_kX[i];
if (((kStart - ki) * (kEnd - ki) < 0)) {
// if ki is between kStart and kEnd, then hi and li will be between
// hStart, hEnd and lStart, lEnd and momi will be between kfmin and
// kfmax
double hi = fh * (ki - kStart) + hStart;
double li = fl * (ki - kStart) + lStart;
if ((hi >= m_hX[0]) && (hi <= m_hX[hNBins - 1]) && (li >= m_lX[0]) &&
(li <= m_lX[lNBins - 1])) {
double momi = fmom * (ki - kStart) + kfmin;
intersections.push_back({{hi, ki, li, momi}});
// calculate intersections with planes perpendicular to l
if (fabs(lStart - lEnd) > eps) {
double fmom = (kfmax - kfmin) / (lEnd - lStart);
double fh = (hEnd - hStart) / (lEnd - lStart);
double fk = (kEnd - kStart) / (lEnd - lStart);
for (size_t i = 0; i < lNBins; i++) {
double li = m_lX[i];
if (((lStart - li) * (lEnd - li) < 0)) {
double hi = fh * (li - lStart) + hStart;
double ki = fk * (li - lStart) + kStart;
if ((hi >= m_hX[0]) && (hi <= m_hX[hNBins - 1]) && (ki >= m_kX[0]) &&
(ki <= m_kX[kNBins - 1])) {
double momi = fmom * (li - lStart) + kfmin;
intersections.push_back({{hi, ki, li, momi}});
}
// intersections with dE
if (!m_dEIntegrated) {
for (size_t i = 0; i < eNBins; i++) {
double kfi = m_eX[i];
if ((kfi - kfmin) * (kfi - kfmax) <= 0) {
double h = qin.X() - qout.X() * kfi;
double k = qin.Y() - qout.Y() * kfi;
double l = qin.Z() - qout.Z() * kfi;
if ((h >= m_hX[0]) && (h <= m_hX[hNBins - 1]) && (k >= m_kX[0]) &&
(k <= m_kX[kNBins - 1]) && (l >= m_lX[0]) &&
(l <= m_lX[lNBins - 1])) {
intersections.push_back({{h, k, l, kfi}});
// endpoints
if ((hStart >= m_hX[0]) && (hStart <= m_hX[hNBins - 1]) &&
(kStart >= m_kX[0]) && (kStart <= m_kX[kNBins - 1]) &&
(lStart >= m_lX[0]) && (lStart <= m_lX[lNBins - 1])) {
intersections.push_back({{hStart, kStart, lStart, kfmin}});
}
if ((hEnd >= m_hX[0]) && (hEnd <= m_hX[hNBins - 1]) && (kEnd >= m_kX[0]) &&
(kEnd <= m_kX[kNBins - 1]) && (lEnd >= m_lX[0]) &&
(lEnd <= m_lX[lNBins - 1])) {
intersections.push_back({{hEnd, kEnd, lEnd, kfmax}});
}
// sort intersections by final momentum
std::stable_sort(intersections.begin(), intersections.end(), compareMomentum);
/**
* Linearly interpolate between the points in integrFlux at xValues and save the
* results in yValues.
* @param xValues :: X-values at which to interpolate
* @param integrFlux :: A workspace with the spectra to interpolate
* @param sp :: A workspace index for a spectrum in integrFlux to interpolate.
* @param yValues :: A vector to save the results.
*/
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
void MDNormalization::calcIntegralsForIntersections(
const std::vector<double> &xValues, const API::MatrixWorkspace &integrFlux,
size_t sp, std::vector<double> &yValues) {
assert(xValues.size() == yValues.size());
// the x-data from the workspace
const auto &xData = integrFlux.x(sp);
const double xStart = xData.front();
const double xEnd = xData.back();
// the values in integrFlux are expected to be integrals of a non-negative
// function
// ie they must make a non-decreasing function
const auto &yData = integrFlux.y(sp);
size_t spSize = yData.size();
const double yMin = 0.0;
const double yMax = yData.back();
size_t nData = xValues.size();
// all integrals below xStart must be 0
if (xValues[nData - 1] < xStart) {
std::fill(yValues.begin(), yValues.end(), yMin);
return;
}
// all integrals above xEnd must be equal tp yMax
if (xValues[0] > xEnd) {
std::fill(yValues.begin(), yValues.end(), yMax);
return;
}
size_t i = 0;
// integrals below xStart must be 0
while (i < nData - 1 && xValues[i] < xStart) {
yValues[i] = yMin;
i++;
}
size_t j = 0;
for (; i < nData; i++) {
// integrals above xEnd must be equal tp yMax
if (j >= spSize - 1) {
yValues[i] = yMax;
} else {
double xi = xValues[i];
while (j < spSize - 1 && xi > xData[j])
j++;
// if x falls onto an interpolation point return the corresponding y
if (xi == xData[j]) {
yValues[i] = yData[j];
} else if (j == spSize - 1) {
// if we get above xEnd it's yMax
} else if (j > 0) {
// interpolate between the consecutive points
double x0 = xData[j - 1];
double x1 = xData[j];
double y0 = yData[j - 1];
double y1 = yData[j];
yValues[i] = y0 + (y1 - y0) * (xi - x0) / (x1 - x0);
} else // j == 0
{
yValues[i] = yMin;
} // namespace MDAlgorithms
} // namespace Mantid