Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
Roman Tolchenov
committed
#include "MantidAPI/CompositeFunction.h"
#include "MantidAPI/ParameterTie.h"
#include "MantidAPI/IConstraint.h"
#include "MantidAPI/FunctionFactory.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/Logger.h"
Peterson, Peter
committed
#include <boost/lexical_cast.hpp>
#include <boost/shared_array.hpp>
#include <sstream>
Roman Tolchenov
committed
#include <algorithm>
namespace Mantid {
namespace API {
namespace {
/// static logger
Kernel::Logger g_log("CompositeFunction");
}
DECLARE_FUNCTION(CompositeFunction)
/// Default constructor
CompositeFunction::CompositeFunction()
: IFunction(), m_nParams(0), m_iConstraintFunction(false) {
declareAttribute("NumDeriv", Attribute(false));
}
/// Destructor
CompositeFunction::~CompositeFunction() {}
/// Function initialization. Declare function parameters in this method.
Roman Tolchenov
committed
* Writes itself into a string. Functions derived from CompositeFunction must
* override this method with something like this:
* std::string NewFunction::asString()const
* {
* ostr << "composite=" << this->name() << ';';
* // write NewFunction's own attributes and parameters
* ostr << CompositeFunction::asString();
* // write NewFunction's own ties and constraints
* // ostr << ";constraints=(" << ... <<")";
* }
* @return the string representation of the composite function
Roman Tolchenov
committed
*/
std::string CompositeFunction::asString() const {
Roman Tolchenov
committed
std::ostringstream ostr;
if (name() != "CompositeFunction" || nAttributes() > 1 ||
getAttribute("NumDeriv").asBool() == true) {
ostr << "composite=" << name();
std::vector<std::string> attr = this->getAttributeNames();
for (const auto &attName : attr) {
std::string attValue = this->getAttribute(attName).value();
if (!attValue.empty()) {
ostr << ',' << attName << '=' << attValue;
}
}
ostr << ';';
for (size_t i = 0; i < nFunctions(); i++) {
IFunction_sptr fun = getFunction(i);
bool isComp = boost::dynamic_pointer_cast<CompositeFunction>(fun) != 0;
Roman Tolchenov
committed
ostr << fun->asString();
if (isComp)
ostr << ')';
if (i < nFunctions() - 1) {
Roman Tolchenov
committed
ostr << ';';
}
}
std::string ties;
for (size_t i = 0; i < nParams(); i++) {
const ParameterTie *tie = getTie(i);
if (tie) {
IFunction_sptr fun = getFunction(functionIndex(i));
std::string tmp = tie->asString(fun.get());
Roman Tolchenov
committed
tmp = tie->asString(this);
if (!tmp.empty()) {
if (!ties.empty()) {
Roman Tolchenov
committed
ties += ",";
}
ties += tmp;
}
}
}
}
Roman Tolchenov
committed
ostr << ";ties=(" << ties << ")";
Roman Tolchenov
committed
}
return ostr.str();
}
/**
* @param ws A pointer to the workspace being fitted
*/
void CompositeFunction::setWorkspace(boost::shared_ptr<const Workspace> ws) {
// Pass it on to each member
auto iend = m_functions.end();
for (auto it = m_functions.begin(); it != iend; ++it) {
(*it)->setWorkspace(ws);
}
}
/**
* @param workspace :: A workspace to fit to.
* @param wi :: An index of a spectrum to fit to.
* @param startX :: A start of the fitting region.
* @param endX :: An end of the fitting region.
*/
void CompositeFunction::setMatrixWorkspace(
boost::shared_ptr<const MatrixWorkspace> workspace, size_t wi,
double startX, double endX) {
for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
m_functions[iFun]->setMatrixWorkspace(workspace, wi, startX, endX);
}
* @param domain :: An instance of FunctionDomain with the function arguments.
* @param values :: A FunctionValues instance for storing the calculated
* values.
*/
void CompositeFunction::function(const FunctionDomain &domain,
FunctionValues &values) const {
FunctionValues tmp(domain);
for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
m_functions[iFun]->function(domain, tmp);
values += tmp;
}
}
/**
* Derivatives of function with respect to active parameters
* @param domain :: Function domain to get the arguments from.
* @param jacobian :: A Jacobian to store the derivatives.
*/
void CompositeFunction::functionDeriv(const FunctionDomain &domain,
Jacobian &jacobian) {
if (getAttribute("NumDeriv").asBool()) {
calNumericalDeriv(domain, jacobian);
} else {
for (size_t iFun = 0; iFun < nFunctions(); ++iFun) {
PartialJacobian J(&jacobian, paramOffset(iFun));
getFunction(iFun)->functionDeriv(domain, J);
}
}
/** Sets a new value to the i-th parameter.
Janik Zikovsky
committed
* @param i :: The parameter index
* @param value :: The new value
* @param explicitlySet :: A boolean falgging the parameter as explicitly set
* (by user)
void CompositeFunction::setParameter(size_t i, const double &value,
bool explicitlySet) {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[iFun]->setParameter(i - m_paramOffsets[iFun], value,
explicitlySet);
Anders Markvardsen
committed
/** Sets a new description to the i-th parameter.
* @param i :: The parameter index
* @param description :: The new description
*/
void CompositeFunction::setParameterDescription(
size_t i, const std::string &description) {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[iFun]->setParameterDescription(i - m_paramOffsets[iFun],
description);
Anders Markvardsen
committed
}
/** Get the i-th parameter.
Janik Zikovsky
committed
* @param i :: The parameter index
* @return value of the requested parameter
double CompositeFunction::getParameter(size_t i) const {
return m_functions[iFun]->getParameter(i - m_paramOffsets[iFun]);
/**
* Sets a new value to a parameter by name.
Janik Zikovsky
committed
* @param name :: The name of the parameter.
* @param value :: The new value
* @param explicitlySet :: A boolean falgging the parameter as explicitly set
* (by user)
void CompositeFunction::setParameter(const std::string &name,
const double &value, bool explicitlySet) {
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
parseName(name, index, pname);
getFunction(index)->setParameter(pname, value, explicitlySet);
Anders Markvardsen
committed
/**
* Sets a new description to a parameter by name.
* @param name :: The name of the parameter.
* @param description :: The new description
Anders Markvardsen
committed
*/
void CompositeFunction::setParameterDescription(
const std::string &name, const std::string &description) {
Anders Markvardsen
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
parseName(name, index, pname);
getFunction(index)->setParameterDescription(pname, description);
Anders Markvardsen
committed
}
/**
* Parameters by name.
Janik Zikovsky
committed
* @param name :: The name of the parameter.
* @return value of the requested named parameter
double CompositeFunction::getParameter(const std::string &name) const {
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
Roman Tolchenov
committed
return getFunction(index)->getParameter(pname);
}
/// Total number of parameters
size_t CompositeFunction::nParams() const { return m_nParams; }
Janik Zikovsky
committed
* @param name :: The name of a parameter
* @return index of the requested named parameter
size_t CompositeFunction::parameterIndex(const std::string &name) const {
Peterson, Peter
committed
std::string pname;
Roman Tolchenov
committed
size_t index;
Russell Taylor
committed
return getFunction(index)->parameterIndex(pname) + m_paramOffsets[index];
Janik Zikovsky
committed
/// @param i :: The index
std::string CompositeFunction::parameterName(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
std::ostringstream ostr;
ostr << 'f' << iFun << '.'
<< m_functions[iFun]->parameterName(i - m_paramOffsets[iFun]);
return ostr.str();
Anders Markvardsen
committed
/// Returns the description of parameter
/// @param i :: The index
/// @return The description of the parameter
std::string CompositeFunction::parameterDescription(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Anders Markvardsen
committed
std::ostringstream ostr;
ostr << m_functions[iFun]->parameterDescription(i - m_paramOffsets[iFun]);
Anders Markvardsen
committed
return ostr.str();
}
* Get the fitting error for a parameter
* @param i :: The index of a parameter
* @return :: the error
*/
double CompositeFunction::getError(size_t i) const {
return m_functions[iFun]->getError(i - m_paramOffsets[iFun]);
* Set the fitting error for a parameter
* @param i :: The index of a parameter
* @param err :: The error value to set
*/
void CompositeFunction::setError(size_t i, double err) {
m_functions[iFun]->setError(i - m_paramOffsets[iFun], err);
/// Value of i-th active parameter. Override this method to make fitted
/// parameters different from the declared
double CompositeFunction::activeParameter(size_t i) const {
size_t iFun = functionIndex(i);
return m_functions[iFun]->activeParameter(i - m_paramOffsets[iFun]);
/// Set new value of i-th active parameter. Override this method to make fitted
/// parameters different from the declared
void CompositeFunction::setActiveParameter(size_t i, double value) {
size_t iFun = functionIndex(i);
m_functions[iFun]->setActiveParameter(i - m_paramOffsets[iFun], value);
}
/// Returns the name of active parameter i
std::string CompositeFunction::nameOfActive(size_t i) const {
size_t iFun = functionIndex(i);
std::ostringstream ostr;
ostr << 'f' << iFun << '.'
<< m_functions[iFun]->nameOfActive(i - m_paramOffsets[iFun]);
Anders Markvardsen
committed
return ostr.str();
}
/// Returns the description of active parameter i
std::string CompositeFunction::descriptionOfActive(size_t i) const {
size_t iFun = functionIndex(i);
Anders Markvardsen
committed
std::ostringstream ostr;
ostr << m_functions[iFun]->descriptionOfActive(i - m_paramOffsets[iFun]);
return ostr.str();
/**
* query to see in the function is active
* @param i :: The index of a declared parameter
* @return true if parameter i is active
*/
bool CompositeFunction::isActive(size_t i) const {
size_t iFun = functionIndex(i);
return m_functions[iFun]->isActive(i - m_paramOffsets[iFun]);
* query to see in the function is active
Janik Zikovsky
committed
* @param i :: The index of a declared parameter
* @return true if parameter i is active
bool CompositeFunction::isFixed(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[iFun]->isFixed(i - m_paramOffsets[iFun]);
Janik Zikovsky
committed
* @param i :: A declared parameter index to be removed from active
void CompositeFunction::fix(size_t i) {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[iFun]->fix(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
/** Makes a parameter active again. It doesn't change the parameter's tie.
Janik Zikovsky
committed
* @param i :: A declared parameter index to be restored to active
Roman Tolchenov
committed
*/
void CompositeFunction::unfix(size_t i) {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
m_functions[iFun]->unfix(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
}
/** Makes sure that the function is consistent.
void CompositeFunction::checkFunction() {
m_nParams = 0;
m_paramOffsets.clear();
m_IFunction.clear();
std::vector<IFunction_sptr> functions(m_functions.begin(), m_functions.end());
for (auto f : functions) {
CompositeFunction_sptr cf =
boost::dynamic_pointer_cast<CompositeFunction>(f);
if (cf)
cf->checkFunction();
Janik Zikovsky
committed
* @param f :: A pointer to the added function
* @return The function index
size_t CompositeFunction::addFunction(IFunction_sptr f) {
m_IFunction.insert(m_IFunction.end(), f->nParams(), m_functions.size());
m_functions.push_back(f);
//?f->init();
if (m_paramOffsets.size() == 0) {
m_paramOffsets.push_back(0);
m_nParams = f->nParams();
m_paramOffsets.push_back(m_nParams);
m_nParams += f->nParams();
}
Roman Tolchenov
committed
return m_functions.size() - 1;
Roman Tolchenov
committed
/** Remove a function
Janik Zikovsky
committed
* @param i :: The index of the function to remove
Roman Tolchenov
committed
*/
void CompositeFunction::removeFunction(size_t i) {
if (i >= nFunctions())
Roman Tolchenov
committed
throw std::out_of_range("Function index out of range.");
IFunction_sptr fun = getFunction(i);
Roman Tolchenov
committed
Roman Tolchenov
committed
size_t dnp = fun->nParams();
Roman Tolchenov
committed
for (size_t j = 0; j < nParams();) {
ParameterTie *tie = getTie(j);
if (tie && tie->findParametersOf(fun.get())) {
Roman Tolchenov
committed
removeTie(j);
Roman Tolchenov
committed
j++;
}
}
// Shift down the function indeces for parameters
for (auto it = m_IFunction.begin(); it != m_IFunction.end();) {
Roman Tolchenov
committed
it = m_IFunction.erase(it);
Roman Tolchenov
committed
*it -= 1;
}
Roman Tolchenov
committed
}
}
m_nParams -= dnp;
// Shift the parameter offsets down by the total number of i-th function's
// params
for (size_t j = i + 1; j < nFunctions(); j++) {
Roman Tolchenov
committed
m_paramOffsets[j] -= dnp;
}
m_paramOffsets.erase(m_paramOffsets.begin() + i);
Roman Tolchenov
committed
m_functions.erase(m_functions.begin() + i);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
/** Replace a function with a new one. The old function is deleted.
* The new function must have already its workspace set.
Janik Zikovsky
committed
* @param f_old :: The pointer to the function to replace. If it's not
Roman Tolchenov
committed
* a member of this composite function nothing happens
Janik Zikovsky
committed
* @param f_new :: A pointer to the new function
Roman Tolchenov
committed
*/
void CompositeFunction::replaceFunctionPtr(const IFunction_sptr f_old,
IFunction_sptr f_new) {
std::vector<IFunction_sptr>::const_iterator it =
std::find(m_functions.begin(), m_functions.end(), f_old);
if (it == m_functions.end())
return;
std::vector<IFunction_sptr>::difference_type iFun = it - m_functions.begin();
Roman Tolchenov
committed
}
Roman Tolchenov
committed
/** Replace a function with a new one. The old function is deleted.
Janik Zikovsky
committed
* @param i :: The index of the function to replace
* @param f :: A pointer to the new function
Roman Tolchenov
committed
*/
void CompositeFunction::replaceFunction(size_t i, IFunction_sptr f) {
if (i >= nFunctions())
Roman Tolchenov
committed
throw std::out_of_range("Function index out of range.");
IFunction_sptr fun = getFunction(i);
Roman Tolchenov
committed
size_t np_old = fun->nParams();
Roman Tolchenov
committed
Roman Tolchenov
committed
size_t np_new = f->nParams();
Roman Tolchenov
committed
// Modify function indeces: The new function may have different number of
// parameters
Roman Tolchenov
committed
{
auto itFun = std::find(m_IFunction.begin(), m_IFunction.end(), i);
if (itFun != m_IFunction.end()) // functions must have at least 1 parameter
Roman Tolchenov
committed
{
if (np_old > np_new) {
m_IFunction.erase(itFun, itFun + np_old - np_new);
} else if (np_old < np_new) {
m_IFunction.insert(itFun, np_new - np_old, i);
} else if (np_new > 0) // it could happen if the old function is an empty
// CompositeFunction
Roman Tolchenov
committed
{
itFun = std::find_if(m_IFunction.begin(), m_IFunction.end(),
std::bind2nd(std::greater<size_t>(), i));
m_IFunction.insert(itFun, np_new, i);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
}
Roman Tolchenov
committed
size_t dnp = np_new - np_old;
Roman Tolchenov
committed
m_nParams += dnp;
// Shift the parameter offsets down by the total number of i-th function's
// params
for (size_t j = i + 1; j < nFunctions(); j++) {
Roman Tolchenov
committed
m_paramOffsets[j] += dnp;
}
m_functions[i] = f;
}
Janik Zikovsky
committed
* @param i :: The index of the function
* @return function at the requested index
IFunction_sptr CompositeFunction::getFunction(std::size_t i) const {
if (i >= nFunctions()) {
throw std::out_of_range("Function index out of range.");
Roman Tolchenov
committed
}
/**
* Get the index of the function to which parameter i belongs
Janik Zikovsky
committed
* @param i :: The parameter index
* @return function index of the requested parameter
size_t CompositeFunction::functionIndex(std::size_t i) const {
if (i >= nParams()) {
throw std::out_of_range("Function parameter index out of range.");
Roman Tolchenov
committed
}
return m_IFunction[i];
* @param varName :: The variable name which may contain function index (
* [f<index.>]name )
Roman Tolchenov
committed
* @param index :: Receives function index or throws std::invalid_argument
Janik Zikovsky
committed
* @param name :: Receives the parameter name
void CompositeFunction::parseName(const std::string &varName, size_t &index,
std::string &name) {
Peterson, Peter
committed
size_t i = varName.find('.');
Roman Tolchenov
committed
throw std::invalid_argument("Parameter " + varName + " not found.");
Peterson, Peter
committed
if (varName[0] != 'f')
throw std::invalid_argument(
"External function parameter name must start with 'f'");
Peterson, Peter
committed
std::string sindex = varName.substr(1, i - 1);
Peterson, Peter
committed
index = boost::lexical_cast<int>(sindex);
if (i == varName.size() - 1)
throw std::invalid_argument("Name cannot be empty");
Peterson, Peter
committed
}
Roman Tolchenov
committed
/** Returns the index of parameter i as it declared in its function
Janik Zikovsky
committed
* @param i :: The parameter index
Roman Tolchenov
committed
* @return The local index of the parameter
*/
size_t CompositeFunction::parameterLocalIndex(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
return i - m_paramOffsets[iFun];
}
/** Returns the name of parameter i as it declared in its function
Janik Zikovsky
committed
* @param i :: The parameter index
* @return The pure parameter name (without the function identifier f#.)
*/
std::string CompositeFunction::parameterLocalName(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[iFun]->parameterName(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
/**
Roman Tolchenov
committed
* Apply the ties.
Roman Tolchenov
committed
*/
void CompositeFunction::applyTies() {
for (size_t i = 0; i < nFunctions(); i++) {
Roman Tolchenov
committed
getFunction(i)->applyTies();
}
}
/**
Roman Tolchenov
committed
*/
void CompositeFunction::clearTies() {
for (size_t i = 0; i < nFunctions(); i++) {
Roman Tolchenov
committed
getFunction(i)->clearTies();
}
}
/** Removes i-th parameter's tie if it is tied or does nothing.
Janik Zikovsky
committed
* @param i :: The index of the tied parameter.
Roman Tolchenov
committed
* @return True if successfull
*/
bool CompositeFunction::removeTie(size_t i) {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
bool res = m_functions[iFun]->removeTie(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
return res;
}
/** Get the tie of i-th parameter
Janik Zikovsky
committed
* @param i :: The parameter index
* @return A pointer to the tie.
Roman Tolchenov
committed
*/
ParameterTie *CompositeFunction::getTie(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[iFun]->getTie(i - m_paramOffsets[iFun]);
Roman Tolchenov
committed
}
/**
* Attaches a tie to this function. The attached tie is owned by the function.
Janik Zikovsky
committed
* @param tie :: A pointer to a new tie
Roman Tolchenov
committed
*/
void CompositeFunction::addTie(ParameterTie *tie) {
Roman Tolchenov
committed
size_t i = getParameterIndex(*tie);
size_t iFun = functionIndex(i);
Roman Tolchenov
committed
m_functions[iFun]->addTie(tie);
}
/**
* Declare a new parameter. To used in the implementation'c constructor.
Janik Zikovsky
committed
* @param name :: The parameter name.
* @param initValue :: The initial value for the parameter
* @param description :: Parameter documentation
Roman Tolchenov
committed
*/
void CompositeFunction::declareParameter(const std::string &name,
double initValue,
const std::string &description) {
(void)name; // Avoid compiler warning
(void)initValue; // Avoid compiler warning
(void)description; // Avoid compiler warning
throw Kernel::Exception::NotImplementedError(
"CompositeFunction cannot not have its own parameters.");
Roman Tolchenov
committed
}
/** Add a constraint
Janik Zikovsky
committed
* @param ic :: Pointer to a constraint.
Roman Tolchenov
committed
*/
void CompositeFunction::addConstraint(IConstraint *ic) {
Roman Tolchenov
committed
size_t i = getParameterIndex(*ic);
size_t iFun = functionIndex(i);
getFunction(iFun)->addConstraint(ic);
Roman Tolchenov
committed
}
/**
* Prepare the function for a fit.
*/
void CompositeFunction::setUpForFit() {
// set up the member functions
for (size_t i = 0; i < nFunctions(); i++) {
getFunction(i)->setUpForFit();
// unfortuately the code below breaks some system tests (IRISFuryAndFuryFit)
// it looks as if using numeric derivatives can give different fit results
// to fit with analytical ones
//
// if parameters have non-constant ties enable numerical derivatives
// for(size_t i = 0; i < nParams(); ++i)
//{
// ParameterTie* tie = getTie( i );
// if ( tie && !tie->isConstant() )
// {
// useNumericDerivatives( true );
// break;
// }
//}
// instead of automatically switching to numeric derivatives
// log a warning about a danger of not using it
if (!getAttribute("NumDeriv").asBool()) {
for (size_t i = 0; i < nParams(); ++i) {
ParameterTie *tie = getTie(i);
if (tie && !tie->isConstant()) {
g_log.warning() << "Numeric derivatives should be used when "
"non-constant ties defined." << std::endl;
break;
}
Anders Markvardsen
committed
}
}
Janik Zikovsky
committed
/// @param i :: the index
IConstraint *CompositeFunction::getConstraint(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[iFun]->getConstraint(i - m_paramOffsets[iFun]);
/** Remove a constraint
Janik Zikovsky
committed
* @param parName :: The name of a parameter which constarint to remove.
void CompositeFunction::removeConstraint(const std::string &parName) {
Roman Tolchenov
committed
size_t iPar = parameterIndex(parName);
size_t iFun = functionIndex(iPar);
getFunction(iFun)->removeConstraint(parameterLocalName(iPar));
}
/** Checks if a constraint has been explicitly set
Janik Zikovsky
committed
* @param i :: The parameter index
* @return true if the function is explicitly set
bool CompositeFunction::isExplicitlySet(size_t i) const {
Roman Tolchenov
committed
size_t iFun = functionIndex(i);
return m_functions[iFun]->isExplicitlySet(i - m_paramOffsets[iFun]);
}
* Returns the index of parameter if the ref points to one of the member
* function
Janik Zikovsky
committed
* @param ref :: A reference to a parameter
Roman Tolchenov
committed
* @return Parameter index or number of nParams() if parameter not found
size_t
CompositeFunction::getParameterIndex(const ParameterReference &ref) const {
if (ref.getFunction() == this && ref.getIndex() < nParams()) {
Roman Tolchenov
committed
return ref.getIndex();
for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
IFunction_sptr fun = getFunction(iFun);
Roman Tolchenov
committed
size_t iLocalIndex = fun->getParameterIndex(ref);
if (iLocalIndex < fun->nParams()) {
Roman Tolchenov
committed
return m_paramOffsets[iFun] + iLocalIndex;
}
}
Roman Tolchenov
committed
return nParams();
* Returns the shrared pointer to the function conataining a parameter
Janik Zikovsky
committed
* @param ref :: The reference
* @return A function containing parameter pointed to by ref
*/
IFunction_sptr
CompositeFunction::getContainingFunction(const ParameterReference &ref) const {
for (size_t iFun = 0; iFun < nFunctions(); iFun++) {
IFunction_sptr fun = getFunction(iFun);
if (fun->getParameterIndex(ref) < fun->nParams()) {
return fun;
}
}
return IFunction_sptr();
}
} // namespace API
} // namespace Mantid