26#include "MantidQtWidgets/Common/QtPropertyBrowser/ParameterPropertyManager.h"
27#include "MantidQtWidgets/Common/QtPropertyBrowser/qtpropertymanager.h"
28#include "MantidQtWidgets/Common/QtPropertyBrowser/qttreepropertybrowser.h"
38const std::regex PREFIX_REGEX(
"(^[f][0-9](.*))");
39inline bool variableIsPrefixed(
const std::string &
name) {
return std::regex_match(
name, PREFIX_REGEX); }
49 m_item(item), m_isMultispectral(false), m_workspace(nullptr), m_workspaceIndex(nullptr), m_base(0), m_ci(0),
60 }
else if (
m_item ==
nullptr) {
62 throw std::runtime_error(
"Parent function handler does not exist");
68 pi->property()->addSubProperty(fnProp);
71 const auto it = std::find_if(itList.cbegin(), itList.cend(),
72 [&fnProp](
auto browserItem) { return browserItem->property() == fnProp; });
73 if (it != itList.cend()) {
76 throw std::runtime_error(
"Browser item not found");
86 QtProperty *fnProp =
m_item->property();
92 fnProp->addSubProperty(
m_type);
97 QStringList functionNames;
98 functionNames <<
"CompositeFunction";
114 if (
m_cf &&
m_cf->nFunctions() > 0) {
115 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
118 throw std::runtime_error(
"IFunction expected but func function of another type");
120 auto h = std::make_unique<PropertyHandler>(f,
m_cf,
m_browser);
121 f->setHandler(std::move(h));
143 QtProperty *
apply(
const std::string &str)
const override {
157 QtProperty *
apply(
const double &
d)
const override {
163 QtProperty *
apply(
const int &i)
const override {
169 QtProperty *
apply(
const bool &b)
const override {
175 QtProperty *
apply(
const std::vector<double> &b)
const override {
181 prop->addSubProperty(sizeProp);
186 QString dpName =
"value[%1]";
187 for (
size_t i = 0; i < b.size(); ++i) {
190 prop->addSubProperty(dprop);
207 for (
size_t iparam = 0; iparam <
m_cf->nParams(); iparam++) {
208 const auto *tie =
m_cf->getTie(iparam);
211 const auto nameIndex_pair =
m_cf->parseName(
m_cf->parameterName(iparam));
213 std::dynamic_pointer_cast<Mantid::API::IFunction>(
m_cf->getFunction(nameIndex_pair.second));
215 h->addTie(QString::fromStdString(tie->asString()));
224 std::vector<std::string> attNames =
function()->getAttributeNames();
226 m_item->property()->removeSubProperty(attribute);
230 for (
const auto &attName : attNames) {
231 if (variableIsPrefixed(attName))
233 QString aName = QString::fromStdString(attName);
237 m_item->property()->addSubProperty(prop);
244 m_item->property()->removeSubProperty(parameter);
247 for (
size_t i = 0; i <
function()->nParams(); i++) {
248 QString parName = QString::fromStdString(
function()->parameterName(i));
249 if (parName.contains(
'.'))
256 m_item->property()->addSubProperty(prop);
258 if (
m_fun->isFixed(i)) {
265 QStringList qc = QString::fromStdString(c->
asString()).split(
"<");
268 double loBound = 0, upBound = 0;
269 if (qc.size() == 2) {
270 if (qc[0].contains(parName)) {
272 upBound = qc[1].toDouble();
275 loBound = qc[0].toDouble();
277 }
else if (qc.size() == 3) {
279 loBound = qc[0].toDouble();
280 upBound = qc[2].toDouble();
284 QtProperty *loProp =
nullptr;
285 QtProperty *upProp =
nullptr;
289 prop->addSubProperty(loProp);
294 prop->addSubProperty(upProp);
296 m_constraints.insert(parName, std::pair<QtProperty *, QtProperty *>(loProp, upProp));
356 if (fnName.find(
"=") == std::string::npos) {
357 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName);
359 f = Mantid::API::FunctionFactory::Instance().createInitialized(fnName);
366 std::shared_ptr<Mantid::API::IPeakFunction> pf = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(f);
376 ws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
386 if (ws && wi < ws->getNumberHistograms()) {
387 const auto &
X = ws->x(wi);
388 size_t istart = 0, iend = 0;
389 for (
size_t i = 0; i <
X.size() - 1; ++i) {
391 if (x < m_browser->startX())
401 const auto &
Y = ws->y(wi);
402 double p0 =
Y[istart];
404 double A1 = (p1 - p0) / (
X[iend] -
X[istart]);
405 double A0 = p0 - A1 *
X[istart];
406 f->setParameter(
"A0", A0);
407 f->setParameter(
"A1", A1);
415 size_t nFunctions =
m_cf->nFunctions() + 1;
416 m_cf->addFunction(f);
419 if (
m_cf->nFunctions() != nFunctions) {
424 f->setHandler(std::make_unique<PropertyHandler>(f,
m_cf,
m_browser));
452 ph->
item()->property()->removeSubProperty(
m_item->property());
454 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
455 if (cf->getFunction(i) ==
function()) {
457 cf->removeFunction(i);
469 QString parName = it.key();
471 QtProperty *prop = it.value();
474 const auto *tie = cf.
getTie(paramIndex);
481 if (parProp !=
nullptr) {
482 parProp->removeSubProperty(prop);
485 parProp->setEnabled(
true);
496 QStringList qtie = QString::fromStdString(tie->asString()).split(
"=");
504 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
508 QtProperty *nameProp = h->
item()->property();
519 if (!
name.isEmpty()) {
531 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
532 if (cf->getFunction(i) ==
function()) {
540 return pref +
"f" + QString::number(iFun);
554 if (!
m_cf || i >=
m_cf->nFunctions())
568 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
584 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
595 if (prop ==
m_item->property())
611 if (!
m_ties.key(prop,
"").isEmpty())
613 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.begin();
615 if (it.value().first == prop || it.value().second == prop) {
621 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
633 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
646 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
662 std::string parName = prop->propertyName().toStdString();
664 m_fun->setParameter(parName, parValue);
667 if (
m_fun->isFixed(
m_fun->parameterIndex(parName))) {
668 const auto subProps = prop->subProperties();
669 if (std::any_of(subProps.cbegin(), subProps.cend(),
670 [](
const auto &subProp) { return subProp->propertyName() ==
"Fix"; })) {
671 fix(prop->propertyName());
680 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
706 void apply(std::string &str)
const override {
727 void apply(
bool &b)
const override {
734 void apply(std::vector<double> &v)
const override {
736 if (members.size() < 1) {
742 int vectorSize = members.size() - 1;
743 if (vectorSize > newSize) {
744 vectorSize = newSize;
748 std::vector<double> newVec(newSize);
749 for (
int i = 1; i < newSize + 1; ++i) {
753 if (i < vectorSize + 1) {
756 newVec[i - 1] = newVal;
765 std::copy(cbegin(newVec), cend(newVec), begin(v));
783 void apply(
const std::string &str)
const override {
789 void apply(
const double &
d)
const override {
795 void apply(
const int &i)
const override {
801 void apply(
const bool &b)
const override {
807 void apply(
const std::vector<double> & )
const override {
811 throw std::runtime_error(
"Vector attribute not implemented.");
828 QString attName = prop->propertyName();
833 m_fun->setAttribute(attName.toStdString(), att);
835 if (resetProperties) {
848 }
catch (std::exception &e) {
851 QMessageBox::critical(
m_browser,
"Mantid - Error", e.what());
857 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
872 auto const attributeType = attValue.
type();
873 if (attributeType ==
"int")
875 else if (attributeType ==
"double")
877 else if (attributeType ==
"std::string")
886template <
typename AttributeType>
888 if (
m_fun->hasAttribute(attName.toStdString())) {
893 if (prop->propertyName() == attName) {
904 for (
auto i = 0u; i <
cfun()->nFunctions(); ++i) {
917 const std::string
name = attName.toStdString();
924 if (prop->propertyName() == attName) {
943 if (subProps.contains(prop)) {
958 (this->*(func))(attribute);
962 for (std::size_t i = 0u; i <
m_cf->nFunctions(); ++i)
977 auto const attributeValue =
function()->getAttribute(attribute->propertyName().toStdString());
978 setAttribute(attribute->propertyName(), attributeValue);
989 (this->*(func))(prop);
993 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1009 double const parValue =
function()->getParameter(prop->propertyName().toStdString());
1017 size_t index =
function()->parameterIndex(prop->propertyName().toStdString());
1036 const QString &fnName = functionNames[i];
1039 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName.toStdString());
1041 }
catch (std::exception &e) {
1042 QMessageBox::critical(
nullptr,
"Mantid - Error",
"Cannot create function " + fnName +
"\n" + e.what());
1072 foreach (QtProperty *sub, subs) {
1073 m_item->property()->removeSubProperty(sub);
1092 m_parent->replaceFunctionPtr(f_old, f);
1099 f->setHandler(std::move(h));
1105 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1118 [&parName](
const auto &parProp) { return parProp->propertyName() == parName; });
1127 [&prop](
const auto &parProp) { return parProp->subProperties().contains(prop); });
1135 QStringList parts = tieStr.split(
"=");
1136 if (parts.size() != 2)
1138 std::string
name = parts[0].trimmed().toStdString();
1139 std::string expr = parts[1].trimmed().toStdString();
1142 cfunction.tie(
name, expr);
1143 cfunction.applyTies();
1144 const auto paramIndex = cfunction.parameterIndex(
name);
1145 const auto paramStatus = cfunction.getParameterStatus(paramIndex);
1147 const bool recursive =
true;
1148 QString parName = QString::fromStdString(cfunction.parameterLocalName(paramIndex, recursive));
1153 QtProperty *tieProp =
m_ties[parName];
1155 const auto tiePropName = fixed ?
"Fix" :
"Tie";
1157 m_ties[parName] = tieProp;
1160 parProp->addSubProperty(tieProp);
1162 tieProp->setEnabled(
false);
1168 }
catch (
const std::exception &exc) {
1169 std::cerr << exc.what();
1170 QMessageBox::critical(
m_browser,
"Mantid - Error",
"Failed to set tie: " + tieStr);
1189 QString parName =
m_ties.key(prop,
"");
1190 if (parName.isEmpty())
1197 auto index = compositeFunction.parameterIndex(globalName);
1198 compositeFunction.removeTie(
index);
1199 parProp->removeSubProperty(prop);
1200 m_ties.remove(QString::fromStdString(globalName));
1203 parProp->setEnabled(
true);
1211 QString parName =
m_ties.key(prop,
"");
1212 if (parName.isEmpty())
1216 if (parProp !=
nullptr) {
1218 m_fun->removeTie(parName.toStdString());
1219 parProp->removeSubProperty(prop);
1222 parProp->setEnabled(
true);
1231 QtProperty *prop =
m_ties[parName];
1241 double fwhmEstimate = 0.;
1245 const auto &
X = ws->x(wi);
1246 const auto &
Y = ws->y(wi);
1247 size_t n =
Y.size() - 1;
1248 if (m_ci < 0 || m_ci >
static_cast<int>(
n)) {
1253 size_t rightHwhmIndex =
m_ci;
1254 while (rightHwhmIndex <
n) {
1255 if (
Y[rightHwhmIndex++] <= halfHeight) {
1261 size_t leftHwhmIndex =
m_ci;
1262 while (leftHwhmIndex > 0) {
1263 if (
Y[leftHwhmIndex--] <= halfHeight) {
1268 fwhmEstimate =
fabs(
X[rightHwhmIndex] -
X[leftHwhmIndex]);
1272 if (fwhmEstimate > fitRange) {
1274 fwhmEstimate = fitRange * 0.1;
1278 return fwhmEstimate;
1291 const auto &
X = ws->x(wi);
1292 const auto &
Y = ws->y(wi);
1293 int n =
static_cast<int>(
Y.size()) - 1;
1317 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1321 }
else if (h->
cfun()) {
1348 const auto &
X = ws->x(wi);
1349 int n =
static_cast<int>(
X.size()) - 2;
1380 return m_pf->height();
1387 return m_pf->centre();
1394 return m_pf->fwhm();
1401 return m_pf->getWidthParameterName();
1408 return m_pf->getCentreParameterName();
1415 return m_pf->isExplicitlySet(
m_pf->parameterIndex(param));
1424 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator old =
m_constraints.find(parProp->propertyName());
1430 hasLo = old.value().first != NULL;
1431 hasUp = old.value().second != NULL;
1443 std::pair<QtProperty *, QtProperty *> cnew;
1448 std::ostringstream ostr;
1450 ostr << loBound <<
"<";
1453 parProp->addSubProperty(cnew.first);
1455 cnew.first = old.value().first;
1459 ostr << parProp->propertyName().toStdString();
1461 ostr <<
"<" << upBound;
1464 parProp->addSubProperty(cnew.second);
1466 cnew.second = old.value().second;
1477 auto c = std::unique_ptr<Mantid::API::IConstraint>(
1478 Mantid::API::ConstraintFactory::Instance().createInitialized(
m_fun.get(), ostr.str()));
1479 m_fun->addConstraint(std::move(c));
1484 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.find(parProp->propertyName());
1487 if (it.value().first) {
1488 parProp->removeSubProperty(it.value().first);
1490 if (it.value().second) {
1491 parProp->removeSubProperty(it.value().second);
1493 m_fun->removeConstraint(parProp->propertyName().toStdString());
1507 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1513 }
else if (h->
cfun()) {
1540 if (
m_cf && (
m_cf->name() ==
"CompositeFunction" ||
m_cf->name() ==
"ProductFunction")) {
1541 QStringList childrenTooltips;
1545 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1547 childrenTooltips << childHandler->updateStructureTooltip();
1549 throw std::runtime_error(
"Error while building structure tooltip: no handler for child");
1553 if (childrenTooltips.empty()) {
1554 newTooltip = QString::fromStdString(
"Empty " +
m_cf->name());
1558 if (
m_cf->name() ==
"ProductFunction") {
1562 newTooltip = QString(
"(%1)").arg(childrenTooltips.join(
' ' + op +
' '));
1565 newTooltip = QString::fromStdString(
function()->
name());
1568 m_item->property()->setToolTip(newTooltip);
1578 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1591 alg->setProperty(
"Function",
m_fun);
1599 for (
size_t i = 0; i < f->nParams(); ++i) {
1600 m_fun->setParameter(i, f->getParameter(i));
1613 if (
index >= 0 &&
index < oldWorkspaces.size()) {
1614 wsName = oldWorkspaces[
index];
1616 QStringList names(
"All");
1626 for (
size_t i = 0; i <
cfun()->nFunctions(); ++i) {
1635 if (
index >= 0 && index < m_browser->m_workspaceNames.size()) {
1639 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
1643 ifun()->setWorkspace(ws);
std::map< DeltaEMode::Type, std::string > index
A composite function is a function containing other functions.
ParameterTie * getTie(size_t i) const override
Get the tie of i-th parameter.
ParameterStatus getParameterStatus(size_t i) const override
Get status of parameter.
Implements FunctionDomain1D with its own storage in form of a std::vector.
Classes inherited from FunctionHandler will handle the function.
IFunction_sptr function() const
Return the handled function.
IFunction_sptr m_fun
pointer to the handled function
A class to store values calculated by a function.
An interface to a background function.
An interface to a constraint.
virtual std::string asString() const =0
Return the string that can be used in this->initialize() to recreate this constraint.
virtual void setHeight(const double h)=0
Sets the parameters such that height == h.
virtual void setCentre(const double c)=0
Sets the parameters such that centre == c.
Mantid::Kernel::IValidator_sptr m_validator
Validator against which to evaluate attribute value to set.
void evaluateValidator(T1 &inputData) const
Evaluates the validator associated with attribute this visitor is to visit.
Attribute is a non-fitting parameter.
int asInt() const
Returns int value if attribute is a int, throws exception otherwise.
Kernel::IValidator_sptr getValidator()
Return a clone of the attribute validator;.
std::string asString() const
Returns string value if attribute is a string, throws exception otherwise.
T apply(AttributeVisitor< T > &v)
Apply an attribute visitor.
void fromString(const std::string &str)
Set value from a string.
double asDouble() const
Returns double value if attribute is a double, throws exception otherwise.
std::string type() const
Returns type of the attribute.
Const version of AttributeVisitor.
Mantid::Kernel::IValidator_sptr m_validator
Validator against which to evaluate attribute value to set.
This is an interface to a fitting function - a semi-abstarct class.
An interface to a peak function, which extend the interface of IFunctionWithLocation by adding method...
virtual void setFwhm(const double w)=0
Sets the parameters such that FWHM = w.
ListValidator is a validator that requires the value of a property to be one of a defined list of pos...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const CompositeFunction > CompositeFunction_const_sptr
shared pointer to the composite function base class (const version)
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
std::shared_ptr< const IFunction > IFunction_const_sptr
shared pointer to the function base class (const version)
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< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Helper class which provides the Collimation Length for SANS instruments.
Simple Exception Struct to differentiate validation error from other exceptions.