Mantid
Loading...
Searching...
No Matches
RefinePowderInstrumentParameters.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
17#include "MantidAPI/IFunction.h"
20#include "MantidAPI/TableRow.h"
21#include "MantidAPI/TextAxis.h"
23
29
31
32#include <boost/algorithm/string.hpp>
33#include <boost/algorithm/string/split.hpp>
34
35#include <fstream>
36#include <iomanip>
37#include <utility>
38
39#include <gsl/gsl_sf_erf.h>
40
41using namespace Mantid;
42using namespace Mantid::API;
43using namespace Mantid::Kernel;
44using namespace Mantid::DataObjects;
48using namespace Mantid::HistogramData;
49
50using namespace std;
51
53
55
56//----------------------------------------------------------------------------------------------
60 : m_BestGSLChi2(0.0), m_MinSigma(0.0), m_MinNumFittedPeaks(0), m_MaxNumberStoredParameters(0) {
61 this->useAlgorithm("RefinePowderInstrumentParameters", 3);
62}
63
64//----------------------------------------------------------------------------------------------
68 // Input/output peaks table workspace
69 declareProperty(std::make_unique<API::WorkspaceProperty<DataObjects::TableWorkspace>>("BraggPeakParameterWorkspace",
70 "Anonymous", Direction::Input),
71 "TableWorkspace containg all peaks' parameters.");
72
73 // Input and output instrument parameters table workspace
75 "InstrumentParameterWorkspace", "AnonymousInstrument", Direction::InOut),
76 "TableWorkspace containg instrument's parameters.");
77
78 // Output workspace
79 declareProperty(std::make_unique<API::WorkspaceProperty<DataObjects::Workspace2D>>("OutputWorkspace", "AnonymousOut",
81 "Output Workspace2D for the d-TOF curves. ");
82
83 // Workspace to output fitted peak parameters
84 declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("OutputInstrumentParameterWorkspace",
85 "AnonymousOut2", Direction::Output),
86 "Output TableWorkspace for the fitted peak parameters for each peak.");
87
88 // Workspace to output N best MC parameters
89 declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("OutputBestResultsWorkspace", "",
91 "Output TableWorkspace for the N best MC fitting results. ");
92
93 // Lower limit on number of peaks for fitting
94 declareProperty("MinNumberFittedPeaks", 5, "Minimum number of fitted peaks for refining instrument parameters.");
95
96 // Refinement algorithm
97 vector<string> algoptions{"DirectFit", "MonteCarlo"};
98 auto validator = std::make_shared<Kernel::StringListValidator>(algoptions);
99 declareProperty("RefinementAlgorithm", "MonteCarlo", validator, "Algorithm to refine the instrument parameters.");
100
101 declareProperty("RandomWalkSteps", 10000, "Number of Monte Carlo random walk steps. ");
102
103 // Parameters to fit
104 declareProperty(std::make_unique<Kernel::ArrayProperty<std::string>>("ParametersToFit"),
105 "Names of the parameters to fit. ");
106
107 // Mininum allowed peak's sigma (avoid wrong fitting peak with very narrow
108 // width)
109 declareProperty("MinSigma", 1.0, "Minimum allowed value for Sigma of a peak.");
110
111 // Method to calcualte the standard error of peaks
112 vector<string> stdoptions{"ConstantValue", "InvertedPeakHeight"};
113 auto listvalidator = std::make_shared<Kernel::StringListValidator>(stdoptions);
114 declareProperty("StandardError", "ConstantValue", listvalidator,
115 "Algorithm to calculate the standard error of peak positions.");
116
117 declareProperty("NumberBestFitRecorded", 1, "Number of best fits (Monte Carlo) recorded and output. ");
118
119 declareProperty("MonteCarloRandomSeed", 0, "Random seed for Monte Carlo simulation. ");
120}
121
122//----------------------------------------------------------------------------------------------
126 enum { DirectFit, MonteCarlo } refinealgorithm;
127
128 // 1. Get input
129 DataObjects::TableWorkspace_sptr peakWS = this->getProperty("BraggPeakParameterWorkspace");
130 DataObjects::TableWorkspace_sptr parameterWS = this->getProperty("InstrumentParameterWorkspace");
131
132 m_MinSigma = getProperty("MinSigma");
133
134 int tempint = getProperty("MinNumberFittedPeaks");
135 if (tempint <= 1) {
136 g_log.error() << "Input MinNumberFittedPeaks = " << tempint << " is too small. \n";
137 throw std::invalid_argument("Input MinNumberFittedPeaks is too small.");
138 }
139 m_MinNumFittedPeaks = static_cast<size_t>(tempint);
140
141 tempint = getProperty("NumberBestFitRecorded");
142 if (tempint <= 0)
143 throw runtime_error("Input NumberBestFitRecorded cannot be less and equal to 0. ");
144 m_MaxNumberStoredParameters = static_cast<size_t>(tempint);
145
146 string algoption = getProperty("RefinementAlgorithm");
147 if (algoption == "DirectFit")
148 refinealgorithm = DirectFit;
149 else if (algoption == "MonteCarlo")
150 refinealgorithm = MonteCarlo;
151 else
152 throw runtime_error("RefinementAlgorithm other than DirectFit and "
153 "MonteCarlo are not supported.");
154
155 // 2. Parse input table workspace
156 genPeaksFromTable(peakWS);
159
160 // 3. Generate a cener workspace as function of d-spacing.
161 bool usemc = false;
162 if (refinealgorithm == MonteCarlo)
163 usemc = true;
165
166 // 4. Fit instrument geometry function
167 stringstream errss;
168 TableWorkspace_sptr mcresultws;
169
170 switch (refinealgorithm) {
171 case DirectFit:
172 // a) Simple (directly) fit all parameters
174 break;
175
176 case MonteCarlo:
177 // b) Use Monte Carlo/Annealing method to search global minimum
178 refineInstrumentParametersMC(parameterWS, true);
179 mcresultws = genMCResultTable();
180 setProperty("OutputBestResultsWorkspace", mcresultws);
181 break;
182
183 default:
184 // c) Unsupported
185 errss << "Refinement algorithm " << algoption << " is not supported. Quit!";
186 g_log.error(errss.str());
187 throw invalid_argument(errss.str());
188 break;
189 }
190
191 // 5. Set output workspace
192 this->setProperty("OutputWorkspace", m_dataWS);
193
194 // 6. Output new instrument parameters
196 this->setProperty("OutputInstrumentParameterWorkspace", fitparamws);
197}
198
199//------- Related to Fitting Instrument Geometry Function -------------------
200
204 g_log.debug() << "=========== Method [FitInstrumentParameters] ===============\n";
205
206 // 1. Initialize the fitting function
207 m_Function = std::make_shared<ThermalNeutronDtoTOFFunction>();
208 m_Function->initialize();
209
210 API::FunctionDomain1DVector domain(m_dataWS->x(1).rawData());
211 API::FunctionValues values(domain);
212 const auto &rawY = m_dataWS->y(0);
213 const auto &rawE = m_dataWS->e(0);
214
215 // 2. Set up parameters values
216 std::vector<std::string> funparamnames = m_Function->getParameterNames();
217
218 std::vector<std::string> paramtofit = getProperty("ParametersToFit");
219 std::sort(paramtofit.begin(), paramtofit.end());
220
221 stringstream msgss;
222 msgss << "Set Instrument Function Parameter : \n";
223 std::map<std::string, double>::iterator paramiter;
224 for (const auto &parname : funparamnames) {
225 paramiter = m_FuncParameters.find(parname);
226 if (paramiter == m_FuncParameters.end()) {
227 // Not found and thus skip
228 continue;
229 }
230
231 double parvalue = paramiter->second;
232 m_Function->setParameter(parname, parvalue);
233 msgss << setw(10) << parname << " = " << parvalue << '\n';
234 }
235 g_log.debug() << msgss.str();
236
237 // 2b. Calculate the statistic of the starting values
238 double gslchi2 = calculateFunctionStatistic(m_Function, m_dataWS, 0);
239 double homchi2 = calculateD2TOFFunction(m_Function, domain, values, rawY, rawE);
240 g_log.debug() << "Fit Starting Value: Chi^2 (GSL) = " << gslchi2 << ", Chi2^2 (Home) = " << homchi2 << '\n';
241
242 // 3. Fix parameters that are not listed in parameter-to-fit. Unfix the rest
243 size_t numparams = funparamnames.size();
244 for (size_t i = 0; i < numparams; ++i) {
245 string parname = funparamnames[i];
246 vector<string>::iterator vsiter;
247 vsiter = std::find(paramtofit.begin(), paramtofit.end(), parname);
248
249 if (vsiter == paramtofit.end())
250 m_Function->fix(i);
251 else
252 m_Function->unfix(i);
253 }
254
255 // 4. Select minimizer. Use Simplex for more than 1 parameters to fit.
256 // Levenberg-MarquardtMD otherwise
257 string minimizer("Levenberg-MarquardtMD");
258 if (paramtofit.size() > 1) {
259 minimizer = "Simplex";
260 }
261 g_log.information() << "Fit use minizer: " << minimizer << '\n';
262
263 // 5. Create and setup fit algorithm
264 g_log.information() << "Fit instrument geometry: " << m_Function->asString() << '\n';
265
266 stringstream outss;
267 for (size_t i = 0; i < m_dataWS->x(0).size(); ++i)
268 outss << m_dataWS->x(0)[i] << "\t\t" << m_dataWS->y(0)[i] << "\t\t" << m_dataWS->e(0)[i] << '\n';
269 g_log.debug() << "Input Peak Position Workspace To Fit: \n" << outss.str() << '\n';
270
271 auto fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
272 fitalg->initialize();
273
274 fitalg->setProperty("Function", std::dynamic_pointer_cast<API::IFunction>(m_Function));
275 fitalg->setProperty("InputWorkspace", m_dataWS);
276 fitalg->setProperty("WorkspaceIndex", 0);
277 fitalg->setProperty("Minimizer", minimizer);
278 fitalg->setProperty("CostFunction", "Least squares");
279 fitalg->setProperty("MaxIterations", 1000);
280
281 bool successfulfit = fitalg->execute();
282 if (!fitalg->isExecuted() || !successfulfit) {
283 // Early return due to bad fit
284 g_log.error() << "Fitting to instrument geometry function failed. \n";
285 throw std::runtime_error("Fitting failed.");
286 }
287
288 double chi2 = fitalg->getProperty("OutputChi2overDoF");
289 std::string fitstatus = fitalg->getProperty("OutputStatus");
290
291 g_log.debug() << "Fit Result (GSL): Chi^2 = " << chi2 << "; Fit Status = " << fitstatus << '\n';
292
293 API::IFunction_sptr fitfunc = fitalg->getProperty("Function");
294
295 // 4. Set the output data (model and diff)
296 m_Function->function(domain, values);
297
298 for (size_t i = 0; i < domain.size(); ++i) {
299 m_dataWS->mutableY(1)[i] = values[i];
300 m_dataWS->mutableY(2)[i] = m_dataWS->y(0)[i] - values[i];
301 }
302
303 double selfchi2 = calculateD2TOFFunction(m_Function, domain, values, rawY, rawE);
304 g_log.debug() << "Homemade Chi^2 = " << selfchi2 << '\n';
305
306 // 5. Update fitted parameters
307 for (const auto &parname : funparamnames) {
308 double parvalue = fitfunc->getParameter(parname);
309 m_FuncParameters[parname] = parvalue;
310 }
311
312 // 6. Pretty screen output
313 stringstream dbss;
314 dbss << "************ Fit Parameter Result *************\n";
315 for (paramiter = m_FuncParameters.begin(); paramiter != m_FuncParameters.end(); ++paramiter) {
316 std::string parname = paramiter->first;
317 double inpparvalue = m_OrigParameters[parname];
318 double parvalue = paramiter->second;
319 dbss << setw(20) << parname << " = " << setw(15) << setprecision(6) << parvalue << "\t\tFrom " << setw(15)
320 << setprecision(6) << inpparvalue << "\t\tDiff = " << inpparvalue - parvalue << '\n';
321 }
322 dbss << "*********************************************\n";
323 g_log.debug() << dbss.str();
324
325 // 7. Play with Zscore: template<typename TYPE>
326 // std::vector<double> getZscore(const std::vector<TYPE>& data, const bool
327 // sorted=false);
328 vector<double> z0 = Kernel::getZscore(m_dataWS->y(0).rawData());
329 vector<double> z1 = Kernel::getZscore(m_dataWS->y(1).rawData());
330 vector<double> z2 = Kernel::getZscore(m_dataWS->y(2).rawData());
331 stringstream zss;
332 zss << setw(20) << "d_h" << setw(20) << "Z DataY" << setw(20) << "Z ModelY" << setw(20) << "Z DiffY" << setw(20)
333 << "DiffY\n";
334 const auto &X = m_dataWS->x(0);
335 const auto &Y = m_dataWS->y(2);
336 for (size_t i = 0; i < z0.size(); ++i) {
337 double d_h = X[i];
338 double zdatay = z0[i];
339 double zmodely = z1[i];
340 double zdiffy = z2[i];
341 double diffy = Y[i];
342 zss << setw(20) << d_h << setw(20) << zdatay << setw(20) << zmodely << setw(20) << zdiffy << setw(20) << diffy
343 << '\n';
344 }
345 g_log.debug() << "Zscore Survey: \b" << zss.str();
346}
347
351 auto fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
352 fitalg->initialize();
353
354 fitalg->setProperty("Function", std::dynamic_pointer_cast<API::IFunction>(func));
355 fitalg->setProperty("InputWorkspace", m_dataWS);
356 fitalg->setProperty("WorkspaceIndex", 0);
357 fitalg->setProperty("Minimizer", "Simplex");
358 fitalg->setProperty("CostFunction", "Least squares");
359 fitalg->setProperty("MaxIterations", 1000);
360
361 bool successfulfit = fitalg->execute();
362 if (!fitalg->isExecuted() || !successfulfit) {
363 // Early return due to bad fit
364 g_log.error() << "Fitting to instrument geometry function failed. \n";
365 throw std::runtime_error("Fitting failed.");
366 }
367
368 gslchi2 = fitalg->getProperty("OutputChi2overDoF");
369 std::string fitstatus = fitalg->getProperty("OutputStatus");
370
371 g_log.debug() << "Function Fit: Chi^2 = " << gslchi2 << "; Fit Status = " << fitstatus << '\n';
372
373 bool fitgood = (fitstatus == "success");
374
375 return fitgood;
376}
377
381 const MatrixWorkspace_sptr &dataws,
382 size_t workspaceindex) {
383 // 1. Fix all parameters of the function
384 vector<string> funcparameters = func->getParameterNames();
385 size_t numparams = funcparameters.size();
386 for (size_t i = 0; i < numparams; ++i) {
387 func->fix(i);
388 }
389
390 // 2. Call a non fit refine
391 auto fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
392 fitalg->initialize();
393
394 fitalg->setProperty("Function", std::dynamic_pointer_cast<API::IFunction>(func));
395 fitalg->setProperty("InputWorkspace", dataws);
396 fitalg->setProperty("WorkspaceIndex", static_cast<int>(workspaceindex));
397 fitalg->setProperty("Minimizer", "Levenberg-MarquardtMD");
398 fitalg->setProperty("CostFunction", "Least squares");
399 fitalg->setProperty("MaxIterations", 2);
400
401 bool successfulfit = fitalg->execute();
402 if (!fitalg->isExecuted() || !successfulfit) {
403 // Early return due to bad fit
404 g_log.error() << "Fitting to instrument geometry function failed. \n";
405 throw std::runtime_error("Fitting failed.");
406 }
407
408 double chi2 = fitalg->getProperty("OutputChi2overDoF");
409 std::string fitstatus = fitalg->getProperty("OutputStatus");
410
411 g_log.debug() << "Function calculation [L.M]: Chi^2 = " << chi2 << "; Fit Status = " << fitstatus << '\n';
412
413 return chi2;
414}
415
419 // 1. Get function's parameter names
421
422 // 2. Parse parameter (table) workspace
423 vector<double> stepsizes, lowerbounds, upperbounds;
424 importMonteCarloParametersFromTable(parameterWS, m_PeakFunctionParameterNames, stepsizes, lowerbounds, upperbounds);
425
426 stringstream dbss;
427 for (size_t i = 0; i < m_PeakFunctionParameterNames.size(); ++i) {
428 dbss << setw(20) << m_PeakFunctionParameterNames[i] << ": Min = " << setw(15) << setprecision(6) << lowerbounds[i]
429 << ", Max = " << setw(15) << setprecision(6) << upperbounds[i] << ", Step Size = " << setw(15)
430 << setprecision(6) << stepsizes[i] << '\n';
431 }
432 g_log.notice() << "Monte Carlo Parameters: \n" << dbss.str();
433
434 // 3. Maximum step size
435 size_t maxsteps;
436 int tempint = getProperty("RandomWalkSteps");
437 if (tempint > 0)
438 maxsteps = static_cast<size_t>(tempint);
439 else
440 throw runtime_error("RandomwWalkSteps cannot be less than or equal to 0. ");
441
442 // 4. Random seed and step size rescale factor
443 int randomseed = getProperty("MonteCarloRandomSeed");
444 srand(randomseed);
445
446 double stepsizescalefactor = 1.1;
447
448 // 5. Monte Carlo simulation
449 doParameterSpaceRandomWalk(m_PeakFunctionParameterNames, lowerbounds, upperbounds, stepsizes, maxsteps,
450 stepsizescalefactor, fit2);
451
452 // 6. Record the result
453 const auto &X = m_dataWS->x(0);
454 const auto &Y = m_dataWS->y(0);
455 const auto &E = m_dataWS->e(0);
456 FunctionDomain1DVector domain(X.rawData());
457 FunctionValues values(domain);
458 for (size_t i = 0; i < m_BestFitParameters.size(); ++i) {
459 // a. Set the function with the
460 for (size_t j = 0; j < m_PeakFunctionParameterNames.size(); ++j) {
461 m_Function->setParameter(m_PeakFunctionParameterNames[j], m_BestFitParameters[i].second[j]);
462 }
463
464 // b. Calculate
465 calculateD2TOFFunction(m_Function, domain, values, Y, E);
466
467 vector<double> vec_n;
469
470 // c. Put the data to output workspace
471 auto &newY = m_dataWS->mutableY(3 * i + 1);
472 auto &newD = m_dataWS->mutableY(3 * i + 2);
473 auto &newN = m_dataWS->mutableY(3 * i + 3);
474 for (size_t j = 0; j < newY.size(); ++j) {
475 newY[j] = values[j];
476 newD[j] = Y[j] - values[j];
477 newN[j] = vec_n[j];
478 }
479 }
480}
481
486void RefinePowderInstrumentParameters::doParameterSpaceRandomWalk(vector<string> parnames, vector<double> lowerbounds,
487 vector<double> upperbounds, vector<double> stepsizes,
488 size_t maxsteps, double stepsizescalefactor,
489 bool fit2) {
490
491 // 1. Set up starting values, esp. to m_Function
492 size_t numparameters = parnames.size();
493 vector<double> paramvalues;
494 for (size_t i = 0; i < numparameters; ++i) {
495 string parname = parnames[i];
496 double parvalue = m_FuncParameters[parname];
497 paramvalues.emplace_back(parvalue);
498 m_Function->setParameter(parname, parvalue);
499 }
500
501 // Calcualte the function's initial statistic
503 g_log.debug() << "Function with starting values has Chi2 = " << m_BestGSLChi2 << " (GSL L.M) \n";
504
505 const auto &X = m_dataWS->x(0);
506 const auto &rawY = m_dataWS->y(0);
507 const auto &rawE = m_dataWS->e(0);
508 FunctionDomain1DVector domain(X.rawData());
509 FunctionValues values(domain);
510
511 // 2. Determine the parameters to fit
512 vector<string> paramstofit = getProperty("ParametersToFit");
513 set<string> paramstofitset;
514 bool refineallparams;
515 if (paramstofit.empty()) {
516 // Default case to refine all parameters
517 refineallparams = true;
518 } else {
519 // Refine part of the parameters
520 refineallparams = false;
521 vector<string>::iterator vsiter;
522 for (vsiter = paramstofit.begin(); vsiter != paramstofit.end(); ++vsiter) {
523 paramstofitset.insert(*vsiter);
524 }
525 }
526
527 stringstream dbss;
528 set<string>::iterator setiter;
529 for (setiter = paramstofitset.begin(); setiter != paramstofitset.end(); ++setiter) {
530 string name = *setiter;
531 dbss << setw(20) << name;
532 }
533 g_log.notice() << "Parameters to refine: " << dbss.str() << '\n';
534
535 // 3. Create a local function for fit and set the parameters unfixed
537 std::shared_ptr<ThermalNeutronDtoTOFFunction>(new ThermalNeutronDtoTOFFunction());
538 func4fit->initialize();
539 for (size_t i = 0; i < numparameters; ++i) {
540 string parname = parnames[i];
541 // Fit or fix
542 if (paramstofitset.count(parname) > 0)
543 func4fit->unfix(i);
544 else
545 func4fit->fix(i);
546 // Constraint
547 double lowerb = lowerbounds[i];
548 double upperb = upperbounds[i];
549 auto newconstraint = std::make_unique<BoundaryConstraint>(func4fit.get(), parname, lowerb, upperb);
550 func4fit->addConstraint(std::move(newconstraint));
551 }
552 g_log.debug() << "Function for fitting in MC: " << func4fit->asString() << '\n';
553
554 // 4. Do MC loops
555 double curchi2 = calculateD2TOFFunction(m_Function, domain, values, rawY, rawE);
556
557 g_log.notice() << "Monte Carlo Random Walk Starting Chi^2 = " << curchi2 << '\n';
558
559 size_t paramindex = 0;
560 size_t numacceptance = 0;
561 for (size_t istep = 0; istep < maxsteps; ++istep) {
562 // a. Determine whether to refine this parameter
563 if (!refineallparams) {
564 if (paramstofitset.count(parnames[paramindex]) == 0) {
565 ++paramindex;
566 if (paramindex >= parnames.size())
567 paramindex = 0;
568 continue;
569 }
570 }
571
572 // b. Propose for a new value
573 double randomnumber = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
574 double newvalue = paramvalues[paramindex] + (randomnumber - 1.0) * stepsizes[paramindex];
575 if (newvalue > upperbounds[paramindex]) {
576 newvalue = lowerbounds[paramindex] + (newvalue - upperbounds[paramindex]);
577 } else if (newvalue < lowerbounds[paramindex]) {
578 newvalue = upperbounds[paramindex] - (lowerbounds[paramindex] - newvalue);
579 }
580
581 try {
582 m_Function->setParameter(parnames[paramindex], newvalue);
583 } catch (runtime_error &) {
584 stringstream errss;
585 errss << "New Value = " << newvalue << ", Random Number = " << randomnumber
586 << "Step Size = " << stepsizes[paramindex] << ", Step size rescale factor = " << stepsizescalefactor;
587 g_log.error(errss.str());
588 throw;
589 }
590
591 // b. Calcualte the new
592 double newchi2 = calculateD2TOFFunction(m_Function, domain, values, rawY, rawE);
593
594 // Optionally fit
595 if (fit2) {
596 // i. Copy the parameters
597 for (size_t i = 0; i < numparameters; ++i) {
598 double parvalue = m_Function->getParameter(i);
599 func4fit->setParameter(i, parvalue);
600 }
601
602 // ii. Fit function
603 double gslchi2;
604 bool fitgood = fitFunction(func4fit, gslchi2);
605
606 if (fitgood) {
607 // iii. Caculate
608 double homchi2 = calculateD2TOFFunction(func4fit, domain, values, rawY, rawE);
609
610 if (gslchi2 < m_BestGSLChi2)
611 m_BestGSLChi2 = gslchi2;
612
613 // iv. Archive
614 vector<double> newparvalues;
615 newparvalues.reserve(numparameters);
616 for (size_t i = 0; i < numparameters; ++i) {
617 double parvalue = func4fit->getParameter(i);
618 newparvalues.emplace_back(parvalue);
619 }
620 m_BestFitParameters.emplace_back(homchi2, newparvalues);
621 m_BestFitChi2s.emplace_back(homchi2, gslchi2);
622
623 // v. Sort and keep in size
624 sort(m_BestFitParameters.begin(), m_BestFitParameters.end());
625 sort(m_BestFitChi2s.begin(), m_BestFitChi2s.end());
627 m_BestFitParameters.pop_back();
628 m_BestFitChi2s.pop_back();
629 }
630 }
631 }
632
633 // c. Accept?
634 bool accept;
635 double prob = exp(-(newchi2 - curchi2) / curchi2);
636 double randnumber = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
637 accept = randnumber < prob;
638
639 // d. Adjust step size
640 if (false) {
641 if (newchi2 < curchi2) {
642 // Decrease step size if it approaches a minima
643 stepsizes[paramindex] = stepsizes[paramindex] / stepsizescalefactor;
644 } else {
645 // Increase step size if it diverges
646 double newstepsize = stepsizes[paramindex] * stepsizescalefactor;
647 double maxstepsize = upperbounds[paramindex] - lowerbounds[paramindex];
648 if (newstepsize >= maxstepsize) {
649 newstepsize = maxstepsize;
650 }
651 stepsizes[paramindex] = newstepsize;
652 }
653 }
654
655 // e. Record the solution
656 if (accept) {
657 // i. Accept the new value
658 paramvalues[paramindex] = newvalue;
659
660 // ii. Add the new values to vector
661 m_BestMCParameters.emplace_back(newchi2, paramvalues);
662
663 // iii. Sort and delete the last if necessary
664 sort(m_BestMCParameters.begin(), m_BestMCParameters.end());
666 m_BestMCParameters.pop_back();
667
668 // iv. Update chi2 and ...
669 curchi2 = newchi2;
670 ++numacceptance;
671 }
672
673 // z. Update the parameter index for next movement
674 ++paramindex;
675 if (paramindex >= numparameters)
676 paramindex = 0;
677
678 } // FOREACH MC Step
679
680 // 3. Debug output
681 stringstream mcresult;
682 mcresult << "Monte Carlo Result for " << m_BestMCParameters.size() << " Best Results\n";
683 mcresult << "Number of acceptance = " << numacceptance << ", out of " << maxsteps << " MC steps."
684 << "Accept ratio = " << static_cast<double>(numacceptance) / static_cast<double>(maxsteps) << '\n';
685 mcresult << "Best " << m_BestMCParameters.size() << " Monte Carlo (no fit) results: \n";
686 for (size_t i = 0; i < m_BestMCParameters.size(); ++i) {
687 mcresult << setw(3) << i << ": Chi^2 = " << m_BestMCParameters[i].first << '\n';
688 }
689 mcresult << "Best " << m_BestMCParameters.size() << " fitting results. Best Chi^2 = " << m_BestGSLChi2 << '\n';
690 for (size_t i = 0; i < m_BestFitParameters.size(); ++i) {
691 mcresult << setw(3) << i << ": Chi^2 = " << m_BestFitParameters[i].first
692 << ", GSL Chi^2 = " << m_BestFitChi2s[i].second << '\n';
693 }
694 g_log.notice() << mcresult.str();
695}
696
700 // 1. Clear output
701 parnames.clear();
702
703 // 2. Get the parameter names from function
704 m_Function = std::make_shared<ThermalNeutronDtoTOFFunction>();
705 std::vector<std::string> funparamnames = m_Function->getParameterNames();
706
707 // 3. Copy
708 parnames = funparamnames;
709}
710
714 const API::FunctionDomain1DVector &domain,
715 API::FunctionValues &values,
716 const Mantid::HistogramData::HistogramY &rawY,
717 const Mantid::HistogramData::HistogramE &rawE) {
718 // 1. Check validity
719 if (!func) {
720 throw std::runtime_error("m_Function has not been initialized!");
721 }
722
723 if (domain.size() != values.size() || domain.size() != rawY.size() || rawY.size() != rawE.size()) {
724 throw std::runtime_error("Input domain, values and raw data have different sizes.");
725 }
726
727 // 2. Calculate vlaues
728 func->function(domain, values);
729
730 // 3. Calculate the difference
731 double chi2 = 0;
732 for (size_t i = 0; i < domain.size(); ++i) {
733 double temp = (values[i] - rawY[i]) / rawE[i];
734 chi2 += temp * temp;
735 // cout << "Peak " << i << ": Model = " << values[i] << ", Data = " <<
736 // rawY[i] << ". Standard Error = " << rawE[i] << '\n';
737 }
738
739 return chi2;
740}
741
742//------------------------------- Processing Inputs
743//----------------------------------------
748 // 1. Check and clear input and output
749 if (!peakparamws) {
750 g_log.error() << "Input tableworkspace for peak parameters is invalid!\n";
751 throw std::invalid_argument("Invalid input table workspace for peak parameters");
752 }
753
754 m_Peaks.clear();
755
756 // 2. Parse table workspace rows to generate peaks
757 vector<string> colnames = peakparamws->getColumnNames();
758 size_t numrows = peakparamws->rowCount();
759
760 for (size_t ir = 0; ir < numrows; ++ir) {
761 // a) Generate peak
762 BackToBackExponential_sptr newpeakptr = std::make_shared<BackToBackExponential>();
763 newpeakptr->initialize();
764
765 // b) Parse parameters
766 int h, k, l;
767 double alpha, beta, tof_h, sigma, sigma2, chi2, height, dbtemp;
768 string strtemp;
769 sigma2 = -1;
770
771 API::TableRow row = peakparamws->getRow(ir);
772 for (auto &colname : colnames) {
773 if (colname == "H")
774 row >> h;
775 else if (colname == "K")
776 row >> k;
777 else if (colname == "L")
778 row >> l;
779 else if (colname == "Alpha")
780 row >> alpha;
781 else if (colname == "Beta")
782 row >> beta;
783 else if (colname == "Sigma2")
784 row >> sigma2;
785 else if (colname == "Sigma")
786 row >> sigma;
787 else if (colname == "Chi2")
788 row >> chi2;
789 else if (colname == "Height")
790 row >> height;
791 else if (colname == "TOF_h")
792 row >> tof_h;
793 else {
794 try {
795 row >> dbtemp;
796 } catch (runtime_error &) {
797 row >> strtemp;
798 }
799 }
800 }
801
802 if (sigma2 > 0)
803 sigma = sqrt(sigma2);
804
805 // c) Set peak parameters and etc.
806 newpeakptr->setParameter("A", alpha);
807 newpeakptr->setParameter("B", beta);
808 newpeakptr->setParameter("S", sigma);
809 newpeakptr->setParameter("X0", tof_h);
810 newpeakptr->setParameter("I", height);
811
812 std::vector<int> hkl;
813 hkl.emplace_back(h);
814 hkl.emplace_back(k);
815 hkl.emplace_back(l);
816
817 m_Peaks.emplace(hkl, newpeakptr);
818
819 m_PeakErrors.emplace(hkl, chi2);
820
821 g_log.information() << "[Generatem_Peaks] Peak " << ir << " HKL = [" << hkl[0] << ", " << hkl[1] << ", " << hkl[2]
822 << "], Input Center = " << setw(10) << setprecision(6) << newpeakptr->centre() << '\n';
823
824 } // ENDFOR Each potential peak
825}
826
831 std::map<std::string, double> &parameters) {
832 // 1. Check column orders
833 std::vector<std::string> colnames = parameterWS->getColumnNames();
834 if (colnames.size() < 2) {
835 g_log.error() << "Input parameter table workspace does not have enough "
836 "number of columns. "
837 << " Number of columns = " << colnames.size() << " < 3 as required. \n";
838 throw std::runtime_error("Input parameter workspace is wrong. ");
839 }
840
841 if (colnames[0] != "Name" || colnames[1] != "Value") {
842 g_log.error() << "Input parameter table workspace does not have the "
843 "columns in order. "
844 << " It must be Name, Value, FitOrTie.\n";
845 throw std::runtime_error("Input parameter workspace is wrong. ");
846 }
847
848 // 2. Import data to maps
849 std::string parname;
850 double value;
851
852 size_t numrows = parameterWS->rowCount();
853
854 for (size_t ir = 0; ir < numrows; ++ir) {
855 try {
856 API::TableRow trow = parameterWS->getRow(ir);
857 trow >> parname >> value;
858 parameters.emplace(parname, value);
859 } catch (runtime_error &) {
860 g_log.error() << "Import table workspace " << parameterWS->getName() << " error in line " << ir << ". "
861 << " Requires [string, double] in the first 2 columns.\n";
862 throw;
863 }
864 }
865}
866
871 const vector<string> &parameternames,
872 vector<double> &stepsizes,
873 vector<double> &lowerbounds,
874 vector<double> &upperbounds) {
875 // 1. Get column information
876 vector<string> colnames = tablews->getColumnNames();
877 size_t imax, imin, istep;
878 imax = colnames.size() + 1;
879 imin = imax;
880 istep = imax;
881
882 for (size_t i = 0; i < colnames.size(); ++i) {
883 if (colnames[i] == "Max")
884 imax = i;
885 else if (colnames[i] == "Min")
886 imin = i;
887 else if (colnames[i] == "StepSize")
888 istep = i;
889 }
890
891 if (imax > colnames.size() || imin > colnames.size() || istep > colnames.size()) {
892 stringstream errss;
893 errss << "Input parameter workspace misses information for Monte Carlo "
894 "minimizer. "
895 << "One or more of the following columns are missing (Max, Min, "
896 "StepSize).";
897 g_log.error(errss.str());
898 throw runtime_error(errss.str());
899 }
900
901 // 2. Parse input to a map
902 stepsizes.clear();
903 lowerbounds.clear();
904 upperbounds.clear();
905
906 map<string, vector<double>> mcparameters;
907 size_t numrows = tablews->rowCount();
908 for (size_t ir = 0; ir < numrows; ++ir) {
909 TableRow row = tablews->getRow(ir);
910 string parname;
911 double tmax, tmin, tstepsize;
912 row >> parname;
913 for (size_t ic = 1; ic < colnames.size(); ++ic) {
914 double tmpdbl = std::numeric_limits<float>::quiet_NaN();
915 string tmpstr;
916 try {
917 row >> tmpdbl;
918 } catch (runtime_error &) {
919 g_log.error() << "Import MC parameter " << colnames[ic] << " error in row " << ir << " of workspace "
920 << tablews->getName() << '\n';
921 row >> tmpstr;
922 g_log.error() << "Should be " << tmpstr << '\n';
923 }
924
925 if (ic == imax)
926 tmax = tmpdbl;
927 else if (ic == imin)
928 tmin = tmpdbl;
929 else if (ic == istep)
930 tstepsize = tmpdbl;
931 }
932 vector<double> tmpvec;
933 tmpvec.emplace_back(tmin);
934 tmpvec.emplace_back(tmax);
935 tmpvec.emplace_back(tstepsize);
936 mcparameters.emplace(parname, tmpvec);
937 }
938
939 // 3. Retrieve the information for geometry parameters
940 for (const auto &parname : parameternames) {
941 // a) Get on hold of the MC parameter vector
942 auto mit = mcparameters.find(parname);
943 if (mit == mcparameters.end()) {
944 // Not found the parameter. raise error!
945 stringstream errss;
946 errss << "Input instrument parameter workspace does not have parameter " << parname
947 << ". Information is incomplete for Monte Carlo simulation.\n";
948 g_log.error(errss.str());
949 throw runtime_error(errss.str());
950 }
951 vector<double> mcparvalues = mit->second;
952
953 // b) Build for the output
954 lowerbounds.emplace_back(mcparvalues[0]);
955 upperbounds.emplace_back(mcparvalues[1]);
956 stepsizes.emplace_back(mcparvalues[2]);
957 }
958}
959
978 const HistogramX &xVals, vector<double> &vec_n) {
979 if (m_Function->name() != "ThermalNeutronDtoTOFFunction") {
980 g_log.warning() << "Function (" << m_Function->name()
981 << " is not ThermalNeutronDtoTOFFunction. And it is not "
982 "required to calculate n.\n";
983 for (size_t i = 0; i < xVals.size(); ++i)
984 vec_n.emplace_back(0);
985 }
986
987 double width = m_Function->getParameter("Width");
988 double tcross = m_Function->getParameter("Tcross");
989
990 for (double dh : xVals) {
991 double n = 0.5 * gsl_sf_erfc(width * (tcross - 1 / dh));
992 vec_n.emplace_back(n);
993 }
994}
995
996//------- Related to Algorith's Output
997//-------------------------------------------------------------------
998
1003void RefinePowderInstrumentParameters::genPeakCentersWorkspace(bool montecarlo, size_t numbestfit) {
1004 // 1. Collect values in a vector for sorting
1005 double lattice = m_FuncParameters["LatticeConstant"];
1006 if (lattice < 1.0E-5) {
1007 std::stringstream errmsg;
1008 errmsg << "Input Lattice constant = " << lattice << " is wrong or not set up right. ";
1009 throw std::invalid_argument(errmsg.str());
1010 }
1011
1012 string stdoption = getProperty("StandardError");
1013 enum { ConstantValue, InvertedPeakHeight } stderroroption;
1014 if (stdoption == "ConstantValue") {
1015 stderroroption = ConstantValue;
1016 } else if (stdoption == "InvertedPeakHeight") {
1017 stderroroption = InvertedPeakHeight;
1018 } else {
1019 stringstream errss;
1020 errss << "Input StandardError (" << stdoption << ") is not supported. ";
1021 g_log.error(errss.str());
1022 throw runtime_error(errss.str());
1023 }
1024
1025 std::map<std::vector<int>, BackToBackExponential_sptr>::iterator peakiter;
1026 std::vector<std::pair<double, std::pair<double, double>>> peakcenters; // d_h [TOF_h, CHI2]
1027
1028 Geometry::UnitCell unitcell(lattice, lattice, lattice, 90.0, 90.0, 90.0);
1029
1030 for (peakiter = m_Peaks.begin(); peakiter != m_Peaks.end(); ++peakiter) {
1031 vector<int> hkl = peakiter->first;
1032 BackToBackExponential_sptr peak = peakiter->second;
1033
1034 double sigma = peak->getParameter("S");
1035 if (sigma < m_MinSigma) {
1036 g_log.information() << "Peak (" << hkl[0] << ", " << hkl[1] << ", " << hkl[2]
1037 << ") has unphysically small Sigma = " << sigma << ". "
1038 << "It is thus excluded. \n";
1039 continue;
1040 }
1041
1042 /* Replaced by UnitCell
1043 double dh = calculateDspaceValue(hkl, lattice);
1044 */
1045 double dh = unitcell.d(hkl[0], hkl[1], hkl[2]);
1046 double center = peak->centre();
1047 double height = peak->height();
1048 double chi2;
1049 if (stderroroption == ConstantValue) {
1050 chi2 = 1.0;
1051 } else if (stderroroption == InvertedPeakHeight) {
1052 chi2 = sqrt(1.0 / height);
1053 } else {
1054 throw runtime_error("Standard error option is not supported. ");
1055 }
1056
1057 peakcenters.emplace_back(dh, make_pair(center, chi2));
1058 }
1059
1060 // 2. Sort by d-spacing value
1061 std::sort(peakcenters.begin(), peakcenters.end());
1062
1063 // 3. Create output workspace
1064 size_t size = peakcenters.size();
1065 size_t nspec;
1066 if (montecarlo) {
1067 // Monte Carlo, 1 + 2*N spectra: raw, N x (refined, diff, n)
1068 nspec = 1 + 3 * numbestfit;
1069 } else {
1070 // Regular fit, 3 spectra: raw, refined, diff, n
1071 nspec = 1 + 3;
1072 }
1073
1074 m_dataWS = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
1075 API::WorkspaceFactory::Instance().create("Workspace2D", nspec, size, size));
1076 m_dataWS->getAxis(0)->setUnit("dSpacing");
1077
1078 // 4. Put data to output workspace
1079 for (size_t i = 0; i < peakcenters.size(); ++i) {
1080 for (size_t j = 0; j < nspec; ++j) {
1081 m_dataWS->mutableX(j)[i] = peakcenters[i].first;
1082 }
1083 m_dataWS->mutableY(0)[i] = peakcenters[i].second.first;
1084 m_dataWS->mutableE(0)[i] = peakcenters[i].second.second;
1085 }
1086}
1087
1092 // 1. Create table workspace
1093 DataObjects::TableWorkspace_sptr tablews = std::make_shared<TableWorkspace>();
1094
1095 tablews->addColumn("double", "Chi2");
1096 tablews->addColumn("double", "GSLChi2");
1097 for (auto &peakFunctionParameterName : m_PeakFunctionParameterNames) {
1098 tablews->addColumn("double", peakFunctionParameterName);
1099 }
1100
1101 // 2. Put values in
1102 for (size_t ib = 0; ib < m_BestFitParameters.size(); ++ib) {
1103 TableRow newrow = tablews->appendRow();
1104 double chi2 = m_BestFitParameters[ib].first;
1105 double gslchi2 = m_BestFitChi2s[ib].second;
1106 newrow << chi2 << gslchi2;
1107 for (size_t ip = 0; ip < m_PeakFunctionParameterNames.size(); ++ip) {
1108 double tempdbl = m_BestFitParameters[ib].second[ip];
1109 newrow << tempdbl;
1110 }
1111 } // ENDFOR 1 Best Answer
1112
1113 return tablews;
1114}
1115
1122 // TableWorkspace is not copyable (default CC is incorrect and no point in
1123 // writing a non-default one)
1125 std::shared_ptr<DataObjects::TableWorkspace>(new DataObjects::TableWorkspace());
1126 newtablews->addColumn("str", "Name");
1127 newtablews->addColumn("double", "Value");
1128 newtablews->addColumn("str", "FitOrTie");
1129 newtablews->addColumn("double", "Min");
1130 newtablews->addColumn("double", "Max");
1131 newtablews->addColumn("double", "StepSize");
1132
1133 std::map<std::string, double>::iterator pariter;
1134
1135 for (pariter = m_FuncParameters.begin(); pariter != m_FuncParameters.end(); ++pariter) {
1136 API::TableRow newrow = newtablews->appendRow();
1137 std::string parname = pariter->first;
1138 double parvalue = pariter->second;
1139 newrow << parname << parvalue;
1140 }
1141
1142 return newtablews;
1143}
1144
1145} // namespace Mantid::CurveFitting::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
double sigma
Definition: GetAllEi.cpp:156
double height
Definition: GetAllEi.cpp:155
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
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
Implements FunctionDomain1D with its own storage in form of a std::vector.
size_t size() const override
Return the number of arguments in the domain.
A class to store values calculated by a function.
size_t size() const
Return the number of values.
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
A property class for workspaces.
RefinePowderInstrumentParameters : Algorithm to refine instrument geometry parameters only.
void genPeaksFromTable(const DataObjects::TableWorkspace_sptr &peakparamws)
Generate peaks from table (workspace)
void importMonteCarloParametersFromTable(const DataObjects::TableWorkspace_sptr &tablews, const std::vector< std::string > &parameternames, std::vector< double > &stepsizes, std::vector< double > &lowerbounds, std::vector< double > &upperbounds)
Import the Monte Carlo related parameters from table.
std::map< std::string, double > m_OrigParameters
Map to store the original (input) parameters.
bool fitFunction(const API::IFunction_sptr &func, double &gslchi2)
Fit function to data.
void doParameterSpaceRandomWalk(std::vector< std::string > parnames, std::vector< double > lowerbounds, std::vector< double > upperbounds, std::vector< double > stepsizes, size_t maxsteps, double stepsizescalefactor, bool fit2)
Core Monte Carlo random walk on parameter-space.
std::vector< std::string > m_PeakFunctionParameterNames
Peak function parameter names.
double calculateD2TOFFunction(const API::IFunction_sptr &func, const API::FunctionDomain1DVector &domain, API::FunctionValues &values, const Mantid::HistogramData::HistogramY &rawY, const Mantid::HistogramData::HistogramE &rawE)
Calculate the value and chi2.
size_t m_MinNumFittedPeaks
Minimum number of fitted peaks for refinement.
void importParametersFromTable(const DataObjects::TableWorkspace_sptr &parameterWS, std::map< std::string, double > &parameters)
Import instrument parameter from table (workspace)
void fitInstrumentParameters()
Fit instrument geometry parameters by ThermalNeutronDtoTOFFunction.
Functions::ThermalNeutronDtoTOFFunction_sptr m_Function
Modelling function.
std::map< std::string, double > m_FuncParameters
Map for function (instrument parameter)
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
std::vector< std::pair< double, std::vector< double > > > m_BestFitParameters
N sets of the peak parameter values for the best N chi2 for MC.
std::map< std::vector< int >, double > m_PeakErrors
Map for all peaks' error (fitted vs. experimental): [HKL]: Chi^2.
std::map< std::vector< int >, Functions::BackToBackExponential_sptr > m_Peaks
Map for all peaks to fit individually.
double calculateFunctionStatistic(const API::IFunction_sptr &func, const API::MatrixWorkspace_sptr &dataws, size_t workspaceindex)
Calculate function's statistic.
DataObjects::Workspace2D_sptr m_dataWS
Output Workspace containing the dspacing ~ TOF peak positions.
DataObjects::TableWorkspace_sptr genMCResultTable()
Generate an output table workspace for N best fitting result.
void calculateThermalNeutronSpecial(const API::IFunction_sptr &m_Function, const Mantid::HistogramData::HistogramX &xVals, std::vector< double > &vec_n)
Calculate d-space value from peak's miller index for thermal neutron.
void getD2TOFFuncParamNames(std::vector< std::string > &parnames)
Get the names of the parameters of D-TOF conversion function.
std::vector< std::pair< double, std::vector< double > > > m_BestMCParameters
N sets of the peak parameter values for the best N chi2 for MC.
void genPeakCentersWorkspace(bool montecarlo, size_t numbestfit)
Generate (output) workspace of peak centers.
std::vector< std::pair< double, double > > m_BestFitChi2s
N sets of the homemade chi2 and gsl chi2.
DataObjects::TableWorkspace_sptr genOutputInstrumentParameterTable()
Generate (output) table worksspace for instrument parameters.
void refineInstrumentParametersMC(const DataObjects::TableWorkspace_sptr &parameterWS, bool fit2=false)
Set up and run a monte carlo simulation to refine the peak parameters.
TableWorkspace is an implementation of Workspace in which the data are organised in columns of same s...
Class to implement unit cell of crystals.
Definition: UnitCell.h:44
double d(double h, double k, double l) const
Return d-spacing ( ) for a given h,k,l coordinate.
Definition: UnitCell.cpp:700
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 debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< ThermalNeutronDtoTOFFunction > ThermalNeutronDtoTOFFunction_sptr
std::shared_ptr< BackToBackExponential > BackToBackExponential_sptr
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::vector< double > getZscore(const std::vector< TYPE > &data)
Return the Z score values for a dataset.
Definition: Statistics.cpp:81
Helper class which provides the Collimation Length for SANS instruments.
STL namespace.
@ 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