Commit 5740f22d authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Re #4158. Started gradual change to a new function interface.

parent 4881943b
......@@ -32,6 +32,8 @@ set ( SRC_FILES
src/IEventList.cpp
src/IEventWorkspace.cpp
src/IFitFunction.cpp
src/IFunction.cpp
src/TempFunction.cpp
src/IFunctionMD.cpp
src/IFunctionMW.cpp
src/IMDEventWorkspace.cpp
......@@ -121,7 +123,9 @@ set ( INC_FILES
inc/MantidAPI/FileFinder.h
inc/MantidAPI/FileProperty.h
inc/MantidAPI/FrameworkManager.h
inc/MantidAPI/FunctionDomain.h
inc/MantidAPI/FunctionFactory.h
inc/MantidAPI/Jacobian.h
inc/MantidAPI/IAlgorithm.h
inc/MantidAPI/IArchiveSearch.h
inc/MantidAPI/IBackgroundFunction.h
......@@ -133,6 +137,8 @@ set ( INC_FILES
inc/MantidAPI/IEventList.h
inc/MantidAPI/IEventWorkspace.h
inc/MantidAPI/IFitFunction.h
inc/MantidAPI/IFunction.h
inc/MantidAPI/TempFunction.h
inc/MantidAPI/IFunctionMD.h
inc/MantidAPI/IFunctionMW.h
inc/MantidAPI/IFunctionWithLocation.h
......
......@@ -5,6 +5,7 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/IFitFunction.h"
#include "MantidAPI/Jacobian.h"
#include <boost/shared_array.hpp>
namespace Mantid
......@@ -104,22 +105,22 @@ public:
/// Return parameter index from a parameter reference.
size_t getParameterIndex(const ParameterReference& ref)const;
/// Get the containing function
IFitFunction* getContainingFunction(const ParameterReference& ref)const;
IFunction* getContainingFunction(const ParameterReference& ref)const;
/// Get the containing function
IFitFunction* getContainingFunction(const IFitFunction* fun);
IFunction* getContainingFunction(const IFunction* fun);
/// Apply the ties
void applyTies();
/// Remove all ties
void clearTies();
// Unhide base class function: removeTie(string). Avoids Intel compiler warning
using IFitFunction::removeTie;
using IFunction::removeTie;
/// Removes i-th parameter's tie
bool removeTie(size_t i);
/// Get the tie of i-th parameter
ParameterTie* getTie(size_t i)const;
/// Overwrite IFitFunction methods
/// Overwrite IFunction methods
void addConstraint(IConstraint* ic);
/// Get constraint of i-th parameter
virtual IConstraint* getConstraint(size_t i)const;
......@@ -131,17 +132,17 @@ public:
/* CompositeFunction own methods */
/// Add a function at the back of the internal function list
virtual size_t addFunction(IFitFunction* f);
virtual size_t addFunction(IFunction* f);
/// Returns the pointer to i-th function
IFitFunction* getFunction(std::size_t i)const;
IFunction* getFunction(std::size_t i)const;
/// Number of functions
std::size_t nFunctions()const{return m_functions.size();}
/// Remove a function
void removeFunction(size_t i, bool del=true);
/// Replace a function
void replaceFunction(size_t i,IFitFunction* f);
void replaceFunction(size_t i,IFunction* f);
/// Replace a function
void replaceFunctionPtr(const IFitFunction* f_old,IFitFunction* f_new);
void replaceFunctionPtr(const IFunction* f_old,IFunction* f_new);
/// Get the function index
std::size_t functionIndex(std::size_t i)const;
/// Get the function index
......@@ -170,7 +171,7 @@ private:
static void parseName(const std::string& varName,size_t& index, std::string& name);
/// Pointers to the included funtions
std::vector<IFitFunction*> m_functions;
std::vector<IFunction*> m_functions;
/// Individual function parameter offsets (function index in m_functions)
/// e.g. m_functions[i]->activeParameter(m_activeOffsets[i]+1) gives second active parameter of i-th function
std::vector<size_t> m_activeOffsets;
......@@ -178,9 +179,9 @@ private:
/// e.g. m_functions[i]->parameter(m_paramOffsets[i]+1) gives second declared parameter of i-th function
std::vector<size_t> m_paramOffsets;
/// Keeps the function index for each declared parameter (parameter declared index)
std::vector<size_t> m_IFitFunction;
std::vector<size_t> m_IFunction;
/// Keeps the function index for each active parameter (parameter active index)
std::vector<size_t> m_IFitFunctionActive;
std::vector<size_t> m_IFunctionActive;
/// Number of active parameters
size_t m_nActive;
/// Total number of parameters
......
#ifndef MANTID_API_FUNCTIONDOMAIN_H_
#define MANTID_API_FUNCTIONDOMAIN_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidKernel/Exception.h"
namespace Mantid
{
namespace API
{
/** Abstract class that represents the domain of a function.
A domain is a generalisation of x (argument) and y (value) arrays.
A domain consists at least of a list of function arguments for which a function should
be evaluated and a buffer for the calculated values. If used in fitting also contains
the fit data and weights.
@author Roman Tolchenov, Tessella plc
@date 15/11/2011
Copyright &copy; 2009 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>
*/
class MANTID_API_DLL FunctionDomain
{
public:
/// Return the number of points, values, etc in the domain
virtual size_t size() const = 0;
/// store i-th calculated value. 0 <= i < size()
virtual void setCalculated(size_t i,double value) = 0;
/// get i-th calculated value. 0 <= i < size()
virtual double getCalculated(size_t i) const = 0;
/// Virtual destructor
virtual ~FunctionDomain(){}
};
} // namespace API
} // namespace Mantid
#endif /*MANTID_API_FUNCTIONDOMAIN_H_*/
......@@ -5,6 +5,7 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IFunction.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FunctionFactory.h"
......@@ -111,139 +112,26 @@ class FitFunctionHandler;
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class MANTID_API_DLL IFitFunction
class MANTID_API_DLL IFitFunction: public virtual IFunction
{
public:
/**
* Atribute visitor class. It provides a separate access method
* for each attribute type. When applied to a particular attribue
* the appropriate method will be used. The child classes must
* implement the virtual AttributeVisitor::apply methods. See
* implementation of Attribute::value() method for an example.
*/
template<typename T = void>
class DLLExport AttributeVisitor: public boost::static_visitor<T>
{
public:
/// Virtual destructor
virtual ~AttributeVisitor() {}
/// implements static_visitor's operator() for std::string
T operator()(std::string& str)const{return apply(str);}
/// implements static_visitor's operator() for double
T operator()(double& d)const{return apply(d);}
/// implements static_visitor's operator() for int
T operator()(int& i)const{return apply(i);}
protected:
/// Implement this mathod to access attribute as string
virtual T apply(std::string&)const = 0;
/// Implement this mathod to access attribute as double
virtual T apply(double&)const = 0;
/// Implement this mathod to access attribute as int
virtual T apply(int&)const = 0;
};
/**
* Const version of AttributeVisitor.
*/
template<typename T = void>
class DLLExport ConstAttributeVisitor: public boost::static_visitor<T>
{
public:
/// Virtual destructor
virtual ~ConstAttributeVisitor() {}
/// implements static_visitor's operator() for std::string
T operator()(std::string& str)const{return apply(str);}
/// implements static_visitor's operator() for double
T operator()(double& d)const{return apply(d);}
/// implements static_visitor's operator() for int
T operator()(int& i)const{return apply(i);}
protected:
/// Implement this mathod to access attribute as string
virtual T apply(const std::string& str)const = 0;
/// Implement this mathod to access attribute as double
virtual T apply(const double& d)const = 0;
/// Implement this mathod to access attribute as int
virtual T apply(const int& i)const = 0;
};
/// Attribute is a non-fitting parameter.
/// It can be one of the types: std::string, int, or double
/// Examples: file name, polinomial order
class MANTID_API_DLL Attribute
{
public:
/// 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){}
/// Apply an attribute visitor
template<typename T>
T apply(AttributeVisitor<T>& v){return boost::apply_visitor(v,m_data);}
/// Apply a const attribute visitor
template<typename T>
T apply(ConstAttributeVisitor<T>& v)const{return boost::apply_visitor(v,m_data);}
/// Returns type of the attribute
std::string type()const;
/// Returns the attribute value as a string
std::string value()const;
/// Returns string value if attribute is a string, throws exception otherwise
std::string asString()const;
/// Returns a string value that is guarenteed to be quoted for use in places where the string is used as the displayed value.
std::string asQuotedString() const;
/// Returns a string value that is guarenteed to be unquoted.
std::string asUnquotedString() const;
/// Returns int value if attribute is a int, throws exception otherwise
int asInt()const;
/// Returns double value if attribute is a double, throws exception otherwise
double asDouble()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&);
/// 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;
/// Flag indicating if the string value should be returned quoted
bool m_quoteValue;
};
//---------------------------------------------------------//
/// Constructor
IFitFunction():m_handler(NULL){}
/// Virtual destructor
virtual ~IFitFunction();
IFitFunction():IFunction(){}
/// Returns the function's name
virtual std::string name()const = 0;
/// Writes itself into a string
virtual std::string asString()const;
/// The string operator
virtual operator std::string()const{return asString();}
/// Set the workspace.
/// @param ws :: Shared pointer to a workspace
/// @param slicing :: A string identifying the data in the workspace to be fitted, e.g. spectrum index, starting and ending x values, etc
/// Concrete form is defined by the derived functions.
/// @param copyData ::
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws,const std::string& slicing,bool copyData = true) = 0;
/// Get the workspace
virtual boost::shared_ptr<const API::Workspace> getWorkspace()const = 0;
/// Iinialize the function
virtual void initialize(){this->init();}
/// The categories the Fit function belong to.
/// Categories must be listed as a comma separated list.
/// For example: "General, Muon\\Custom" which adds
/// a function to the category "General" and the sub-category
/// "Muon\\Custom"
virtual const std::string category() const { return "General";}
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws,const std::string& slicing,bool copyData)
{
setWorkspace(ws,copyData);
setSlicing(slicing);
}
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws,bool copyData) = 0;
virtual void setSlicing(const std::string& slicing) = 0;
/// Returns the size of the fitted data (number of double values returned by the function getData())
virtual size_t dataSize()const = 0;
......@@ -256,172 +144,12 @@ public:
/// Derivatives of function with respect to active parameters
virtual void functionDeriv(Jacobian* out);
/// Set i-th parameter
virtual void setParameter(size_t, const double& value, bool explicitlySet = true) = 0;
/// Set i-th parameter description
virtual void setParameterDescription(size_t, const std::string& description) = 0;
/// Get i-th parameter
virtual double getParameter(size_t i)const = 0;
/// Set parameter by name.
virtual void setParameter(const std::string& name, const double& value, bool explicitlySet = true) = 0;
/// Set description of parameter by name.
virtual void setParameterDescription(const std::string& name, const std::string& description) = 0;
/// Get parameter by name.
virtual double getParameter(const std::string& name)const = 0;
/// Total number of parameters
virtual size_t nParams()const = 0;
/// Returns the index of parameter name
virtual size_t parameterIndex(const std::string& name)const = 0;
/// Returns the name of parameter i
virtual std::string parameterName(size_t i)const = 0;
/// Returns the description of parameter i
virtual std::string parameterDescription(size_t i)const = 0;
/// Checks if a parameter has been set explicitly
virtual bool isExplicitlySet(size_t i)const = 0;
/// Number of active (in terms of fitting) parameters
virtual size_t nActive()const = 0;
/// Value of i-th active parameter. Override this method to make fitted parameters different from the declared
virtual double activeParameter(size_t i)const;
/// Set new value of i-th active parameter. Override this method to make fitted parameters different from the declared
virtual void setActiveParameter(size_t i, double value);
/// Update parameters after a fitting iteration
virtual void updateActive(const double* in);
/// Returns "global" index of active parameter i
virtual size_t indexOfActive(size_t i)const = 0;
/// Returns the name of active parameter i
virtual std::string nameOfActive(size_t i)const = 0;
/// Returns the name of active parameter i
virtual std::string descriptionOfActive(size_t i)const = 0;
/// Check if a declared parameter i is active
virtual bool isActive(size_t i)const = 0;
/// Get active index for a declared parameter i
virtual size_t activeIndex(size_t i)const = 0;
/// Removes a declared parameter i from the list of active
virtual void removeActive(size_t i) = 0;
/// Restores a declared parameter i to the active status
virtual void restoreActive(size_t i) = 0;
/// Return parameter index from a parameter reference. Usefull for constraints and ties in composite functions
virtual size_t getParameterIndex(const ParameterReference& ref)const = 0;
/// Get a function containing the parameter refered to by the reference. In case of a simple function
/// it will be the same as ParameterReference::getFunction(). In case of a CompositeFunction it returns
/// a top-level function that contains the parameter. The return function itself can be a CompositeFunction
/// @param ref :: The Parameter reference
/// @return A pointer to the containing function
virtual IFitFunction* getContainingFunction(const ParameterReference& ref)const = 0;
/// The same as the method above but the argument is a function
virtual IFitFunction* getContainingFunction(const IFitFunction* fun) = 0;
/// Tie a parameter to other parameters (or a constant)
virtual ParameterTie* tie(const std::string& parName,const std::string& expr);
/// Apply the ties
virtual void applyTies() = 0;
/// Removes the tie off a parameter
virtual void removeTie(const std::string& parName);
/// Remove all ties
virtual void clearTies() = 0;
/// Removes i-th parameter's tie
virtual bool removeTie(size_t i) = 0;
/// Get the tie of i-th parameter
virtual ParameterTie* getTie(size_t i)const = 0;
/// Add a constraint to function
virtual void addConstraint(IConstraint* ic) = 0;
/// Get constraint of i-th parameter
virtual IConstraint* getConstraint(size_t i)const = 0;
/// Remove a constraint
virtual void removeConstraint(const std::string& parName) = 0;
/// Add a penalty to the output if some parameters do not satisfy constraints.
virtual void addPenalty(double *out)const;
/// Modify the derivatives to correct for a penalty
virtual void addPenaltyDeriv(Jacobian *out)const;
/// Set the parameters of the function to satisfy the constraints of
/// of the function. For example
/// for a BoundaryConstraint this if param value less than lower boundary
/// it is set to that value and vice versa for if the param value is larger
/// than the upper boundary value.
virtual void setParametersToSatisfyConstraints() {};
/// Returns the number of attributes associated with the function
virtual size_t nAttributes()const{return 0;}
/// Returns a list of attribute names
virtual std::vector<std::string> getAttributeNames()const{return std::vector<std::string>();}
/// 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());
}
/// 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());
}
/// Check if attribute attName exists
virtual bool hasAttribute(const std::string& attName)const { (void)attName; return false;}
/// Set a function handler
void setHandler(FitFunctionHandler* handler);
/// Return the handler
FitFunctionHandler* getHandler()const{return m_handler;}
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="") = 0;
/// Create an instance of a tie without actually tying it to anything
virtual ParameterTie* createTie(const std::string& parName);
/// Add a new tie
virtual void addTie(ParameterTie* tie) = 0;
friend class ParameterTie;
friend class CompositeFunction;
/// Pointer to a function handler
FitFunctionHandler* m_handler;
/// Static reference to the logger class
static Kernel::Logger& g_log;
};
/** Represents the Jacobian in functionDeriv.
* It is abstract to abstract from any GSL
*/
class Jacobian
{
public:
/** Set a value to a Jacobian matrix element.
* @param iY :: The index of a data point.
* @param iP :: The index of a declared parameter.
* @param value :: The derivative value.
*/
virtual void set(size_t iY, size_t iP, double value) = 0;
/** Get the value to a Jacobian matrix element.
* @param iY :: The index of a data point.
* @param iP :: The index of a declared parameter.
*/
virtual double get(size_t iY, size_t iP) = 0;
///@cond do not document
/** Add number to all iY (data) Jacobian elements for a given iP (parameter)
* @param value :: Value to add
*/
virtual void addNumberToColumn(const double& value, const size_t& iActiveP)
{
(void)value; (void)iActiveP; // Avoid compiler warning
throw Kernel::Exception::NotImplementedError("No addNumberToColumn() method of Jacobian provided");
}
///@endcond
/// Virtual destructor
virtual ~Jacobian() {};
protected:
friend class TempFunction;
};
/// Overload operator <<
......@@ -434,13 +162,13 @@ MANTID_API_DLL std::ostream& operator<<(std::ostream& ostr,const IFitFunction& f
* single function and there is no need to duplicate the function tree
* structure.
*/
class FitFunctionHandler
class FunctionHandler
{
public:
/// Constructor
FitFunctionHandler(IFitFunction* fun):m_fun(fun){}
FunctionHandler(IFitFunction* fun):m_fun(fun){}
/// Virtual destructor
virtual ~FitFunctionHandler(){}
virtual ~FunctionHandler(){}
/// abstract init method. It is called after setting handler to the function
virtual void init() = 0;
/// Return the handled function
......
#ifndef MANTID_API_IFUNCTION_H_
#define MANTID_API_IFUNCTION_H_
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/FunctionDomain.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/Exception.h"
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
#include <string>
#include <vector>
#ifdef _WIN32
#pragma warning( disable: 4250 )
#endif
namespace Mantid
{
namespace API
{
//----------------------------------------------------------------------
// Forward declaration
//----------------------------------------------------------------------
class Workspace;
class Jacobian;
class ParameterTie;
class IConstraint;
class ParameterReference;
class FunctionHandler;
/** This is an interface to a fitting function - a semi-abstarct class.
Functions derived from IFunction can be used with the Fit algorithm.
IFunction defines the structure of a fitting funtion.
A function has a number of named parameters (not arguments), type double, on which it depends.
Parameters must be declared either in the constructor or in the init() method
of a derived class with method declareParameter(...). Method nParams() returns
the number of declared parameters. A parameter can be accessed either by its name
or the index. For example in case of Gaussian the parameters can be "Height",
"PeakCentre" and "Sigma".
To fit a function to a set of data its parameters must be adjusted so that the difference
between the data and the corresponding function values were minimized. This is the aim
of the Fit algorithm. But Fit does not work with the declared parameters directly.
Instead it uses other - active - parameters. The active parameters can be a subset of the
declared parameters or completely different ones. The rationale for this is following.
The fitting parameters sometimes need to be fixed during the fit or "tied" (expressed
in terms of other parameters). In this case the active parameters will be those
declared parameters which are not tied in any sence. Also some of the declared parameters
can be unsuitable for the use in a fitting algorithm. In this case different active parameters
can be used in place of the inefficient declared parameters. An example is Gaussian where
"Sigma" makes the fit unstable. So in the fit it can be replaced with variable Weight = 1 / Sigma
which is more efficient. The number of active parameters (returned by nActive()) cannot be
greater than nParams(). The function which connects the active parameters with the declared ones
must be monotonic so that the forward and backward transformations between the two sets are
single-valued (this is my understanding). At the moment only simple one to one transformations
of Weight - Sigma type are allowed. More complecated cases of simultaneous transformations of
several parameters are not supported.
The active parameters can be accessed by their index. The implementations of the access method
for both active and declared parameters must ensure that any changes to one of them
immediately reflected on the other so that the two are consistent at any moment.
IFunction declares method nameOfActive(int i) which returns the name of the declared parameter
corresponding to the i-th active parameter. I am not completely sure in the usefulness of it.
IFunction provides methods for tying and untying parameters. Only the declared parameters can be
tied. A tied parameter cannot be active. When a parameter is tied it becomes inactive.
This implies that the number of active parameters is variable and can change at runtime.
Method addConstraint adds constraints on possible values of a declared parameter. Constraints
and ties are used only in fitting.
The main method of IFunction is called function(out,xValues,nData). It calculates nData output values
out[i] at arguments xValues[i]. Implement functionDeriv method for the function to be used with
fitting algorithms using derivatives. functionDeriv calculates patrial derivatives of the
function with respect to the fitting parameters.
Any non-fitting parameters can be implemented as attributes (class IFunction::Attribute).
An attribute can have one of three types: std::string, int, or double. The type is set at construction
and cannot be changed later. To read or write the attributes there are two ways. If the type