16#include "MantidHistogramData/HistogramBuilder.h"
17#include "MantidIndexing/IndexInfo.h"
21#include "MantidTypes/SpectrumDefinition.h"
23#include <boost/algorithm/string/classification.hpp>
24#include <boost/algorithm/string/split.hpp>
38 : m_peakFunction(), m_bkgdFunction(), m_vecPeakParamValues(), m_vecBkgdParamValues(), m_SpectrumMap(),
39 m_spectraSet(), m_useAutoBkgd(false), m_funcParamWS(), inputWS(), m_newWSFromParent(false), binParameters(),
40 m_genBackground(false), m_useRawParameter(false), m_maxChi2(0.), m_numPeakWidth(0.), m_funcParameterNames(),
41 i_height(-1), i_centre(-1), i_width(-1), i_a0(-1), i_a1(-1), i_a2(-1), m_useFuncParamWS(false), m_wsIndex(-1) {}
49 "Input TableWorkspace for peak's parameters.");
54 declareProperty(
"PeakType",
"", std::make_shared<StringListValidator>(peakFullNames),
"Peak function type. ");
56 for (
size_t i = 0; i < peakFullNames.size(); ++i)
57 g_log.
debug() <<
"Peak function " << i <<
": " << peakFullNames[i] <<
"\n";
60 "List of peak parameter values. They must have a 1-to-1 "
61 "mapping to PeakParameterNames list. ");
64 std::vector<std::string> bkgdtypes{
"Auto",
67 "Quadratic (A0, A1, A2)",
71 declareProperty(
"BackgroundType",
"Linear", std::make_shared<StringListValidator>(bkgdtypes),
"Type of Background.");
74 "List of background parameter values. They must have a "
75 "1-to-1 mapping to PeakParameterNames list. ");
79 "InputWorkspace (optional) to take information for the instrument, and "
80 "where to evaluate the x-axis.");
83 "Spectrum of the peak to be generated. "
84 "It is only applied to the case by input parameter values in "
88 std::make_shared<Kernel::RebinParamsValidator>(
true)),
89 "A comma separated list of first bin boundary, width, last "
90 "bin boundary. Optionally\n"
91 "this can be followed by a comma and more widths and last "
93 "Negative width values indicate logarithmic binning.");
95 declareProperty(
"NumberWidths", 2.,
"Number of peak width to evaluate each peak for. Default=2.");
98 "Output Workspace to put the calculated data.");
100 declareProperty(
"GenerateBackground",
true,
"Whether or not to generate the background");
102 declareProperty(
"MaxAllowedChi2", 100.0,
"Maximum chi^2 of the peak allowed to calculate. Default 100.");
105 "If selected, the peaks that are wider than fit window "
106 "(denoted by negative chi^2) are ignored.");
109 "Flag to show whether the parameter table contains raw parameters. "
110 "In the case that parameter values are input via vector, and this flag "
112 "the default order of effective peak parameters is centre, height and "
114 "the default order of effective background parameters is A0, A1 and "
123 std::string peaktype, bkgdtype;
140 std::map<specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>> functionmap;
144 std::vector<std::pair<double, API::IFunction_sptr>> vecpeakfunc;
146 functionmap.emplace(
m_wsIndex, vecpeakfunc);
158 if (!paramwsname.empty()) {
170 if (peakfunctype.find(
'(') != std::string::npos) {
171 std::vector<std::string> strs;
172 boost::split(strs, peakfunctype, boost::is_any_of(
" ("));
173 peakfunctype = strs[0];
178 if (bkgdfunctype.find(
'(') != std::string::npos) {
179 std::vector<std::string> strs;
180 boost::split(strs, bkgdfunctype, boost::is_any_of(
" ("));
181 bkgdfunctype = strs[0];
184 if (bkgdfunctype ==
"Auto") {
186 bkgdfunctype =
"Quadratic";
187 }
else if (bkgdfunctype ==
"None") {
190 }
else if (bkgdfunctype ==
"Linear" || bkgdfunctype ==
"Flat") {
192 bkgdfunctype = bkgdfunctype +
"Background";
221 std::map<
specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>> &functionmap) {
225 size_t numbkgdparams = 0;
229 g_log.
warning(
"There is no background function specified. ");
232 std::map<specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>>::iterator mapiter;
235 for (
size_t ipeak = 0; ipeak < numpeaks; ++ipeak) {
245 }
else if (chi2 < 0.) {
246 g_log.
notice() <<
"Skip Peak " << ipeak <<
" (chi^2 " << chi2 <<
" < 0 )"
250 g_log.
debug() <<
"[DB] Chi-square = " << chi2 <<
"\n";
255 for (
size_t p = 0; p < numpeakparams; ++p) {
261 for (
size_t p = 0; p < numbkgdparams; ++p) {
263 double parvalue =
m_funcParamWS->cell<
double>(ipeak, p + 1 + numpeakparams);
297 mapiter = functionmap.find(wsindex);
298 if (mapiter == functionmap.end()) {
299 std::vector<std::pair<double, API::IFunction_sptr>> tempvector;
300 std::pair<std::map<specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>>::iterator,
bool> ret;
301 ret = functionmap.emplace(wsindex, tempvector);
306 mapiter->second.emplace_back(centre, clonefunction);
308 g_log.
information() <<
"Peak " << ipeak <<
": Spec = " << wsindex <<
" func: " << clonefunction->asString() <<
"\n";
313 for (mapiter = functionmap.begin(); mapiter != functionmap.end(); ++mapiter) {
314 std::vector<std::pair<double, API::IFunction_sptr>> &vec_centrefunc = mapiter->second;
315 std::sort(vec_centrefunc.begin(), vec_centrefunc.end());
330 for (
size_t i = 0; i < numpeakparams; ++i)
334 std::stringstream errss;
336 <<
") is not correct (should be " << numpeakparams <<
" for peak of type " <<
m_peakFunction->name()
338 throw std::runtime_error(errss.str());
343 throw std::runtime_error(
"Input peak parameters must have 3 numbers for "
344 "effective parameter names.");
358 throw std::runtime_error(
"Number of background parameters' value is not correct. ");
360 for (
size_t i = 0; i < numbkgdparams; ++i)
366 throw std::runtime_error(
"There is no enough effective background parameter values.");
370 for (
size_t i = 0; i < numbkgdparams; ++i)
388 const std::map<
specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>> &functionmap,
391 std::map<specnum_t, std::vector<std::pair<double, API::IFunction_sptr>>>::const_iterator mapiter;
392 for (mapiter = functionmap.begin(); mapiter != functionmap.end(); ++mapiter) {
401 const std::vector<std::pair<double, API::IFunction_sptr>> &vec_centrefunc = mapiter->second;
402 size_t numpeaksinspec = mapiter->second.size();
404 for (
size_t ipeak = 0; ipeak < numpeaksinspec; ++ipeak) {
405 const std::pair<double, API::IFunction_sptr> ¢refunc = vec_centrefunc[ipeak];
409 double centre = centrefunc.first;
410 double fwhm = thispeak->fwhm();
413 const auto &
X = dataWS->x(wsindex);
419 double middle = 0.5 * (centre + leftPeak->centre());
420 if (leftbound < middle)
423 auto left = std::lower_bound(
X.cbegin(),
X.cend(), leftbound);
428 if (ipeak != numpeaksinspec - 1) {
431 double middle = 0.5 * (centre + rightPeak->centre());
432 if (rightbound > middle)
435 auto right = std::lower_bound(
left + 1,
X.cend(), rightbound);
443 centrefunc.second->function(domain, values);
446 std::size_t offset = (
left -
X.begin());
447 std::size_t numY = values.
size();
449 auto &dataY = dataWS->mutableY(wsindex);
450 for (std::size_t i = 0; i < numY; i++) {
451 dataY[i + offset] += values[i];
479 std::vector<std::string> colnames =
m_funcParamWS->getColumnNames();
481 if (colnames[0] !=
"spectrum")
482 throw std::runtime_error(
"First column must be 'spectrum' in integer. ");
483 if (colnames.back() !=
"chi2")
484 throw std::runtime_error(
"Last column must be 'chi2'.");
489 for (
size_t i = 0; i < colnames.size() - 2; ++i) {
490 std::string str = colnames[i + 1];
491 std::vector<std::string> tokens;
492 split(tokens, str, is_any_of(
"."));
497 size_t numparamcols = colnames.size() - 2;
501 size_t numbkgdparams = 0;
504 size_t numparams = numpeakparams + numbkgdparams;
505 if (numparamcols < numparams)
506 throw std::runtime_error(
"Parameters number is not correct. ");
507 else if (numparamcols > numparams)
508 g_log.
warning(
"Number of parameters given in table workspace is more than "
509 "number of parameters of function(s) to generate peaks. ");
512 for (
size_t i = 0; i < numpeakparams; ++i) {
514 std::stringstream errss;
517 <<
"Allowed function parameters are ";
518 std::vector<std::string> parnames =
m_peakFunction->getParameterNames();
519 for (
auto &parname : parnames)
520 errss << parname <<
", ";
521 throw std::runtime_error(errss.str());
526 for (
size_t i = 0; i < numbkgdparams; ++i) {
528 std::stringstream errss;
529 errss <<
"Background function does not have paramter " <<
m_funcParameterNames[i + numpeakparams];
530 throw std::runtime_error(errss.str());
535 if (numparamcols != 6)
536 throw std::runtime_error(
"Number of columns must be 6 if not using raw.");
566 size_t numpeaks = peakParmsWS->rowCount();
569 for (
size_t ipk = 0; ipk < numpeaks; ipk++) {
571 auto specid =
static_cast<specnum_t>((*col)[ipk]);
574 std::stringstream outss;
575 outss <<
"Peak " << ipk <<
": specid = " << specid;
595 for (
size_t i = 0; i < compfunc->nFunctions(); ++i) {
613 std::vector<std::string> parnames = function->getParameterNames();
614 std::vector<std::string>::iterator piter;
615 piter = std::find(parnames.begin(), parnames.end(), paramname);
616 return piter != parnames.end();
629 std::string errmsg(
"Must define either InputWorkspace or BinningParameters.");
631 throw std::invalid_argument(errmsg);
635 g_log.
notice() <<
"Both binning parameters and input workspace are given. "
636 <<
"Using input worksapce to generate output workspace!\n";
638 HistogramBuilder builder;
639 builder.setX(
inputWS->x(0).size());
640 builder.setY(
inputWS->y(0).size());
642 builder.setDistribution(
inputWS->isDistribution());
643 outputWS = create<MatrixWorkspace>(*
inputWS, builder.build());
647 outputWS->setSharedX(iws,
inputWS->sharedX(iws));
666 throw std::invalid_argument(
"Input spectra list is empty. Unable to generate a new workspace.");
668 if (binparameters.size() < 3) {
669 std::stringstream errss;
670 errss <<
"Number of input binning parameters are not enough (" << binparameters.size() <<
"). "
671 <<
"Binning parameters should be 3 (x0, step, xf).";
673 throw std::invalid_argument(errss.str());
676 double x0 = binparameters[0];
677 double dx = binparameters[1];
678 double xf = binparameters[2];
679 if (x0 >= xf || (xf - x0) < dx || dx == 0.) {
680 std::stringstream errss;
681 errss <<
"Order of input binning parameters is not correct. It is not "
683 <<
"x0 = " << x0 <<
", xf = " << xf <<
", dx = " << dx;
685 throw std::invalid_argument(errss.str());
688 std::vector<double> xarray;
691 while (xvalue <= xf) {
693 xarray.emplace_back(xvalue);
699 xvalue +=
fabs(dx) * xvalue;
702 std::vector<Indexing::SpectrumNumber> specNums;
705 g_log.
debug() <<
"Build WorkspaceIndex-Spectrum " << specNums.size() <<
" , " << specid <<
"\n";
706 specNums.emplace_back(specid);
709 Indexing::IndexInfo indices(specNums.size());
712 indices.setSpectrumDefinitions(std::vector<SpectrumDefinition>(specNums.size()));
713 indices.setSpectrumNumbers(std::move(specNums));
714 return create<Workspace2D>(indices, BinEdges(std::move(xarray)));
720 std::vector<std::string> vec_funcparnames;
722 for (
auto &funcname : funcnames) {
724 vec_funcparnames.emplace_back(funcname);
729 std::stringstream parnamess;
730 parnamess << funcname <<
" (";
731 std::vector<std::string> funcpars = tempfunc->getParameterNames();
732 for (
size_t j = 0; j < funcpars.size(); ++j) {
733 parnamess << funcpars[j];
734 if (j != funcpars.size() - 1)
739 vec_funcparnames.emplace_back(parnamess.str());
742 return vec_funcparnames;
#define DECLARE_ALGORITHM(classname)
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.
Implements FunctionDomain1D with its own storage in form of a std::vector.
A class to store values calculated by a function.
size_t size() const
Return the number of values.
An interface to a peak function, which extend the interface of IFunctionWithLocation by adding method...
A property class for workspaces.
GeneratePeaks : Generate peaks from a table workspace containing peak parameters.
API::IBackgroundFunction_sptr m_bkgdFunction
Background function.
std::set< specnum_t > m_spectraSet
Set of spectra (workspace indexes) in the original workspace that contain peaks to generate.
int m_wsIndex
Spectrum if only 1 peak is to plot.
int i_height
Indexes of height, centre, width, a0, a1, and a2 in input parameter table.
void createFunction(std::string &peaktype, std::string &bkgdtype)
Create a function for fitting.
void init() override
Define algorithm's properties.
void exec() override
Implement abstract Algorithm methods.
API::MatrixWorkspace_sptr createOutputWorkspace()
Create output workspace.
std::vector< double > m_vecPeakParamValues
bool m_useFuncParamWS
Flag to use parameter table workspace.
bool hasParameter(const API::IFunction_sptr &function, const std::string ¶mname)
Check whether function has a certain parameter.
void generatePeaks(const std::map< specnum_t, std::vector< std::pair< double, API::IFunction_sptr > > > &functionmap, const API::MatrixWorkspace_sptr &dataWS)
Generate peaks in output data workspaces.
std::map< specnum_t, specnum_t > m_SpectrumMap
Spectrum map from full spectra workspace to partial spectra workspace.
API::MatrixWorkspace_const_sptr inputWS
Input workspace (optional)
double m_maxChi2
Maximum chi-square to have peak generated.
API::MatrixWorkspace_sptr createDataWorkspace(std::vector< double > binparameters)
Create a Workspace2D (MatrixWorkspace) with given spectra and bin parameters.
std::vector< std::string > m_funcParameterNames
List of functions' parameters naems.
bool m_useRawParameter
Flag to indicate parameter table workspace containing raw parameters names.
std::vector< std::string > addFunctionParameterNames(const std::vector< std::string > &funcnames)
Add function parameter names to.
void getSpectraSet(const DataObjects::TableWorkspace_const_sptr &peakParmsWS)
Get set of spectra of the input table workspace Spectra is set to the column named 'spectrum'.
std::vector< double > binParameters
Binning parameters.
void processAlgProperties(std::string &peakfunctype, std::string &bkgdfunctype)
Process algorithm properties.
API::IPeakFunction_sptr getPeakFunction(const API::IFunction_sptr &infunction)
Get the IPeakFunction part in the input function.
API::IPeakFunction_sptr m_peakFunction
Peak function.
void importPeaksFromTable(std::map< specnum_t, std::vector< std::pair< double, API::IFunction_sptr > > > &functionmap)
Import peak and background functions from table workspace.
void processTableColumnNames()
Process column names with peak parameter names.
bool m_newWSFromParent
Flag whether the new workspace is exactly as input.
bool m_useAutoBkgd
Flag to use automatic background (???)
bool m_genBackground
Flag to generate background.
std::vector< double > m_vecBkgdParamValues
double m_numPeakWidth
Number of FWHM for peak to extend.
void importPeakFromVector(std::vector< std::pair< double, API::IFunction_sptr > > &functionmap)
Import peak and background function parameters from vector.
DataObjects::TableWorkspace_sptr m_funcParamWS
Parameter table workspace.
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 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< IPeakFunction > IPeakFunction_sptr
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
std::shared_ptr< const Column > Column_const_sptr
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< CompositeFunction > CompositeFunction_sptr
shared pointer to the composite function base class
std::shared_ptr< const TableWorkspace > TableWorkspace_const_sptr
shared pointer to Mantid::DataObjects::TableWorkspace (const version)
void split(const int A, int &S, int &V)
Split a number into the sign and positive value.
int32_t specnum_t
Typedef for a spectrum Number.
@ Input
An input workspace.
@ Output
An output workspace.