Mantid
Loading...
Searching...
No Matches
ConvertToMDMinMaxGlobal.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
11#include "MantidAPI/Run.h"
12#include "MantidAPI/Sample.h"
24
25using namespace Mantid;
26using namespace Mantid::Kernel;
27using namespace Mantid::API;
28using namespace Mantid::DataObjects;
29
30namespace Mantid::MDAlgorithms {
31
32// Register the algorithm into the AlgorithmFactory
33DECLARE_ALGORITHM(ConvertToMDMinMaxGlobal)
34
35
36const std::string ConvertToMDMinMaxGlobal::name() const { return "ConvertToMDMinMaxGlobal"; }
37
39int ConvertToMDMinMaxGlobal::version() const { return 1; }
40
42const std::string ConvertToMDMinMaxGlobal::category() const { return "MDAlgorithms\\Creation"; }
43
47 auto ws_valid = std::make_shared<CompositeValidator>();
48 ws_valid->add<InstrumentValidator>();
49 // the validator which checks if the workspace has axis and any units
50 ws_valid->add<WorkspaceUnitValidator>("");
51 // histogram needed by ConvertUnits
52 ws_valid->add<HistogramValidator>();
54 std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, ws_valid),
55 "An input Matrix Workspace (Workspace2D or Event workspace) ");
56
57 std::vector<std::string> Q_modes = MDAlgorithms::MDTransfFactory::Instance().getKeys();
58 // something to do with different moments of time when algorithm or test loads
59 // library. To avoid empty factory always do this.
60 if (Q_modes.empty())
61 Q_modes.assign(1, "ERROR IN LOADING Q-converters");
62
64 declareProperty("QDimensions", Q_modes[0], std::make_shared<StringListValidator>(Q_modes),
65 "String, describing MD-analysis modes, this algorithm can process. "
66 "There are 3 modes currently available and described in details on"
67 "*MD Transformation factory* page. "
68 "The modes names are **CopyToMD**, **|Q|** and **Q3D**",
71 std::vector<std::string> dE_modes = Kernel::DeltaEMode::availableTypes();
72 declareProperty("dEAnalysisMode", dE_modes[Kernel::DeltaEMode::Direct],
73 std::make_shared<StringListValidator>(dE_modes),
74 "You can analyze neutron energy transfer in **Direct**, "
75 "**Indirect** or **Elastic** mode. "
76 "The analysis mode has to correspond to experimental set up. "
77 "Selecting inelastic mode increases "
78 "the number of the target workspace dimensions by one. See "
79 "*MD Transformation factory* for further details.",
81
82 setPropertySettings("dEAnalysisMode",
83 std::make_unique<VisibleWhenProperty>("QDimensions", IS_NOT_EQUAL_TO, "CopyToMD"));
84
85 std::vector<std::string> TargFrames{"AutoSelect", "Q", "HKL"};
86 declareProperty("Q3DFrames", "AutoSelect", std::make_shared<StringListValidator>(TargFrames),
87 "What will be the Q-dimensions of the output workspace in **Q3D** case?"
88 " **AutoSelect**: **Q** by default, **HKL** if sample has a UB matrix."
89 " **Q** - momentum in inverse angstroms. Can be used for both "
90 "laboratory or sample frame."
91 " **HKL** - reciprocal lattice units");
92
93 setPropertySettings("Q3DFrames", std::make_unique<VisibleWhenProperty>("QDimensions", IS_EQUAL_TO, "Q3D"));
94
95 declareProperty(std::make_unique<ArrayProperty<std::string>>("OtherDimensions", Direction::Input),
96 "List(comma separated) of additional to **Q** and **DeltaE** variables "
97 "which form additional "
98 "(orthogonal) to **Q** dimensions in the target workspace (e.g. "
99 "Temperature or Magnetic field). "
100 "These variables had to be logged during experiment and the names of "
101 "these variables have to coincide "
102 "with the log names for the records of these variables in the source "
103 "workspace.");
104
105 declareProperty(std::make_unique<ArrayProperty<double>>("MinValues", Direction::Output));
106 declareProperty(std::make_unique<ArrayProperty<double>>("MaxValues", Direction::Output));
107}
108
109//----------------------------------------------------------------------------------------------
113 std::vector<double> MinValues, MaxValues;
114 std::string QDimension = getPropertyValue("QDimensions");
115 std::string GeometryMode = getPropertyValue("dEAnalysisMode");
116 std::string Q3DFrames = getPropertyValue("Q3DFrames");
117 std::vector<std::string> OtherDimensions = getProperty("OtherDimensions");
118
119 MatrixWorkspace_sptr ws = getProperty("InputWorkspace"), wstemp;
121
122 if (QDimension == "CopyToMD") {
123 double xmin, xmax;
124 ws->getXMinMax(xmin, xmax);
125 MinValues.emplace_back(xmin);
126 MaxValues.emplace_back(xmax);
127 } else // need to calculate the appropriate q values
128 {
129 double qmax, deltaEmax, deltaEmin;
130 auto conv = createChildAlgorithm("ConvertUnits", 0.0, 0.9);
131 conv->setProperty<MatrixWorkspace_sptr>("InputWorkspace", ws);
132 conv->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", wstemp);
133 // Calculate maxumum momentum transfer Q
134 if (GeometryMode == "Elastic") {
135 conv->setProperty("Target", "Momentum");
136 conv->setProperty("Emode", "Elastic");
137 conv->executeAsChildAlg();
138
139 wstemp = conv->getProperty("OutputWorkspace");
140 evWS = std::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>(wstemp);
141 if (evWS)
142 qmax = evWS->getTofMax() * 2; // assumes maximum scattering angle 180 degrees
143 else
144 qmax = wstemp->getXMax() * 2.; // assumes maximum scattering angle 180 degrees
145 } else // inelastic
146 {
147 conv->setProperty("Target", "DeltaE");
148 conv->setProperty("Emode", GeometryMode);
149 conv->executeAsChildAlg();
150 wstemp = conv->getProperty("OutputWorkspace");
151 evWS = std::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>(wstemp);
152 if (evWS) {
153 deltaEmin = evWS->getTofMin();
154 deltaEmax = evWS->getTofMax();
155 } else {
156 wstemp->getXMinMax(deltaEmin, deltaEmax);
157 }
158
159 // Deal with nonphysical energies - conversion to DeltaE yields +-DBL_MAX
160 if (deltaEmin < -DBL_MAX / 2)
161 deltaEmin = -deltaEmax;
162 if (deltaEmax > DBL_MAX / 2)
163 deltaEmax = -deltaEmin;
164
165 // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV))
166 const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 /
168 if (GeometryMode == "Direct") {
169 const auto Ei = ws->run().getPropertyValueAsType<double>("Ei");
170 qmax = std::sqrt(energyToK * Ei) + std::sqrt(energyToK * (Ei - deltaEmin));
171 } else // indirect
172 {
173 double Ef = -DBL_MAX, Eftemp = Ef;
174 const auto &pmap = ws->constInstrumentParameters();
175 const auto &specInfo = ws->spectrumInfo();
176 for (size_t i = 0; i < ws->getNumberHistograms(); i++) {
177 if (!specInfo.hasDetectors(i))
178 continue;
179 const auto &det = specInfo.detector(i);
180 const auto &par = pmap.getRecursive(det.getComponentID(), "eFixed");
181 Eftemp = (par) ? par->value<double>() : Eftemp;
182 Ef = (Eftemp > Ef) ? Eftemp : Ef;
183 if (Ef <= 0)
184 throw std::runtime_error("Could not find a fixed final energy for "
185 "indirect geometry instrument.");
186 }
187 qmax = std::sqrt(energyToK * Ef) + std::sqrt(energyToK * (Ef + deltaEmax));
188 }
189 }
190 // Calculate limits from qmax
191 if (QDimension == "|Q|") {
192 MinValues.emplace_back(0.);
193 MaxValues.emplace_back(qmax);
194 } else // Q3D
195 {
196 // Q in angstroms
197 if ((Q3DFrames == "Q") || ((Q3DFrames == "AutoSelect") && (!ws->sample().hasOrientedLattice()))) {
198 MinValues.emplace_back(-qmax);
199 MinValues.emplace_back(-qmax);
200 MinValues.emplace_back(-qmax);
201 MaxValues.emplace_back(qmax);
202 MaxValues.emplace_back(qmax);
203 MaxValues.emplace_back(qmax);
204 } else // HKL
205 {
206 if (!ws->sample().hasOrientedLattice()) {
207 g_log.error() << "Sample has no oriented lattice\n";
208 throw std::invalid_argument("No UB set");
209 }
210 Mantid::Geometry::OrientedLattice ol = ws->sample().getOrientedLattice();
211 qmax /= (2. * M_PI);
212 MinValues.emplace_back(-qmax * ol.a());
213 MinValues.emplace_back(-qmax * ol.b());
214 MinValues.emplace_back(-qmax * ol.c());
215 MaxValues.emplace_back(qmax * ol.a());
216 MaxValues.emplace_back(qmax * ol.b());
217 MaxValues.emplace_back(qmax * ol.c());
218 }
219 }
220
221 // Push deltaE if necessary
222 if (GeometryMode != "Elastic") {
223 MinValues.emplace_back(deltaEmin);
224 MaxValues.emplace_back(deltaEmax);
225 }
226 }
227
228 for (auto &OtherDimension : OtherDimensions) {
229 if (!ws->run().hasProperty(OtherDimension)) {
230 g_log.error() << "The workspace does not have a property " << OtherDimension << '\n';
231 throw std::invalid_argument("Property not found. Please see error log.");
232 }
233 Kernel::Property *pProperty = (ws->run().getProperty(OtherDimension));
234 auto *p = dynamic_cast<TimeSeriesProperty<double> *>(pProperty);
235 if (p) {
236 MinValues.emplace_back(p->getStatistics().minimum);
237 MaxValues.emplace_back(p->getStatistics().maximum);
238 } else // it may be not a time series property but just number property
239 {
240 auto *property = dynamic_cast<Kernel::PropertyWithValue<double> *>(pProperty);
241 if (!property) {
242 std::string ERR = " Can not interpret property, used as dimension.\n Property: " + OtherDimension +
243 " is neither a time series (run) property nor "
244 "a property with value<double>";
245 throw(std::invalid_argument(ERR));
246 }
247 double val = *property;
248 MinValues.emplace_back(val);
249 MaxValues.emplace_back(val);
250 }
251 }
252
253 setProperty("MinValues", MinValues);
254 setProperty("MaxValues", MaxValues);
255}
256
257} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
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
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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
Kernel::Logger & g_log
Definition: Algorithm.h:451
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
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...
Class to implement UB matrix.
double a(int nd) const
Get lattice parameter a1-a3 as function of index (0-2)
Definition: UnitCell.cpp:94
double c() const
Get lattice parameter.
Definition: UnitCell.cpp:128
double b() const
Get lattice parameter.
Definition: UnitCell.cpp:123
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
The concrete, templated class for properties.
Base class for properties.
Definition: Property.h:94
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A specialised Property class for holding a series of time-value pairs.
ConvertToMDMinMaxGlobal : Algorithm to calculate limits for ConvertToMD transformation which can be o...
void init() override
Initialize the algorithm's properties.
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
static constexpr double meV
1 meV in Joules.
Helper class which provides the Collimation Length for SANS instruments.
Generate a tableworkspace to store the calibration results.
STL namespace.
static const std::vector< std::string > availableTypes()
Returns the string list of available modes.
Definition: DeltaEMode.cpp:35
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54