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<std::string, std::string> splitParameterName(std::string const &paramName) {
19 QString functionIndex;
20 QString initialParamName = QString::fromStdString(paramName);
21 QString parameterName = QString::fromStdString(paramName);
22 int j = initialParamName.lastIndexOf('.');
23 if (j > 0) {
24 ++j;
25 functionIndex = initialParamName.mid(0, j);
26 parameterName = initialParamName.mid(j);
27 }
28 return std::make_pair(functionIndex.toStdString(), parameterName.toStdString());
29}
30
31IFunction_sptr getFunctionWithPrefix(std::string const &prefix, const IFunction_sptr &fun) {
32 if (prefix.empty() || !fun) {
33 return fun;
34 }
35 auto compFun = std::dynamic_pointer_cast<CompositeFunction>(fun);
36 if (!compFun) {
37 throw std::runtime_error("Function " + fun->name() + " is not composite");
38 }
39 auto const functionPrefix(QString::fromStdString(prefix));
40 auto j = functionPrefix.indexOf('.');
41 if (j < 0) {
42 throw std::runtime_error("Error in fit function prefix: " + prefix + "\nIt must end with a dot (.)");
43 }
44 if (j < 2 || functionPrefix[0] != 'f') {
45 throw std::runtime_error("Error in fit function prefix: " + prefix +
46 "\nIt must start with an 'f' followed by an integer.");
47 }
48 auto funIndex = functionPrefix.mid(1, j - 1).toInt();
49 return getFunctionWithPrefix(functionPrefix.mid(j + 1).toStdString(), compFun->getFunction(funIndex));
50}
51
52std::pair<std::string, int> splitFunctionPrefix(std::string const &prefix) {
53 if (prefix.empty())
54 return std::make_pair("", -1);
55 auto const functionPrefix(QString::fromStdString(prefix));
56 auto j = functionPrefix.lastIndexOf('.', -2);
57 auto parentPrefix = functionPrefix.left(j > 0 ? j + 1 : 0);
58 auto funIndex = functionPrefix.mid(j + 2, functionPrefix.size() - j - 3).toInt();
59 return std::make_pair(parentPrefix.toStdString(), funIndex);
60}
61
62std::pair<std::string, std::pair<std::string, std::string>> splitConstraintString(std::string const &constraint) {
63 std::pair<std::string, std::pair<std::string, std::string>> error;
64 if (constraint.empty())
65 return error;
66 std::string lowerBoundStr;
67 std::string upperBoundStr;
68 std::string paramName;
70 expr.parse(constraint);
71 if (expr.name() != "==") {
72 return error;
73 }
74 if (expr.size() == 3) { // lower < param < upper
75 try {
76 // check that the first and third terms are numbers
77 boost::lexical_cast<double>(expr[0].str());
78 boost::lexical_cast<double>(expr[2].str());
79 if (expr[1].operator_name() == "<" && expr[2].operator_name() == "<") {
80 lowerBoundStr = expr[0].str();
81 upperBoundStr = expr[2].str();
82 } else { // assume that the operators are ">"
83 lowerBoundStr = expr[2].str();
84 upperBoundStr = expr[0].str();
85 }
86 paramName = expr[1].str();
87 } catch (...) { // error in constraint
88 return error;
89 }
90 } else if (expr.size() == 2) { // lower < param or param > lower etc
91 size_t paramPos = 0;
92 try // find position of the parameter name in expression
93 {
94 boost::lexical_cast<double>(expr[1].name());
95 } catch (...) {
96 paramPos = 1;
97 }
98 std::string op = expr[1].operator_name();
99 if (paramPos == 0) { // parameter goes first
100 if (op == "<") { // param < number
101 upperBoundStr = expr[1].str();
102 } else { // param > number
103 lowerBoundStr = expr[1].str();
104 }
105 paramName = expr[0].str();
106 } else { // parameter is second
107 try {
108 boost::lexical_cast<double>(expr[0].name());
109 } catch (...) { // error - neither terms are numbers
110 return error;
111 }
112 if (op == "<") { // number < param
113 lowerBoundStr = expr[0].str();
114 } else { // number > param
115 upperBoundStr = expr[0].str();
116 }
117 paramName = expr[1].str();
118 }
119 }
120 return std::make_pair(paramName, std::make_pair(lowerBoundStr, upperBoundStr));
121}
122
123bool isNumber(std::string const &str) {
124 return !str.empty() && str.find_first_not_of("0123456789.-") == std::string::npos;
125}
126
127std::vector<std::string> splitStringBy(std::string const &str, std::string const &delimiter) {
128 std::vector<std::string> subStrings;
129 boost::split(subStrings, str, boost::is_any_of(delimiter));
130 subStrings.erase(std::remove_if(subStrings.begin(), subStrings.end(),
131 [](std::string const &subString) { return subString.empty(); }),
132 subStrings.cend());
133 return subStrings;
134}
135
136std::size_t getFunctionIndexAt(std::string const &parameter, std::size_t const &index) {
137 auto const subStrings = splitStringBy(parameter, ".");
138 if (index < subStrings.size()) {
139 auto const functionIndex = splitStringBy(subStrings[index], "f");
140 if (functionIndex.size() == 1 && isNumber(functionIndex[0]))
141 return std::stoull(functionIndex[0]);
142 }
143
144 throw std::invalid_argument("No function index was found.");
145}
146
147} // namespace MantidQt::MantidWidgets
std::string name
Definition Run.cpp:60
double error
std::map< DeltaEMode::Type, std::string > index
This class represents an expression made up of names, binary operators and brackets.
Definition Expression.h:36
void parse(const std::string &str)
Parse a string and create an expression.
const std::string & name() const
Returns the name of the expression which is a function or variable name.
Definition Expression.h:71
std::string str() const
Returns this expression as a string.
const std::string & operator_name() const
Returns the expression's binary operator on its left.
Definition Expression.h:74
size_t size() const
Returns the number of argumens.
Definition Expression.h:79
EXPORT_OPT_MANTIDQT_COMMON std::pair< std::string, std::pair< std::string, std::string > > 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::pair< std::string, int > splitFunctionPrefix(std::string const &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 bool isNumber(std::string const &str)
Checks if a string contains a number, or whether it contains characters.
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 IFunction_sptr getFunctionWithPrefix(std::string const &prefix, const IFunction_sptr &fun)
Get a child function of a parent function whose parameters start with a given prefix.
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< std::string, std::string > splitParameterName(std::string const &parameterName)
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:743