33#include <boost/math/distributions/students_t.hpp>
43 enum Kind :
char { Opening, Closing };
50 bool operator<(
const RangePoint &point)
const {
51 if (this->value == point.value) {
56 return this->kind == Opening;
58 return this->value < point.value;
66void joinOverlappingRanges(std::vector<double> &exclude) {
67 if (exclude.empty()) {
77 std::vector<RangePoint> points;
78 points.reserve(exclude.size());
79 for (
auto point = exclude.begin(); point != exclude.end(); point += 2) {
80 points.emplace_back(RangePoint{RangePoint::Opening, *point});
81 points.emplace_back(RangePoint{RangePoint::Closing, *(point + 1)});
84 std::sort(points.begin(), points.end());
91 for (
auto &point : points) {
92 if (point.kind == RangePoint::Opening) {
95 exclude.emplace_back(point.value);
102 exclude.emplace_back(point.value);
110bool greaterIsLess(
double x1,
double x2) {
return x1 > x2; }
113using namespace Kernel;
123 const std::string &workspacePropertyName,
126 m_endX(
EMPTY_DBL()), m_maxSize(0), m_noErrCol(false) {
128 throw std::runtime_error(
"Cannot create FitMW: no workspace given");
140 m_maxSize(10), m_noErrCol(false) {}
160 "A value of x in, or on the low x boundary of, the first bin to "
162 "the fit (default lowest value of x)");
164 "A value in, or on the high x boundary of, the last bin the fitting "
166 "(default the highest value of x)");
168 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
169 mustBePositive->setLower(0);
171 "The maximum number of values per a simple domain.");
174 auto mustBeOrderedPairs = std::make_shared<ArrayOrderedPairsValidator<double>>();
176 "A list of pairs of doubles that specify ranges that must be "
177 "excluded from fit.");
187 std::shared_ptr<API::FunctionValues> &values,
size_t i0) {
193 throw std::runtime_error(
"Workspace contains no data.");
197 std::vector<double> xData;
200 xData.emplace_back(
X->toDouble(i));
207 auto to = xData.begin() + endRowNo;
213 domain.reset(seqDomain);
223 creator->setRange(*(from +
m), *(from + k - 1));
239 values->expand(i0 + domain->size());
243 assert(
n == domain->size());
245 if (endRowNo >
Y->size()) {
246 throw std::runtime_error(
"TableWorkspaceDomainCreator: Inconsistent TableWorkspace");
255 auto y =
Y->toDouble(i);
256 auto error = errors->toDouble(i);
261 }
else if (!std::isfinite(
y)) {
264 throw std::runtime_error(
"Infinte number or NaN found in input data.");
268 }
else if (!std::isfinite(
error)) {
271 throw std::runtime_error(
"Infinte number or NaN found in input data.");
272 }
else if (
error <= 0) {
276 weight = 1.0 /
error;
277 if (!std::isfinite(weight)) {
279 throw std::runtime_error(
"Error of a data point is probably too small.");
284 values->setFitData(j,
y);
285 values->setFitWeight(j, weight);
287 m_domain = std::dynamic_pointer_cast<API::FunctionDomain1D>(domain);
300 const std::string &baseName,
API::IFunction_sptr function, std::shared_ptr<API::FunctionDomain> domain,
301 std::shared_ptr<API::FunctionValues> values,
const std::string &outputWorkspacePropertyName) {
304 throw std::logic_error(
"FunctionValues expected");
308 std::list<API::IFunction_sptr> functionsToDisplay(1, function);
314 const size_t nhistograms = functionsToDisplay.size() + 2;
315 const size_t nyvalues = values->size();
324 auto iend = functionsToDisplay.end();
326 for (
auto it = functionsToDisplay.begin(); it != iend; ++it) {
328 textAxis->
setLabel(wsIndex, (*it)->name());
330 if (it == functionsToDisplay.begin())
337 const auto &Ycal = ws->y(1);
338 auto &Diff = ws->mutableY(2);
339 const size_t nData = values->size();
340 for (
size_t i = 0; i < nData; ++i) {
341 if (values->getFitWeight(i) != 0.0) {
342 Diff[i] = values->getFitData(i) - Ycal[i];
348 if (!outputWorkspacePropertyName.empty()) {
351 "Name of the output Workspace holding resulting simulated spectrum");
370 const auto compositeFn = std::dynamic_pointer_cast<API::CompositeFunction>(function);
374 const size_t nlocals = compositeFn->nFunctions();
375 for (
size_t i = 0; i < nlocals; ++i) {
376 auto localFunction = compositeFn->getFunction(i);
377 auto localComposite = std::dynamic_pointer_cast<API::CompositeFunction>(localFunction);
381 functionList.insert(functionList.end(), localFunction);
401 std::shared_ptr<Functions::Convolution> convolution = std::dynamic_pointer_cast<Functions::Convolution>(function);
403 const auto compositeFn = std::dynamic_pointer_cast<API::CompositeFunction>(convolution->getFunction(1));
405 functionList.insert(functionList.end(), convolution);
407 auto resolution = convolution->getFunction(0);
408 const size_t nlocals = compositeFn->nFunctions();
409 for (
size_t i = 0; i < nlocals; ++i) {
410 auto localFunction = compositeFn->getFunction(i);
411 std::shared_ptr<Functions::Convolution> localConvolution = std::make_shared<Functions::Convolution>();
412 localConvolution->addFunction(resolution);
413 localConvolution->addFunction(localFunction);
414 functionList.insert(functionList.end(), localConvolution);
429 const API::IFunction_sptr &function, std::shared_ptr<API::MatrixWorkspace> &ws,
const size_t wsIndex,
430 const std::shared_ptr<API::FunctionDomain> &domain,
431 const std::shared_ptr<API::FunctionValues> &resultValues)
const {
432 const size_t nData = resultValues->size();
433 resultValues->zeroCalculated();
440 double prob = std::erf(
sigma / sqrt(2));
442 double alpha = (1 + prob) / 2;
445 function->function(*domain, *resultValues);
447 size_t nParams = function->nParams();
450 auto covar = function->getCovarianceMatrix();
451 bool hasErrors =
false;
453 for (
size_t j = 0; j < nParams; ++j) {
454 if (function->getError(j) != 0.0) {
461 if (covar || hasErrors) {
465 function->functionDeriv(*domain, J);
467 function->calNumericalDeriv(*domain, J);
476 std::vector<double> E(nData);
477 for (
size_t k = 0; k < nData; ++k) {
479 for (
size_t i = 0; i < nParams; ++i) {
482 for (
size_t j = i + 1; j < nParams; ++j) {
483 s += J.
get(k, i) * C[i][j] * J.
get(k, j) * 2;
489 size_t dof = nData - nParams;
490 auto &yValues = ws->mutableY(wsIndex);
491 auto &eValues = ws->mutableE(wsIndex);
494 boost::math::students_t dist(
static_cast<double>(dof));
495 T = boost::math::quantile(dist, alpha);
497 for (
size_t i = 0; i < nData; i++) {
498 yValues[i] = resultValues->getCalculated(i);
499 eValues[i] = T * std::sqrt(E[i]);
505 auto &yValues = ws->mutableY(wsIndex);
506 auto &eValues = ws->mutableE(wsIndex);
507 for (
size_t i = 0; i < nData; i++) {
508 yValues[i] = resultValues->getCalculated(i);
510 for (
size_t j = 0; j < nParams; ++j) {
511 double d = J.
get(i, j) * function->getError(j);
514 eValues[i] = std::sqrt(err);
519 auto &yValues = ws->mutableY(wsIndex);
520 for (
size_t i = 0; i < nData; i++) {
521 yValues[i] = resultValues->getCalculated(i);
534 const size_t nyvalues) {
535 size_t nxvalues(nyvalues);
539 auto tAxis = std::make_unique<API::TextAxis>(nhistograms);
540 ws->replaceAxis(1, std::move(tAxis));
546 std::vector<double> xData;
547 std::vector<double> yData;
548 std::vector<double> eData;
554 xData.emplace_back(inputX->toDouble(i));
555 yData.emplace_back(inputY->toDouble(i));
556 eData.emplace_back(inputE->toDouble(i));
560 for (
size_t i = 0; i < nhistograms; i++) {
576 std::vector<double> xData;
579 xData.emplace_back(
X->toDouble(i));
581 size_t startIndex, endIndex;
583 return endIndex - startIndex;
593 throw std::runtime_error(
"Cannot initialize empty function.");
606 if (domain && values) {
616 const auto sizeOfData = xData.size();
617 if (sizeOfData == 0) {
618 throw std::runtime_error(
"Workspace contains no data.");
626 Mantid::MantidVec::iterator from;
627 Mantid::MantidVec::iterator to;
629 bool isXAscending = xData.front() < xData.back();
633 from = xData.begin();
637 throw std::invalid_argument(
"Both StartX and EndX must be given to set fitting interval.");
638 }
else if (isXAscending) {
642 from = std::lower_bound(xData.begin(), xData.end(),
m_startX);
643 to = std::upper_bound(from, xData.end(),
m_endX);
648 from = std::lower_bound(xData.begin(), xData.end(),
m_startX, greaterIsLess);
649 to = std::upper_bound(from, xData.end(),
m_endX, greaterIsLess);
655 if (to - from == 0) {
656 throw std::invalid_argument(
"StartX and EndX values do not capture a range "
657 "within the workspace interval.");
660 return std::make_pair(std::distance(xData.begin(), from), std::distance(xData.begin(), to));
676 m_maxSize =
static_cast<size_t>(maxSizeInt);
680 throw std::runtime_error(
"Exclude property has an odd number of entries. "
681 "It has to be even as each pair specifies a "
682 "start and an end of an interval to exclude.");
703 auto columnNames = ws->getColumnNames();
706 if (xColName !=
"") {
707 auto column = ws->getColumn(xColName);
708 if (!column->isNumber()) {
709 throw std::invalid_argument(xColName +
" does not contain numbers");
714 if (yColName !=
"") {
715 auto column = ws->getColumn(yColName);
716 if (!column->isNumber()) {
717 throw std::invalid_argument(yColName +
" does not contain numbers");
722 if (eColName !=
"") {
723 auto column = ws->getColumn(eColName);
724 if (!column->isNumber()) {
725 throw std::invalid_argument(eColName +
" does not contain numbers");
730 for (
const auto &name : columnNames) {
731 auto column = ws->getColumn(name);
732 if (xColName ==
"" && column->getPlotType() == 1) {
733 xColName = column->name();
735 if (yColName ==
"" && column->getPlotType() == 2) {
736 yColName = column->name();
738 if (eColName ==
"" && column->getPlotType() == 5) {
739 eColName = column->name();
743 if (xColName !=
"" && yColName !=
"") {
746 throw std::invalid_argument(
"No valid input for X or Y column names");
757 auto tableWorkspace = std::dynamic_pointer_cast<API::ITableWorkspace>(ws);
758 if (!tableWorkspace) {
759 throw std::invalid_argument(
"InputWorkspace must be a TableWorkspace.");
762 std::vector<std::string> columnNames;
771 if (columnNames.size() == 2) {
776 throw std::invalid_argument(
"No error column provided.");
780 throw std::invalid_argument(
"X or Y Columns not found");
Kind kind
The kind of the point: either openning or closing the range.
double value
The value of the point.
Implements FunctionDomain1D with its own storage in form of a std::vector.
A class to store values calculated by a function.
An base class for domain creators for use in Fit.
DomainType
Type of domain to create.
bool m_convolutionCompositeMembers
Perform convolution of output composite components.
bool m_outputCompositeMembers
Output separate composite function values.
std::vector< std::string > m_workspacePropertyNames
Property names for workspaces to get the data from.
Kernel::IPropertyManager * m_manager
Pointer to a property manager.
bool m_ignoreInvalidData
Flag to ignore nans, infinities and zero errors.
void declareProperty(Kernel::Property *prop, const std::string &doc)
Declare a property to the algorithm.
DomainType m_domainType
Domain type.
This is an interface to a fitting function - a semi-abstarct class.
Represents the Jacobian in IFitFunction::functionDeriv.
virtual double get(size_t iY, size_t iP)=0
Get the value to a Jacobian matrix element.
Class to represent a text axis of a workspace.
void setLabel(const std::size_t &index, const std::string &lbl)
Set the label at the given index.
A property class for workspaces.
ExcludeRangeFinder : Helper clss that finds if a point should be excluded from fit.
bool isExcluded(double value)
Check if an x-value lies in an exclusion range.
An implementation of CompositeDomain.
void addCreator(const API::IDomainCreator_sptr &creator)
Add new domain creator.
static SeqDomain * create(API::IDomainCreator::DomainType type)
Create an instance of SeqDomain in one of two forms: either SeqDomain for sequential domain creation ...
void setXYEColumnNames(const API::ITableWorkspace_sptr &ws) const
Set the names of the X, Y and Error columns.
std::string m_yColName
Store the Y column name.
std::shared_ptr< API::Workspace > createOutputWorkspace(const std::string &baseName, API::IFunction_sptr function, std::shared_ptr< API::FunctionDomain > domain, std::shared_ptr< API::FunctionValues > values, const std::string &outputWorkspacePropertyName) override
Create an output workspace with the calculated values.
std::string m_startXPropertyName
Store startX property name.
size_t m_startRowNo
Store number of the first row used in fitting.
std::string m_workspacePropertyName
Store workspace property name.
size_t m_maxSize
Max size for seq domain.
void addFunctionValuesToWS(const API::IFunction_sptr &function, std::shared_ptr< API::MatrixWorkspace > &ws, const size_t wsIndex, const std::shared_ptr< API::FunctionDomain > &domain, const std::shared_ptr< API::FunctionValues > &resultValues) const
Add the calculated function values to the workspace.
std::string m_maxSizePropertyName
Store maxSize property name.
std::weak_ptr< API::FunctionDomain1D > m_domain
Store the created domain and values.
void setInitialValues(API::IFunction &function)
Set initial values for parameters with default values.
void setWorkspace(API::ITableWorkspace_sptr ws)
Set the workspace.
std::string m_endXPropertyName
Store endX property name.
std::string m_xColName
Store the X column name.
std::pair< size_t, size_t > getXInterval(std::vector< double > XData) const
Calculate size and starting iterator in the X array.
bool m_noErrCol
Flag to indicate if no error column was found.
TableWorkspaceDomainCreator(Kernel::IPropertyManager *fit, const std::string &workspacePropertyName, DomainType domainType=Simple)
Constructor.
std::vector< double > m_exclude
Ranges that must be excluded from fit.
std::string m_yColumnPropertyName
Store YColumnName property name.
std::string m_xColumnPropertyName
Store XColumnName property name.
std::string m_errColName
Store the Y Error column name.
void declareDatasetProperties(const std::string &suffix="", bool addProp=true) override
Declare properties that specify the dataset within the workspace to fit to.
void appendCompositeFunctionMembers(std::list< API::IFunction_sptr > &functionList, const API::IFunction_sptr &function) const
std::shared_ptr< API::MatrixWorkspace > createEmptyResultWS(const size_t nhistograms, const size_t nyvalues)
Creates the blank output workspace of the correct size.
void setParameters() const
Set all parameters.
std::string m_excludePropertyName
Store the Exclude property name.
void setColumnNames(const std::string &xColName, const std::string &yColName, const std::string &errColName) const
Set the names Of the x, y and error columns.
std::weak_ptr< API::FunctionValues > m_values
void setAndValidateWorkspace(const API::Workspace_sptr &ws) const
Check workspace is in the correct form.
void appendConvolvedCompositeFunctionMembers(std::list< API::IFunction_sptr > &functionList, const API::IFunction_sptr &function) const
If the fit function is Convolution and flag m_convolutionCompositeMembers is set and Convolution's se...
API::ITableWorkspace_sptr m_tableWorkspace
The input TableWorkspace.
void initFunction(API::IFunction_sptr function) override
Initialize the function with the workspace.
void createDomain(std::shared_ptr< API::FunctionDomain > &domain, std::shared_ptr< API::FunctionValues > &values, size_t i0=0) override
Create a domain from the input workspace.
std::string m_errorColumnPropertyName
Store errorColumnName property name.
size_t getDomainSize() const override
Return the size of the domain to be created.
Support for a property that holds an array of values.
Interface to PropertyManager.
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
virtual bool existsProperty(const std::string &name) const =0
Checks whether the named property is already in the list of managed property.
virtual TypedValue getProperty(const std::string &name) const =0
Get the value of a property.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
std::shared_ptr< IDomainCreator > IDomainCreator_sptr
Typedef for a shared pointer to IDomainCreator.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
void MANTID_CURVEFITTING_DLL estimate(API::IFunction &function, const API::FunctionDomain1D &domain, const API::FunctionValues &values)
ParameterEstimator estimates parameter values of some fitting functions from fitting data.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
constexpr bool operator<(const wide_integer< Bits, Signed > &lhs, const wide_integer< Bits2, Signed2 > &rhs)
@ Output
An output workspace.