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";
35const static std::string UNWEIGHTED_LEAST_SQUARES =
"Unweighted least squares";
36const static std::string WEIGHTED_LEAST_SQUARES =
"Least squares";
41const static std::string LEVENBERG_MARQUARDT_MD =
"Levenberg-MarquardtMD";
42const static std::string LEVENBERG_MARQUARDT =
"Levenberg-Marquardt";
52 const size_t wsIndex) {
53 const auto minX = ws.
x(wsIndex).front();
54 const auto maxX = ws.
x(wsIndex).back();
55 std::vector<double> filtered;
56 filtered.reserve(ranges.size());
57 for (
size_t i = 0; i < ranges.size() / 2; ++i) {
58 const auto first = ranges[2 * i];
59 const auto second = ranges[2 * i + 1];
60 if (!(first > maxX || second < minX)) {
61 filtered.emplace_back(first);
62 filtered.emplace_back(second);
75 const size_t wsIndex) {
76 const auto minX = ws.
x(wsIndex).front();
77 const auto maxX = ws.
x(wsIndex).back();
79 return std::pair<double, double>(minX, maxX);
81 const auto minmaxIt = std::minmax_element(ranges.cbegin(), ranges.cend());
82 const auto minEdge = *minmaxIt.first;
83 const auto maxEdge = *minmaxIt.second;
84 return std::pair<double, double>(std::min(minEdge, minX), std::max(maxEdge, maxX));
92std::vector<double> includedRanges(
const std::vector<double> &ranges,
const std::pair<double, double> &totalRange) {
94 return {totalRange.first, totalRange.second};
98 enum class Edge { start = -1, end = 1 };
99 std::vector<std::pair<double, Edge>> edges(ranges.size());
100 for (
size_t i = 0; i < ranges.size(); ++i) {
101 edges[i].first = ranges[i];
102 edges[i].second = i % 2 == 0 ? Edge::start : Edge::end;
104 std::sort(edges.begin(), edges.end(), [](
const std::pair<double, Edge> &p1,
const std::pair<double, Edge> &p2) {
105 if (p1.first == p2.first)
106 return p1.second < p2.second;
107 return p1.first < p2.first;
111 std::vector<double> mergedRanges;
112 mergedRanges.reserve(ranges.size());
113 auto edgeIt = edges.begin();
114 mergedRanges.emplace_back(std::max(edges.front().first, totalRange.first));
115 while (edgeIt != edges.end()) {
116 auto endEdgeIt = edgeIt + 1;
117 while (endEdgeIt != edges.end()) {
118 const auto val = *endEdgeIt;
119 const auto prevVal = *(endEdgeIt - 1);
120 if (val.second == Edge::start && prevVal.second == Edge::end) {
121 mergedRanges.emplace_back(prevVal.first);
122 mergedRanges.emplace_back(val.first);
130 mergedRanges.emplace_back(std::min(edges.back().first, totalRange.second));
141 const size_t wsIndex) {
142 const auto filteredRanges = filterRangesOutsideX(ranges, ws, wsIndex);
143 if (!ranges.empty() && filteredRanges.empty()) {
144 throw std::runtime_error(
"The given XRanges mismatch with the histogram at workspace index " +
147 const auto fullRange = totalRange(filteredRanges, ws, wsIndex);
148 return includedRanges(filteredRanges, fullRange);
155std::vector<double> invertRanges(
const std::vector<double> &ranges) {
156 std::vector<double> inversion(ranges.size() - 2);
157 for (
size_t i = 1; i < ranges.size() - 1; ++i) {
158 inversion[i - 1] = ranges[i];
175 const std::vector<double> &ranges,
const std::string &costFunction,
176 const std::string &minimizer) {
177 const auto fitRanges = histogramRanges(ranges, *ws, wsIndex);
178 const auto excludedRanges = invertRanges(fitRanges);
181 fit.
setProperty(
"WorkspaceIndex",
static_cast<int>(wsIndex));
186 fit.
setProperty(Prop::COST_FUNCTION, costFunction);
190 std::vector<double> parameters(fitResult->rowCount() - 1);
191 for (
size_t row = 0; row < parameters.size(); ++row) {
192 parameters[row] = fitResult->cell<
double>(row, 1);
202std::string makeFunctionString(
const std::string &name,
const std::vector<double> ¶meters) {
203 const auto degree = parameters.size() - 1;
204 std::ostringstream s;
205 s <<
"name=" << name;
207 s <<
",n=" << degree;
208 for (
size_t d = 0;
d <= degree; ++
d) {
209 s <<
',' <<
'A' <<
d <<
'=' << parameters[
d];
218std::string makeNameString(
const size_t degree) {
219 std::ostringstream name;
222 name <<
"FlatBackground";
225 name <<
"LinearBackground";
231 name <<
"Polynomial";
243 const size_t wsIndex) {
244 const auto degree = parameters.size() - 1;
245 auto bkg = std::dynamic_pointer_cast<Mantid::API::IFunction1D>(
250 bkg->setAttribute(
"n", att);
252 for (
size_t d = 0;
d <= degree; ++
d) {
254 bkg->setParameter(param, parameters[d]);
256 auto *
y =
const_cast<double *
>(ws.
mutableY(wsIndex).rawData().data());
257 bkg->function1D(y, ws.
points(wsIndex).rawData().data(), ws.
y(wsIndex).size());
276 return "CorrectionFunctions\\BackgroundCorrections";
281 return "Fits a polynomial background to a workspace.";
288 auto increasingAxis = std::make_shared<API::IncreasingAxisValidator>();
289 auto nonnegativeInt = std::make_shared<Kernel::BoundedValidator<int>>();
290 nonnegativeInt->setLower(0);
291 auto orderedPairs = std::make_shared<Kernel::ArrayOrderedPairsValidator<double>>();
294 "An input workspace.");
297 "A workspace containing the fitted background.");
298 declareProperty(Prop::POLY_DEGREE, 0, nonnegativeInt,
"Degree of the fitted polynomial.");
300 "A list of fitting ranges given as pairs of X values.");
301 std::array<std::string, 2> costFuncOpts{{CostFunc::WEIGHTED_LEAST_SQUARES, CostFunc::UNWEIGHTED_LEAST_SQUARES}};
304 "The cost function to be passed to the Fit algorithm.");
305 std::array<std::string, 2> minimizerOpts{{Minimizer::LEVENBERG_MARQUARDT_MD, Minimizer::LEVENBERG_MARQUARDT}};
308 "The minimizer to be passed to the Fit algorithm.");
318 const std::vector<double> inputRanges =
getProperty(Prop::XRANGES);
319 const std::string costFunction =
getProperty(Prop::COST_FUNCTION);
320 const std::string minimizer =
getProperty(Prop::MINIMIZER);
321 const auto polyDegree =
static_cast<size_t>(
static_cast<int>(
getProperty(Prop::POLY_DEGREE)));
322 const std::vector<double> initialParams(polyDegree + 1, 0.1);
323 const auto name = makeNameString(polyDegree);
324 const auto fitFunction = makeFunctionString(
name, initialParams);
325 const auto nHistograms =
static_cast<int64_t
>(inWS->getNumberHistograms());
328 for (int64_t i = 0; i < nHistograms; ++i) {
330 const bool logging{
false};
332 const auto parameters = executeFit(*fit, fitFunction, inWS, i, inputRanges, costFunction, minimizer);
333 evaluateInPlace(
name, 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.
const std::string name() const override
Algorithms name for identification.
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...
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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.