Mantid
Loading...
Searching...
No Matches
MDTransfModQ.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 +
10namespace Mantid::MDAlgorithms {
11// register the class, whith conversion factory under ModQ name
12// clang-format off
13DECLARE_MD_TRANSFID(MDTransfModQ, |Q|)
14// clang-format on
15
16
23const std::string MDTransfModQ::inputUnitID(Kernel::DeltaEMode::Type dEmode,
24 API::MatrixWorkspace_const_sptr inWS) const {
25 UNUSED_ARG(inWS);
26 switch (dEmode) {
28 return "Momentum";
30 return "DeltaE";
32 return "DeltaE";
33 default:
34 throw(std::invalid_argument(" MDTransfModQ::inputUnitID: this class "
35 "supports only conversion in Elastic and "
36 "Inelastic energy transfer modes"));
37 }
38}
39
48 UNUSED_ARG(inWS);
49 switch (mode) {
51 return 2;
53 return 2;
55 return 1;
56 default:
57 throw(std::invalid_argument("Unknown or unsupported energy conversion mode"));
58 }
59}
60
76bool MDTransfModQ::calcMatrixCoord(const double &deltaEOrK0, std::vector<coord_t> &Coord, double &signal,
77 double &ErrSq) const {
78 UNUSED_ARG(signal);
79 UNUSED_ARG(ErrSq);
81 return calcMatrixCoordElastic(deltaEOrK0, Coord);
82 } else {
83 return calcMatrixCoordInelastic(deltaEOrK0, Coord);
84 }
85}
86
97bool MDTransfModQ::calcGenericVariables(std::vector<coord_t> &Coord, size_t nd) {
98 // sanity check. If fails, something went fundamentally wrong
99 if (m_NMatrixDim + m_AddDimCoordinates.size() != nd) {
100 std::string ERR = "Number of matrix dimensions: " + std::to_string(m_NMatrixDim) +
101 " plus number of additional dimensions: " + std::to_string(m_AddDimCoordinates.size()) +
102 " not equal to number of workspace dimensions: " + std::to_string(nd);
103 throw(std::invalid_argument(ERR));
104 }
105
106 // in Elastic case, 1 coordinate (|Q|) came from workspace
107 // in inelastic 2 coordinates (|Q| dE) came from workspace. All other are
108 // defined by properties.
109 // m_NMatrixDim is either 1 in elastic case or 2 in inelastic
110 size_t ic(0);
111 for (size_t i = m_NMatrixDim; i < nd; i++) {
113 return false;
114 Coord[i] = m_AddDimCoordinates[ic];
115 ic++;
116 }
117 return true;
118}
119
128bool MDTransfModQ::calcYDepCoordinates(std::vector<coord_t> &Coord, size_t i) {
129 UNUSED_ARG(Coord);
130 m_ex = (m_DetDirecton + i)->X();
131 m_ey = (m_DetDirecton + i)->Y();
132 m_ez = (m_DetDirecton + i)->Z();
133 // if input energy changes on each detector (efixed, indirect mode only), then
134 // set up its value
135 if (m_pEfixedArray) {
136 m_eFixed = double(*(m_pEfixedArray + i));
138 }
139 // if spectra masked, this spectra should be excluded
140 if (m_pDetMasks) {
141 if (*(m_pDetMasks + i) > 0)
142 return false;
143 }
144 return true;
145}
146
161bool MDTransfModQ::calcMatrixCoordInelastic(const double &deltaE, std::vector<coord_t> &Coord) const {
162 if (deltaE < m_DimMin[1] || deltaE >= m_DimMax[1])
163 return false;
164 Coord[1] = static_cast<coord_t>(deltaE);
165
166 // x,y,z refer to internal coordinate system where Z is the beam direction
167 double qx{0.0}, qy{0.0}, qz{0.0};
168 if (this->m_Emode == Kernel::DeltaEMode::Direct) {
169 const double kFinal = sqrt((m_eFixed - deltaE) / PhysicalConstants::E_mev_toNeutronWavenumberSq);
170 qx = -m_ex * kFinal;
171 qy = -m_ey * kFinal;
172 qz = m_kFixed - m_ez * kFinal;
173 } else {
174 const double kInitial = sqrt((m_eFixed + deltaE) / PhysicalConstants::E_mev_toNeutronWavenumberSq);
175 qx = -m_ex * m_kFixed;
176 qy = -m_ey * m_kFixed;
177 qz = kInitial - m_ez * m_kFixed;
178 }
179
180 // transformation matrix has to be here for "Crystal AS Powder conversion
181 // mode, further specialization possible if "powder" mode defined"
182 double Qx = (m_RotMat[0] * qx + m_RotMat[1] * qy + m_RotMat[2] * qz);
183 double Qy = (m_RotMat[3] * qx + m_RotMat[4] * qy + m_RotMat[5] * qz);
184 double Qz = (m_RotMat[6] * qx + m_RotMat[7] * qy + m_RotMat[8] * qz);
185
186 double Qsq = Qx * Qx + Qy * Qy + Qz * Qz;
187 if (Qsq < m_DimMin[0] || Qsq >= m_DimMax[0])
188 return false;
189 Coord[0] = static_cast<coord_t>(sqrt(Qsq));
190
191 return true;
192}
207bool MDTransfModQ::calcMatrixCoordElastic(const double &k0, std::vector<coord_t> &Coord) const {
208
209 double qx = -m_ex * k0;
210 double qy = -m_ey * k0;
211 double qz = (1 - m_ez) * k0;
212 // transformation matrix has to be here for "Crystal AS Powder mode, further
213 // specialization possible if powder mode is defined "
214 double Qx = (m_RotMat[0] * qx + m_RotMat[1] * qy + m_RotMat[2] * qz);
215 double Qy = (m_RotMat[3] * qx + m_RotMat[4] * qy + m_RotMat[5] * qz);
216 double Qz = (m_RotMat[6] * qx + m_RotMat[7] * qy + m_RotMat[8] * qz);
217
218 double Qsq = Qx * Qx + Qy * Qy + Qz * Qz;
219 if (Qsq < m_DimMin[0] || Qsq >= m_DimMax[0])
220 return false;
221 Coord[0] = static_cast<coord_t>(sqrt(Qsq));
222 return true;
223}
234std::vector<double> MDTransfModQ::getExtremumPoints(const double eMin, const double eMax, size_t det_num) const {
235 std::vector<double> rez(2);
236 switch (m_Emode) {
238 rez[0] = eMin;
239 rez[1] = eMax;
240 return rez;
241 }
244 double ei = m_eFixed;
245 if (m_pEfixedArray)
246 ei = double(*(m_pEfixedArray + det_num));
247
248 double ez = (m_DetDirecton + det_num)->Z();
249 double eps_extr = ei * (1 - ez * ez);
250 if (eps_extr > eMin && eps_extr < eMax) {
251 rez.resize(3);
252 rez[0] = eMin;
253 rez[1] = eps_extr;
254 rez[2] = eMax;
255 } else {
256 rez[0] = eMin;
257 rez[1] = eMax;
258 }
259 return rez;
260 }
261 default: {
262 throw std::invalid_argument("Undefined or unsupported energy conversion mode ");
263 }
264 }
265 return rez;
266}
267
271 //********** Generic part of initialization, common for elastic and inelastic
272 // modes:
273 // get transformation matrix (needed for CrystalAsPoder mode)
274 m_RotMat = ConvParams.getTransfMatrix();
275 m_pEfixedArray = nullptr;
276 if (!ConvParams.m_PreprDetTable)
277 throw(std::runtime_error("The detectors have not been preprocessed but "
278 "they have to before running initialize"));
279
280 // get pointer to the positions of the detectors
281 std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections");
282 m_DetDirecton = &DetDir[0]; //
283
284 // get min and max values defined by the algorithm.
285 ConvParams.getMinMax(m_DimMin, m_DimMax);
286 // m_DimMin/max here are momentums and they are verified on momentum squared
287 // base
288 if (m_DimMin[0] < 0)
289 m_DimMin[0] = 0;
290 if (m_DimMax[0] < 0)
291 m_DimMax[0] = 0;
292
293 // m_DimMin here is a momentum and it is verified on momentum squared base
294 m_DimMin[0] *= m_DimMin[0];
295 m_DimMax[0] *= m_DimMax[0];
296 if (std::fabs(m_DimMin[0] - m_DimMax[0]) < FLT_EPSILON || m_DimMax[0] < m_DimMin[0]) {
297 std::string ERR =
298 "ModQ coordinate transformation: Min Q^2 value: " + boost::lexical_cast<std::string>(m_DimMin[0]) +
299 " is more or equal then Max Q^2 value: " + boost::lexical_cast<std::string>(m_DimMax[0]);
300 throw(std::invalid_argument(ERR));
301 }
302 m_AddDimCoordinates = ConvParams.getAddCoord();
303
304 //************ specific part of the initialization, dependent on emode:
305 m_Emode = ConvParams.getEMode();
308 // energy needed in inelastic case
309 volatile auto Ei = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>("Ei");
310 m_eFixed = Ei;
311 if (Ei != m_eFixed) // Ei is NaN, try Efixed, but the value should be
312 // overridden later
313 {
314 try {
315 m_eFixed = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>("eFixed");
316 } catch (...) {
317 }
318 }
319
320 // the wave vector of incident neutrons;
322 m_pEfixedArray = nullptr;
323 if (m_Emode == static_cast<int>(Kernel::DeltaEMode::Indirect))
324 m_pEfixedArray = ConvParams.m_PreprDetTable->getColDataArray<float>("eFixed");
326 throw(std::invalid_argument("MDTransfModQ::initialize::Unknown energy conversion mode"));
327
328 m_pDetMasks = ConvParams.m_PreprDetTable->getColDataArray<int>("detMask");
329}
343 UNUSED_ARG(inWS);
344 std::vector<std::string> default_dim_ID;
345 switch (dEmode) {
347 default_dim_ID.resize(1);
348 break;
349 }
352 default_dim_ID.resize(2);
353 default_dim_ID[1] = "DeltaE";
354 break;
355 }
356 default:
357 throw(std::invalid_argument("MDTransfModQ::getDefaultDimID::Unknown energy conversion mode"));
358 }
359 default_dim_ID[0] = "|Q|";
360
361 return default_dim_ID;
362}
363
371 UNUSED_ARG(inWS);
372 std::vector<std::string> UnitID = this->getDefaultDimID(dEmode, inWS);
373 // TODO: is it really momentum transfer, as MomentumTransfer units are seems
374 // bound to elastic mode only (at least accorting to Units description on
375 // Wiki)?
376 if (dEmode == Kernel::DeltaEMode::Elastic) {
377 UnitID[0] = "Momentum";
378 } else {
379 UnitID[0] = "MomentumTransfer";
380 }
381 return UnitID;
382}
383
386 : m_ex(0), m_ey(0), m_ez(1), m_DetDirecton(nullptr), //,m_NMatrixDim(-1)
387 m_NMatrixDim(0), // uninitialized
388 m_Emode(Kernel::DeltaEMode::Undefined), // uninitialized
389 m_kFixed(1.), m_eFixed(1.), m_pEfixedArray(nullptr), m_pDetMasks(nullptr) {}
390
391std::vector<std::string> MDTransfModQ::getEmodes() const { return Kernel::DeltaEMode::availableTypes(); }
392
399 Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const {
401 auto isQ = true;
402 setter(mdWorkspace, underlyingWorkspace, isQ, m_Emode);
403}
404
405} // 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:64
Class for 3D vectors.
Definition: V3D.h:34
DisplayNormalizationSetter: Sets the displaynormalization on a workspace based on several parameters ...
Class responsible for conversion of input workspace data into proper number of output dimensions for ...
Definition: MDTransfModQ.h:30
void setDisplayNormalization(Mantid::API::IMDWorkspace_sptr mdWorkspace, Mantid::API::MatrixWorkspace_sptr underlyingWorkspace) const override
Set the display normalization for Q.
bool calcGenericVariables(std::vector< coord_t > &Coord, size_t nd) override
Method fills-in all additional properties requested by user and not defined by matrix workspace itsel...
std::vector< double > m_RotMat
Definition: MDTransfModQ.h:84
Kernel::V3D const * m_DetDirecton
Definition: MDTransfModQ.h:89
bool calcMatrixCoord(const double &deltaEOrK0, std::vector< coord_t > &Coord, double &signal, double &ErrSq) const override
Convert single point of matrix workspace into reciprocal space and (optionally) modify signal and err...
std::vector< double > m_DimMin
Definition: MDTransfModQ.h:86
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.
std::vector< double > m_DimMax
Definition: MDTransfModQ.h:86
Kernel::DeltaEMode::Type m_Emode
Definition: MDTransfModQ.h:95
bool calcMatrixCoordElastic(const double &k0, std::vector< coord_t > &Coord) const
how to transform workspace data in elastic case
std::vector< std::string > getEmodes() const override
energy conversion modes supported by this class; The class supports three standard energy conversion ...
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.
std::vector< coord_t > m_AddDimCoordinates
the vector of the additional coordinates which define additional MD dimensions.
Definition: MDTransfModQ.h:100
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 ModQ mode are |Q| and dE if necessary
void initialize(const MDWSDescription &ConvParams) override
function initializes all variables necessary for converting workspace variables into MD variables in ...
std::vector< double > getExtremumPoints(const double eMin, const double eMax, size_t det_num) const override
method returns the vector of input coordinates values where the transformed coordinates reach its ext...
bool calcMatrixCoordInelastic(const double &deltaE, std::vector< coord_t > &Coord) const
how to transform workspace data in inelastic case
bool calcYDepCoordinates(std::vector< coord_t > &Coord, size_t i) override
Method updates the value of pre-processed detector coordinates in Q-space, used by other functions.
helper class describes the properties of target MD workspace, which should be obtained as the result ...
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)
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
Definition: IMDWorkspace.h:146
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
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
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
Defines the possible energy transfer modes:
Definition: DeltaEMode.h:23
static const std::vector< std::string > availableTypes()
Returns the string list of available modes.
Definition: DeltaEMode.cpp:35
Type
Define the available energy transfer modes It is important to assign enums proper numbers,...
Definition: DeltaEMode.h:29