15#include "MantidHistogramData/HistogramX.h"
16#include "MantidHistogramData/HistogramY.h"
21#include <boost/algorithm/string.hpp>
46using Mantid::HistogramData::HistogramX;
47using Mantid::HistogramData::HistogramY;
61 : m_lebailFunction(), m_dataWS(), m_outputWS(), parameterWS(), reflectionWS(), m_wsIndex(0), m_startX(DBL_MAX),
62 m_endX(DBL_MIN), m_inputPeakInfoVec(), m_backgroundFunction(), m_funcParameters(), m_origFuncParameters(),
63 m_peakType(), m_backgroundType(), m_backgroundParameters(), m_backgroundParameterNames(), m_bkgdorder(0),
64 mPeakRadius(0), m_lebailFitChi2(0.), m_lebailCalChi2(0.), mMinimizer(), m_dampingFactor(0.),
65 m_inputParameterPhysical(false), m_fitMode(), m_indicatePeakHeight(0.), m_MCGroups(), m_numMCGroups(0),
66 m_bestRwp(0.), m_bestRp(0.), m_bestParameters(), m_bestBackgroundData(), m_bestMCStep(0), m_numMinimizeSteps(0),
67 m_Temperature(DBL_MIN), m_useAnnealing(false), m_walkStyle(RANDOMWALK), m_minimumPeakHeight(DBL_MAX),
68 m_tolerateInputDupHKL2Peaks(false), m_bkgdParameterNames(), m_numberBkgdParameters(0), m_bkgdParameterBuffer(),
69 m_bestBkgdParams(), m_roundBkgd(0), m_bkgdParameterStepVec(), m_peakCentreTol(0.) {}
79 "Input workspace containing the data to fit by LeBail algorithm.");
83 "Output workspace containing calculated pattern or "
84 "calculated background. ");
89 "Input table workspace containing the parameters "
90 "required by LeBail fit. ");
93 auto tablewsprop1 = std::make_unique<WorkspaceProperty<TableWorkspace>>(
95 this->
declareProperty(std::move(tablewsprop1),
"Input table workspace containing the "
96 "parameters required by LeBail fit. ");
100 "Input table workspace containing the list of reflections (HKL). ");
103 auto tablewsprop2 = std::make_unique<WorkspaceProperty<TableWorkspace>>(
"OutputPeaksWorkspace",
"",
Direction::Output,
105 this->
declareProperty(std::move(tablewsprop2),
"Optional output table workspace "
106 "containing all peaks' peak "
110 this->
declareProperty(
"WorkspaceIndex", 0,
"Workspace index of the spectrum to fit by LeBail.");
114 "Region of data (TOF) for LeBail fit. Default is whole range. ");
117 std::vector<std::string> functions{
"LeBailFit",
"Calculation",
"MonteCarlo",
"RefineBackground"};
118 auto validator = std::make_shared<Kernel::StringListValidator>(functions);
119 this->
declareProperty(
"Function",
"LeBailFit", validator,
"Functionality");
122 vector<string> peaktypes{
"ThermalNeutronBk2BkExpConvPVoigt",
"NeutronBk2BkExpConvPVoigt"};
123 auto peaktypevalidator = std::make_shared<StringListValidator>(peaktypes);
124 declareProperty(
"PeakType",
"ThermalNeutronBk2BkExpConvPVoigt", peaktypevalidator,
"Peak profile type.");
129 std::vector<std::string> bkgdtype{
"Polynomial",
"Chebyshev",
"FullprofPolynomial"};
130 auto bkgdvalidator = std::make_shared<Kernel::StringListValidator>(bkgdtype);
131 declareProperty(
"BackgroundType",
"Polynomial", bkgdvalidator,
"Background type");
135 "Optional: enter a comma-separated list of background order parameters "
139 auto tablewsprop3 = std::make_unique<WorkspaceProperty<TableWorkspace>>(
141 this->
declareProperty(std::move(tablewsprop3),
"Optional table workspace containing the fit result for background.");
144 this->
declareProperty(
"PeakRadius", 5,
"Range (multiplier relative to FWHM) for a full peak. ");
149 declareProperty(
"PlotIndividualPeaks",
false,
"Option to output each individual peak in mode Calculation.");
151 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"Calculation"));
155 "Heigh of peaks (reflections) if its calculated height is "
156 "smaller than user-defined minimum.");
158 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"Calculation"));
162 "For 'Calculation' mode only, use peak heights specified in "
163 "ReflectionWorkspace. "
164 "Otherwise, calcualte peaks' heights. ");
166 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"Calculation"));
171 std::vector<std::string> minimizerOptions = API::FuncMinimizerFactory::Instance().getKeys();
174 "The minimizer method applied to do the fit, default is "
175 "Levenberg-Marquardt",
179 declareProperty(
"Damping", 1.0,
"Damping factor if minimizer is 'Damped Gauss-Newton'");
183 declareProperty(
"NumberMinimizeSteps", 100,
"Number of Monte Carlo random walk steps.");
185 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"LeBailFit"));
187 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"MonteCarlo"));
189 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"RefineBackground"));
193 auto mcwsprop = std::make_unique<WorkspaceProperty<TableWorkspace>>(
"MCSetupWorkspace",
"",
Direction::Input,
195 declareProperty(std::move(mcwsprop),
"Name of table workspace containing parameters' "
196 "setup for Monte Carlo simualted annearling. ");
203 "Temperature used Monte Carlo. "
204 "Negative temperature is for simulated annealing. ");
206 std::make_unique<VisibleWhenProperty>(
"Function",
IS_EQUAL_TO,
"MonteCarlo"));
208 declareProperty(
"UseAnnealing",
true,
"Allow annealing temperature adjusted automatically.");
212 "Flag to use drunken walk algorithm. "
213 "Otherwise, random walk algorithm is used. ");
217 "Minimum height of a peak to be counted "
218 "during smoothing background by exponential smooth algorithm. ");
222 "Flag to allow degenerated peaks in input .hkl file. "
223 "Otherwise, an exception will be thrown if this situation occurs.");
227 "Tolerance in TOF to import peak from Bragg "
228 "peaks list. If it specified, all peaks within Xmin-Tol and "
229 "Xmax+Tol will be imported. "
230 "It is used in the case that the geometry parameters are "
231 "close to true values. ");
262 g_log.
warning() <<
"Input instrument parameters values cause some peaks to have "
263 "unphysical profile parameters.\n";
265 g_log.
warning() <<
"Function mode FIT is disabled. Convert to Calculation mode.\n";
277 g_log.
notice() <<
"Function: Pattern Calculation.\n";
283 g_log.
notice() <<
"Function: Do LeBail Fit ==> Monte Carlo.\n";
287 g_log.
notice(
"Function: Do LeBail Fit By Monte Carlo Random Walk.");
295 g_log.
notice() <<
"Function: Refine Background (Precisely).\n";
301 std::stringstream errmsg;
302 errmsg <<
"FunctionMode = " <<
m_fitMode <<
" is not supported in exec().";
304 throw std::runtime_error(errmsg.str());
317 g_log.
notice() <<
"\nFinal R factor: Rwp = " << finalR.
Rwp <<
", Rp = " << finalR.
Rp
344 g_log.
warning(
"Bkpos is out side of data range. It MIGHT NOT BE RIGHT. ");
349 for (
size_t i = i0; i < numparams; ++i) {
351 parss <<
"A" << (i - i0);
356 "input vector sized "
357 << numparams <<
".\n";
359 g_log.
information() <<
"[Input] Use background specified by table workspace.\n";
368 throw runtime_error(
"FullprofPolynomial: Bkpos must be given! ");
374 throw runtime_error(
"There is something wrong to set up FullprofPolynomial. ");
378 throw runtime_error(
"Polynomial and Chebyshev at least be order 0 (1 parameter). ");
399 Rfactor rfactor(-DBL_MAX, -DBL_MAX);
402 bool useinputpeakheights = this->
getProperty(
"UseInputPeakHeights");
403 if (useinputpeakheights)
404 g_log.
warning(
"UseInputPeakHeights is temporarily turned off now. ");
411 vector<double> emptyvec;
412 bool resultphysical =
425 bool ploteachpeak = this->
getProperty(
"PlotIndividualPeaks");
426 g_log.
information() <<
"Output individual peaks = " << ploteachpeak <<
".\n";
435 par_rwp.
name =
"Rwp";
439 g_log.
notice() <<
"Rwp = " << rfactor.
Rwp <<
", Rp = " << rfactor.
Rp <<
"\n";
441 if (!resultphysical) {
442 g_log.
warning() <<
"Input parameters are unable to generate peaks that are physical."
472 vector<double> valueVec(vecX.size(), 0);
473 size_t numpts = vecX.size();
479 Rfactor currR(DBL_MAX, DBL_MAX);
481 vector<double> backgroundvalues = values.
toVector();
482 for (
size_t i = 0; i < numpts; ++i) {
489 backgroundvalues, valueVec, currR);
493 bufss <<
"Starting background parameter ";
496 bufss <<
". Starting Rwp = " << currR.
Rwp;
505 Rfactor newR(DBL_MAX, DBL_MAX);
507 backgroundvalues = values.
toVector();
508 for (
size_t i = 0; i < numpts; ++i) {
514 backgroundvalues, valueVec, newR);
527 if (newR.
Rwp < bestR.
Rwp) {
533 ss <<
"Temp best background parameter ";
548 bufss1 <<
"Best background parameter ";
553 Rfactor outputR(-DBL_MAX, -DBL_MAX);
555 backgroundvalues = values.
toVector();
556 for (
size_t i = 0; i < numpts; ++i) {
562 backgroundvalues, valueVec, outputR);
564 g_log.
notice() <<
"[RefineBackground] Best Rwp = " << bestR.
Rwp <<
", vs. recovered best Rwp = " << outputR.
Rwp
570 for (
size_t i = 0; i < numpts; ++i) {
571 vecY1[i] = valueVec[i] + backgroundvalues[i];
572 vecY2[i] = vecY[i] - (valueVec[i] + backgroundvalues[i]);
581 auto outtablews = std::make_shared<TableWorkspace>();
582 outtablews->addColumn(
"str",
"Name");
583 outtablews->addColumn(
"double",
"Value");
584 outtablews->addColumn(
"double",
"Error");
589 TableRow newrow = outtablews->appendRow();
590 newrow << parname << parvalue << 1.0;
593 setProperty(
"BackgroundParametersWorkspace", outtablews);
623 double r = 2 * (
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX) - 0.5);
626 g_log.
information() <<
"[DBx804] Background " << iparam <<
" propose new value = " << newvalue <<
" from "
627 << currvalue <<
".\n";
646 throw runtime_error(
"Function parameters must be set up by this point.");
657 vector<vector<int>> vecHKL;
658 vector<pair<vector<int>,
double>>::iterator piter;
660 vecHKL.emplace_back(piter->first);
675 std::vector<double> fitrange = this->
getProperty(
"FitRegion");
677 double tof_min, tof_max;
678 if (fitrange.empty()) {
679 tof_min = inpws->x(wsindex)[0];
680 tof_max = inpws->x(wsindex).back();
681 }
else if (fitrange.size() == 2) {
682 tof_min = fitrange[0];
683 tof_max = fitrange[1];
685 g_log.
warning() <<
"Input FitRegion has more than 2 entries. Using "
686 "default in stread.\n";
688 tof_min = inpws->x(wsindex)[0];
689 tof_max = inpws->x(wsindex).back();
694 cropalg->initialize();
696 cropalg->setProperty(
"InputWorkspace", inpws);
697 cropalg->setPropertyValue(
"OutputWorkspace",
"MyData");
698 cropalg->setProperty(
"XMin", tof_min);
699 cropalg->setProperty(
"XMax", tof_max);
701 bool cropstatus = cropalg->execute();
703 std::stringstream errmsg;
704 errmsg <<
"DBx309 Cropping workspace unsuccessful. Fatal Error. Quit!";
706 throw std::runtime_error(errmsg.str());
711 g_log.
error(
"Unable to retrieve a Workspace2D object from ChildAlgorithm "
713 throw runtime_error(
"Unable to retrieve a Workspace2D object from "
714 "ChildAlgorithm CropWorkspace");
716 g_log.
debug() <<
"DBx307: Cropped Workspace... Range From " << cropws->x(wsindex)[0] <<
" To "
717 << cropws->x(wsindex).back() <<
" of size " << cropws->x(wsindex).size() <<
"\n";
736 int tempindex = this->
getProperty(
"WorkspaceIndex");
739 if (
m_wsIndex >= inpWS->getNumberHistograms()) {
742 errss <<
"Input WorkspaceIndex " << tempindex <<
" is out of boundary [0, " << inpWS->getNumberHistograms()
745 throw runtime_error(errss.str());
762 std::string function = this->
getProperty(
"Function");
764 if (function ==
"Calculation") {
767 }
else if (function ==
"CalculateBackground") {
770 }
else if (function ==
"MonteCarlo") {
773 }
else if (function ==
"LeBailFit") {
776 }
else if (function ==
"RefineBackground") {
781 errss <<
"Function mode " << function <<
" is not supported by LeBailFit().";
783 throw invalid_argument(errss.str());
794 errss <<
"Input number of random walk steps (" <<
m_numMinimizeSteps <<
") cannot be less and equal to zero.";
796 throw invalid_argument(errss.str());
816 g_log.
error() <<
"Input parameter table workspace does not have enough "
817 "number of columns. "
818 <<
" Number of columns (Input =" <<
parameterWS->columnCount() <<
") >= 3 as required.\n";
819 throw std::invalid_argument(
"Input parameter workspace is wrong. ");
827 std::vector<std::string> colnames =
parameterWS->getColumnNames();
828 size_t numcols = colnames.size();
830 std::map<std::string, double> tempdblmap;
831 std::map<std::string, std::string> tempstrmap;
832 std::map<std::string, double>::iterator dbliter;
833 std::map<string, string>::iterator striter;
837 std::string strvalue;
839 for (
size_t ir = 0; ir < numrows; ++ir) {
848 for (
size_t icol = 0; icol < numcols; ++icol) {
849 colname = colnames[icol];
850 if (colname !=
"FitOrTie" && colname !=
"Name") {
852 g_log.
debug() <<
"Col-name = " << colname <<
", ";
854 g_log.
debug() <<
"Value = " << dblvalue <<
".\n";
856 tempdblmap.emplace(colname, dblvalue);
859 g_log.
debug() <<
"Col-name = " << colname <<
", ";
861 strvalue.erase(std::find_if(strvalue.rbegin(), strvalue.rend(), std::not_fn(::isspace)).base(), strvalue.end());
863 g_log.
debug() <<
"Value = " << strvalue <<
".\n";
864 tempstrmap.emplace(colname, strvalue);
871 striter = tempstrmap.find(
"Name");
872 if (striter != tempstrmap.end()) {
873 newparameter.
name = striter->second;
875 std::stringstream errmsg;
876 errmsg <<
"Parameter (table) workspace " <<
parameterWS->getName()
877 <<
" does not contain column 'Name'. It is not a valid input. "
880 throw std::invalid_argument(errmsg.str());
884 striter = tempstrmap.find(
"FitOrTie");
885 if (striter != tempstrmap.end()) {
886 std::string fitortie = striter->second;
888 if (fitortie.length() > 0) {
889 char fc = fitortie.c_str()[0];
890 if (fc ==
't' || fc ==
'T') {
894 newparameter.
fit = tofit;
896 std::stringstream errmsg;
897 errmsg <<
"Parameter (table) workspace " <<
parameterWS->getName()
898 <<
" does not contain column 'FitOrTie'. It is not a valid "
901 throw std::invalid_argument(errmsg.str());
905 dbliter = tempdblmap.find(
"Value");
906 if (dbliter != tempdblmap.end()) {
907 newparameter.
curvalue = dbliter->second;
909 std::stringstream errmsg;
910 errmsg <<
"Parameter (table) workspace " <<
parameterWS->getName()
911 <<
" does not contain column 'Value'. It is not a valid input. "
914 throw std::invalid_argument(errmsg.str());
918 dbliter = tempdblmap.find(
"Min");
919 if (dbliter != tempdblmap.end()) {
920 newparameter.
minvalue = dbliter->second;
926 dbliter = tempdblmap.find(
"Max");
927 if (dbliter != tempdblmap.end()) {
928 newparameter.
maxvalue = dbliter->second;
934 dbliter = tempdblmap.find(
"StepSize");
935 if (dbliter != tempdblmap.end()) {
936 newparameter.
stepsize = dbliter->second;
954 if (newparameter.
fit) {
957 <<
"], MC Step = " << newparameter.
stepsize <<
", Fit? = " << newparameter.
fit <<
"\n";
973 std::vector<std::string> colnames =
reflectionWS->getColumnNames();
974 if (colnames.size() < 3) {
975 g_log.
error() <<
"Input parameter table workspace does not have enough "
976 "number of columns. "
977 <<
" Number of columns = " << colnames.size() <<
" < 3 as required.\n";
978 throw std::runtime_error(
"Input parameter workspace is wrong. ");
980 if (colnames[0] !=
"H" || colnames[1] !=
"K" || colnames[2] !=
"L") {
982 errss <<
"Input Bragg peak parameter TableWorkspace does not have the "
984 <<
"It must be H, K, L. for the first 3 columns.";
986 throw std::runtime_error(errss.str());
990 bool hasPeakHeight =
false;
991 if (colnames.size() >= 4 && colnames[3] ==
"PeakHeight") {
993 hasPeakHeight =
true;
1009 for (
size_t ir = 0; ir < numrows; ++ir) {
1012 trow >> h >> k >> l;
1015 std::vector<int> hkl;
1016 hkl.emplace_back(h);
1017 hkl.emplace_back(k);
1018 hkl.emplace_back(l);
1021 double peakheight = 1.0;
1022 if (hasPeakHeight) {
1029 g_log.
information() <<
"Imported HKL TableWorkspace. Size of Rows = " << numrows <<
"\n";
1037 vector<double> &bkgdorderparams) {
1038 g_log.
debug() <<
"DB1105A Parsing background TableWorkspace.\n";
1041 bkgdorderparams.clear();
1044 std::vector<std::string> colnames = bkgdparamws->getColumnNames();
1045 if (colnames.size() < 2) {
1047 errss <<
"Input background parameter table workspace " << bkgdparamws->getName() <<
" has only " << colnames.size()
1048 <<
" columns, which is fewer than 2 columns as required. ";
1050 throw runtime_error(errss.str());
1052 if (!(colnames[0].starts_with(
"Name") && colnames[1].starts_with(
"Value"))) {
1055 errss <<
"Input parameter table workspace have wrong column definition. "
1056 <<
"Column 0 should be Name. And column 1 should be Value. "
1057 "Current input is: \n";
1058 for (
size_t i = 0; i < 2; ++i)
1059 errss <<
"Column " << i <<
": " << colnames[0] <<
"\n";
1061 throw runtime_error(errss.str());
1067 std::map<std::string, double> parmap;
1068 for (
size_t ir = 0; ir < bkgdparamws->rowCount(); ++ir) {
1070 std::string parname;
1072 row >> parname >> parvalue;
1075 boost::algorithm::trim(parname);
1077 if (!parname.empty() && (parname[0] ==
'A' || parname ==
"Bkpos")) {
1080 parmap.emplace(parname, parvalue);
1085 bkgdparnames.reserve(parmap.size());
1086 bkgdorderparams.reserve(parmap.size());
1088 std::map<std::string, double>::iterator mit;
1089 for (mit = parmap.begin(); mit != parmap.end(); ++mit) {
1090 std::string parname = mit->first;
1091 double parvalue = mit->second;
1092 bkgdparnames.emplace_back(parname);
1093 bkgdorderparams.emplace_back(parvalue);
1097 std::stringstream msg;
1098 msg <<
"Finished importing background TableWorkspace. "
1099 <<
"Background Order = " << bkgdorderparams.size() <<
": ";
1100 for (
size_t iod = 0; iod < bkgdorderparams.size(); ++iod) {
1101 msg << bkgdparnames[iod] <<
" = " << bkgdorderparams[iod] <<
"; ";
1116 peakWS->addColumn(
"int",
"H");
1117 peakWS->addColumn(
"int",
"K");
1118 peakWS->addColumn(
"int",
"L");
1119 peakWS->addColumn(
"double",
"Height");
1120 peakWS->addColumn(
"double",
"TOF_h");
1121 peakWS->addColumn(
"double",
"Alpha");
1122 peakWS->addColumn(
"double",
"Beta");
1123 peakWS->addColumn(
"double",
"Sigma2");
1124 peakWS->addColumn(
"double",
"Gamma");
1125 peakWS->addColumn(
"double",
"FWHM");
1126 peakWS->addColumn(
"int",
"PeakGroup");
1127 peakWS->addColumn(
"double",
"Chi^2");
1128 peakWS->addColumn(
"str",
"FitStatus");
1137 peak->getMillerIndex(h, k, l);
1138 double tof_h = peak->centre();
1139 double height = peak->height();
1140 double alpha = peak->getPeakParameter(
"Alpha");
1141 double beta = peak->getPeakParameter(
"Beta");
1142 double sigma2 = peak->getPeakParameter(
"Sigma2");
1143 double gamma = peak->getPeakParameter(
"Gamma");
1144 double fwhm = peak->fwhm();
1148 newrow << h << k << l <<
height << tof_h << alpha << beta << sigma2 << gamma << fwhm << -1 << -1.0 <<
"N/A";
1152 errss <<
"Peak (" << h <<
", " << k <<
", " << l <<
"): TOF_h (=" << tof_h <<
") is NEGATIVE!";
1158 this->
setProperty(
"OutputPeaksWorkspace", peakWS);
1180 tablews->
addColumn(
"double",
"StepSize");
1181 tablews->
addColumn(
"double",
"StartValue");
1185 std::map<std::string, Parameter>::const_iterator paramiter;
1186 std::map<std::string, double>::iterator opiter;
1187 for (paramiter = parammap.begin(); paramiter != parammap.end(); ++paramiter) {
1188 std::string parname = paramiter->first;
1189 if (parname !=
"Height") {
1193 double parvalue = paramiter->second.curvalue;
1196 char fitortie =
't';
1197 if (paramiter->second.fit) {
1200 std::stringstream ss;
1202 std::string fit_tie = ss.str();
1206 double origparvalue = -1.0E100;
1208 origparvalue = opiter->second;
1210 double diff = origparvalue - parvalue;
1213 double paramerror = paramiter->second.fiterror;
1216 double min = paramiter->second.minvalue;
1217 double max = paramiter->second.maxvalue;
1218 double step = paramiter->second.stepsize;
1221 newparam << parname << parvalue << fit_tie << paramerror << min << max << step << origparvalue << diff;
1228 throw runtime_error(
"Impossible to have this situation happen. Flag 541.");
1238 fitchi2row <<
"FitChi2" <<
m_lebailFitChi2 <<
"t" << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
1240 chi2row <<
"Chi2" <<
m_lebailCalChi2 <<
"t" << 0.0 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
1244 setProperty(
"OutputParameterWorkspace", parameterws);
1267 bool plotindpeak = this->
getProperty(
"PlotIndividualPeaks");
1278 m_outputWS = std::dynamic_pointer_cast<DataObjects::Workspace2D>(
1283 for (
size_t j = 0; j <
m_outputWS->getNumberHistograms(); ++j)
1293 auto tAxis = std::make_unique<API::TextAxis>(nspec);
1294 tAxis->setLabel(0,
"Data");
1295 tAxis->setLabel(1,
"Calc");
1296 tAxis->setLabel(2,
"Diff");
1297 tAxis->setLabel(3,
"CalcNoBkgd");
1298 tAxis->setLabel(4,
"OutBkgd");
1299 tAxis->setLabel(5,
"InpCalc");
1300 tAxis->setLabel(6,
"InBkgd");
1301 tAxis->setLabel(7,
"DataNoBkgd");
1302 tAxis->setLabel(8,
"SmoothedBkgd");
1306 for (
size_t i = 0; i < (nspec - 9); ++i) {
1307 std::stringstream ss;
1309 tAxis->setLabel(9 + i, ss.str());
1313 m_outputWS->replaceAxis(1, std::move(tAxis));
1330 std::vector<double> vecCalPurePeaks(domain.size(), 0.0);
1354 Rfactor startR(-DBL_MAX, -DBL_MAX);
1357 HistogramY vecBkgd =
m_lebailFunction->function(vecX.rawData(),
false,
true);
1367 if (!startvaluevalid) {
1369 throw runtime_error(
"Starting value of instrument profile parameters can "
1370 "generate peaks with"
1371 " unphyiscal parameters values.");
1374 doMarkovChain(parammap, vecX, vecPurePeak, vecBkgd.rawData(), maxcycles, startR, randomseed);
1377 Rfactor finalR(-DBL_MAX, -DBL_MAX);
1387 vecCalY = vecCalPurePeaks;
1390 vecDiff = vecInY - vecCalY;
1392 vecCalPurePeak = vecCalPurePeaks;
1394 vecCalBkgd = vecInY - vecCalPurePeaks;
1399 par_rwp.
name =
"Rwp";
1401 parammap[
"Rwp"] = par_rwp;
1408 const Mantid::HistogramData::HistogramY &vecPurePeak,
const vector<double> &vecBkgd,
1409 size_t maxcycles,
const Rfactor &startR,
int randomseed) {
1412 Rfactor currR(-DBL_MAX, -DBL_MAX), newR(-DBL_MAX, -DBL_MAX);
1414 map<string, Parameter> mapCurrParameter = parammap;
1415 map<string, Parameter> newparammap = mapCurrParameter;
1417 std::vector<double> veccalpurepeaks(vecX.size(), 0.0);
1425 g_log.
notice() <<
"[MC-Start] Random-walk Starting Rwp = " << currR.Rwp <<
", Rp = " << currR.Rp <<
"\n";
1429 vector<double> vecIndex(maxcycles + 1);
1430 vector<Rfactor> vecR(maxcycles + 1);
1431 size_t numinvalidmoves = 0;
1432 size_t numacceptance = 0;
1433 bool prevcyclebetterR =
true;
1436 int numRecentAcceptance = 0;
1437 int numRecentSteps = 0;
1438 int numConsecutiveInvalid = 0;
1443 int numMaxConsecutiveInvalid = 5;
1444 int m_numStepsCheckTemperature = 10;
1449 for (
size_t icycle = 1; icycle <= maxcycles; ++icycle) {
1458 bool hasnewvalues =
proposeNewValues(MCGroup.second, currR, mapCurrParameter, newparammap, prevcyclebetterR);
1460 if (!hasnewvalues) {
1470 g_log.
debug() <<
"[Calculation] Rwp = " << newR.
Rwp <<
", Rp = " << newR.
Rp <<
".\n";
1476 acceptchange =
false;
1477 prevcyclebetterR =
false;
1478 ++numConsecutiveInvalid;
1482 prevcyclebetterR = newR.
Rwp < currR.Rwp;
1485 g_log.
debug() <<
"[DBx317] Step " << icycle <<
": New Rwp = " << setprecision(10) << newR.
Rwp
1486 <<
", Rp = " << setprecision(5) << newR.
Rp <<
"; Accepted = " << acceptchange
1487 <<
"; Proposed parameters valid =" << validparams <<
"\n";
1510 ++numRecentAcceptance;
1515 if (numConsecutiveInvalid >= numMaxConsecutiveInvalid) {
1521 numConsecutiveInvalid = 0;
1522 numRecentAcceptance = 0;
1528 if (numRecentSteps == m_numStepsCheckTemperature) {
1530 if (numRecentAcceptance <= 2) {
1532 }
else if (numRecentAcceptance >= 8) {
1536 numRecentAcceptance = 0;
1553 vecIndex[icycle] =
static_cast<double>(icycle);
1554 if (currR.Rwp < 1.0E5)
1555 vecR[icycle] = currR;
1562 if (icycle % 10 == 0)
1563 progress(
double(icycle) /
double(maxcycles));
1571 <<
", Acceptance ratio = " << double(numacceptance) / double(maxcycles *
m_numMCGroups) <<
".\n"
1572 <<
"Rwp: Starting = " << startR.
Rwp <<
", Best = " <<
m_bestRwp <<
", Ending = " << currR.Rwp <<
"\n"
1573 <<
"Rp : Starting = " << startR.
Rp <<
", Best = " <<
m_bestRp <<
", Ending = " << currR.Rp <<
"\n";
1575 map<string, Parameter>::iterator mapiter;
1576 for (mapiter = mapCurrParameter.begin(); mapiter != mapCurrParameter.end(); ++mapiter) {
1577 const Parameter ¶m = mapiter->second;
1579 g_log.
notice() << setw(10) << param.
name <<
"\t: Average Stepsize = " << setw(10) << setprecision(5)
1580 << param.
sumstepsize / double(maxcycles) <<
", Max Step Size = " << setw(10) << setprecision(5)
1583 <<
", Number of No Move = " << setw(4) << param.
numnomove <<
", Minimum tried value = " << setw(4)
1587 g_log.
notice() <<
"Number of invalid proposed moves = " << numinvalidmoves <<
"\n";
1590 stringstream filenamess;
1591 filenamess <<
"r_trace_" << vecR.size() <<
".dat";
1603 size_t numrows = tablews->rowCount();
1604 for (
size_t i = 0; i < numrows; ++i) {
1606 TableRow temprow = tablews->getRow(i);
1609 int nonnegative,
group;
1611 temprow >> parname >> a0 >> a1 >> nonnegative >>
group;
1614 map<int, vector<string>>::iterator giter;
1617 giter->second.emplace_back(parname);
1620 m_MCGroups.emplace(
group, std::initializer_list<std::string>{parname});
1626 piter->second.mcA0 = a0;
1627 piter->second.mcA1 = a1;
1628 piter->second.nonnegative = (nonnegative != 0);
1635 map<string, Parameter>::iterator mapiter;
1637 mapiter->second.movedirection = 1;
1638 mapiter->second.sumstepsize = 0.0;
1639 mapiter->second.numpositivemove = 0;
1640 mapiter->second.numnegativemove = 0;
1641 mapiter->second.numnomove = 0;
1642 mapiter->second.maxabsstepsize = -0.0;
1652 stringstream dboutss;
1653 dboutss <<
"Monte Carlo minimizer refines: ";
1657 vector<string> geomparams;
1667 dboutss <<
"Geometry parameters: ";
1668 for (
const auto &geomparam : geomparams)
1669 dboutss << geomparam <<
"\t\t";
1673 vector<string> alphs;
1680 dboutss <<
"Alpha parameters";
1681 for (
const auto &alph : alphs)
1682 dboutss << alph <<
"\t\t";
1686 vector<string> betas;
1693 dboutss <<
"Beta parameters";
1694 for (
const auto &beta : betas)
1695 dboutss << beta <<
"\t\t";
1699 vector<string> sigs;
1705 dboutss <<
"Sig parameters";
1706 for (
const auto &sig : sigs)
1707 dboutss << sig <<
"\t\t";
1716 for (
const auto &parname : sigs) {
1723 for (
const auto &parname : alphs) {
1733 for (
const auto &parname : betas) {
1772 map<string, Parameter>::iterator mapiter;
1774 mapiter->second.movedirection = 1;
1775 mapiter->second.sumstepsize = 0.0;
1776 mapiter->second.numpositivemove = 0;
1777 mapiter->second.numnegativemove = 0;
1778 mapiter->second.numnomove = 0;
1779 mapiter->second.maxabsstepsize = -0.0;
1792 map<string, Parameter>::iterator pariter;
1796 errss <<
"Parameter " << parname <<
" does not exisit Le Bail function parameters. ";
1798 throw runtime_error(errss.str());
1801 if (pariter->second.fit)
1802 parnamesforMC.emplace_back(parname);
1826 bool outputwithbkgd,
const HistogramY &vecBkgd, std::vector<double> &values,
1828 HistogramY veccalbkgd(vecX.size());
1829 bool veccalbkgdIsEmpty =
true;
1832 double maxfwhm = vecX.back() - vecX.front();
1837 g_log.
information() <<
"Proposed new instrument profile values cause peak(s) to have "
1838 <<
"unphysical parameter values.\n";
1846 vector<double> vecPureY(vecY.size(), 0.);
1847 if (vecBkgd.size() == vecY.size()) {
1850 "background vector. "
1852 ::transform(vecY.begin(), vecY.end(), vecBkgd.begin(), vecPureY.begin(), ::minus<double>());
1856 "and newly calculated background. "
1859 ::transform(vecY.begin(), vecY.end(), veccalbkgd.begin(), vecPureY.begin(), ::minus<double>());
1860 veccalbkgdIsEmpty =
false;
1864 peaksvalid =
m_lebailFunction->calculatePeaksIntensities(vecX.rawData(), vecPureY, values);
1868 g_log.
debug() <<
"Calculate diffraction pattern from input data with "
1869 "background removed. "
1871 peaksvalid =
m_lebailFunction->calculatePeaksIntensities(vecX.rawData(), vecY.rawData(), values);
1875 if (values.size() != vecY.size()) {
1876 g_log.
error() <<
"Input/output vector 'values' has a wrong size = " << values.size() <<
". Resize it to "
1877 << vecY.size() <<
".\n";
1878 throw runtime_error(
"Impossible...");
1882 if (outputwithbkgd) {
1883 if (vecBkgd.size() == vecY.size()) {
1884 ::transform(values.begin(), values.end(), vecBkgd.begin(), values.begin(), ::plus<double>());
1886 if (veccalbkgdIsEmpty)
1887 throw runtime_error(
"Programming logic error.");
1888 ::transform(values.begin(), values.end(), veccalbkgd.begin(), values.begin(), ::plus<double>());
1892 vector<double> caldata(values.size(), 0.0);
1893 if (vecBkgd.size() == vecY.size()) {
1895 std::transform(values.begin(), values.end(), vecBkgd.begin(), caldata.begin(), std::plus<double>());
1898 if (veccalbkgdIsEmpty)
1899 throw runtime_error(
"Programming logic error (2). ");
1900 std::transform(values.begin(), values.end(), veccalbkgd.begin(), caldata.begin(), std::plus<double>());
1929 map<string, Parameter> &newparammap,
bool prevBetterRwp) {
1933 bool anyparamtorefine =
false;
1936 g_log.
debug() <<
"Parameter Number In Group = " << mcgroup.size() <<
"\n";
1937 for (
const auto ¶mname : mcgroup) {
1939 auto mapiter = curparammap.find(paramname);
1940 if (mapiter == curparammap.end()) {
1941 stringstream errmsg;
1942 errmsg <<
"Parameter to update (" << paramname <<
") is not in the pool of parameters to get updated. "
1944 <<
"Number of parameters to update in this group = " << curparammap.size() <<
". They are ";
1945 for (mapiter = curparammap.begin(); mapiter != curparammap.end(); ++mapiter) {
1946 errmsg << mapiter->first <<
", ";
1949 throw runtime_error(errmsg.str());
1954 anyparamtorefine =
true;
1959 double randomnumber = 2 *
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX) - 1.0;
1962 double weight = r.
Rwp;
1973 newvalue = param.
curvalue + stepsize;
1976 int prevRightDirection;
1978 prevRightDirection = 1;
1980 prevRightDirection = -1;
1982 double randirint =
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX);
1983 g_log.
debug() <<
"[TestRandom] random = " << randirint <<
"\n";
1986 if (randirint < 0.1) {
1988 stepsize = -1.0 *
fabs(stepsize) *
static_cast<double>(param.
movedirection * prevRightDirection);
1989 }
else if (randirint < 0.4) {
1993 stepsize =
fabs(stepsize) *
static_cast<double>(param.
movedirection * prevRightDirection);
1996 newvalue = param.
curvalue + stepsize;
1998 throw runtime_error(
"Unrecoganized walk style. ");
2004 newvalue =
fabs(newvalue);
2009 int toss = rand() % 2;
2010 double direction = -1.0;
2012 }
else if (newvalue > param.
maxvalue) {
2013 int toss = rand() % 2;
2014 double direction = 1.0;
2019 auto newmiter = newparammap.find(paramname);
2020 if (newmiter == newparammap.end())
2021 throw runtime_error(
"New parameter map does not contain parameter that is updated.");
2022 newmiter->second.curvalue = newvalue;
2023 g_log.
debug() <<
"[ProposeNewValue] " << paramname <<
" --> " << newvalue <<
"; random number = " << randomnumber
2031 }
else if (stepsize < 0) {
2047 g_log.
debug() <<
"[DBx257] " << paramname <<
"\t"
2048 <<
"Proposed value = " << setw(15) << newvalue <<
" (orig = " << param.
curvalue
2049 <<
", step = " << stepsize <<
"), totRwp = " << r.
Rwp <<
"\n";
2052 return anyparamtorefine;
2070 if (direction > 0) {
2086 if (direction > 0) {
2088 double dval = (newvalue - param.
maxvalue) / deltaX;
2089 newvalue = param.
minvalue + deltaX * (dval - floor(dval));
2092 double dval = (param.
minvalue - newvalue) / deltaX;
2093 newvalue = param.
maxvalue - deltaX * (dval - floor(dval));
2097 if (direction > 0) {
2118 double new_goodness = newR.
Rwp;
2119 double cur_goodness = currR.
Rwp;
2121 if (new_goodness < cur_goodness) {
2124 }
else if (new_goodness > 1.0 - 1.0E-9) {
2126 g_log.
debug() <<
"Goodness > " << 1.0 - 1.0E-9 <<
". Reject!"
2131 double dice =
static_cast<double>(rand()) /
static_cast<double>(RAND_MAX);
2132 g_log.
debug() <<
"[TestRandom] dice " << dice <<
"\n";
2133 double bar = exp(-(new_goodness - cur_goodness) / (cur_goodness *
m_Temperature));
2135 accept = dice < bar;
2151 Rfactor rfactor,
size_t istep) {
2153 double goodness = rfactor.
Rwp;
2177 g_log.
warning(
"[Book keep best MC result] Shouldn't be here as it is found "
2178 "that it is not the best solution ");
2189 map<string, Parameter>::const_iterator srcmapiter;
2190 map<string, Parameter>::iterator tgtmapiter;
2191 for (srcmapiter = srcparammap.begin(); srcmapiter != srcparammap.end(); ++srcmapiter) {
2192 string parname = srcmapiter->first;
2193 Parameter srcparam = srcmapiter->second;
2195 tgtmapiter = tgtparammap.find(parname);
2196 if (tgtmapiter == tgtparammap.end()) {
2198 errss <<
"Parameter " << parname <<
" cannot be found in target Parameter map containing " << tgtparammap.size()
2201 throw runtime_error(
"Programming or memory error! This situation cannot happen!");
2204 tgtmapiter->second.curvalue = srcparam.
curvalue;
2210 std::map<std::string, double> outmap;
2211 std::map<std::string, Parameter>::iterator miter;
2212 for (miter = inmap.begin(); miter != inmap.end(); ++miter) {
2213 outmap.emplace(miter->first, miter->second.curvalue);
2226 ofile.open(filename.c_str());
2228 for (
size_t i = 0; i < vecX.size(); ++i)
2229 ofile << setw(15) << setprecision(5) << vecX[i] << setw(15) << setprecision(5) << vecR[i].Rwp << setw(15)
2230 << setprecision(5) << vecR[i].Rp <<
"\n";
#define DECLARE_ALGORITHM(classname)
const double EPSILON(1.0E-10)
const int DATADIFFINDEX(2)
const int CALDATAINDEX(1)
const int INPUTPUREPEAKINDEX(7)
const int OBSDATAINDEX(0)
const int CALBKGDINDEX(4)
const double NOBOUNDARYLIMIT(1.0E10)
const int CALPUREPEAKINDEX(3)
const int INPUTBKGDINDEX(6)
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
Implements FunctionDomain1D with its own storage in form of a std::vector.
A class to store values calculated by a function.
const std::vector< double > & toVector() const
Return the calculated values as a vector.
TableRowHelper appendRow()
Appends a row.
TableRow represents a row in a TableWorkspace.
size_t size() const
Returns the number of rows in the TableWorkspace.
A property class for workspaces.
bool calculateDiffractionPattern(const Mantid::HistogramData::HistogramX &vecX, const Mantid::HistogramData::HistogramY &vecY, bool inputraw, bool outputwithbkgd, const Mantid::HistogramData::HistogramY &vecBkgd, std::vector< double > &values, Kernel::Rfactor &rfactor)
Calculate diffraction pattern in Le Bail algorithm for MC Random walk.
std::string mMinimizer
Minimizer.
void proposeNewBackgroundValues()
Propose new background parameters.
bool acceptOrDeny(Kernel::Rfactor currR, Kernel::Rfactor newR)
Determine whether the proposed value should be accepted or denied.
std::vector< std::pair< std::vector< int >, double > > m_inputPeakInfoVec
Input Bragg peak information for future processing;.
Functions::BackgroundFunction_sptr m_backgroundFunction
Background function.
bool m_tolerateInputDupHKL2Peaks
Flag to allow peaks with duplicated (HKL)^2 in input .hkl file.
std::map< std::string, double > m_origFuncParameters
Input function parameters that are stored for reference.
void addParameterToMCMinimize(std::vector< std::string > &parnamesforMC, const std::string &parname)
Add parameter (to a vector of string/name) for MC random walk.
bool m_inputParameterPhysical
Flag to show whether the input profile parameters are physical to all peaks.
void exec() override
Implement abstract Algorithm methods.
API::MatrixWorkspace_sptr cropWorkspace(const API::MatrixWorkspace_sptr &inpws, size_t wsindex)
Crop the workspace for better usage.
void doMarkovChain(const std::map< std::string, Parameter > ¶mmap, const Mantid::HistogramData::HistogramX &vecX, const Mantid::HistogramData::HistogramY &vecPurePeak, const std::vector< double > &vecBkgd, size_t maxcycles, const Kernel::Rfactor &startR, int randomseed)
Work on Markov chain to 'solve' LeBail function.
FunctionMode m_fitMode
Fit mode.
void init() override
Declare the input properties for this algorithm.
std::map< std::string, Parameter > m_funcParameters
Function parameters updated by fit.
LeBailFunction_sptr m_lebailFunction
Le Bail Function (Composite)
std::vector< double > m_backgroundParameters
Background polynomials.
std::vector< double > m_bkgdParameterBuffer
void parseInstrumentParametersTable()
Import peak parameters.
std::vector< std::string > m_bkgdParameterNames
void exportInstrumentParameterToTable(const std::map< std::string, Parameter > ¶mmap)
Output parameters (fitted or tied)
void processInputBackground()
Process and calculate input background.
std::vector< double > m_bestBkgdParams
int mPeakRadius
Peak Radius.
void parseBraggPeaksParametersTable()
Import Miller Indices (HKL)
double limitProposedValueInBound(const Parameter ¶m, double newvalue, double direction, int choice)
Limit proposed value in the specified boundary.
double m_indicatePeakHeight
void applyParameterValues(const std::map< std::string, Parameter > &srcparammap, std::map< std::string, Parameter > &tgtparammap)
Apply the value of parameters in the source to target.
std::map< std::string, double > convertToDoubleMap(std::map< std::string, Parameter > &inmap)
Convert a map of Parameter to a map of double.
void execRefineBackground()
Calcualte background by fitting peak heights.
double m_dampingFactor
Damping factor.
double m_minimumPeakHeight
Minimum height of a peak to be counted in smoothing background.
DataObjects::Workspace2D_sptr m_outputWS
void execPatternCalculation()
Calculate LeBail pattern from from input peak parameters.
void recoverBackgroundParameters(const std::vector< double > &bkgdparamvec)
Restore/recover the buffered background parameters to m_background function.
std::map< int, std::vector< std::string > > m_MCGroups
bool m_useAnnealing
Flag to use Annealing Simulation (i.e., use automatic adjusted temperature)
API::MatrixWorkspace_sptr m_dataWS
Instance data.
size_t m_numMinimizeSteps
Number of minimization steps. For both MC and regular.
void setupBuiltInRandomWalkStrategy()
Set up Monte Carlo random walk strategy.
void storeBackgroundParameters(std::vector< double > &bkgdparamvec)
Store/buffer current background parameters.
double m_lebailFitChi2
Fit Chi^2.
void exportBraggPeakParameterToTable()
Create and set up output table workspace for peaks.
std::map< std::string, Parameter > m_bestParameters
enum Mantid::CurveFitting::Algorithms::LeBailFit::@2 m_walkStyle
Monte Carlo algorithm.
void createOutputDataWorkspace()
Create output data workspace.
DataObjects::TableWorkspace_sptr parameterWS
std::vector< double > m_bestBackgroundData
double m_Temperature
Monte Carlo temperature.
void parseBackgroundTableWorkspace(const DataObjects::TableWorkspace_sptr &bkgdparamws, std::vector< std::string > &bkgdparnames, std::vector< double > &bkgdorderparams)
Parse content in a table workspace to vector for background parameters.
void bookKeepBestMCResult(const std::map< std::string, Parameter > ¶mmap, const std::vector< double > &bkgddata, Kernel::Rfactor rfactor, size_t istep)
Book keep the (sopposed) best MC result.
std::vector< std::string > m_backgroundParameterNames
std::string m_backgroundType
Background type.
void processInputProperties()
Process input properties.
void execRandomWalkMinimizer(size_t maxcycles, std::map< std::string, Parameter > ¶mmap)
Main for random walk process.
std::string m_peakType
============================= =========================== ///
std::vector< double > m_bkgdParameterStepVec
size_t m_numberBkgdParameters
void createLeBailFunction()
Create LeBailFunction.
DataObjects::TableWorkspace_sptr reflectionWS
bool proposeNewValues(const std::vector< std::string > &mcgroup, Kernel::Rfactor r, std::map< std::string, Parameter > &curparammap, std::map< std::string, Parameter > &newparammap, bool prevBetterRwp)
Propose new parameters.
void setupRandomWalkStrategyFromTable(const DataObjects::TableWorkspace_sptr &tablews)
Set up Monte Carlo random walk strategy.
LeBailFunction : LeBailFunction is to calculate peak intensities in a composite function including ne...
TableWorkspace is an implementation of Workspace in which the data are organised in columns of same s...
API::Column_sptr addColumn(const std::string &type, const std::string &name) override
Creates a new column.
Support for a property that holds an array of values.
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)
ListValidator is a validator that requires the value of a property to be one of a defined list of pos...
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IPowderDiffPeakFunction > IPowderDiffPeakFunction_sptr
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
void writeRfactorsToFile(const std::vector< double > &vecX, const std::vector< Kernel::Rfactor > &vecR, const std::string &filename)
Write a set of (XY) data to a column file.
const Rfactor badR(DBL_MAX, DBL_MAX)
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::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Rfactor MANTID_KERNEL_DLL getRFactor(const std::vector< double > &obsI, const std::vector< double > &calI, const std::vector< double > &obsE)
Return the R-factors (Rwp) of a diffraction pattern data.
Helper class which provides the Collimation Length for SANS instruments.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
LeBailFit : Algorithm to do Le Bail Fit.
@ InOut
Both an input & output workspace.
@ Input
An input workspace.
@ Output
An output workspace.
R factor for powder data analysis.