Mantid
Loading...
Searching...
No Matches
PDFFourierTransform2.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#include "MantidAPI/Axis.h"
9#include "MantidAPI/Run.h"
10#include "MantidAPI/Sample.h"
14#include "MantidHistogramData/Histogram.h"
15#include "MantidHistogramData/LinearGenerator.h"
22#include "MantidKernel/Unit.h"
24
25#include <cmath>
26#include <sstream>
27
28namespace Mantid::Algorithms {
29
30using std::string;
31using namespace HistogramData;
32
33// Register the algorithm into the AlgorithmFactory
34DECLARE_ALGORITHM(PDFFourierTransform2)
35
36using namespace Mantid::Kernel;
37using namespace Mantid::API;
38using namespace DataObjects;
39
40namespace { // anonymous namespace
42const string BIG_G_OF_R("G(r)");
44const string LITTLE_G_OF_R("g(r)");
46const string RDF_OF_R("RDF(r)");
48const string G_K_OF_R("G_k(r)");
49
51const string S_OF_Q("S(Q)");
53const string S_OF_Q_MINUS_ONE("S(Q)-1");
55const string Q_S_OF_Q_MINUS_ONE("Q[S(Q)-1]");
56
57const string FORWARD("Forward");
58
59const string BACKWARD("Backward");
60
61} // namespace
62
63const std::string PDFFourierTransform2::name() const { return "PDFFourierTransform"; }
64
65int PDFFourierTransform2::version() const { return 2; }
66
67const std::string PDFFourierTransform2::category() const { return "Diffraction\\Utility"; }
68
72 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
73 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
74 "Input spectrum density or paired-distribution function");
75 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
76 "Result paired-distribution function or Input spectrum density");
77
78 std::vector<std::string> directionOptions;
79 directionOptions.emplace_back(FORWARD);
80 directionOptions.emplace_back(BACKWARD);
81 declareProperty("Direction", FORWARD, std::make_shared<StringListValidator>(directionOptions),
82 "The direction of the fourier transform");
83 declareProperty("rho0", EMPTY_DBL(), mustBePositive,
84 "Average number density used for g(r) and RDF(r) conversions (optional)");
85 declareProperty("Filter", false, "Set to apply Lorch function filter to the input");
86
87 // Set up spectral density data type
88 std::vector<std::string> soqTypes;
89 soqTypes.emplace_back(S_OF_Q);
90 soqTypes.emplace_back(S_OF_Q_MINUS_ONE);
91 soqTypes.emplace_back(Q_S_OF_Q_MINUS_ONE);
92 declareProperty("InputSofQType", S_OF_Q, std::make_shared<StringListValidator>(soqTypes),
93 "To identify spectral density function (deprecated)");
94 setPropertySettings("InputSofQType", std::make_unique<InvisibleProperty>());
95 declareProperty("SofQType", S_OF_Q, std::make_shared<StringListValidator>(soqTypes),
96 "To identify spectral density function");
97 mustBePositive->setLower(0.0);
98
99 declareProperty("DeltaQ", EMPTY_DBL(), mustBePositive,
100 "Step size of Q of S(Q) to calculate. Default = "
101 ":math:`\\frac{\\pi}{R_{max}}`.");
102 setPropertySettings("DeltaQ", std::make_unique<EnabledWhenProperty>("Direction", IS_EQUAL_TO, BACKWARD));
103 declareProperty("Qmin", EMPTY_DBL(), mustBePositive,
104 "Minimum Q in S(Q) to calculate in Fourier transform (optional).");
105 setPropertySettings("Qmin", std::make_unique<EnabledWhenProperty>("Direction", IS_EQUAL_TO, FORWARD));
106 declareProperty("Qmax", EMPTY_DBL(), mustBePositive,
107 "Maximum Q in S(Q) to calculate in Fourier transform. "
108 "(optional, defaults to 40 on backward transform.)");
109
110 // Set up PDF data type
111 std::vector<std::string> pdfTypes;
112 pdfTypes.emplace_back(BIG_G_OF_R);
113 pdfTypes.emplace_back(LITTLE_G_OF_R);
114 pdfTypes.emplace_back(RDF_OF_R);
115 pdfTypes.emplace_back(G_K_OF_R);
116 declareProperty("PDFType", BIG_G_OF_R, std::make_shared<StringListValidator>(pdfTypes),
117 "Type of output PDF including G(r)");
118
119 declareProperty("DeltaR", EMPTY_DBL(), mustBePositive,
120 "Step size of r of G(r) to calculate. Default = "
121 ":math:`\\frac{\\pi}{Q_{max}}`.");
122 setPropertySettings("DeltaR", std::make_unique<EnabledWhenProperty>("Direction", IS_EQUAL_TO, FORWARD));
123 declareProperty("Rmin", EMPTY_DBL(), mustBePositive, "Minimum r for G(r) to calculate. (optional)");
124 setPropertySettings("Rmin", std::make_unique<EnabledWhenProperty>("Direction", IS_EQUAL_TO, BACKWARD));
125 declareProperty("Rmax", EMPTY_DBL(), mustBePositive,
126 "Maximum r for G(r) to calculate. (optional, defaults to 20 "
127 "on forward transform.)");
128
129 string recipGroup("Reciprocal Space");
130 setPropertyGroup("SofQType", recipGroup);
131 setPropertyGroup("DeltaQ", recipGroup);
132 setPropertyGroup("Qmin", recipGroup);
133 setPropertyGroup("Qmax", recipGroup);
134
135 string realGroup("Real Space");
136 setPropertyGroup("PDFType", realGroup);
137 setPropertyGroup("DeltaR", realGroup);
138 setPropertyGroup("Rmin", realGroup);
139 setPropertyGroup("Rmax", realGroup);
140}
141
142std::map<string, string> PDFFourierTransform2::validateInputs() {
143 std::map<string, string> result;
144
145 double Qmin = getProperty("Qmin");
146 double Qmax = getProperty("Qmax");
147 if ((!isEmpty(Qmin)) && (!isEmpty(Qmax)))
148 if (Qmax <= Qmin)
149 result["Qmax"] = "Must be greater than Qmin";
150
151 // check for null pointers - this is to protect against workspace groups
152 API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
153 if (!inputWS) {
154 return result;
155 }
156
157 if (inputWS->getNumberHistograms() != 1) {
158 result["InputWorkspace"] = "Input workspace must have only one spectrum";
159 }
160 const std::string inputXunit = inputWS->getAxis(0)->unit()->unitID();
161 if (inputXunit != "MomentumTransfer" && inputXunit != "dSpacing" && inputXunit != "AtomicDistance") {
162 result["InputWorkspace"] = "Input workspace units not supported";
163 }
164
165 return result;
166}
167
168size_t PDFFourierTransform2::determineMinIndex(double min, const std::vector<double> &X, const std::vector<double> &Y) {
169 // check against available X-range
170 if (isEmpty(min)) {
171 min = X.front();
172 } else if (min < X.front()) {
173 g_log.information("Specified input min < range of data. Adjusting to data range.");
174 min = X.front();
175 }
176
177 // get index for the min from the X-range, tightening the range if a partial x bin value is provided
178 auto iter = std::lower_bound(X.begin(), X.end(), min);
179 size_t min_index = std::distance(X.begin(), iter);
180
181 // go to first non-nan value
182 auto iter_first_normal =
183 std::find_if(std::next(Y.begin(), min_index), Y.end(), static_cast<bool (*)(double)>(std::isnormal));
184 size_t first_normal_index = std::distance(Y.begin(), iter_first_normal);
185 if (first_normal_index > min_index) {
186 g_log.information("Specified input min where data is nan/inf or zero. Adjusting to data range.");
187 min_index = first_normal_index;
188 }
189
190 return min_index;
191}
192
193size_t PDFFourierTransform2::determineMaxIndex(double max, const std::vector<double> &X, const std::vector<double> &Y) {
194 // check against available X-range
195 if (isEmpty(max)) {
196 max = X.back();
197 } else if (max > X.back()) {
198 g_log.information() << "Specified input max > range of data. Adjusting to data range.\n";
199 max = X.back();
200 }
201
202 // get index for the max from the X-range, tightening the range if a partial x bin value is provided
203 auto iter = std::upper_bound(X.begin(), X.end(), max) - 1;
204 size_t max_index = std::distance(X.begin(), iter);
205
206 // go to first non-nan value. This works for both histogram (bin edge) data and
207 // point data, as the integration proceeds by calculating rectangles between pairs of X values.
208 // For point data the Y value corresponding to the left of this pair is used in the nested for loop in the exec.
209 auto back_iter = std::find_if(Y.rbegin(), Y.rend(), static_cast<bool (*)(double)>(std::isnormal));
210 size_t first_normal_index = Y.size() - std::distance(Y.rbegin(), back_iter);
211 if (first_normal_index < max_index) {
212 g_log.information("Specified input max where data is nan/inf or zero. Adjusting to data range.");
213 max_index = first_normal_index;
214 }
215
216 return max_index;
217}
218
220 double rho0 = getProperty("rho0");
221
222 if (isEmpty(rho0)) {
223 API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
224
225 const Kernel::Material &material = inputWS->sample().getMaterial();
226 double materialDensity = material.numberDensity();
227
228 if (!isEmpty(materialDensity) && materialDensity > 0)
229 rho0 = materialDensity;
230 else
231 rho0 = 1.;
232 }
233
234 return rho0;
235}
236
237void PDFFourierTransform2::convertToSQMinus1(std::vector<double> &FOfQ, std::vector<double> &Q,
238 std::vector<double> &DFOfQ, const std::vector<double> &DQ) {
239 // convert to S(Q)-1
240 string soqType = getProperty("SofQType");
241 string inputSOQType = getProperty("InputSofQType");
242 if (!isDefault("InputSofQType") && isDefault("SofQType")) {
243 soqType = inputSOQType;
244 g_log.warning() << "InputSofQType has been deprecated and replaced by SofQType\n";
245 }
246 if (soqType == S_OF_Q) {
247 g_log.information() << "Subtracting one from all values\n";
248 // there is no error propagation for subtracting one
249 std::for_each(FOfQ.begin(), FOfQ.end(), [](double &F) { F--; });
250 soqType = S_OF_Q_MINUS_ONE;
251 }
252 if (soqType == Q_S_OF_Q_MINUS_ONE) {
253 g_log.information() << "Dividing all values by Q\n";
254 // error propagation
255 for (size_t i = 0; i < DFOfQ.size(); ++i) {
256 DFOfQ[i] = (Q[i] / DQ[i] + FOfQ[i] / DFOfQ[i]) * (FOfQ[i] / Q[i]);
257 }
258 // convert the function
259 std::transform(FOfQ.begin(), FOfQ.end(), FOfQ.begin(), Q.begin(), std::divides<double>());
260 soqType = S_OF_Q_MINUS_ONE;
261 }
262 if (soqType != S_OF_Q_MINUS_ONE) {
263 // should never get here
264 std::stringstream msg;
265 msg << "Do not understand SofQType = " << soqType;
266 throw std::runtime_error(msg.str());
267 }
268 return;
269}
270
271void PDFFourierTransform2::convertToLittleGRMinus1(std::vector<double> &FOfR, const std::vector<double> &R,
272 std::vector<double> &DFOfR, const std::vector<double> &DR,
273 const std::string &PDFType, const double &rho0,
274 const double &cohScatLen) {
275 if (PDFType == LITTLE_G_OF_R) {
276 for (size_t i = 0; i < FOfR.size(); ++i) {
277 // transform the data
278 FOfR[i] = FOfR[i] - 1.0;
279 }
280 } else if (PDFType == BIG_G_OF_R) {
281 const double factor = 4. * M_PI * rho0;
282 for (size_t i = 0; i < FOfR.size(); ++i) {
283 // error propagation - assuming uncertainty in r = 0
284 DFOfR[i] = (R[i] / DR[i] + FOfR[i] / DFOfR[i]) * (FOfR[i] / R[i]);
285 // transform the data
286 FOfR[i] = FOfR[i] / (factor * R[i]);
287 }
288 } else if (PDFType == RDF_OF_R) {
289 const double factor = 4. * M_PI * rho0;
290 for (size_t i = 0; i < FOfR.size(); ++i) {
291 // error propagation - assuming uncertainty in r = 0
292 DFOfR[i] = (2.0 * R[i] / DR[i] + FOfR[i] / DFOfR[i]) * (FOfR[i] / R[i]);
293 // transform the data
294 FOfR[i] = FOfR[i] / (factor * R[i] * R[i]) - 1.0;
295 }
296 } else if (PDFType == G_K_OF_R) {
297 const double factor = 0.01 * pow(cohScatLen, 2);
298
299 for (size_t i = 0; i < FOfR.size(); ++i) {
300 // error propagation - assuming uncertainty in r = 0
301 DFOfR[i] = DFOfR[i] / factor;
302 // transform the data
303 FOfR[i] = FOfR[i] / factor;
304 }
305 }
306 return;
307}
308
309void PDFFourierTransform2::convertFromSQMinus1(HistogramData::HistogramY &FOfQ, const HistogramData::HistogramX &Q,
310 HistogramData::HistogramE &DFOfQ) {
311 // convert to S(Q)-1string
312 string soqType = getProperty("SofQType");
313 string inputSOQType = getProperty("InputSofQType");
314 if (!isDefault("InputSofQType") && isDefault("SofQType")) {
315 soqType = inputSOQType;
316 g_log.warning() << "InputSofQType has been deprecated and replaced by SofQType\n";
317 }
318 if (soqType == S_OF_Q) {
319 for (size_t i = 0; i < FOfQ.size(); ++i) {
320 // transform the data
321 FOfQ[i] = FOfQ[i] + 1.0;
322 }
323 } else if (soqType == Q_S_OF_Q_MINUS_ONE) {
324 for (size_t i = 0; i < FOfQ.size(); ++i) {
325 DFOfQ[i] = Q[i] * DFOfQ[i];
326 FOfQ[i] = FOfQ[i] * Q[i];
327 }
328 }
329 return;
330}
331
332void PDFFourierTransform2::convertFromLittleGRMinus1(HistogramData::HistogramY &FOfR,
333 const HistogramData::HistogramX &R,
334 HistogramData::HistogramE &DFOfR, const std::string &PDFType,
335 const double &rho0, const double &cohScatLen) {
336 // convert to the correct form of PDF
337 if (PDFType == LITTLE_G_OF_R) {
338 for (size_t i = 0; i < FOfR.size(); ++i) {
339 // transform the data
340 FOfR[i] = FOfR[i] + 1.0;
341 }
342 } else if (PDFType == BIG_G_OF_R) {
343 const double factor = 4. * M_PI * rho0;
344 for (size_t i = 0; i < FOfR.size(); ++i) {
345 // error propagation - assuming uncertainty in r = 0
346 DFOfR[i] = DFOfR[i] * R[i];
347 // transform the data
348 FOfR[i] = FOfR[i] * factor * R[i];
349 }
350 } else if (PDFType == RDF_OF_R) {
351 const double factor = 4. * M_PI * rho0;
352 for (size_t i = 0; i < FOfR.size(); ++i) {
353 // error propagation - assuming uncertainty in r = 0
354 DFOfR[i] = DFOfR[i] * R[i];
355 // transform the data
356 FOfR[i] = (FOfR[i] + 1.0) * factor * R[i] * R[i];
357 }
358 } else if (PDFType == G_K_OF_R) {
359 const double factor = 0.01 * pow(cohScatLen, 2);
360
361 for (size_t i = 0; i < FOfR.size(); ++i) {
362 // error propagation - assuming uncertainty in r = 0
363 DFOfR[i] = DFOfR[i] * factor;
364 // transform the data
365 FOfR[i] = FOfR[i] * factor;
366 }
367 }
368 return;
369}
370//----------------------------------------------------------------------------------------------
374 // get input data
375 API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
376 auto inputX = inputWS->x(0).rawData(); // x for input
377 std::vector<double> inputDX(inputX.size(), 0.0); // dx for input
378 if (inputWS->sharedDx(0))
379 inputDX = inputWS->dx(0).rawData();
380 auto inputY = inputWS->y(0).rawData(); // y for input
381 auto inputDY = inputWS->e(0).rawData(); // dy for input
382
383 // need bin edges
384 if (inputX.size() == inputY.size()) {
385 inputX = BinEdges(Points(inputWS->x(0))).rawData();
386 }
387
388 // transform input data into Q/MomentumTransfer
389 string direction = getProperty("Direction");
390 const std::string inputXunit = inputWS->getAxis(0)->unit()->unitID();
391 if (inputXunit == "MomentumTransfer") {
392 // nothing to do
393 } else if (inputXunit == "dSpacing") {
394 // convert the x-units to Q/MomentumTransfer
395 const double PI_2(2. * M_PI);
396 std::for_each(inputX.begin(), inputX.end(), [&PI_2](double &Q) { Q /= PI_2; });
397 std::transform(inputDX.begin(), inputDX.end(), inputX.begin(), inputDX.begin(), std::divides<double>());
398 // reverse all of the arrays
399 std::reverse(inputX.begin(), inputX.end());
400 std::reverse(inputDX.begin(), inputDX.end());
401 std::reverse(inputY.begin(), inputY.end());
402 std::reverse(inputDY.begin(), inputDY.end());
403 } else if (inputXunit == "AtomicDistance") {
404 // nothing to do
405 }
406 g_log.debug() << "Input unit is " << inputXunit << "\n";
407
408 // convert from histogram to density
409 if (!inputWS->isHistogramData()) {
410 g_log.warning() << "This algorithm has not been tested on density data "
411 "(only on histograms)\n";
412 /* Don't do anything for now
413 double deltaQ;
414 for (size_t i = 0; i < inputFOfQ.size(); ++i)
415 {
416 deltaQ = inputQ[i+1] -inputQ[i];
417 inputFOfQ[i] = inputFOfQ[i]*deltaQ;
418 inputDfOfQ[i] = inputDfOfQ[i]*deltaQ; // TODO feels wrong
419 inputQ[i] += -.5*deltaQ;
420 inputDQ[i] += .5*(inputDQ[i] + inputDQ[i+1]); // TODO running average
421 }
422 inputQ.emplace_back(inputQ.back()+deltaQ);
423 inputDQ.emplace_back(inputDQ.back()); // copy last value
424 */
425 }
426
427 const std::string PDFType = getProperty("PDFType");
428 double rho0 = determineRho0();
429 const Kernel::Material &material = inputWS->sample().getMaterial();
430 const auto cohScatLen = material.cohScatterLength();
431
432 // A material needs to be provided in order to calculate G_K(r)
433 if (PDFType == "G_k(r)" && cohScatLen == 0.0) {
434 std::stringstream msg;
435 msg << "Coherent Scattering Length is zero. Please check a sample material has been specified";
436 throw std::runtime_error(msg.str());
437 }
438
439 // convert to S(Q)-1 or g(R)+1
440 if (direction == FORWARD) {
441 convertToSQMinus1(inputY, inputX, inputDY, inputDX);
442 } else if (direction == BACKWARD) {
443 convertToLittleGRMinus1(inputY, inputX, inputDY, inputDX, PDFType, rho0, cohScatLen);
444 }
445
446 double inMin, inMax, outDelta, outMax;
447 inMin = getProperty("Qmin");
448 inMax = getProperty("Qmax");
449 outDelta = getProperty("DeltaR");
450 outMax = getProperty("Rmax");
451 if (isEmpty(outMax)) {
452 outMax = 20;
453 }
454 if (direction == BACKWARD) {
455 inMin = getProperty("Rmin");
456 inMax = getProperty("Rmax");
457 outDelta = getProperty("DeltaQ");
458 outMax = getProperty("Qmax");
459 if (isEmpty(outMax)) {
460 outMax = 40;
461 }
462 }
463
464 // determine input-range
465 size_t Xmin_index = determineMinIndex(inMin, inputX, inputY);
466 size_t Xmax_index = determineMaxIndex(inMax, inputX, inputY);
467 g_log.notice() << "Adjusting to data: input min = " << inputX[Xmin_index] << " input max = " << inputX[Xmax_index]
468 << "\n";
469 // determine r axis for result
470 if (isEmpty(outDelta))
471 outDelta = M_PI / inputX[Xmax_index];
472 auto sizer = static_cast<size_t>(outMax / outDelta);
473
474 bool filter = getProperty("Filter");
475
476 // create the output workspace
477
478 API::MatrixWorkspace_sptr outputWS = create<Workspace2D>(1, Points(sizer));
479 outputWS->copyExperimentInfoFrom(inputWS.get());
480 if (direction == FORWARD) {
481 outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("AtomicDistance");
482 outputWS->setYUnitLabel("PDF");
483 outputWS->mutableRun().addProperty("Qmin", inputX[Xmin_index], "Angstroms^-1", true);
484 outputWS->mutableRun().addProperty("Qmax", inputX[Xmax_index], "Angstroms^-1", true);
485 } else if (direction == BACKWARD) {
486 outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer");
487 outputWS->setYUnitLabel("Spectrum Density");
488 outputWS->mutableRun().addProperty("Rmin", inputX[Xmin_index], "Angstroms", true);
489 outputWS->mutableRun().addProperty("Rmax", inputX[Xmax_index], "Angstroms", true);
490 }
491 outputWS->setDistribution(true);
492 BinEdges edges(sizer + 1, LinearGenerator(outDelta / 2, outDelta));
493 outputWS->setBinEdges(0, edges);
494 auto &outputX = outputWS->mutableX(0);
495 g_log.information() << "Using output min = " << outputX.front() << "and output max = " << outputX.back() << "\n";
496 // always calculate G(r) then convert
497 auto &outputY = outputWS->mutableY(0);
498 auto &outputE = outputWS->mutableE(0);
499
500 // do the math
501 // Evaluate integral of Qsin(QR) over the Q bin width rather than just take value at bin centre
502 // Useful if Q bins widths are large - width typically increases with Q for TOF data. Following Gudrun approach
503
504 double corr = 0.5 / M_PI / M_PI / rho0;
505 if (direction == BACKWARD) {
506 corr = 4.0 * M_PI * rho0;
507 }
508 const double inXMax = inputX[Xmax_index];
509 for (size_t outXIndex = 0; outXIndex < sizer; outXIndex++) {
510 const double outX = 0.5 * (outputX[outXIndex] + outputX[outXIndex + 1]);
511 const double outXFac = corr / (outX * outX * outX);
512
513 double fs = 0;
514 double errorSquared = 0;
515 auto pdfIntegral = [outX](const double x) -> double { return sin(x * outX) - x * outX * cos(x * outX); };
516 double inX2 = inputX[Xmin_index];
517 double integralX2 = pdfIntegral(inX2);
518
519 for (size_t inXIndex = Xmin_index; inXIndex < Xmax_index; inXIndex++) {
520 const double inX1 = inX2;
521 inX2 = inputX[inXIndex + 1];
522 const double integralX1 = integralX2;
523 integralX2 = pdfIntegral(inX2);
524 double defIntegral = integralX2 - integralX1;
525
526 // multiply by filter function sin(q*pi/qmax)/(q*pi/qmax)
527 auto inXCen = 0.5 * (inX1 + inX2);
528 if (filter && fabs(inXCen) > 1e-8) {
529 const double lorchKernel = inXCen * M_PI / inXMax;
530 defIntegral *= sin(lorchKernel) / lorchKernel;
531 }
532 fs += defIntegral * inputY[inXIndex];
533
534 const double error = defIntegral * inputDY[inXIndex];
535 errorSquared += error * error;
536 }
537
538 // put the information into the output
539 outputY[outXIndex] = fs * outXFac;
540 outputE[outXIndex] = sqrt(errorSquared) * outXFac;
541 }
542
543 if (direction == FORWARD) {
544 convertFromLittleGRMinus1(outputY, outputX, outputE, PDFType, rho0, cohScatLen);
545 } else if (direction == BACKWARD) {
546 convertFromSQMinus1(outputY, outputX, outputE);
547 }
548
549 // set property
550 setProperty("OutputWorkspace", outputWS);
551}
552
553} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
double error
#define fabs(x)
Definition Matrix.cpp:22
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
bool isDefault(const std::string &name) const
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
A property class for workspaces.
void init() override
Initialize the properties.
size_t determineMinIndex(double min, const std::vector< double > &X, const std::vector< double > &Y)
void convertToLittleGRMinus1(std::vector< double > &FOfR, const std::vector< double > &R, std::vector< double > &DFOfR, const std::vector< double > &DR, const std::string &PDFType, const double &rho0, const double &cohScatLen)
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
int version() const override
Algorithm's version for identification.
size_t determineMaxIndex(double max, const std::vector< double > &X, const std::vector< double > &Y)
void convertFromSQMinus1(HistogramData::HistogramY &FOfQ, const HistogramData::HistogramX &Q, HistogramData::HistogramE &DFOfQ)
const std::string category() const override
Algorithm's category for identification.
void convertFromLittleGRMinus1(HistogramData::HistogramY &FOfR, const HistogramData::HistogramX &R, HistogramData::HistogramE &DFOfR, const std::string &PDFType, const double &rho0, const double &cohScatLen)
void convertToSQMinus1(std::vector< double > &FOfQ, std::vector< double > &Q, std::vector< double > &DFOfQ, const std::vector< double > &DQ)
const std::string name() const override
Algorithm's name for identification.
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 setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition Material.h:50
double cohScatterLength(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Get the coherent scattering length for a given wavelength in fm.
Definition Material.cpp:328
double numberDensity() const
Get the number density.
Definition Material.cpp:189
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54