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";
115 if (
m_cf &&
m_cf->nFunctions() > 0) {
116 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
119 throw std::runtime_error(
"IFunction expected but func function of another type");
121 auto h = std::make_unique<PropertyHandler>(f,
m_cf,
m_browser);
122 f->setHandler(std::move(h));
144 QtProperty *
apply(
const std::string &str)
const override {
158 QtProperty *
apply(
const double &
d)
const override {
164 QtProperty *
apply(
const int &i)
const override {
170 QtProperty *
apply(
const bool &b)
const override {
176 QtProperty *
apply(
const std::vector<double> &b)
const override {
182 prop->addSubProperty(sizeProp);
187 QString dpName =
"value[%1]";
188 for (
size_t i = 0; i < b.size(); ++i) {
191 prop->addSubProperty(dprop);
208 for (
size_t iparam = 0; iparam <
m_cf->nParams(); iparam++) {
209 const auto *tie =
m_cf->getTie(iparam);
212 const auto nameIndex_pair =
m_cf->parseName(
m_cf->parameterName(iparam));
214 std::dynamic_pointer_cast<Mantid::API::IFunction>(
m_cf->getFunction(nameIndex_pair.second));
216 h->addTie(QString::fromStdString(tie->asString()));
225 std::vector<std::string> attNames =
function()->getAttributeNames();
227 m_item->property()->removeSubProperty(attribute);
231 for (
const auto &attName : attNames) {
232 if (variableIsPrefixed(attName))
234 QString aName = QString::fromStdString(attName);
238 m_item->property()->addSubProperty(prop);
245 m_item->property()->removeSubProperty(parameter);
248 for (
size_t i = 0; i <
function()->nParams(); i++) {
249 QString parName = QString::fromStdString(
function()->parameterName(i));
250 if (parName.contains(
'.'))
257 m_item->property()->addSubProperty(prop);
259 if (
m_fun->isFixed(i)) {
266 QStringList qc = QString::fromStdString(c->
asString()).split(
"<");
269 double loBound = 0, upBound = 0;
270 if (qc.size() == 2) {
271 if (qc[0].contains(parName)) {
273 upBound = qc[1].toDouble();
276 loBound = qc[0].toDouble();
278 }
else if (qc.size() == 3) {
280 loBound = qc[0].toDouble();
281 upBound = qc[2].toDouble();
285 QtProperty *loProp =
nullptr;
286 QtProperty *upProp =
nullptr;
290 prop->addSubProperty(loProp);
295 prop->addSubProperty(upProp);
297 m_constraints.insert(parName, std::pair<QtProperty *, QtProperty *>(loProp, upProp));
357 if (fnName.find(
"=") == std::string::npos) {
358 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName);
360 f = Mantid::API::FunctionFactory::Instance().createInitialized(fnName);
367 std::shared_ptr<Mantid::API::IPeakFunction> pf = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(f);
377 ws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
387 if (ws && wi < ws->getNumberHistograms()) {
388 const auto &
X = ws->x(wi);
389 size_t istart = 0, iend = 0;
390 for (
size_t i = 0; i <
X.size() - 1; ++i) {
392 if (x < m_browser->startX())
402 const auto &
Y = ws->y(wi);
403 double p0 =
Y[istart];
405 double A1 = (p1 - p0) / (
X[iend] -
X[istart]);
406 double A0 = p0 - A1 *
X[istart];
407 f->setParameter(
"A0", A0);
408 f->setParameter(
"A1", A1);
416 size_t nFunctions =
m_cf->nFunctions() + 1;
417 m_cf->addFunction(f);
420 if (
m_cf->nFunctions() != nFunctions) {
425 f->setHandler(std::make_unique<PropertyHandler>(f,
m_cf,
m_browser));
453 ph->
item()->property()->removeSubProperty(
m_item->property());
455 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
456 if (cf->getFunction(i) ==
function()) {
458 cf->removeFunction(i);
470 QString parName = it.key();
472 QtProperty *prop = it.value();
475 const auto *tie = cf.
getTie(paramIndex);
482 if (parProp !=
nullptr) {
483 parProp->removeSubProperty(prop);
486 parProp->setEnabled(
true);
497 QStringList qtie = QString::fromStdString(tie->asString()).split(
"=");
505 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
509 QtProperty *nameProp = h->
item()->property();
520 if (!
name.isEmpty()) {
532 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
533 if (cf->getFunction(i) ==
function()) {
541 return pref +
"f" + QString::number(iFun);
555 if (!
m_cf || i >=
m_cf->nFunctions())
569 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
585 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
596 if (prop ==
m_item->property())
612 if (!
m_ties.key(prop,
"").isEmpty())
614 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.begin();
616 if (it.value().first == prop || it.value().second == prop) {
622 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
634 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
647 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
663 std::string parName = prop->propertyName().toStdString();
665 m_fun->setParameter(parName, parValue);
668 if (
m_fun->isFixed(
m_fun->parameterIndex(parName))) {
669 const auto subProps = prop->subProperties();
670 if (std::any_of(subProps.cbegin(), subProps.cend(),
671 [](
const auto &subProp) { return subProp->propertyName() ==
"Fix"; })) {
672 fix(prop->propertyName());
681 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
707 void apply(std::string &str)
const override {
728 void apply(
bool &b)
const override {
735 void apply(std::vector<double> &v)
const override {
737 if (members.size() < 1) {
743 int vectorSize =
static_cast<int>(members.size()) - 1;
744 if (vectorSize > newSize) {
745 vectorSize = newSize;
749 std::vector<double> newVec(newSize);
750 for (
int i = 1; i < newSize + 1; ++i) {
754 if (i < vectorSize + 1) {
757 newVec[i - 1] = newVal;
766 std::copy(cbegin(newVec), cend(newVec), begin(v));
784 void apply(
const std::string &str)
const override {
790 void apply(
const double &
d)
const override {
796 void apply(
const int &i)
const override {
802 void apply(
const bool &b)
const override {
808 void apply(
const std::vector<double> & )
const override {
812 throw std::runtime_error(
"Vector attribute not implemented.");
829 QString attName = prop->propertyName();
834 m_fun->setAttribute(attName.toStdString(), att);
836 if (resetProperties) {
849 }
catch (std::exception &e) {
852 QMessageBox::critical(
m_browser,
"Mantid - Error", e.what());
858 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
873 auto const attributeType = attValue.
type();
874 if (attributeType ==
"int")
876 else if (attributeType ==
"double")
878 else if (attributeType ==
"std::string")
887template <
typename AttributeType>
889 if (
m_fun->hasAttribute(attName.toStdString())) {
894 if (prop->propertyName() == attName) {
905 for (
auto i = 0u; i <
cfun()->nFunctions(); ++i) {
918 const std::string
name = attName.toStdString();
925 if (prop->propertyName() == attName) {
944 if (subProps.contains(prop)) {
959 (this->*(func))(attribute);
963 for (std::size_t i = 0u; i <
m_cf->nFunctions(); ++i)
978 auto const attributeValue =
function()->getAttribute(attribute->propertyName().toStdString());
979 setAttribute(attribute->propertyName(), attributeValue);
990 (this->*(func))(prop);
994 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1010 double const parValue =
function()->getParameter(prop->propertyName().toStdString());
1018 size_t index =
function()->parameterIndex(prop->propertyName().toStdString());
1037 const QString &fnName = functionNames[i];
1040 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName.toStdString());
1042 }
catch (std::exception &e) {
1043 QMessageBox::critical(
nullptr,
"Mantid - Error",
"Cannot create function " + fnName +
"\n" + e.what());
1073 foreach (QtProperty *sub, subs) {
1074 m_item->property()->removeSubProperty(sub);
1093 m_parent->replaceFunctionPtr(f_old, f);
1100 f->setHandler(std::move(h));
1106 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1119 [&parName](
const auto &parProp) { return parProp->propertyName() == parName; });
1128 [&prop](
const auto &parProp) { return parProp->subProperties().contains(prop); });
1136 QStringList parts = tieStr.split(
"=");
1137 if (parts.size() != 2)
1139 std::string
name = parts[0].trimmed().toStdString();
1140 std::string expr = parts[1].trimmed().toStdString();
1143 cfunction.tie(
name, expr);
1144 cfunction.applyTies();
1145 const auto paramIndex = cfunction.parameterIndex(
name);
1146 const auto paramStatus = cfunction.getParameterStatus(paramIndex);
1148 const bool recursive =
true;
1149 QString parName = QString::fromStdString(cfunction.parameterLocalName(paramIndex, recursive));
1154 QtProperty *tieProp =
m_ties[parName];
1156 const auto tiePropName = fixed ?
"Fix" :
"Tie";
1158 m_ties[parName] = tieProp;
1161 parProp->addSubProperty(tieProp);
1163 tieProp->setEnabled(
false);
1169 }
catch (
const std::exception &exc) {
1170 std::cerr << exc.what();
1171 QMessageBox::critical(
m_browser,
"Mantid - Error",
"Failed to set tie: " + tieStr);
1190 QString parName =
m_ties.key(prop,
"");
1191 if (parName.isEmpty())
1198 auto index = compositeFunction.parameterIndex(globalName);
1199 compositeFunction.removeTie(
index);
1200 parProp->removeSubProperty(prop);
1201 m_ties.remove(QString::fromStdString(globalName));
1204 parProp->setEnabled(
true);
1212 QString parName =
m_ties.key(prop,
"");
1213 if (parName.isEmpty())
1217 if (parProp !=
nullptr) {
1219 m_fun->removeTie(parName.toStdString());
1220 parProp->removeSubProperty(prop);
1223 parProp->setEnabled(
true);
1232 QtProperty *prop =
m_ties[parName];
1242 double fwhmEstimate = 0.;
1246 const auto &
X = ws->x(wi);
1247 const auto &
Y = ws->y(wi);
1248 size_t n =
Y.size() - 1;
1249 if (m_ci < 0 || m_ci >
static_cast<int>(
n)) {
1254 size_t rightHwhmIndex =
m_ci;
1255 while (rightHwhmIndex <
n) {
1256 if (
Y[rightHwhmIndex++] <= halfHeight) {
1262 size_t leftHwhmIndex =
m_ci;
1263 while (leftHwhmIndex > 0) {
1264 if (
Y[leftHwhmIndex--] <= halfHeight) {
1269 fwhmEstimate =
fabs(
X[rightHwhmIndex] -
X[leftHwhmIndex]);
1273 if (fwhmEstimate > fitRange) {
1275 fwhmEstimate = fitRange * 0.1;
1279 return fwhmEstimate;
1292 const auto &
X = ws->x(wi);
1293 const auto &
Y = ws->y(wi);
1294 int n =
static_cast<int>(
Y.size()) - 1;
1318 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1322 }
else if (h->
cfun()) {
1349 const auto &
X = ws->x(wi);
1350 int n =
static_cast<int>(
X.size()) - 2;
1381 return m_pf->height();
1388 return m_pf->centre();
1395 return m_pf->fwhm();
1402 return m_pf->getWidthParameterName();
1409 return m_pf->getCentreParameterName();
1416 return m_pf->isExplicitlySet(
m_pf->parameterIndex(param));
1425 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator old =
m_constraints.find(parProp->propertyName());
1431 hasLo = old.value().first != NULL;
1432 hasUp = old.value().second != NULL;
1444 std::pair<QtProperty *, QtProperty *> cnew;
1449 std::ostringstream ostr;
1451 ostr << loBound <<
"<";
1454 parProp->addSubProperty(cnew.first);
1456 cnew.first = old.value().first;
1460 ostr << parProp->propertyName().toStdString();
1462 ostr <<
"<" << upBound;
1465 parProp->addSubProperty(cnew.second);
1467 cnew.second = old.value().second;
1478 auto c = std::unique_ptr<Mantid::API::IConstraint>(
1479 Mantid::API::ConstraintFactory::Instance().createInitialized(
m_fun.get(), ostr.str()));
1480 m_fun->addConstraint(std::move(c));
1485 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.find(parProp->propertyName());
1488 if (it.value().first) {
1489 parProp->removeSubProperty(it.value().first);
1491 if (it.value().second) {
1492 parProp->removeSubProperty(it.value().second);
1494 m_fun->removeConstraint(parProp->propertyName().toStdString());
1508 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1514 }
else if (h->
cfun()) {
1541 if (
m_cf && (
m_cf->name() ==
"CompositeFunction" ||
m_cf->name() ==
"ProductFunction")) {
1542 QStringList childrenTooltips;
1546 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1548 childrenTooltips << childHandler->updateStructureTooltip();
1550 throw std::runtime_error(
"Error while building structure tooltip: no handler for child");
1554 if (childrenTooltips.empty()) {
1555 newTooltip = QString::fromStdString(
"Empty " +
m_cf->name());
1559 if (
m_cf->name() ==
"ProductFunction") {
1563 newTooltip = QString(
"(%1)").arg(childrenTooltips.join(
' ' + op +
' '));
1566 newTooltip = QString::fromStdString(
function()->
name());
1569 m_item->property()->setToolTip(newTooltip);
1579 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1592 alg->setProperty(
"Function",
m_fun);
1600 for (
size_t i = 0; i < f->nParams(); ++i) {
1601 m_fun->setParameter(i, f->getParameter(i));
1614 if (
index >= 0 &&
index < oldWorkspaces.size()) {
1615 wsName = oldWorkspaces[
index];
1617 QStringList names(
"All");
1628 for (
size_t i = 0; i <
cfun()->nFunctions(); ++i) {
1637 if (
index >= 0 && index < m_browser->m_workspaceNames.size()) {
1641 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
1645 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.