49 auto ws_valid = std::make_shared<CompositeValidator>();
57 "An input Matrix Workspace (Workspace2D or Event workspace) ");
59 std::vector<std::string> Q_modes = MDAlgorithms::MDTransfFactory::Instance().getKeys();
63 Q_modes.assign(1,
"ERROR IN LOADING Q-converters");
66 declareProperty(
"QDimensions", Q_modes[0], std::make_shared<StringListValidator>(Q_modes),
67 "String, describing MD-analysis modes, this algorithm can process. "
68 "There are 3 modes currently available and described in details on"
69 "*MD Transformation factory* page. "
70 "The modes names are **CopyToMD**, **|Q|** and **Q3D**",
75 std::make_shared<StringListValidator>(dE_modes),
76 "You can analyze neutron energy transfer in **Direct**, "
77 "**Indirect** or **Elastic** mode. "
78 "The analysis mode has to correspond to experimental set up. "
79 "Selecting inelastic mode increases "
80 "the number of the target workspace dimensions by one. See "
81 "*MD Transformation factory* for further details.",
85 std::make_unique<VisibleWhenProperty>(
"QDimensions",
IS_NOT_EQUAL_TO,
"CopyToMD"));
87 std::vector<std::string> TargFrames{
"AutoSelect",
"Q",
"HKL"};
88 declareProperty(
"Q3DFrames",
"AutoSelect", std::make_shared<StringListValidator>(TargFrames),
89 "What will be the Q-dimensions of the output workspace in **Q3D** case?"
90 " **AutoSelect**: **Q** by default, **HKL** if sample has a UB matrix."
91 " **Q** - momentum in inverse angstroms. Can be used for both "
92 "laboratory or sample frame."
93 " **HKL** - reciprocal lattice units");
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 "
115 std::vector<double> MinValues, MaxValues;
119 std::vector<std::string> OtherDimensions =
getProperty(
"OtherDimensions");
124 if (QDimension ==
"CopyToMD") {
125 const auto [xmin, xmax] = ws->getXMinMax();
126 MinValues.emplace_back(xmin);
127 MaxValues.emplace_back(xmax);
130 double qmax, deltaEmax, deltaEmin;
135 if (GeometryMode ==
"Elastic") {
136 conv->setProperty(
"Target",
"Momentum");
137 conv->setProperty(
"Emode",
"Elastic");
138 conv->executeAsChildAlg();
140 wstemp = conv->getProperty(
"OutputWorkspace");
141 evWS = std::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>(wstemp);
143 qmax = evWS->getTofMax() * 2;
145 qmax = wstemp->getXMax() * 2.;
148 conv->setProperty(
"Target",
"DeltaE");
149 conv->setProperty(
"Emode", GeometryMode);
150 conv->executeAsChildAlg();
151 wstemp = conv->getProperty(
"OutputWorkspace");
152 evWS = std::dynamic_pointer_cast<Mantid::DataObjects::EventWorkspace>(wstemp);
154 deltaEmin = evWS->getTofMin();
155 deltaEmax = evWS->getTofMax();
157 std::tie(deltaEmin, deltaEmax) = wstemp->getXMinMax();
161 if (deltaEmin < -DBL_MAX / 2)
162 deltaEmin = -deltaEmax;
163 if (deltaEmax > DBL_MAX / 2)
164 deltaEmax = -deltaEmin;
169 if (GeometryMode ==
"Direct") {
170 const auto Ei = ws->run().getPropertyValueAsType<
double>(
"Ei");
171 qmax = std::sqrt(energyToK * Ei) + std::sqrt(energyToK * (Ei - deltaEmin));
174 double Ef = -DBL_MAX, Eftemp = Ef;
175 const auto &
pmap = ws->constInstrumentParameters();
176 const auto &specInfo = ws->spectrumInfo();
177 for (
size_t i = 0; i < ws->getNumberHistograms(); i++) {
178 if (!specInfo.hasDetectors(i))
180 const auto &det = specInfo.detector(i);
181 const auto &par =
pmap.getRecursive(det.getComponentID(),
"eFixed");
182 Eftemp = (par) ? par->value<
double>() : Eftemp;
183 Ef = (Eftemp > Ef) ? Eftemp : Ef;
185 throw std::runtime_error(
"Could not find a fixed final energy for "
186 "indirect geometry instrument.");
188 qmax = std::sqrt(energyToK * Ef) + std::sqrt(energyToK * (Ef + deltaEmax));
192 if (QDimension ==
"|Q|") {
193 MinValues.emplace_back(0.);
194 MaxValues.emplace_back(qmax);
198 if ((Q3DFrames ==
"Q") || ((Q3DFrames ==
"AutoSelect") && (!ws->sample().hasOrientedLattice()))) {
199 MinValues.emplace_back(-qmax);
200 MinValues.emplace_back(-qmax);
201 MinValues.emplace_back(-qmax);
202 MaxValues.emplace_back(qmax);
203 MaxValues.emplace_back(qmax);
204 MaxValues.emplace_back(qmax);
207 if (!ws->sample().hasOrientedLattice()) {
208 g_log.
error() <<
"Sample has no oriented lattice\n";
209 throw std::invalid_argument(
"No UB set");
213 MinValues.emplace_back(-qmax * ol.
a());
214 MinValues.emplace_back(-qmax * ol.
b());
215 MinValues.emplace_back(-qmax * ol.
c());
216 MaxValues.emplace_back(qmax * ol.
a());
217 MaxValues.emplace_back(qmax * ol.
b());
218 MaxValues.emplace_back(qmax * ol.
c());
223 if (GeometryMode !=
"Elastic") {
224 MinValues.emplace_back(deltaEmin);
225 MaxValues.emplace_back(deltaEmax);
229 for (
auto &OtherDimension : OtherDimensions) {
230 if (!ws->run().hasProperty(OtherDimension)) {
231 g_log.
error() <<
"The workspace does not have a property " << OtherDimension <<
'\n';
232 throw std::invalid_argument(
"Property not found. Please see error log.");
237 MinValues.emplace_back(p->getStatistics().minimum);
238 MaxValues.emplace_back(p->getStatistics().maximum);
243 std::string ERR =
" Can not interpret property, used as dimension.\n Property: " + OtherDimension +
244 " is neither a time series (run) property nor "
245 "a property with value<double>";
246 throw(std::invalid_argument(ERR));
248 double val = *property;
249 MinValues.emplace_back(val);
250 MaxValues.emplace_back(val);