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 foreach (QtBrowserItem *
item, itList) {
72 if (
item->property() == fnProp) {
78 throw std::runtime_error(
"Browser item not found");
87 QtProperty *fnProp =
m_item->property();
93 fnProp->addSubProperty(
m_type);
98 QStringList functionNames;
99 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++) {
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)) {
262 prop->addSubProperty(tieProp);
263 m_ties[parName] = tieProp;
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));
359 if (fnName.find(
"=") == std::string::npos) {
369 std::shared_ptr<Mantid::API::IPeakFunction> pf = std::dynamic_pointer_cast<Mantid::API::IPeakFunction>(f);
379 ws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(
389 if (ws && wi < ws->getNumberHistograms()) {
390 const auto &
X = ws->x(wi);
391 size_t istart = 0, iend = 0;
392 for (
size_t i = 0; i <
X.size() - 1; ++i) {
394 if (x < m_browser->startX())
404 const auto &
Y = ws->y(wi);
405 double p0 =
Y[istart];
407 double A1 = (p1 - p0) / (
X[iend] -
X[istart]);
408 double A0 = p0 - A1 *
X[istart];
409 f->setParameter(
"A0", A0);
410 f->setParameter(
"A1", A1);
418 size_t nFunctions =
m_cf->nFunctions() + 1;
419 m_cf->addFunction(f);
422 if (
m_cf->nFunctions() != nFunctions) {
427 f->setHandler(std::make_unique<PropertyHandler>(f,
m_cf,
m_browser));
455 ph->
item()->property()->removeSubProperty(
m_item->property());
457 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
458 if (cf->getFunction(i) ==
function()) {
460 cf->removeFunction(i);
472 QMap<QString, QtProperty *>::const_iterator it =
m_ties.begin();
473 for (; it !=
m_ties.end(); ++it) {
474 QtProperty *prop = it.value();
478 QStringList qtie = QString::fromStdString(tie->
asString()).split(
"=");
486 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
490 QtProperty *nameProp = h->
item()->property();
501 if (!name.isEmpty()) {
504 name += QString::fromStdString(
function()->name());
513 for (
int i = 0; i < static_cast<int>(cf->nFunctions()); i++) {
514 if (cf->getFunction(i) ==
function()) {
522 return pref +
"f" + QString::number(iFun);
536 if (!
m_cf || i >=
m_cf->nFunctions())
550 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
566 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
577 if (prop ==
m_item->property())
593 if (!
m_ties.key(prop,
"").isEmpty())
595 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.begin();
597 if (it.value().first == prop || it.value().second == prop) {
603 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
615 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
628 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
644 std::string parName = prop->propertyName().toStdString();
646 m_fun->setParameter(parName, parValue);
652 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
675 void apply(std::string &str)
const override {
696 void apply(
bool &b)
const override {
703 void apply(std::vector<double> &v)
const override {
705 if (members.size() < 1) {
711 int vectorSize = members.size() - 1;
712 if (vectorSize > newSize) {
713 vectorSize = newSize;
717 std::vector<double> newVec(newSize);
718 for (
int i = 1; i < newSize + 1; ++i) {
722 if (i < vectorSize + 1) {
725 newVec[i - 1] = newVal;
734 std::copy(cbegin(newVec), cend(newVec), begin(v));
752 void apply(
const std::string &str)
const override {
758 void apply(
const double &
d)
const override {
764 void apply(
const int &i)
const override {
770 void apply(
const bool &b)
const override {
776 void apply(
const std::vector<double> & )
const override {
780 throw std::runtime_error(
"Vector attribute not implemented.");
797 QString attName = prop->propertyName();
802 m_fun->setAttribute(attName.toStdString(), att);
804 if (resetProperties) {
817 }
catch (std::exception &e) {
820 QMessageBox::critical(
m_browser,
"Mantid - Error", e.what());
826 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
841 auto const attributeType = attValue.
type();
842 if (attributeType ==
"int")
844 else if (attributeType ==
"double")
846 else if (attributeType ==
"std::string")
855template <
typename AttributeType>
857 if (
m_fun->hasAttribute(attName.toStdString())) {
862 if (prop->propertyName() == attName) {
873 for (
auto i = 0u; i <
cfun()->nFunctions(); ++i) {
886 const std::string name = attName.toStdString();
887 if (
m_fun->hasAttribute(name)) {
890 m_fun->setAttribute(name, att);
893 if (prop->propertyName() == attName) {
912 if (subProps.contains(prop)) {
927 (this->*(func))(attribute);
931 for (std::size_t i = 0u; i <
m_cf->nFunctions(); ++i)
946 auto const attributeValue =
function()->getAttribute(attribute->propertyName().toStdString());
947 setAttribute(attribute->propertyName(), attributeValue);
958 (this->*(func))(prop);
962 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
978 double const parValue =
function()->getParameter(prop->propertyName().toStdString());
986 size_t index =
function()->parameterIndex(prop->propertyName().toStdString());
1005 const QString &fnName = functionNames[i];
1010 }
catch (std::exception &e) {
1011 QMessageBox::critical(
nullptr,
"Mantid - Error",
"Cannot create function " + fnName +
"\n" + e.what());
1041 foreach (QtProperty *sub, subs) {
m_item->property()->removeSubProperty(sub); }
1059 m_parent->replaceFunctionPtr(f_old, f);
1063 h->setCentre(h->centre());
1066 f->setHandler(std::move(h));
1072 for (
size_t i = 0; i <
m_cf->nFunctions(); i++) {
1085 if (parProp->propertyName() == parName) {
1095 if (subs.contains(prop)) {
1103 QStringList parts = tieStr.split(
"=");
1104 if (parts.size() != 2)
1106 std::string name = parts[0].trimmed().toStdString();
1107 std::string expr = parts[1].trimmed().toStdString();
1110 cfun.tie(name, expr);
1111 const bool recursive =
true;
1112 QString parName = QString::fromStdString(
cfun.parameterLocalName(
cfun.parameterIndex(name), recursive));
1114 if (parProp->propertyName() == parName) {
1116 QtProperty *tieProp =
m_ties[parName];
1119 m_ties[parName] = tieProp;
1123 parProp->addSubProperty(tieProp);
1129 QMessageBox::critical(
m_browser,
"Mantid - Error",
"Failed to set tie: " + tieStr);
1138 m_fun->tie(parName.toStdString(), parValue.toStdString());
1140 QtProperty *tieProp =
m_ties[parName];
1143 m_ties[parName] = tieProp;
1147 parProp->addSubProperty(tieProp);
1148 tieProp->setEnabled(
false);
1160 QString parName =
m_ties.key(prop,
"");
1161 if (parName.isEmpty())
1168 auto index = compositeFunction.parameterIndex(globalName);
1169 compositeFunction.removeTie(
index);
1170 parProp->removeSubProperty(prop);
1171 m_ties.remove(QString::fromStdString(globalName));
1174 parProp->setEnabled(
true);
1182 QString parName =
m_ties.key(prop,
"");
1183 if (parName.isEmpty())
1187 if (parProp !=
nullptr) {
1189 m_fun->removeTie(parName.toStdString());
1190 parProp->removeSubProperty(prop);
1193 parProp->setEnabled(
true);
1202 QtProperty *prop =
m_ties[parName];
1216 const auto &
X = ws->x(wi);
1217 const auto &
Y = ws->y(wi);
1218 size_t n =
Y.size() - 1;
1219 if (m_ci < 0 || m_ci >
static_cast<int>(
n)) {
1224 size_t rightHwhmIndex =
m_ci;
1225 while (rightHwhmIndex <
n) {
1226 if (
Y[rightHwhmIndex++] <= halfHeight) {
1232 size_t leftHwhmIndex =
m_ci;
1233 while (leftHwhmIndex > 0) {
1234 if (
Y[leftHwhmIndex--] <= halfHeight) {
1239 fwhm =
fabs(
X[rightHwhmIndex] -
X[leftHwhmIndex]);
1243 if (
fwhm > fitRange) {
1245 fwhm = fitRange * 0.1;
1262 const auto &
X = ws->x(wi);
1263 const auto &
Y = ws->y(wi);
1264 int n =
static_cast<int>(
Y.size()) - 1;
1288 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1292 }
else if (h->
cfun()) {
1319 const auto &
X = ws->x(wi);
1320 int n =
static_cast<int>(
X.size()) - 2;
1351 return m_pf->height();
1358 return m_pf->centre();
1365 return m_pf->fwhm();
1372 return m_pf->getWidthParameterName();
1379 return m_pf->getCentreParameterName();
1386 return m_pf->isExplicitlySet(
m_pf->parameterIndex(param));
1395 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator old =
m_constraints.find(parProp->propertyName());
1401 hasLo = old.value().first != NULL;
1402 hasUp = old.value().second != NULL;
1414 std::pair<QtProperty *, QtProperty *> cnew;
1419 std::ostringstream ostr;
1421 ostr << loBound <<
"<";
1424 parProp->addSubProperty(cnew.first);
1426 cnew.first = old.value().first;
1430 ostr << parProp->propertyName().toStdString();
1432 ostr <<
"<" << upBound;
1435 parProp->addSubProperty(cnew.second);
1437 cnew.second = old.value().second;
1448 auto c = std::unique_ptr<Mantid::API::IConstraint>(
1450 m_fun->addConstraint(std::move(c));
1455 QMap<QString, std::pair<QtProperty *, QtProperty *>>::iterator it =
m_constraints.find(parProp->propertyName());
1458 if (it.value().first) {
1459 parProp->removeSubProperty(it.value().first);
1461 if (it.value().second) {
1462 parProp->removeSubProperty(it.value().second);
1464 m_fun->removeConstraint(parProp->propertyName().toStdString());
1478 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1484 }
else if (h->
cfun()) {
1511 if (
m_cf && (
m_cf->name() ==
"CompositeFunction" ||
m_cf->name() ==
"ProductFunction")) {
1512 QStringList childrenTooltips;
1516 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1518 childrenTooltips << childHandler->updateStructureTooltip();
1520 throw std::runtime_error(
"Error while building structure tooltip: no handler for child");
1524 if (childrenTooltips.empty()) {
1525 newTooltip = QString::fromStdString(
"Empty " +
m_cf->name());
1529 if (
m_cf->name() ==
"ProductFunction") {
1533 newTooltip = QString(
"(%1)").arg(childrenTooltips.join(
' ' + op +
' '));
1536 newTooltip = QString::fromStdString(
function()->name());
1539 m_item->property()->setToolTip(newTooltip);
1549 for (
size_t i = 0; i <
m_cf->nFunctions(); ++i) {
1562 alg->setProperty(
"Function",
m_fun);
1570 for (
size_t i = 0; i < f->nParams(); ++i) {
1571 m_fun->setParameter(i, f->getParameter(i));
1584 if (
index >= 0 &&
index < oldWorkspaces.size()) {
1585 wsName = oldWorkspaces[
index];
1587 QStringList names(
"All");
1595 for (
size_t i = 0; i <
cfun()->nFunctions(); ++i) {
1604 if (
index >= 0 && index < m_browser->m_workspaceNames.size()) {
1608 auto mws = std::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>(ws);
1612 ifun()->setWorkspace(ws);
std::map< DeltaEMode::Type, std::string > index
A composite function is a function containing other functions.
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.
virtual std::string asString(const IFunction *fun=nullptr) const
Return the string that can be used to recreate this tie.
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...
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.