Mantid
Loading...
Searching...
No Matches
ConvertToMDParent.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 +
8
12#include "MantidAPI/Run.h"
14
19
22
23using namespace Mantid::API;
24using namespace Mantid::DataObjects;
25using namespace Mantid::Kernel;
26
27namespace Mantid::MDAlgorithms {
28
30const std::string ConvertToMDParent::category() const { return "MDAlgorithms\\Creation"; }
31
35 auto ws_valid = std::make_shared<CompositeValidator>();
36 //
37 ws_valid->add<InstrumentValidator>();
38 // the validator which checks if the workspace has axis and any units
39 ws_valid->add<WorkspaceUnitValidator>("");
40
42 std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, ws_valid),
43 "An input Matrix Workspace (2DMatrix or Event workspace) ");
44
45 std::vector<std::string> Q_modes = MDTransfFactory::Instance().getKeys();
46 // something to do with different moments of time when algorithm or test loads
47 // library. To avoid empty factory always do this.
48 if (Q_modes.empty())
49 Q_modes.assign(1, "ERROR IN LOADING Q-converters");
50
52 declareProperty("QDimensions", Q_modes[0], std::make_shared<StringListValidator>(Q_modes),
53 "String, describing available analysis modes, registered "
54 "with MD Transformation factory."
55 "There are 3 modes currently available and described in "
56 "details on *MD Transformation factory* page."
57 "The modes names are **CopyToMD**, **|Q|** and **Q3D**",
60 std::vector<std::string> dE_modes = Kernel::DeltaEMode::availableTypes();
61 declareProperty("dEAnalysisMode", dE_modes[Kernel::DeltaEMode::Direct],
62 std::make_shared<StringListValidator>(dE_modes),
63 "You can analyze neutron energy transfer in **Direct**, "
64 "**Indirect** or **Elastic** mode."
65 "The analysis mode has to correspond to experimental set up. "
66 "Selecting inelastic mode increases"
67 "the number of the target workspace dimensions by one. See "
68 "*MD Transformation factory* for further details.",
70
71 MDWSTransform QSclAndFrames;
72 std::vector<std::string> TargFrames = QSclAndFrames.getTargetFrames();
73 declareProperty("Q3DFrames", TargFrames[CnvrtToMD::AutoSelect], std::make_shared<StringListValidator>(TargFrames),
74 "Selects Q-dimensions of the output workspace in **Q3D** case. "
75 " **AutoSelect**: Choose the target coordinate frame as the function of "
76 "goniometer and UB matrix values set on the input workspace."
77 " **Q (lab frame)**: Wave-vector converted into the lab frame."
78 " **Q (sample frame)**: Wave-vector converted into the frame of the "
79 "sample (taking out the goniometer rotation)."
80 " **HKL**: Use the sample's UB matrix to convert Wave-vector to "
81 "crystal's HKL indices."
82 "See *MD Transformation factory* **(Q3D)** for more details about "
83 "this. ");
84
85 std::vector<std::string> QScales = QSclAndFrames.getQScalings();
86 declareProperty("QConversionScales", QScales[CnvrtToMD::NoScaling], std::make_shared<StringListValidator>(QScales),
87 "This property to normalize three momentums obtained in **Q3D** mode."
88 " See *MD Transformation factory* "
89 "for description and available scaling modes. The value can be modified "
90 "depending on the target coordinate "
91 "system, defined by the property **OutputDimensions**. ");
92
93 setPropertySettings("Q3DFrames", std::make_unique<Kernel::VisibleWhenProperty>("QDimensions", IS_EQUAL_TO, "Q3D"));
94 setPropertySettings("QconversionScales",
95 std::make_unique<Kernel::VisibleWhenProperty>("QDimensions", IS_EQUAL_TO, "Q3D"));
96
97 declareProperty(std::make_unique<ArrayProperty<std::string>>("OtherDimensions", Direction::Input),
98 "List(comma separated) of additional to **Q** and **DeltaE** variables "
99 "which form additional "
100 "(orthogonal) to **Q** dimensions in the target workspace (e.g. "
101 "Temperature or Magnetic field). "
102 "These variables had to be logged during experiment and the names of "
103 "these variables have to coincide "
104 "with the log names for the records of these variables in the source "
105 "workspace.");
106
107 // this property is mainly for ChildAlgorithms to set-up as they have to
108 // identify if they use the same instrument.
109 declareProperty(std::make_unique<PropertyWithValue<std::string>>("PreprocDetectorsWS", "PreprocessedDetectorsWS",
111 "The name of the table workspace where the part of the detectors "
112 "transformation into reciprocal space, "
113 "calculated by :ref:`algm-PreprocessDetectorsToMD` algorithm is stored. "
114 "If the workspace is not found in analysis "
115 "data service, :ref:`algm-PreprocessDetectorsToMD` used to calculate it. "
116 "If found, the algorithm uses existing "
117 "workspace. The field is useful if one expects to analyze number of "
118 "different experiments obtained on "
119 "the same instrument."
120 ".. warning:: Dangerous if one uses number of workspaces with modified "
121 "derived instrument one after another."
122 " *In this case this property has to be set to* **\"-\"** *sting (minus "
123 "without quotes) or empty (possible from script only) "
124 "to force the workspace recalculation each time the algorithm is "
125 "invoked.*");
126 getPointerToProperty("PreprocDetectorsWS")->setAutoTrim(false);
127
128 declareProperty(std::make_unique<PropertyWithValue<bool>>("UpdateMasks", false, Direction::Input),
129 "if PreprocessDetectorWS is used to build the workspace with "
130 "preprocessed detectors at first algorithm call,"
131 "and the input workspaces instruments are different by just different "
132 "masked detectors, setting this "
133 "option to true forces :ref:`algm-PreprocessDetectorsToMD` update only "
134 "the detectors masks for all subsequent "
135 "calls to this algorithm."
136 ".. warning:: *This is temporary solution necessary until Mantid masks "
137 "spectra by 0 rather then by NaN.*");
138
139 // if one needs to use Lorentz corrections
140 declareProperty(std::make_unique<PropertyWithValue<bool>>("LorentzCorrection", false, Direction::Input),
141 "Correct the weights of events or signals and errors transformed into "
142 "reciprocal space by multiplying them "
143 "by the Lorentz multiplier:\n :math:`sin(\\theta)^2/\\lambda^4`. "
144 "Currently works in Q3D Elastic case only "
145 "and is ignored in any other case.");
146 declareProperty(std::make_unique<PropertyWithValue<bool>>("IgnoreZeroSignals", false, Direction::Input),
147 "Enabling this property forces the algorithm to ignore bins with zero "
148 "signal for an input matrix workspace. Input event workspaces are not "
149 "affected. "
150 "This violates the data normalization but may substantially accelerate "
151 "calculations in situations when the normalization is not important "
152 "(e.g. peak finding).");
153
154 declareProperty(std::make_unique<ArrayProperty<double>>("Uproj"),
155 //"The functionality of this parameter set to non-default
156 // value is still not fully verified (see ticket #5982). "
157 "Defines the first projection vector of the target Q "
158 "coordinate system in **Q3D** mode - Default (1,0,0)");
159
160 declareProperty(std::make_unique<ArrayProperty<double>>("Vproj"),
161 //"The functionality of this parameter set to non-default
162 // value is still not fully verified (see ticket #5982). "
163 "Defines the second projection vector of the target Q "
164 "coordinate system in **Q3D** mode - Default (0,1,0).");
165
166 declareProperty(std::make_unique<ArrayProperty<double>>("Wproj"),
167 //"The functionality of this parameter set to non-default
168 // value is still not fully verified (see ticket #5982). "
169 "Defines the third projection vector of the target Q "
170 "coordinate system in **Q3D** mode. - Default (0,0,1)");
171 // if one needs no events near the origin of Q
172 declareProperty(std::make_unique<PropertyWithValue<double>>("AbsMinQ", 0.0, Direction::Input),
173 "Do not add events to MD workspace that are closer to the origin "
174 "in QSample radius than this value. Needed for 3D"
175 "views to remove noise. ");
176}
192 const std::string &dEModeRequested, bool updateMasks,
193 const std::string &OutWSName) {
194
197
198 // Do we need to reuse output workspace
199 bool storeInDataService(true);
200 std::string tOutWSName(OutWSName);
201 if (tOutWSName == "-" || tOutWSName.empty()) // TargTableWS is recalculated each time;
202 {
203 storeInDataService = false;
204 tOutWSName = "ServiceTableWS"; // TODO: should be hidden?
205 } else {
206 storeInDataService = true;
207 }
208
209 // if output workspace exists in dataservice, we may try to use it
210 if (storeInDataService && API::AnalysisDataService::Instance().doesExist(tOutWSName)) {
211 TargTableWS = API::AnalysisDataService::Instance().retrieveWS<DataObjects::TableWorkspace>(tOutWSName);
212 // get number of all histograms (may be masked or invalid)
213 size_t nHist = InWS2D->getNumberHistograms();
214 size_t nDetMap = TargTableWS->rowCount();
215 if (nHist == nDetMap) {
216 // let's take at least some precaution to ensure that instrument have not
217 // changed
218 std::string currentWSInstrumentName = InWS2D->getInstrument()->getName();
219 std::string oldInstrName = TargTableWS->getLogs()->getPropertyValueAsType<std::string>("InstrumentName");
220
221 if (oldInstrName == currentWSInstrumentName) {
222 // a direct mode instrument can be unchanged but incident energy can be
223 // different.
224 // It is cheap operation so we should always replace incident energy on
225 // the target workspace
226 bool hasEi = InWS2D->run().hasProperty("Ei");
227 bool hasEfix = InWS2D->run().hasProperty("eFixed");
228 if (hasEi || hasEfix) {
229
230 double Ei;
231 if (hasEi)
232 Ei = InWS2D->run().getPropertyValueAsType<double>("Ei");
233 if (hasEfix)
234 Ei = InWS2D->run().getPropertyValueAsType<double>("eFixed");
235
236 TargTableWS->logs()->addProperty<double>("Ei", Ei, true);
237 } else {
238 Emode = Kernel::DeltaEMode::fromString(dEModeRequested);
239 if (Emode == Kernel::DeltaEMode::Direct)
240 throw(std::invalid_argument("Input neutron's energy has to be present at the workspace as "
241 "Ei or eFixed number log in Direct inelastic mode"));
242 // if(Emode==Kernel::DeltaEMode::Indirect && !hasEfix)
243 // throw(std::invalid_argument("Input neutron's energy has to be
244 // present at the workspace as eFixed number log in Indirect
245 // inelastic mode"));
246 }
247
248 if (!updateMasks)
249 return TargTableWS;
250 // Target workspace with preprocessed detectors exists and seems is
251 // correct one.
252 // We still need to update masked detectors information
253 TargTableWS = this->runPreprocessDetectorsToMDChildUpdatingMasks(InWS2D, tOutWSName, dEModeRequested, Emode);
254 return TargTableWS;
255 }
256 } else // there is a workspace in the data service with the same name but
257 // this ws is not suitable as target for this algorithm.
258 { // Should delete this WS from the dataservice
259 API::AnalysisDataService::Instance().remove(tOutWSName);
260 }
261 }
262 // No result found in analysis data service or the result is unsatisfactory.
263 // Try to calculate target workspace.
264
265 TargTableWS = this->runPreprocessDetectorsToMDChildUpdatingMasks(InWS2D, tOutWSName, dEModeRequested, Emode);
266
267 if (storeInDataService)
268 API::AnalysisDataService::Instance().addOrReplace(tOutWSName, TargTableWS);
269 // else
270 // TargTableWS->setName(OutWSName);
271
272 // check if we got what we wanted:
273
274 // in direct or indirect mode input ws has to have input energy
276 auto m_Ei = TargTableWS->getLogs()->getPropertyValueAsType<double>("Ei");
277 if (isNaN(m_Ei)) {
278 // Direct mode needs Ei
279 if (Emode == Kernel::DeltaEMode::Direct)
280 throw(std::invalid_argument("Input neutron's energy has to be defined in inelastic mode "));
281
282 // Do we have at least something for Indirect?
283 auto *eFixed = TargTableWS->getColDataArray<float>("eFixed");
284 if (!eFixed)
285 throw(std::invalid_argument("Input neutron's energy has to be defined in inelastic mode "));
286
287 auto NDetectors = TargTableWS->getLogs()->getPropertyValueAsType<uint32_t>("ActualDetectorsNum");
288 for (uint32_t i = 0; i < NDetectors; i++)
289 if (isNaN(*(eFixed + i)))
290 throw(std::invalid_argument("Undefined eFixed energy for detector N: " + std::to_string(i)));
291 }
292 }
293
294 return TargTableWS;
295}
296
298 const Mantid::API::MatrixWorkspace_const_sptr &InWS2D, const std::string &OutWSName,
299 const std::string &dEModeRequested, Kernel::DeltaEMode::Type &Emode) {
300 // prospective result
302
303 Mantid::API::Algorithm_sptr childAlg = createChildAlgorithm("PreprocessDetectorsToMD", 0., 1.);
304 if (!childAlg)
305 throw(std::runtime_error("Can not create child ChildAlgorithm to preprocess detectors"));
306
307 auto pTargWSProp =
308 dynamic_cast<WorkspaceProperty<MatrixWorkspace> *>(childAlg->getPointerToProperty("InputWorkspace"));
309 if (!pTargWSProp) {
310 throw std::runtime_error("Bad program logic: an algorithm workspace "
311 "property is not castable to a matrix workspace");
312 }
313
314 // TODO: bad unnecessary const_cast but WorkspaceProperty is missing const
315 // assignment operators and I am not sure if ADS guarantees workspaces
316 // const-ness
317 // so, const cast is localized here despite input workspace is and should be
318 // const in this case.
319 *pTargWSProp = std::const_pointer_cast<MatrixWorkspace>(InWS2D);
320
321 childAlg->setProperty("OutputWorkspace", OutWSName);
322 childAlg->setProperty("GetMaskState", true);
323 childAlg->setProperty("UpdateMasksInfo", true);
324 childAlg->setProperty("OutputWorkspace", OutWSName);
325
326 // check and get energy conversion mode to define additional ChildAlgorithm
327 // parameters
328 Emode = Kernel::DeltaEMode::fromString(dEModeRequested);
329 if (Emode == Kernel::DeltaEMode::Indirect)
330 childAlg->setProperty("GetEFixed", true);
331
332 childAlg->execute();
333 if (!childAlg->isExecuted())
334 throw(std::runtime_error("Can not properly execute child algorithm PreprocessDetectorsToMD"));
335
336 TargTableWS = childAlg->getProperty("OutputWorkspace");
337 if (!TargTableWS)
338 throw(std::runtime_error("Can not retrieve results of child algorithm PreprocessDetectorsToMD"));
339
340 return TargTableWS;
341}
342
343} // namespace Mantid::MDAlgorithms
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
Definition: Algorithm.cpp:2033
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
A validator which checks that a workspace has a valid instrument.
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
TableWorkspace is an implementation of Workspace in which the data are organised in columns of same s...
size_t rowCount() const override
Number of rows in the workspace.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
The concrete, templated class for properties.
void setAutoTrim(const bool &setting)
Sets if the property is set to automatically trim string unput values of whitespace.
Definition: Property.cpp:371
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
bool isNaN(T val)
Template to check if a variable equal to NaN.
DataObjects::TableWorkspace_sptr runPreprocessDetectorsToMDChildUpdatingMasks(const Mantid::API::MatrixWorkspace_const_sptr &InWS2D, const std::string &OutWSName, const std::string &dEModeRequested, Kernel::DeltaEMode::Type &Emode)
DataObjects::TableWorkspace_const_sptr preprocessDetectorsPositions(const Mantid::API::MatrixWorkspace_const_sptr &InWS2D, const std::string &dEModeRequested, bool updateMasks, const std::string &OutWSName)
The method responsible for analyzing input workspace parameters and preprocessing detectors positions...
const std::string category() const override
Algorithm's category for identification.
void init() override
Initialize the algorithm's properties.
std::vector< std::string > getTargetFrames() const
returns the list of possible target frames to convert to
Definition: MDWSTransform.h:84
std::vector< std::string > getQScalings() const
return the list of possible scalings for momentums
Definition: MDWSTransform.h:80
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< const TableWorkspace > TableWorkspace_const_sptr
shared pointer to Mantid::DataObjects::TableWorkspace (const version)
std::string to_string(const wide_integer< Bits, Signed > &n)
static const std::vector< std::string > availableTypes()
Returns the string list of available modes.
Definition: DeltaEMode.cpp:35
static Type fromString(const std::string &modeStr)
Returns the emode from the given string.
Definition: DeltaEMode.cpp:69
Type
Define the available energy transfer modes It is important to assign enums proper numbers,...
Definition: DeltaEMode.h:29
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53