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// register the class, whith conversion factory under Q3D name
13DECLARE_MD_TRANSFID(MDTransfQ3D, Q3D)
14
15
17unsigned int MDTransfQ3D::getNMatrixDimensions(Kernel::DeltaEMode::Type mode,
18 API::MatrixWorkspace_const_sptr inWS) const {
19 UNUSED_ARG(inWS);
20 switch (mode) {
22 return 4;
24 return 4;
26 return 3;
27 default:
28 throw(std::invalid_argument("Unknow or unsupported energy conversion mode"));
29 }
30}
31
47bool MDTransfQ3D::calcMatrixCoord(const double &deltaEOrK0, std::vector<coord_t> &Coord, double &s, double &err) const {
49 return calcMatrixCoord3DElastic(deltaEOrK0, Coord, s, err);
50 } else {
51 return calcMatrixCoord3DInelastic(deltaEOrK0, Coord);
52 }
53}
54
69bool MDTransfQ3D::calcMatrixCoord3DInelastic(const double &deltaE, std::vector<coord_t> &Coord) const {
70 Coord[3] = static_cast<coord_t>(deltaE);
71 if (Coord[3] < m_DimMin[3] || Coord[3] >= m_DimMax[3])
72 return false;
73
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 Coord[0] = static_cast<coord_t>(m_RotMat[0] * qx + m_RotMat[1] * qy + m_RotMat[2] * qz);
95
96 if (Coord[0] < m_DimMin[0] || Coord[0] >= m_DimMax[0])
97 return false;
98 Coord[1] = static_cast<coord_t>(m_RotMat[3] * qx + m_RotMat[4] * qy + m_RotMat[5] * qz);
99 if (Coord[1] < m_DimMin[1] || Coord[1] >= m_DimMax[1])
100 return false;
101 Coord[2] = static_cast<coord_t>(m_RotMat[6] * qx + m_RotMat[7] * qy + m_RotMat[8] * qz);
102 if (Coord[2] < m_DimMin[2] || Coord[2] >= m_DimMax[2])
103 return false;
104
105 if (std::sqrt(Coord[0] * Coord[0] + Coord[1] * Coord[1] + Coord[2] * Coord[2]) < m_AbsMin)
106 return false;
107
108 return true;
109}
110
127bool MDTransfQ3D::calcMatrixCoord3DElastic(const double &k0, std::vector<coord_t> &Coord, double &signal,
128 double &errSq) const {
129
130 double qx = -m_ex * k0;
131 double qy = -m_ey * k0;
132 double qz = (1 - m_ez) * k0;
133 if (convention == "Crystallography") {
134 qx = -qx;
135 qy = -qy;
136 qz = -qz;
137 }
138
139 // Dimension limits have to be converted to coord_t, otherwise floating point
140 // error will cause valid events to be discarded.
141 Coord[0] = static_cast<coord_t>(m_RotMat[0] * qx + m_RotMat[1] * qy + m_RotMat[2] * qz);
142 if (Coord[0] < static_cast<coord_t>(m_DimMin[0]) || Coord[0] >= static_cast<coord_t>(m_DimMax[0]))
143 return false;
144
145 Coord[1] = static_cast<coord_t>(m_RotMat[3] * qx + m_RotMat[4] * qy + m_RotMat[5] * qz);
146 if (Coord[1] < static_cast<coord_t>(m_DimMin[1]) || Coord[1] >= static_cast<coord_t>(m_DimMax[1]))
147 return false;
148
149 Coord[2] = static_cast<coord_t>(m_RotMat[6] * qx + m_RotMat[7] * qy + m_RotMat[8] * qz);
150 if (Coord[2] < static_cast<coord_t>(m_DimMin[2]) || Coord[2] >= static_cast<coord_t>(m_DimMax[2]))
151 return false;
152
153 if (std::sqrt(Coord[0] * Coord[0] + Coord[1] * Coord[1] + Coord[2] * Coord[2]) < m_AbsMin)
154 return false;
155
156 /*Apply Lorentz corrections if necessary */
158 double kdash = k0 / (2 * M_PI);
159 double correct = m_SinThetaSq * kdash * kdash * kdash * kdash;
160 signal *= correct;
161 errSq *= (correct * correct);
162 }
163
164 return true;
165}
166
167std::vector<double> MDTransfQ3D::getExtremumPoints(const double xMin, const double xMax, size_t det_num) const {
168 UNUSED_ARG(det_num);
169
170 std::vector<double> rez(2);
171 rez[0] = xMin;
172 rez[1] = xMax;
173
174 return rez;
175}
176
185bool MDTransfQ3D::calcYDepCoordinates(std::vector<coord_t> &Coord, size_t i) {
186 UNUSED_ARG(Coord);
187 m_ex = (m_DetDirecton + i)->X();
188 m_ey = (m_DetDirecton + i)->Y();
189 m_ez = (m_DetDirecton + i)->Z();
190 // if Lorentz-corrected, retrieve the sin(Theta)^2 for the detector;
193 // if input energy changes on each detector (efixed, indirect mode only), then
194 // set up its value
195 if (m_pEfixedArray) {
196 m_eFixed = double(*(m_pEfixedArray + i));
198 }
199 // if masks are defined and detector masked -- no further calculations
200 if (m_pDetMasks) {
201 if (*(m_pDetMasks + i) > 0)
202 return false;
203 }
204
205 return true;
206}
207
211 m_pEfixedArray = nullptr;
212 m_pDetMasks = nullptr;
213 convention = Kernel::ConfigService::Instance().getString("Q.convention");
214 //********** Generic part of initialization, common for elastic and inelastic
215 // modes:
216 // get transformation matrix (needed for CrystalAsPoder mode)
217 m_RotMat = ConvParams.getTransfMatrix();
218
219 if (!ConvParams.m_PreprDetTable)
220 throw(std::runtime_error("The detectors have not been preprocessed but "
221 "they have to before running initialize"));
222 // get pointer to the positions of the preprocessed detectors
223 std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections");
224 m_DetDirecton = &DetDir[0]; //
225
226 // get min and max values defined by the algorithm.
227 ConvParams.getMinMax(m_DimMin, m_DimMax);
228 // get additional coordinates which are
229 m_AddDimCoordinates = ConvParams.getAddCoord();
230
231 //************ specific part of the initialization, dependent on emode:
232 m_Emode = ConvParams.getEMode();
235 // energy needed in inelastic case
236 m_eFixed = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>("Ei");
237 // the wave vector of incident neutrons;
239
240 m_pEfixedArray = nullptr;
241 if (m_Emode == static_cast<int>(Kernel::DeltaEMode::Indirect))
242 m_pEfixedArray = ConvParams.m_PreprDetTable->getColDataArray<float>("eFixed");
243 } else {
245 throw(std::runtime_error("MDTransfQ3D::initialize::Unknown or "
246 "unsupported energy conversion mode"));
247 // check if we need to calculate Lorentz corrections and if we do, prepare
248 // values for their precalculation:
251 auto &TwoTheta = ConvParams.m_PreprDetTable->getColVector<double>("TwoTheta");
252 SinThetaSq.resize(TwoTheta.size());
253 for (size_t i = 0; i < TwoTheta.size(); i++) {
254 double sth = sin(0.5 * TwoTheta[i]);
255 SinThetaSq[i] = sth * sth;
256 }
259 throw(std::runtime_error("MDTransfQ3D::initialize::Uninitilized "
260 "Sin(Theta)^2 array for calculating Lorentz "
261 "corrections"));
262 }
263 }
264 // use detectors masks untill signals are masked by 0 instead of NaN
265 m_pDetMasks = ConvParams.m_PreprDetTable->getColDataArray<int>("detMask");
266 m_AbsMin = ConvParams.absMin();
267}
280 UNUSED_ARG(inWS);
281 std::vector<std::string> default_dim_ID;
282 switch (dEmode) {
284 default_dim_ID.resize(3);
285 break;
286 }
289 default_dim_ID.resize(4);
290 default_dim_ID[3] = "DeltaE";
291 break;
292 }
293 default:
294 throw(std::invalid_argument("MDTransfQ3D::getDefaultDimID::Unknown energy conversion mode"));
295 }
296 default_dim_ID[0] = "Q1";
297 default_dim_ID[1] = "Q2";
298 default_dim_ID[2] = "Q3";
299
300 return default_dim_ID;
301}
302
310 UNUSED_ARG(inWS);
311 std::vector<std::string> UnitID = this->getDefaultDimID(dEmode, inWS);
312
313 // TODO: is it really momentum transfer, as MomentumTransfer units are seems
314 // bound to elastic mode only (at least accorting to Units description on
315 // Wiki)?
316 std::string kUnits("MomentumTransfer");
317 if (dEmode == Kernel::DeltaEMode::Elastic)
318 kUnits = "Momentum";
319
320 UnitID[0] = kUnits;
321 UnitID[1] = kUnits;
322 UnitID[2] = kUnits;
323 return UnitID;
324}
325
328 : m_isLorentzCorrected(false), m_SinThetaSqArray(nullptr), SinThetaSq(), m_SinThetaSq(0.), m_AbsMin(0.) {}
329
330} // 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:48
Class for 3D vectors.
Definition V3D.h:34
std::vector< double > m_RotMat
Kernel::V3D const * m_DetDirecton
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 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
bool calcMatrixCoord3DElastic(const double &k0, std::vector< coord_t > &Coord, double &signal, double &errSq) const
how to transform workspace data in elastic case
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
bool calcMatrixCoord3DInelastic(const double &deltaE, std::vector< coord_t > &Coord) const
how to transform workspace data in inelastic case
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.
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