Commit 74952cc2 authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #5893. Merged ParamFunctionAttributeHolder into IFunction.

Added an attribute to CompositeFunction to enable/disable numeric differentiation.
parent 1a31160c
......@@ -87,7 +87,6 @@ set ( SRC_FILES
src/NullCoordTransform.cpp
src/NumericAxis.cpp
src/ParamFunction.cpp
src/ParamFunctionAttributeHolder.cpp
src/ParameterReference.cpp
src/ParameterTie.cpp
src/Progress.cpp
......@@ -228,7 +227,6 @@ set ( INC_FILES
inc/MantidAPI/NullCoordTransform.h
inc/MantidAPI/NumericAxis.h
inc/MantidAPI/ParamFunction.h
inc/MantidAPI/ParamFunctionAttributeHolder.h
inc/MantidAPI/ParameterReference.h
inc/MantidAPI/ParameterTie.h
inc/MantidAPI/Progress.h
......
......@@ -54,7 +54,7 @@ class MANTID_API_DLL CompositeFunction : public virtual IFunction
{
public:
/// Default constructor
CompositeFunction(): m_nParams(0),m_useNumericDerivatives(false){}
CompositeFunction();
///Destructor
virtual ~CompositeFunction();
......@@ -142,6 +142,9 @@ public:
/// Remove a constraint
void removeConstraint(const std::string& parName);
/// Set a value to attribute attName
virtual void setAttribute(const std::string& attName,const Attribute& );
/* CompositeFunction own methods */
/// Add a function at the back of the internal function list
......
......@@ -150,6 +150,8 @@ public:
T operator()(double& d)const{return apply(d);}
/// implements static_visitor's operator() for int
T operator()(int& i)const{return apply(i);}
/// implements static_visitor's operator() for bool
T operator()(bool& b)const{return apply(b);}
protected:
/// Implement this mathod to access attribute as string
virtual T apply(std::string&)const = 0;
......@@ -157,6 +159,8 @@ public:
virtual T apply(double&)const = 0;
/// Implement this mathod to access attribute as int
virtual T apply(int&)const = 0;
/// Implement this mathod to access attribute as bool
virtual T apply(bool&)const = 0;
};
/**
......@@ -174,6 +178,8 @@ public:
T operator()(double& d)const{return apply(d);}
/// implements static_visitor's operator() for int
T operator()(int& i)const{return apply(i);}
/// implements static_visitor's operator() for bool
T operator()(bool& b)const{return apply(b);}
protected:
/// Implement this mathod to access attribute as string
virtual T apply(const std::string& str)const = 0;
......@@ -181,6 +187,8 @@ public:
virtual T apply(const double& d)const = 0;
/// Implement this mathod to access attribute as int
virtual T apply(const int& i)const = 0;
/// Implement this mathod to access attribute as bool
virtual T apply(const bool& i)const = 0;
};
/// Attribute is a non-fitting parameter.
......@@ -190,13 +198,15 @@ public:
{
public:
/// Create empty string attribute
explicit Attribute():m_data(""), m_quoteValue(false) {}
explicit Attribute():m_data(std::string()), m_quoteValue(false) {}
/// Create string attribute
explicit Attribute(const std::string& str, bool quoteValue=false):m_data(str), m_quoteValue(quoteValue) {}
/// Create int attribute
explicit Attribute(const int& i):m_data(i){}
/// Create double attribute
explicit Attribute(const double& d):m_data(d){}
/// Create bool attribute
explicit Attribute(const bool& b):m_data(b){}
/// Apply an attribute visitor
template<typename T>
T apply(AttributeVisitor<T>& v){return boost::apply_visitor(v,m_data);}
......@@ -217,17 +227,21 @@ public:
int asInt()const;
/// Returns double value if attribute is a double, throws exception otherwise
double asDouble()const;
/// Returns bool value if attribute is a bool, throws exception otherwise
bool asBool()const;
/// Sets new value if attribute is a string
void setString(const std::string& str);
/// Sets new value if attribute is a double
void setDouble(const double&);
/// Sets new value if attribute is a int
void setInt(const int&);
/// Sets new value if attribute is a bool
void setBool(const bool&);
/// Set value from a string.
void fromString(const std::string& str);
private:
/// The data holder as boost variant
mutable boost::variant<std::string,int,double> m_data;
mutable boost::variant<std::string,int,double,bool> m_data;
/// Flag indicating if the string value should be returned quoted
bool m_quoteValue;
};
......@@ -337,6 +351,8 @@ public:
//@}
/** @name Ties */
//@{
/// Tie a parameter to other parameters (or a constant)
virtual ParameterTie* tie(const std::string& parName, const std::string& expr, bool isDefault = false);
/// Add several ties
......@@ -351,8 +367,11 @@ public:
virtual bool removeTie(size_t i) = 0;
/// Get the tie of i-th parameter
virtual ParameterTie* getTie(size_t i)const = 0;
//@}
/** @name Constraints */
//@{
/// Add a list of conatraints from a string
virtual void addConstraints(const std::string& str, bool isDefault = false);
/// Add a constraint to function
......@@ -361,28 +380,27 @@ public:
virtual IConstraint* getConstraint(size_t i)const = 0;
/// Remove a constraint
virtual void removeConstraint(const std::string& parName) = 0;
//@}
/// Set up the function for a fit.
virtual void setUpForFit() = 0;
/** @name Attributes */
//@{
/// Returns the number of attributes associated with the function
virtual size_t nAttributes()const{return 0;}
virtual size_t nAttributes()const;
/// Returns a list of attribute names
virtual std::vector<std::string> getAttributeNames()const{return std::vector<std::string>();}
virtual std::vector<std::string> getAttributeNames()const;
/// Return a value of attribute attName
virtual Attribute getAttribute(const std::string& attName)const
{
throw std::invalid_argument("Attribute "+attName+" not found in function "+this->name());
}
virtual Attribute getAttribute(const std::string& attName)const;
/// Set a value to attribute attName
virtual void setAttribute(const std::string& attName,const Attribute& )
{
throw std::invalid_argument("Attribute "+attName+" not found in function "+this->name());
}
virtual void setAttribute(const std::string& attName,const Attribute& );
/// Check if attribute attName exists
virtual bool hasAttribute(const std::string& attName)const { (void)attName; return false;}
virtual bool hasAttribute(const std::string& attName)const;
/// Set an attribute value
template<typename T>
void setAttributeValue(const std::string& attName,const T& value){setAttribute(attName,Attribute(value));}
//@}
/// Set up the function for a fit.
virtual void setUpForFit() = 0;
/// Calculate numerical derivatives
void calNumericalDeriv(const FunctionDomain& domain, Jacobian& out);
......@@ -400,7 +418,7 @@ public:
protected:
/// Function initialization. Declare function parameters in this method.
virtual void init(){};
virtual void init();
/// Declare a new parameter
virtual void declareParameter(const std::string& name, double initValue = 0, const std::string& description="") = 0;
......@@ -416,13 +434,19 @@ protected:
/// Add a new tie. Derived classes must provide storage for ties
virtual void addTie(ParameterTie* tie) = 0;
/// Override to declare function attributes
virtual void declareAttributes() {}
/// Override to declare function parameters
virtual void declareParameters() {}
/// Declare a single attribute
void declareAttribute(const std::string & name, const API::IFunction::Attribute & defaultValue);
/// Store an attribute's value
void storeAttributeValue(const std::string& name, const API::IFunction::Attribute & value);
friend class ParameterTie;
friend class CompositeFunction;
/// Values storage for numeric derivatives
FunctionValues m_minusStep;
/// Values storage for numeric derivatives
FunctionValues m_plusStep;
/// Flag to hint that the function is being used in parallel computations
bool m_isParallel;
......@@ -434,6 +458,10 @@ protected:
/// Static reference to the logger class
static Kernel::Logger& g_log;
private:
/// The declared attributes
std::map<std::string, API::IFunction::Attribute> m_attrs;
};
///shared pointer to the function base class
......
......@@ -124,8 +124,6 @@ public:
protected:
/// Function initialization. Declare function parameters in this method.
virtual void init(){};
/// Declare a new parameter
virtual void declareParameter(const std::string& name,double initValue = 0, const std::string& description="");
......
#ifndef MANTID_API_PARAMFUNCTIONATTRIBUTEHOLDER_H_
#define MANTID_API_PARAMFUNCTIONATTRIBUTEHOLDER_H_
/**
Copyright &copy; 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
Mantid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
Mantid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/ParamFunction.h"
namespace Mantid
{
namespace API
{
/**
*
* Defines a structure to simplify handling of attributes/parameters for fit functions
*
* It holds the attributes themselves and defines a declareAttributes function that
* can be overridden to define the attributes of the model. Similary, fit parameters
* can be declared with the declareParameters function.
*
*/
class MANTID_API_DLL ParamFunctionAttributeHolder : public API::ParamFunction
{
public:
/// Default constructor
ParamFunctionAttributeHolder();
/// Returns the number of attributes associated with the function
size_t nAttributes() const;
/// Check if attribute named exists
bool hasAttribute(const std::string& name)const;
/// Returns a list of attribute names
std::vector<std::string> getAttributeNames() const;
/// Return a value of attribute attName
API::IFunction::Attribute getAttribute(const std::string& name) const;
/// Set a value to a named attribute.
void setAttribute(const std::string& name, const API::IFunction::Attribute & value);
protected:
/// Initialize the function holder
void init();
/// Override to declare function attributes
virtual void declareAttributes() {}
/// Override to declare function parameters
virtual void declareParameters() {};
/// Declare a single attribute
void declareAttribute(const std::string & name, const API::IFunction::Attribute & defaultValue);
/// Store an attribute's value
void storeAttributeValue(const std::string& name, const API::IFunction::Attribute & value);
private:
/// The declared attributes
std::map<std::string, API::IFunction::Attribute> m_attrs;
};
}
}
#endif /* MANTID_API_PARAMFUNCTIONATTRIBUTEHOLDER_H_ */
......@@ -22,6 +22,14 @@ using std::size_t;
DECLARE_FUNCTION(CompositeFunction)
/// Default constructor
CompositeFunction::CompositeFunction():
m_nParams(0),
m_useNumericDerivatives(false)
{
declareAttribute("NumDeriv", Attribute(false));
}
///Destructor
CompositeFunction::~CompositeFunction()
{
......@@ -55,9 +63,20 @@ std::string CompositeFunction::asString()const
return "name=" + name();
}
if (name() != "CompositeFunction")
if ( name() != "CompositeFunction" || nAttributes() > 1 || getAttribute("NumDeriv").asBool() == true )
{
ostr << "composite=" <<name() << ";";
ostr << "composite=" <<name() ;
std::vector<std::string> attr = this->getAttributeNames();
for(size_t i=0;i<attr.size();i++)
{
std::string attName = attr[i];
std::string attValue = this->getAttribute(attr[i]).value();
if (!attValue.empty())
{
ostr<<','<<attName<<'='<<attValue;
}
}
ostr << ';';
}
for(size_t i=0;i<nFunctions();i++)
{
......@@ -771,6 +790,16 @@ void CompositeFunction::useNumericDerivatives( bool yes ) const
m_useNumericDerivatives = yes;
}
/// Set a value to attribute attName
void CompositeFunction::setAttribute(const std::string& attName,const Attribute& att)
{
storeAttributeValue( attName, att );
if ( attName == "NumDeriv" )
{
useNumericDerivatives( att.asBool() );
}
}
} // namespace API
} // namespace Mantid
......@@ -29,6 +29,7 @@
#include <limits>
#include <sstream>
#include <iostream>
#include <algorithm>
namespace Mantid
{
......@@ -293,19 +294,24 @@ std::ostream& operator<<(std::ostream& ostr,const IFunction& f)
return ostr;
}
/**
* Const attribute visitor returning the type of the attribute
*/
class AttType: public IFunction::ConstAttributeVisitor<std::string>
namespace
{
protected:
/// Apply if string
std::string apply(const std::string&)const{return "std::string";}
/// Apply if int
std::string apply(const int&)const{return "int";}
/// Apply if double
std::string apply(const double&)const{return "double";}
};
/**
* Const attribute visitor returning the type of the attribute
*/
class AttType: public IFunction::ConstAttributeVisitor<std::string>
{
protected:
/// Apply if string
std::string apply(const std::string&)const{return "std::string";}
/// Apply if int
std::string apply(const int&)const{return "int";}
/// Apply if double
std::string apply(const double&)const{return "double";}
/// Apply if bool
std::string apply(const bool&)const{return "bool";}
};
}
std::string IFunction::Attribute::type()const
{
......@@ -313,33 +319,38 @@ std::string IFunction::Attribute::type()const
return apply(tmp);
}
/**
* Const attribute visitor returning the type of the attribute
*/
class AttValue: public IFunction::ConstAttributeVisitor<std::string>
namespace
{
public:
AttValue(bool quoteString=false) :
IFunction::ConstAttributeVisitor<std::string>(),
m_quoteString(quoteString)
{
}
protected:
/// Apply if string
std::string apply(const std::string& str)const
/**
* Const attribute visitor returning the type of the attribute
*/
class AttValue: public IFunction::ConstAttributeVisitor<std::string>
{
return (m_quoteString) ? std::string("\"" + str + "\"") : str;
}
/// Apply if int
std::string apply(const int& i)const{return boost::lexical_cast<std::string>(i);}
/// Apply if double
std::string apply(const double& d)const{return boost::lexical_cast<std::string>(d);}
public:
AttValue(bool quoteString=false) :
IFunction::ConstAttributeVisitor<std::string>(),
m_quoteString(quoteString)
{
}
private:
/// Flag to quote a string value returned
bool m_quoteString;
};
protected:
/// Apply if string
std::string apply(const std::string& str)const
{
return (m_quoteString) ? std::string("\"" + str + "\"") : str;
}
/// Apply if int
std::string apply(const int& i)const{return boost::lexical_cast<std::string>(i);}
/// Apply if double
std::string apply(const double& d)const{return boost::lexical_cast<std::string>(d);}
/// Apply if bool
std::string apply(const bool& b)const{return b ? "true" : "false";}
private:
/// Flag to quote a string value returned
bool m_quoteString;
};
}
std::string IFunction::Attribute::value()const
{
......@@ -444,6 +455,22 @@ double IFunction::Attribute::asDouble()const
}
}
/**
* Return the attribute as a bool if it is a bool.
*/
bool IFunction::Attribute::asBool()const
{
try
{
return boost::get<bool>(m_data);
}
catch(...)
{
throw std::runtime_error("Trying to access a "+type()+" attribute "
"as bool");
}
}
/** Sets new value if attribute is a string. If the type is wrong
* throws an exception
* @param str :: The new value
......@@ -495,39 +522,64 @@ void IFunction::Attribute::setInt(const int& i)
}
}
/**
* Attribute visitor setting new value to an attribute
/** Sets new value if attribute is an bool. If the type is wrong
* throws an exception
* @param b :: The new value
*/
class SetValue: public IFunction::AttributeVisitor<>
void IFunction::Attribute::setBool(const bool& b)
{
try
{
boost::get<bool>(m_data) = b;
}
catch(...)
{
throw std::runtime_error("Trying to access a "+type()+" attribute "
"as bool");
}
}
namespace
{
public:
/**
* Constructor
* @param value :: The value to set
* Attribute visitor setting new value to an attribute
*/
SetValue(const std::string& value):m_value(value){}
protected:
/// Apply if string
void apply(std::string& str)const{str = m_value;}
/// Apply if int
void apply(int& i)const
{
std::istringstream istr(m_value+" ");
istr >> i;
if (!istr.good()) throw std::invalid_argument("Failed to set int attribute "
"from string "+m_value);
}
/// Apply if double
void apply(double& d)const
{
std::istringstream istr(m_value+" ");
istr >> d;
if (!istr.good()) throw std::invalid_argument("Failed to set double attribute "
"from string "+m_value);
}
private:
std::string m_value; ///<the value as a string
};
class SetValue: public IFunction::AttributeVisitor<>
{
public:
/**
* Constructor
* @param value :: The value to set
*/
SetValue(const std::string& value):m_value(value){}
protected:
/// Apply if string
void apply(std::string& str)const{str = m_value;}
/// Apply if int
void apply(int& i)const
{
std::istringstream istr(m_value+" ");
istr >> i;
if (!istr.good()) throw std::invalid_argument("Failed to set int attribute "
"from string "+m_value);
}
/// Apply if double
void apply(double& d)const
{
std::istringstream istr(m_value+" ");
istr >> d;
if (!istr.good()) throw std::invalid_argument("Failed to set double attribute "
"from string "+m_value);
}
/// Apply if bool
void apply(bool& b)const
{
b = ( m_value == "true" || m_value == "TRUE" || m_value == "1" );
}
private:
std::string m_value; ///<the value as a string
};
}
/** Set value from a string. Throws exception if the string has wrong format
* @param str :: String representation of the new value
......@@ -558,7 +610,10 @@ void IFunction::setActiveParameter(size_t i, double value)
setParameter(i,value);
}
/// Returns the name of active parameter i
/**
* Returns the name of an active parameter.
* @param i :: Index of a parameter. The parameter must be active.
*/
std::string IFunction::nameOfActive(size_t i)const
{
if ( !isActive(i) )
......@@ -568,7 +623,10 @@ std::string IFunction::nameOfActive(size_t i)const
return parameterName(i);
}
/// Returns the name of active parameter i
/**
* Returns the description of an active parameter.