Mantid
Loading...
Searching...
No Matches
FunctionBrowserUtils.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
10
11#include <boost/algorithm/string.hpp>
12#include <boost/lexical_cast.hpp>
13
15
16using namespace Mantid::API;
17
18std::pair<QString, QString> splitParameterName(const QString &paramName) {
19 QString functionIndex;
20 QString parameterName = paramName;
21 int j = paramName.lastIndexOf('.');
22 if (j > 0) {
23 ++j;
24 functionIndex = paramName.mid(0, j);
25 parameterName = paramName.mid(j);
26 }
27 return std::make_pair(functionIndex, parameterName);
28}
29
30IFunction_sptr getFunctionWithPrefix(const QString &prefix, const IFunction_sptr &fun) {
31 if (prefix.isEmpty() || !fun) {
32 return fun;
33 }
34 auto compFun = std::dynamic_pointer_cast<CompositeFunction>(fun);
35 if (!compFun) {
36 throw std::runtime_error("Function " + fun->name() + " is not composite");
37 }
38 auto j = prefix.indexOf('.');
39 if (j < 0) {
40 throw std::runtime_error("Error in fit function prefix: " + prefix.toStdString() + "\nIt must end with a dot (.)");
41 }
42 if (j < 2 || prefix[0] != 'f') {
43 throw std::runtime_error("Error in fit function prefix: " + prefix.toStdString() +
44 "\nIt must start with an 'f' followed by an integer.");
45 }
46 auto funIndex = prefix.mid(1, j - 1).toInt();
47 return getFunctionWithPrefix(prefix.mid(j + 1), compFun->getFunction(funIndex));
48}
49
50std::pair<QString, int> splitFunctionPrefix(const std::string &prefix) {
51 return splitFunctionPrefix(QString::fromStdString(prefix));
52}
53
54std::pair<QString, int> splitFunctionPrefix(const QString &prefix) {
55 if (prefix.isEmpty())
56 return std::make_pair("", -1);
57 auto j = prefix.lastIndexOf('.', -2);
58 auto parentPrefix = prefix.left(j > 0 ? j + 1 : 0);
59 auto funIndex = prefix.mid(j + 2, prefix.size() - j - 3).toInt();
60 return std::make_pair(parentPrefix, funIndex);
61}
62
63std::pair<QString, std::pair<QString, QString>> splitConstraintString(const std::string &constraint) {
64 return splitConstraintString(QString::fromStdString(constraint));
65}
66
67std::pair<QString, std::pair<QString, QString>> splitConstraintString(const QString &constraint) {
68 std::pair<QString, std::pair<QString, QString>> error;
69 if (constraint.isEmpty())
70 return error;
71 QString lowerBoundStr;
72 QString upperBoundStr;
73 QString paramName;
75 expr.parse(constraint.toStdString());
76 if (expr.name() != "==") {
77 return error;
78 }
79 if (expr.size() == 3) { // lower < param < upper
80 try {
81 // check that the first and third terms are numbers
82 boost::lexical_cast<double>(expr[0].str());
83 boost::lexical_cast<double>(expr[2].str());
84 if (expr[1].operator_name() == "<" && expr[2].operator_name() == "<") {
85 lowerBoundStr = QString::fromStdString(expr[0].str());
86 upperBoundStr = QString::fromStdString(expr[2].str());
87 } else { // assume that the operators are ">"
88 lowerBoundStr = QString::fromStdString(expr[2].str());
89 upperBoundStr = QString::fromStdString(expr[0].str());
90 }
91 paramName = QString::fromStdString(expr[1].str());
92 } catch (...) { // error in constraint
93 return error;
94 }
95 } else if (expr.size() == 2) { // lower < param or param > lower etc
96 size_t paramPos = 0;
97 try // find position of the parameter name in expression
98 {
99 boost::lexical_cast<double>(expr[1].name());
100 }
101 catch (...) {
102 paramPos = 1;
103 }
104 std::string op = expr[1].operator_name();
105 if (paramPos == 0) { // parameter goes first
106 if (op == "<") { // param < number
107 upperBoundStr = QString::fromStdString(expr[1].str());
108 } else { // param > number
109 lowerBoundStr = QString::fromStdString(expr[1].str());
110 }
111 paramName = QString::fromStdString(expr[0].str());
112 } else { // parameter is second
113 try {
114 boost::lexical_cast<double>(expr[0].name());
115 } catch (...) { // error - neither terms are numbers
116 return error;
117 }
118 if (op == "<") { // number < param
119 lowerBoundStr = QString::fromStdString(expr[0].str());
120 } else { // number > param
121 upperBoundStr = QString::fromStdString(expr[0].str());
122 }
123 paramName = QString::fromStdString(expr[1].str());
124 }
125 }
126 return std::make_pair(paramName, std::make_pair(lowerBoundStr, upperBoundStr));
127}
128
129bool isNumber(std::string const &str) {
130 return !str.empty() && str.find_first_not_of("0123456789.-") == std::string::npos;
131}
132
133std::vector<std::string> splitStringBy(std::string const &str, std::string const &delimiter) {
134 std::vector<std::string> subStrings;
135 boost::split(subStrings, str, boost::is_any_of(delimiter));
136 subStrings.erase(std::remove_if(subStrings.begin(), subStrings.end(),
137 [](std::string const &subString) { return subString.empty(); }),
138 subStrings.cend());
139 return subStrings;
140}
141
142std::size_t getFunctionIndexAt(std::string const &parameter, std::size_t const &index) {
143 auto const subStrings = splitStringBy(parameter, ".");
144 if (index < subStrings.size()) {
145 auto const functionIndex = splitStringBy(subStrings[index], "f");
146 if (functionIndex.size() == 1 && isNumber(functionIndex[0]))
147 return std::stoull(functionIndex[0]);
148 }
149
150 throw std::invalid_argument("No function index was found.");
151}
152
153} // namespace MantidQt::MantidWidgets
double error
Definition: IndexPeaks.cpp:133
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
This class represents an expression made up of names, binary operators and brackets.
Definition: Expression.h:36
std::string name() const
Returns the name of the expression which is a function or variable name.
Definition: Expression.h:71
std::string operator_name() const
Returns the the expression's binary operator on its left.
Definition: Expression.h:74
void parse(const std::string &str)
Parse a string and create an expression.
Definition: Expression.cpp:159
size_t size() const
Returns the number of argumens.
Definition: Expression.h:79
EXPORT_OPT_MANTIDQT_COMMON IFunction_sptr getFunctionWithPrefix(const QString &prefix, const IFunction_sptr &fun)
Get a child function of a parent function whose parameters start with a given prefix.
EXPORT_OPT_MANTIDQT_COMMON bool isNumber(std::string const &str)
Checks if a string contains a number, or whether it contains characters.
EXPORT_OPT_MANTIDQT_COMMON std::pair< QString, std::pair< QString, QString > > splitConstraintString(const std::string &constraint)
Split a constraint definition into a parameter name and a pair of bounds, for example -1 < f0....
EXPORT_OPT_MANTIDQT_COMMON std::size_t getFunctionIndexAt(std::string const &parameter, std::size_t const &index)
Returns the function index found at index of a parameter.
EXPORT_OPT_MANTIDQT_COMMON std::pair< QString, int > splitFunctionPrefix(const std::string &prefix)
Split a function (eg f0.f3.f1.) into the parent prefix (f0.f3.) and the index of the child function (...
EXPORT_OPT_MANTIDQT_COMMON std::vector< std::string > splitStringBy(std::string const &str, std::string const &delimiter)
Splits the string by the given delimiters.
EXPORT_OPT_MANTIDQT_COMMON std::pair< QString, QString > splitParameterName(const QString &paramName)
Split a qualified parameter name into function index and local parameter name.
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732