47 auto ws_valid = std::make_shared<CompositeValidator>();
55 "An input Matrix Workspace (Workspace2D or Event workspace) ");
57 std::vector<std::string> Q_modes = MDAlgorithms::MDTransfFactory::Instance().getKeys();
61 Q_modes.assign(1,
"ERROR IN LOADING Q-converters");
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**",
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.",
83 std::make_unique<VisibleWhenProperty>(
"QDimensions",
IS_NOT_EQUAL_TO,
"CopyToMD"));
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");
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 "
113 std::vector<double> MinValues, MaxValues;
117 std::vector<std::string> OtherDimensions =
getProperty(
"OtherDimensions");
122 if (QDimension ==
"CopyToMD") {
124 ws->getXMinMax(xmin, xmax);
125 MinValues.emplace_back(xmin);
126 MaxValues.emplace_back(xmax);
129 double qmax, deltaEmax, deltaEmin;
134 if (GeometryMode ==
"Elastic") {
135 conv->setProperty(
"Target",
"Momentum");
136 conv->setProperty(
"Emode",
"Elastic");
137 conv->executeAsChildAlg();
139 wstemp = conv->getProperty(
"OutputWorkspace");
140 evWS = std::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>(wstemp);
142 qmax = evWS->getTofMax() * 2;
144 qmax = wstemp->getXMax() * 2.;
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);
153 deltaEmin = evWS->getTofMin();
154 deltaEmax = evWS->getTofMax();
156 wstemp->getXMinMax(deltaEmin, deltaEmax);
160 if (deltaEmin < -DBL_MAX / 2)
161 deltaEmin = -deltaEmax;
162 if (deltaEmax > DBL_MAX / 2)
163 deltaEmax = -deltaEmin;
168 if (GeometryMode ==
"Direct") {
169 const auto Ei = ws->run().getPropertyValueAsType<
double>(
"Ei");
170 qmax = std::sqrt(energyToK * Ei) + std::sqrt(energyToK * (Ei - deltaEmin));
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))
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;
184 throw std::runtime_error(
"Could not find a fixed final energy for "
185 "indirect geometry instrument.");
187 qmax = std::sqrt(energyToK * Ef) + std::sqrt(energyToK * (Ef + deltaEmax));
191 if (QDimension ==
"|Q|") {
192 MinValues.emplace_back(0.);
193 MaxValues.emplace_back(qmax);
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);
206 if (!ws->sample().hasOrientedLattice()) {
207 g_log.
error() <<
"Sample has no oriented lattice\n";
208 throw std::invalid_argument(
"No UB set");
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());
222 if (GeometryMode !=
"Elastic") {
223 MinValues.emplace_back(deltaEmin);
224 MaxValues.emplace_back(deltaEmax);
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.");
236 MinValues.emplace_back(p->getStatistics().minimum);
237 MaxValues.emplace_back(p->getStatistics().maximum);
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));
247 double val = *property;
248 MinValues.emplace_back(val);
249 MaxValues.emplace_back(val);