Mantid
Loading...
Searching...
No Matches
MDTransfQ3D.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10
11namespace Mantid::MDAlgorithms {
12
13// register the class, whith conversion factory under Q3D name
14DECLARE_MD_TRANSFID(MDTransfQ3D, Q3D)
15
16
18unsigned int MDTransfQ3D::getNMatrixDimensions(Kernel::DeltaEMode::Type mode,
19 API::MatrixWorkspace_const_sptr inWS) const {
20 UNUSED_ARG(inWS);
21 switch (mode) {
23 return 4;
25 return 4;
27 return 3;
28 default:
29 throw(std::invalid_argument("Unknow or unsupported energy conversion mode"));
30 }
31}
32
48bool MDTransfQ3D::calcMatrixCoord(const double &deltaEOrK0, std::vector<coord_t> &Coord, double &s, double &err) const {
50 return calcMatrixCoord3DElastic(deltaEOrK0, Coord, s, err);
51 } else {
52 return calcMatrixCoord3DInelastic(deltaEOrK0, Coord);
53 }
54}
55
70bool MDTransfQ3D::calcMatrixCoord3DInelastic(const double deltaE, std::vector<coord_t> &Coord) const {
71 Coord[3] = static_cast<coord_t>(deltaE);
72 if (Coord[3] < m_DimMin[3] || Coord[3] >= m_DimMax[3])
73 return false;
74 // x,y,z refer to internal coordinate system where Z is the beam direction
75 double qx{0.0}, qy{0.0}, qz{0.0};
77 const double kFinal = sqrt((m_eFixed - deltaE) / PhysicalConstants::E_mev_toNeutronWavenumberSq);
78 qx = -m_ex * kFinal;
79 qy = -m_ey * kFinal;
80 qz = m_kFixed - m_ez * kFinal;
81 } else {
82 qx = -m_ex * m_kFixed;
83 qy = -m_ey * m_kFixed;
84 const double kInitial = sqrt((m_eFixed + deltaE) / PhysicalConstants::E_mev_toNeutronWavenumberSq);
85 qz = kInitial - m_ez * m_kFixed;
86 }
87
88 if (convention == "Crystallography") {
89 qx = -qx;
90 qy = -qy;
91 qz = -qz;
92 }
93
94 return calcMatrixCoord3D(qx, qy, qz, Coord);
95}
96
113bool MDTransfQ3D::calcMatrixCoord3DElastic(const double k0, std::vector<coord_t> &Coord, double &signal,
114 double &errSq) const {
115
116 double qx = -m_ex * k0;
117 double qy = -m_ey * k0;
118 double qz = (1 - m_ez) * k0;
119 if (convention == "Crystallography") {
120 qx = -qx;
121 qy = -qy;
122 qz = -qz;
123 }
124
125 if (calcMatrixCoord3D(qx, qy, qz, Coord)) {
126 /*Apply Lorentz corrections if necessary */
128 double kdash = k0 / (2 * M_PI);
129 double correct = m_SinThetaSq * kdash * kdash * kdash * kdash;
130 signal *= correct;
131 errSq *= (correct * correct);
132 }
133 return true;
134 }
135 return false;
136}
137
138std::vector<double> MDTransfQ3D::getExtremumPoints(const double xMin, const double xMax, size_t det_num) const {
139 UNUSED_ARG(det_num);
140
141 std::vector<double> rez(2);
142 rez[0] = xMin;
143 rez[1] = xMax;
144
145 return rez;
146}
147
156bool MDTransfQ3D::calcYDepCoordinates(std::vector<coord_t> &Coord, size_t i) {
157 UNUSED_ARG(Coord);
158 m_ex = (m_DetDirecton + i)->X();
159 m_ey = (m_DetDirecton + i)->Y();
160 m_ez = (m_DetDirecton + i)->Z();
161 // if Lorentz-corrected, retrieve the sin(Theta)^2 for the detector;
164 // if input energy changes on each detector (efixed, indirect mode only), then
165 // set up its value
166 if (m_pEfixedArray) {
167 m_eFixed = double(*(m_pEfixedArray + i));
169 }
170 // if masks are defined and detector masked -- no further calculations
171 if (m_pDetMasks) {
172 if (*(m_pDetMasks + i) > 0)
173 return false;
174 }
175
176 return true;
177}
178
182 m_pEfixedArray = nullptr;
183 m_pDetMasks = nullptr;
184 m_invertRot = false;
185 convention = Kernel::ConfigService::Instance().getString("Q.convention");
186 //********** Generic part of initialization, common for elastic and inelastic
187 // modes:
188 // get transformation matrix (needed for CrystalAsPoder mode)
189 m_RotMat = ConvParams.getTransfMatrix();
190
191 if (!ConvParams.m_PreprDetTable)
192 throw(std::runtime_error("The detectors have not been preprocessed but "
193 "they have to before running initialize"));
194 // get pointer to the positions of the preprocessed detectors
195 std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections");
196 m_DetDirecton = &DetDir[0]; //
197
198 // get min and max values defined by the algorithm.
199 ConvParams.getMinMax(m_DimMin, m_DimMax);
200 // get additional coordinates which are
201 m_AddDimCoordinates = ConvParams.getAddCoord();
202
203 //************ specific part of the initialization, dependent on emode:
204 m_Emode = ConvParams.getEMode();
207 // energy needed in inelastic case
208 m_eFixed = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>("Ei");
209 // the wave vector of incident neutrons;
211
212 m_pEfixedArray = nullptr;
213 if (m_Emode == static_cast<int>(Kernel::DeltaEMode::Indirect))
214 m_pEfixedArray = ConvParams.m_PreprDetTable->getColDataArray<float>("eFixed");
215 } else {
217 throw(std::runtime_error("MDTransfQ3D::initialize::Unknown or "
218 "unsupported energy conversion mode"));
219 // check if we need to calculate Lorentz corrections and if we do, prepare
220 // values for their precalculation:
223 auto &TwoTheta = ConvParams.m_PreprDetTable->getColVector<double>("TwoTheta");
224 SinThetaSq.resize(TwoTheta.size());
225 for (size_t i = 0; i < TwoTheta.size(); i++) {
226 double sth = sin(0.5 * TwoTheta[i]);
227 SinThetaSq[i] = sth * sth;
228 }
231 throw(std::runtime_error("MDTransfQ3D::initialize::Uninitilized "
232 "Sin(Theta)^2 array for calculating Lorentz "
233 "corrections"));
234 }
235 }
236 // use detectors masks untill signals are masked by 0 instead of NaN
237 m_pDetMasks = ConvParams.m_PreprDetTable->getColDataArray<int>("detMask");
238 m_AbsMin = ConvParams.absMin();
239}
252 UNUSED_ARG(inWS);
253 std::vector<std::string> default_dim_ID;
254 switch (dEmode) {
256 default_dim_ID.resize(3);
257 break;
258 }
261 default_dim_ID.resize(4);
262 default_dim_ID[3] = "DeltaE";
263 break;
264 }
265 default:
266 throw(std::invalid_argument("MDTransfQ3D::getDefaultDimID::Unknown energy conversion mode"));
267 }
268 default_dim_ID[0] = "Q1";
269 default_dim_ID[1] = "Q2";
270 default_dim_ID[2] = "Q3";
271
272 return default_dim_ID;
273}
274
282 UNUSED_ARG(inWS);
283 std::vector<std::string> UnitID = this->getDefaultDimID(dEmode, inWS);
284
285 // TODO: is it really momentum transfer, as MomentumTransfer units are seems
286 // bound to elastic mode only (at least accorting to Units description on
287 // Wiki)?
288 std::string kUnits("MomentumTransfer");
289 if (dEmode == Kernel::DeltaEMode::Elastic)
290 kUnits = "Momentum";
291
292 UnitID[0] = kUnits;
293 UnitID[1] = kUnits;
294 UnitID[2] = kUnits;
295 return UnitID;
296}
297
298bool MDTransfQ3D::calcMatrixCoord3D(double qx, double qy, double qz, std::vector<coord_t> &Coord) const {
299 std::array<coord_t, 3> coord{};
300 if (m_invertRot) {
301 calcMatrixCoordLinSys(qx, qy, qz, coord);
302 }
303 // Dimension limits have to be converted to coord_t, otherwise floating point
304 // error will cause valid events to be discarded.
305 for (auto i = 0; i < 3; i++) {
306 Coord[i] =
308 ? coord[i]
309 : static_cast<coord_t>(m_RotMat[3 * i + 0] * qx + m_RotMat[3 * i + 1] * qy + m_RotMat[3 * i + 2] * qz);
310 if (Coord[i] < static_cast<coord_t>(m_DimMin[i]) || Coord[i] >= static_cast<coord_t>(m_DimMax[i])) {
311 return false;
312 }
313 }
314
315 if (std::sqrt(Coord[0] * Coord[0] + Coord[1] * Coord[1] + Coord[2] * Coord[2]) < m_AbsMin) {
316 return false;
317 }
318
319 return true;
320}
321
324 : m_isLorentzCorrected(false), m_SinThetaSqArray(nullptr), SinThetaSq(), m_SinThetaSq(0.), m_AbsMin(0.) {}
325
326} // namespace Mantid::MDAlgorithms
#define DECLARE_MD_TRANSFID(classname, regID)
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
Class for 3D vectors.
Definition V3D.h:34
std::vector< double > m_RotMat
Kernel::V3D const * m_DetDirecton
void calcMatrixCoordLinSys(double qx, double qy, double qz, std::array< coord_t, 3 > &Coord) const
std::vector< double > m_DimMin
std::vector< double > m_DimMax
Kernel::DeltaEMode::Type m_Emode
std::vector< coord_t > m_AddDimCoordinates
the vector of the additional coordinates which define additional MD dimensions.
Class responsible for conversion of input workspace data into proper number of output dimensions for ...
Definition MDTransfQ3D.h:28
bool calcMatrixCoord3DElastic(const double k0, std::vector< coord_t > &Coord, double &signal, double &errSq) const
how to transform workspace data in elastic case
bool calcMatrixCoord(const double &deltaEOrK0, std::vector< coord_t > &Coord, double &s, double &err) const override
Calculates 3D transformation of the variable coordinates and (if applicable) signal and error dependi...
std::vector< double > SinThetaSq
Definition MDTransfQ3D.h:71
std::vector< std::string > getDefaultDimID(Kernel::DeltaEMode::Type dEmode, API::MatrixWorkspace_const_sptr inWS=API::MatrixWorkspace_const_sptr()) const override
the default dimID-s in Q3D mode are Q1,Q2,Q3 and dE if necessary
void initialize(const MDWSDescription &ConvParams) override
function initalizes all variables necessary for converting workspace variables into MD variables in M...
std::vector< double > getExtremumPoints(const double xMin, const double xMax, size_t det_num) const override
method returns the vector of input coordinates values where the transformed coordinates reach its ext...
bool calcYDepCoordinates(std::vector< coord_t > &Coord, size_t i) override
Method updates the value of preprocessed detector coordinates in Q-space, used by other functions.
std::vector< std::string > outputUnitID(Kernel::DeltaEMode::Type dEmode, API::MatrixWorkspace_const_sptr inWS=API::MatrixWorkspace_const_sptr()) const override
function returns units ID-s which this transformation prodiuces its ouptut.
bool calcMatrixCoord3DInelastic(const double deltaE, std::vector< coord_t > &Coord) const
how to transform workspace data in inelastic case
bool calcMatrixCoord3D(double qx, double qy, double qz, std::vector< coord_t > &Coord) const
unsigned int getNMatrixDimensions(Kernel::DeltaEMode::Type mode, API::MatrixWorkspace_const_sptr inWS=API::MatrixWorkspace_const_sptr()) const override
return the number of dimensions, calculated by the transformation from the workspace.
helper class describes the properties of target MD workspace, which should be obtained as the result ...
bool isLorentsCorrections() const
check if one needs to perform Lorentz corrections
Kernel::DeltaEMode::Type getEMode() const
std::vector< coord_t > getAddCoord() const
void getMinMax(std::vector< double > &min, std::vector< double > &max) const
get vector of minimal and maximal values from the class
DataObjects::TableWorkspace_const_sptr m_PreprDetTable
std::vector< double > getTransfMatrix() const
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
const std::string Q3D("Q3D")
Only convert to Q-vector.
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
Defines the possible energy transfer modes:
Definition DeltaEMode.h:23
Type
Define the available energy transfer modes It is important to assign enums proper numbers,...
Definition DeltaEMode.h:29