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);
250 for (
size_t i = 0; i <
function()->nParams(); i++) {
251 QString parName = QString::fromStdString(
function()->parameterName(i));
252 if (parName.contains(
'.'))
259 m_item->property()->addSubProperty(prop);
261 if (
m_fun->isFixed(i)) {
268 QStringList qc = QString::fromStdString(c->
asString()).split(
"<");
271 double loBound = 0, upBound = 0;
272 if (qc.size() == 2) {
273 if (qc[0].contains(parName)) {
275 upBound = qc[1].toDouble();
278 loBound = qc[0].toDouble();
280 }
else if (qc.size() == 3) {
282 loBound = qc[0].toDouble();
283 upBound = qc[2].toDouble();
287 QtProperty *loProp =
nullptr;
288 QtProperty *upProp =
nullptr;
292 prop->addSubProperty(loProp);
297 prop->addSubProperty(upProp);
299 m_constraints.insert(parName, std::pair<QtProperty *, QtProperty *>(loProp, upProp));
366 if (fnName.find(
"=") == std::string::npos) {
367 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName);
369 f = Mantid::API::FunctionFactory::Instance().createInitialized(fnName);
375 std::shared_ptr<Mantid::API::IPeakFunction> pf = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(f);
385 ws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
395 if (ws && wi < ws->getNumberHistograms()) {
396 const auto &
X = ws->x(wi);
398 for (
size_t i = 0; i <
X.size() - 1; ++i) {
400 if (x < m_browser->startX())
410 const auto &
Y = ws->y(wi);
414 double A0 = p0 - A1 *
X[
istart];
415 f->setParameter(
"A0", A0);
416 f->setParameter(
"A1", A1);
424 size_t nFunctions =
m_cf->nFunctions() + 1;
425 m_cf->addFunction(f);
429 if (
m_cf->nFunctions() != nFunctions) {
435 f->setHandler(std::make_unique<PropertyHandler>(f,
m_cf,
m_browser));
463 ph->
item()->property()->removeSubProperty(
m_item->property());
465 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
466 if (cf->getFunction(i) ==
function()) {
468 cf->removeFunction(i);
480 QString parName = it.key();
482 QtProperty *prop = it.value();
485 const auto *tie = cf.
getTie(paramIndex);
492 if (parProp !=
nullptr) {
493 parProp->removeSubProperty(prop);
496 parProp->setEnabled(
true);
507 QStringList qtie = QString::fromStdString(tie->asString()).split(
"=");
515 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
519 QtProperty *nameProp = h->
item()->property();
530 if (!
name.isEmpty()) {
542 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
543 if (cf->getFunction(i) ==
function()) {
551 return pref +
"f" + QString::number(iFun);
565 if (!
m_cf || i >=
m_cf->nFunctions())
579 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
595 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
606 if (prop ==
m_item->property())
622 if (!
m_ties.key(prop,
"").isEmpty())
624 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.begin();
626 if (it.value().first == prop || it.value().second == prop) {
632 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
644 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
657 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
673 std::string parName = prop->propertyName().toStdString();
675 m_fun->setParameter(parName, parValue);
677 if (
m_fun->isFixed(
m_fun->parameterIndex(parName))) {
678 const auto subProps = prop->subProperties();
679 if (std::any_of(subProps.cbegin(), subProps.cend(),
680 [](
const auto &subProp) { return subProp->propertyName() ==
"Fix"; })) {
681 fix(prop->propertyName());
692 bool res = pit.value()->setParameter(prop);
717 void apply(std::string &str)
const override {
738 void apply(
bool &b)
const override {
745 void apply(std::vector<double> &v)
const override {
747 if (members.size() < 1) {
753 int vectorSize =
static_cast<int>(members.size()) - 1;
754 if (vectorSize > newSize) {
755 vectorSize = newSize;
759 std::vector<double> newVec(newSize);
760 for (
int i = 1; i < newSize + 1; ++i) {
764 if (i < vectorSize + 1) {
767 newVec[i - 1] = newVal;
776 std::copy(cbegin(newVec), cend(newVec), begin(v));
794 void apply(
const std::string &str)
const override {
800 void apply(
const double &
d)
const override {
806 void apply(
const int &i)
const override {
812 void apply(
const bool &b)
const override {
818 void apply(
const std::vector<double> & )
const override {
822 throw std::runtime_error(
"Vector attribute not implemented.");
839 QString attName = prop->propertyName();
844 m_fun->setAttribute(attName.toStdString(), att);
846 if (resetProperties) {
859 }
catch (std::exception &e) {
862 QMessageBox::critical(
m_browser,
"Mantid - Error", e.what());
868 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
883 auto const attributeType = attValue.
type();
884 if (attributeType ==
"int")
886 else if (attributeType ==
"double")
888 else if (attributeType ==
"std::string")
897template <
typename AttributeType>
899 if (
m_fun->hasAttribute(attName.toStdString())) {
906 for (
const QtProperty *prop : attributes) {
907 if (prop->propertyName() == attName) {
918 for (
auto i = 0u; i <
cfun()->nFunctions(); ++i) {
931 const std::string
name = attName.toStdString();
938 if (prop->propertyName() == attName) {
957 if (subProps.contains(prop)) {
972 (this->*(func))(attribute);
976 for (std::size_t i = 0u; i <
m_cf->nFunctions(); ++i)
991 auto const attributeValue =
function()->getAttribute(attribute->propertyName().toStdString());
992 setAttribute(attribute->propertyName(), attributeValue);
1003 (this->*(func))(prop);
1007 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1023 double const parValue =
function()->getParameter(prop->propertyName().toStdString());
1031 size_t index =
function()->parameterIndex(prop->propertyName().toStdString());
1050 const QString &fnName = functionNames[i];
1053 f = Mantid::API::FunctionFactory::Instance().createFunction(fnName.toStdString());
1055 }
catch (std::exception &e) {
1056 QMessageBox::critical(
nullptr,
"Mantid - Error",
"Cannot create function " + fnName +
"\n" + e.what());
1086 for (QtProperty *sub : subs) {
1087 m_item->property()->removeSubProperty(sub);
1106 m_parent->replaceFunctionPtr(f_old, f);
1113 f->setHandler(std::move(h));
1119 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1132 [&parName](
const auto &parProp) { return parProp->propertyName() == parName; });
1141 [&prop](
const auto &parProp) { return parProp->subProperties().contains(prop); });
1149 QStringList parts = tieStr.split(
"=");
1150 if (parts.size() != 2)
1152 std::string
name = parts[0].trimmed().toStdString();
1153 std::string expr = parts[1].trimmed().toStdString();
1156 cfunction.tie(
name, expr);
1157 cfunction.applyTies();
1158 const auto paramIndex = cfunction.parameterIndex(
name);
1159 const auto paramStatus = cfunction.getParameterStatus(paramIndex);
1161 const bool recursive =
true;
1162 QString parName = QString::fromStdString(cfunction.parameterLocalName(paramIndex, recursive));
1167 QtProperty *tieProp =
m_ties[parName];
1169 const auto tiePropName = fixed ?
"Fix" :
"Tie";
1171 m_ties[parName] = tieProp;
1174 parProp->addSubProperty(tieProp);
1176 tieProp->setEnabled(
false);
1182 }
catch (
const std::exception &exc) {
1183 std::cerr << exc.what();
1184 QMessageBox::critical(
m_browser,
"Mantid - Error",
"Failed to set tie: " + tieStr);
1203 QString parName =
m_ties.key(prop,
"");
1204 if (parName.isEmpty())
1211 auto index = compositeFunction.parameterIndex(globalName);
1212 compositeFunction.removeTie(
index);
1213 parProp->removeSubProperty(prop);
1214 m_ties.remove(QString::fromStdString(globalName));
1217 parProp->setEnabled(
true);
1225 QString parName =
m_ties.key(prop,
"");
1226 if (parName.isEmpty())
1230 if (parProp !=
nullptr) {
1232 m_fun->removeTie(parName.toStdString());
1233 parProp->removeSubProperty(prop);
1236 parProp->setEnabled(
true);
1245 QtProperty *prop =
m_ties[parName];
1255 double fwhmEstimate = 0.;
1259 const auto &
X = ws->x(wi);
1260 const auto &
Y = ws->y(wi);
1261 size_t n =
Y.size() - 1;
1262 if (m_ci < 0 || m_ci >
static_cast<int>(
n)) {
1267 size_t rightHwhmIndex =
m_ci;
1268 while (rightHwhmIndex <
n) {
1269 if (
Y[rightHwhmIndex++] <= halfHeight) {
1275 size_t leftHwhmIndex =
m_ci;
1276 while (leftHwhmIndex > 0) {
1277 if (
Y[leftHwhmIndex--] <= halfHeight) {
1282 fwhmEstimate =
fabs(
X[rightHwhmIndex] -
X[leftHwhmIndex]);
1286 if (fwhmEstimate > fitRange) {
1288 fwhmEstimate = fitRange * 0.1;
1292 return fwhmEstimate;
1305 const auto &
X = ws->x(wi);
1306 const auto &
Y = ws->y(wi);
1307 int n =
static_cast<int>(
Y.size()) - 1;
1331 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1335 }
else if (h->
cfun()) {
1362 const auto &
X = ws->x(wi);
1363 int n =
static_cast<int>(
X.size()) - 2;
1394 return m_pf->height();
1401 return m_pf->centre();
1408 return m_pf->fwhm();
1415 return m_pf->getWidthParameterName();
1422 return m_pf->getCentreParameterName();
1429 return m_pf->isExplicitlySet(
m_pf->parameterIndex(param));
1438 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator old =
m_constraints.find(parProp->propertyName());
1444 hasLo = old.value().first != NULL;
1445 hasUp = old.value().second != NULL;
1457 std::pair<QtProperty *, QtProperty *> cnew;
1462 std::ostringstream ostr;
1464 ostr << loBound <<
"<";
1467 parProp->addSubProperty(cnew.first);
1469 cnew.first = old.value().first;
1473 ostr << parProp->propertyName().toStdString();
1475 ostr <<
"<" << upBound;
1478 parProp->addSubProperty(cnew.second);
1480 cnew.second = old.value().second;
1491 auto c = std::unique_ptr<Mantid::API::IConstraint>(
1492 Mantid::API::ConstraintFactory::Instance().createInitialized(
m_fun.get(), ostr.str()));
1493 m_fun->addConstraint(std::move(c));
1498 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.find(parProp->propertyName());
1501 if (it.value().first) {
1502 parProp->removeSubProperty(it.value().first);
1504 if (it.value().second) {
1505 parProp->removeSubProperty(it.value().second);
1507 m_fun->removeConstraint(parProp->propertyName().toStdString());
1521 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1527 }
else if (h->
cfun()) {
1554 if (
m_cf && (
m_cf->name() ==
"CompositeFunction" ||
m_cf->name() ==
"ProductFunction")) {
1555 QStringList childrenTooltips;
1559 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1561 childrenTooltips << childHandler->updateStructureTooltip();
1563 throw std::runtime_error(
"Error while building structure tooltip: no handler for child");
1567 if (childrenTooltips.empty()) {
1568 newTooltip = QString::fromStdString(
"Empty " +
m_cf->name());
1572 if (
m_cf->name() ==
"ProductFunction") {
1576 newTooltip = QString(
"(%1)").arg(childrenTooltips.join(
' ' + op +
' '));
1579 newTooltip = QString::fromStdString(
function()->
name());
1582 m_item->property()->setToolTip(newTooltip);
1592 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1605 alg->setProperty(
"Function",
m_fun);
1613 for (
size_t i = 0; i < f->nParams(); ++i) {
1614 m_fun->setParameter(i, f->getParameter(i));
1627 if (
index >= 0 &&
index < oldWorkspaces.size()) {
1628 wsName = oldWorkspaces[
index];
1630 QStringList names(
"All");
1641 for (
size_t i = 0; i <
cfun()->nFunctions(); ++i) {
1650 if (
index >= 0 && index < m_browser->m_workspaceNames.size()) {
1654 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
1658 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.