25const static std::string COST_FUNCTION =
"CostFunction";
26const static std::string INPUT_WS =
"InputWorkspace";
27const static std::string OUTPUT_WS =
"OutputWorkspace";
28const static std::string POLY_DEGREE =
"Degree";
29const static std::string XRANGES =
"XRanges";
30const static std::string MINIMIZER =
"Minimizer";
31const static std::string IGNORE_INVALID_DATA =
"IgnoreInvalidData";
36const static std::string UNWEIGHTED_LEAST_SQUARES =
"Unweighted least squares";
37const static std::string WEIGHTED_LEAST_SQUARES =
"Least squares";
42const static std::string LEVENBERG_MARQUARDT_MD =
"Levenberg-MarquardtMD";
43const static std::string LEVENBERG_MARQUARDT =
"Levenberg-Marquardt";
53 const size_t wsIndex) {
54 const auto minX = ws.
x(wsIndex).front();
55 const auto maxX = ws.
x(wsIndex).back();
56 std::vector<double> filtered;
57 filtered.reserve(ranges.size());
58 for (
size_t i = 0; i < ranges.size() / 2; ++i) {
59 const auto first = ranges[2 * i];
60 const auto second = ranges[2 * i + 1];
61 if (!(first > maxX || second < minX)) {
62 filtered.emplace_back(first);
63 filtered.emplace_back(second);
76 const size_t wsIndex) {
77 const auto minX = ws.
x(wsIndex).front();
78 const auto maxX = ws.
x(wsIndex).back();
80 return std::pair<double, double>(minX, maxX);
82 const auto minmaxIt = std::minmax_element(ranges.cbegin(), ranges.cend());
83 const auto minEdge = *minmaxIt.first;
84 const auto maxEdge = *minmaxIt.second;
85 return std::pair<double, double>(std::min(minEdge, minX), std::max(maxEdge, maxX));
93std::vector<double> includedRanges(
const std::vector<double> &ranges,
const std::pair<double, double> &totalRange) {
95 return {totalRange.first, totalRange.second};
99 enum class Edge { start = -1, end = 1 };
100 std::vector<std::pair<double, Edge>> edges(ranges.size());
101 for (
size_t i = 0; i < ranges.size(); ++i) {
102 edges[i].first = ranges[i];
103 edges[i].second = i % 2 == 0 ? Edge::start : Edge::end;
105 std::sort(edges.begin(), edges.end(), [](
const std::pair<double, Edge> &p1,
const std::pair<double, Edge> &p2) {
106 if (p1.first == p2.first)
107 return p1.second < p2.second;
108 return p1.first < p2.first;
112 std::vector<double> mergedRanges;
113 mergedRanges.reserve(ranges.size());
114 auto edgeIt = edges.begin();
115 mergedRanges.emplace_back(std::max(edges.front().first, totalRange.first));
116 while (edgeIt != edges.end()) {
117 auto endEdgeIt = edgeIt + 1;
118 while (endEdgeIt != edges.end()) {
119 const auto val = *endEdgeIt;
120 const auto prevVal = *(endEdgeIt - 1);
121 if (val.second == Edge::start && prevVal.second == Edge::end) {
122 mergedRanges.emplace_back(prevVal.first);
123 mergedRanges.emplace_back(val.first);
131 mergedRanges.emplace_back(std::min(edges.back().first, totalRange.second));
142 const size_t wsIndex) {
143 const auto filteredRanges = filterRangesOutsideX(ranges, ws, wsIndex);
144 if (!ranges.empty() && filteredRanges.empty()) {
145 throw std::runtime_error(
"The given XRanges mismatch with the histogram at workspace index " +
148 const auto fullRange = totalRange(filteredRanges, ws, wsIndex);
149 return includedRanges(filteredRanges, fullRange);
156std::vector<double> invertRanges(
const std::vector<double> &ranges) {
157 std::vector<double> inversion(ranges.size() - 2);
158 for (
size_t i = 1; i < ranges.size() - 1; ++i) {
159 inversion[i - 1] = ranges[i];
176 const std::vector<double> &ranges,
const std::string &costFunction,
177 const std::string &minimizer,
const bool &ignoreInvalidData) {
178 const auto fitRanges = histogramRanges(ranges, *ws, wsIndex);
179 const auto excludedRanges = invertRanges(fitRanges);
182 fit.
setProperty(
"WorkspaceIndex",
static_cast<int>(wsIndex));
187 fit.
setProperty(Prop::COST_FUNCTION, costFunction);
188 fit.
setProperty(Prop::IGNORE_INVALID_DATA, ignoreInvalidData);
192 std::vector<double> parameters(fitResult->rowCount() - 1);
193 for (
size_t row = 0; row < parameters.size(); ++row) {
194 parameters[row] = fitResult->cell<
double>(row, 1);
204std::string makeFunctionString(
const std::string &
name,
const std::vector<double> ¶meters) {
205 const auto degree = parameters.size() - 1;
206 std::ostringstream s;
207 s <<
"name=" <<
name;
209 s <<
",n=" << degree;
210 for (
size_t d = 0;
d <= degree; ++
d) {
211 s <<
',' <<
'A' <<
d <<
'=' << parameters[
d];
220std::string makeNameString(
const size_t degree) {
221 std::ostringstream
name;
224 name <<
"FlatBackground";
227 name <<
"LinearBackground";
233 name <<
"Polynomial";
245 const size_t wsIndex) {
246 const auto degree = parameters.size() - 1;
247 auto bkg = std::dynamic_pointer_cast<Mantid::API::IFunction1D>(
248 Mantid::API::FunctionFactory::Instance().createFunction(
name));
252 bkg->setAttribute(
"n", att);
254 for (
size_t d = 0;
d <= degree; ++
d) {
256 bkg->setParameter(param, parameters[d]);
258 auto *
y =
const_cast<double *
>(ws.
mutableY(wsIndex).rawData().data());
259 bkg->function1D(y, ws.
points(wsIndex).rawData().data(), ws.
y(wsIndex).size());
278 return "CorrectionFunctions\\BackgroundCorrections";
283 return "Fits a polynomial background to a workspace.";
290 auto increasingAxis = std::make_shared<API::IncreasingAxisValidator>();
291 auto nonnegativeInt = std::make_shared<Kernel::BoundedValidator<int>>();
292 nonnegativeInt->setLower(0);
293 auto orderedPairs = std::make_shared<Kernel::ArrayOrderedPairsValidator<double>>();
296 "An input workspace.");
299 "A workspace containing the fitted background.");
300 declareProperty(Prop::POLY_DEGREE, 0, nonnegativeInt,
"Degree of the fitted polynomial.");
302 "A list of fitting ranges given as pairs of X values.");
303 std::array<std::string, 2> costFuncOpts{{CostFunc::WEIGHTED_LEAST_SQUARES, CostFunc::UNWEIGHTED_LEAST_SQUARES}};
306 "The cost function to be passed to the Fit algorithm.");
307 std::array<std::string, 2> minimizerOpts{{Minimizer::LEVENBERG_MARQUARDT_MD, Minimizer::LEVENBERG_MARQUARDT}};
310 "The minimizer to be passed to the Fit algorithm.");
311 declareProperty(Prop::IGNORE_INVALID_DATA,
false,
"Flag to ignore infinities, NaNs and data with zero errors.");
321 const std::vector<double> inputRanges =
getProperty(Prop::XRANGES);
322 const std::string costFunction =
getProperty(Prop::COST_FUNCTION);
323 const bool ignoreInvalidData =
getProperty(Prop::IGNORE_INVALID_DATA);
324 const std::string minimizer =
getProperty(Prop::MINIMIZER);
325 const auto polyDegree =
static_cast<size_t>(
static_cast<int>(
getProperty(Prop::POLY_DEGREE)));
326 const std::vector<double> initialParams(polyDegree + 1, 0.1);
327 const auto polyDegreeStr = makeNameString(polyDegree);
328 const auto fitFunction = makeFunctionString(polyDegreeStr, initialParams);
329 const auto nHistograms =
static_cast<int64_t
>(inWS->getNumberHistograms());
332 for (int64_t i = 0; i < nHistograms; ++i) {
334 const bool logging{
false};
336 const auto parameters =
337 executeFit(*fit, fitFunction, inWS, i, inputRanges, costFunction, minimizer, ignoreInvalidData);
338 evaluateInPlace(polyDegreeStr, parameters, *outWS, i);
#define DECLARE_ALGORITHM(classname)
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
Base class from which all concrete algorithm classes should be derived.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
void executeAsChildAlg() override
Execute as a Child Algorithm.
Attribute is a non-fitting parameter.
void fromString(const std::string &str)
Set value from a string.
Base MatrixWorkspace Abstract Class.
HistogramData::Points points(const size_t index) const
const HistogramData::HistogramX & x(const size_t index) const
HistogramData::HistogramY & mutableY(const size_t index) &
const HistogramData::HistogramY & y(const size_t index) const
Helper class for reporting progress from algorithms.
A property class for workspaces.
CalculatePolynomialBackground : This algorithm fits a polynomial background to an input workspace and...
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
void exec() override
Execute the algorithm.
int version() const override
Algorithm's version for identification.
const std::string category() const override
Algorithm's category for identification.
void init() override
Initialize the algorithm's properties.
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.
ListValidator is a validator that requires the value of a property to be one of a defined list of pos...
String constants for cost function options.
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
boost::graph_traits< PeakGraph >::edge_descriptor Edge
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
String constants for minimizer options.
String constants for algorithm's properties.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.