Skip to content

Commit

Permalink
Re #4158. Added an experimental fitting algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Dec 7, 2011
1 parent b2d1abc commit 2971e0e
Show file tree
Hide file tree
Showing 12 changed files with 753 additions and 19 deletions.
1 change: 1 addition & 0 deletions Code/Mantid/Framework/API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set ( SRC_FILES
src/FileFinder.cpp
src/FileProperty.cpp
src/FrameworkManager.cpp
src/FunctionDomain.cpp
src/FunctionFactory.cpp
src/IDataFileChecker.cpp
src/IEventList.cpp
Expand Down
29 changes: 23 additions & 6 deletions Code/Mantid/Framework/API/inc/MantidAPI/FunctionDomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Mantid
{
namespace API
{
/** Abstract class that represents the domain of a function.
/** Base 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
Expand Down Expand Up @@ -43,14 +43,31 @@ namespace API
class MANTID_API_DLL FunctionDomain
{
public:
/// Constructor.
FunctionDomain(size_t n);
/// Virtual destructor
virtual ~FunctionDomain(){}
/// Return the number of points, values, etc in the domain
virtual size_t size() const = 0;
virtual size_t size() const {return m_calculated.size();}
/// store i-th calculated value. 0 <= i < size()
virtual void setCalculated(size_t i,double value) = 0;
virtual void setCalculated(size_t i,double value) {m_calculated[i] = value;}
/// get i-th calculated value. 0 <= i < size()
virtual double getCalculated(size_t i) const = 0;
/// Virtual destructor
virtual ~FunctionDomain(){}
virtual double getCalculated(size_t i) const {return m_calculated[i];}
/// set a fitting data value
virtual void setFitData(size_t i,double value);
virtual void setFitData(const std::vector<double>& values);
/// get a fitting data value
virtual double getFitData(size_t i) const;
/// set a fitting weight
virtual void setFitWeight(size_t i,double value);
virtual void setFitWeights(const std::vector<double>& values);
/// get a fitting weight
virtual double getFitWeight(size_t i) const;
protected:
void setDataSize();
std::vector<double> m_calculated; ///< buffer for calculated values
std::vector<double> m_data; ///< buffer for fit data
std::vector<double> m_weights; ///< buffer for fitting weights (reciprocal errors)
};

} // namespace API
Expand Down
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/IFitFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class MANTID_API_DLL IFitFunction: public virtual IFunction
setWorkspace(ws,copyData);
setSlicing(slicing);
}
/// Get the workspace
virtual boost::shared_ptr<const API::Workspace> getWorkspace()const = 0;
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws,bool copyData) = 0;
virtual void setSlicing(const std::string& slicing) = 0;

Expand Down
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/API/inc/MantidAPI/IFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class MANTID_API_DLL IFunction
/// @param ws :: Shared pointer to a workspace
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws) = 0;
/// Get the workspace
virtual boost::shared_ptr<const API::Workspace> getWorkspace()const = 0;
//virtual boost::shared_ptr<const API::Workspace> getWorkspace()const = 0;
/// Iinialize the function
virtual void initialize(){this->init();}

Expand Down
34 changes: 23 additions & 11 deletions Code/Mantid/Framework/API/inc/MantidAPI/TempFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//----------------------------------------------------------------------
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IFunction.h"
#include "MantidAPI/IFitFunction.h"
#include "MantidAPI/IFunctionMW.h"
#include "MantidKernel/Exception.h"

#ifdef _WIN32
Expand All @@ -17,7 +17,7 @@ namespace Mantid
{
namespace API
{
/** This is a temporari helper class to aid transition from IFitFunction to IFunction.
/** This is a temporary helper class to aid transition from IFitFunction to IFunction.
@author Roman Tolchenov, Tessella Support Services plc
@date 17/11/2011
Expand Down Expand Up @@ -46,15 +46,15 @@ class MANTID_API_DLL TempFunction: public virtual IFunction
{
public:
/// Constructor
TempFunction(IFitFunction* function);
TempFunction(IFunctionMW* function);

/// Returns the function's name
virtual std::string name()const {return m_function->name();}
/// Set the workspace. Make
/// @param ws :: Shared pointer to a workspace
virtual void setWorkspace(boost::shared_ptr<const Workspace> ws) { UNUSED_ARG(ws) }
/// Get the workspace
virtual boost::shared_ptr<const API::Workspace> getWorkspace()const {return m_function->getWorkspace();}
//virtual boost::shared_ptr<const API::Workspace> getWorkspace()const {return m_function->getWorkspace();}

/// The categories the Fit function belong to.
/// Categories must be listed as a comma separated list.
Expand All @@ -63,12 +63,8 @@ class MANTID_API_DLL TempFunction: public virtual IFunction
/// "Muon\\Custom"
virtual const std::string category() const { return m_function->category();}

/// Function you want to fit to.
/// @param out :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
virtual void function(FunctionDomain& domain)const {
UNUSED_ARG(domain)
throw Kernel::Exception::NotImplementedError("TempFunction not implemented.");
}
virtual void function(FunctionDomain& domain)const;
virtual void functionDeriv(FunctionDomain& domain, Jacobian& jacobian);

/// Set i-th parameter
virtual void setParameter(size_t i, const double& value, bool explicitlySet = true) {m_function->setParameter(i,value,explicitlySet);}
Expand Down Expand Up @@ -151,7 +147,23 @@ class MANTID_API_DLL TempFunction: public virtual IFunction
virtual void addTie(ParameterTie* tie) {m_function->addTie(tie);}

/// Pointer to underlying IFitFunction
IFitFunction* m_function;
IFunctionMW* m_function;
};

/**
* The domain for 1D functions.
*/
class MANTID_API_DLL FunctionDomain1D: public FunctionDomain
{
public:
FunctionDomain1D(double start, double end, size_t n);
FunctionDomain1D(const std::vector<double>& xvalues);
/// get an x value
/// @param i :: Index
double getX(size_t i) const {return m_X.at(i);}
protected:
std::vector<double> m_X; ///< vector of function arguments
friend class TempFunction;
};


Expand Down
115 changes: 115 additions & 0 deletions Code/Mantid/Framework/API/src/FunctionDomain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/FunctionDomain.h"
#include <iostream>

namespace Mantid
{
namespace API
{

/**
* Constructs a domain base of size n.
* @param n :: Size of the domain, i.e. number of values a function should calculate.
*/
FunctionDomain::FunctionDomain(size_t n)
{
if (n == 0)
{
throw std::invalid_argument("FunctionDomain cannot have zero size.");
}
m_calculated.resize(n);
}

/**
* Set a fitting data value.
* @param i :: Index
* @param value :: Value
*/
void FunctionDomain::setFitData(size_t i,double value)
{
if (m_data.size() != m_calculated.size())
{
setDataSize();
}
m_data[i] = value;
}

/**
* Set fitting data values.
* @param values :: Values for fitting
*/
void FunctionDomain::setFitData(const std::vector<double>& values)
{
if (values.size() != this->size())
{
throw std::invalid_argument("Setting data of a wrong size");
}
m_data.assign(values.begin(),values.end());
}

/**
* Get a fitting data value
* @param i :: Index
*/
double FunctionDomain::getFitData(size_t i) const
{
if (m_data.size() != m_calculated.size())
{
throw std::runtime_error("Fitting data was not set");
}
return m_data[i];
}

/**
* Set a fitting weight
* @param i :: Index
* @param value :: Value
*/
void FunctionDomain::setFitWeight(size_t i,double value)
{
if (m_data.size() != m_calculated.size())
{
setDataSize();
}
m_weights[i] = value;
}

/**
* Set fitting data values.
* @param values :: Values for fitting
*/
void FunctionDomain::setFitWeights(const std::vector<double>& values)
{
if (values.size() != this->size())
{
throw std::invalid_argument("Setting data of a wrong size");
}
m_weights.assign(values.begin(),values.end());
}

/**
* Get a fitting weight.
* @param i :: Index
*/
double FunctionDomain::getFitWeight(size_t i) const
{
if (m_data.size() != m_calculated.size())
{
throw std::runtime_error("Fitting data was not set");
}
return m_weights[i];
}

/**
* Resize the fitting data and weight buffers to match the size of the calculated buffer.
*/
void FunctionDomain::setDataSize()
{
m_data.resize(m_calculated.size());
m_weights.resize(m_calculated.size());
}

} // namespace API
} // namespace Mantid
54 changes: 53 additions & 1 deletion Code/Mantid/Framework/API/src/TempFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,62 @@ namespace Mantid
namespace API
{

TempFunction::TempFunction(IFitFunction* function):
TempFunction::TempFunction(IFunctionMW* function):
IFunction(),
m_function(function)
{}

void TempFunction::function(FunctionDomain& domain)const
{
FunctionDomain1D* domain1D = dynamic_cast<FunctionDomain1D*>(&domain);
if (!domain1D)
{
throw std::invalid_argument("Function defined only on 1D domain");
}
m_function->functionMW(&domain1D->m_calculated[0],&domain1D->m_X[0],domain1D->size());
}

void TempFunction::functionDeriv(FunctionDomain& domain, Jacobian& jacobian)
{
FunctionDomain1D* domain1D = dynamic_cast<FunctionDomain1D*>(&domain);
if (!domain1D)
{
throw std::invalid_argument("Function defined only on 1D domain");
}
m_function->functionDerivMW(&jacobian,&domain1D->m_X[0],domain1D->size());
}

/*--- FunctionDomain1D ---*/

/**
* Create a domain from interval bounds and number of divisions.
* @param start :: Starting point
* @param end :: End point
* @param n :: Number of points
*/
FunctionDomain1D::FunctionDomain1D(double start, double end, size_t n):
FunctionDomain(n)
{
// n > 0, FunctionDomain(n) must throw if it isn't
double dx = (end - start) / (n - 1);
m_X.resize(n);
double x = start;
for(size_t i = 0; i < n; ++i, x += dx)
{
m_X[i] = x;
}
}

/**
* Create a domain form a vector.
* @param xvalues :: Points
*/
FunctionDomain1D::FunctionDomain1D(const std::vector<double>& xvalues):
FunctionDomain(xvalues.size())
{
m_X.assign(xvalues.begin(),xvalues.end());
}


} // namespace API
} // namespace Mantid
24 changes: 24 additions & 0 deletions Code/Mantid/Framework/API/test/TempFunctionTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@ class TempFunctionTest : public CxxTest::TestSuite
TempFunction fun(new TFT_Funct);
TS_ASSERT_EQUALS(fun.name(),"TFT_Funct");
TS_ASSERT_EQUALS(fun.nParams(),4);

Mantid::API::FunctionDomain1D domain(0.0,1.0,10);
TS_ASSERT_EQUALS(domain.size(),10);
TS_ASSERT_EQUALS(domain.getX(0),0);
TS_ASSERT_DELTA(domain.getX(9),1.0,1e-9);
TS_ASSERT_EQUALS(domain.getX(1),1.0 / 9);

fun.setParameter("c0",3.0);
fun.setParameter("c1",1.0);
fun.function(domain);

for(size_t i = 0; i < domain.size(); ++i)
{
double x = domain.getX(i);
double y = domain.getCalculated(i);
TS_ASSERT_EQUALS(y,3.0 + x);
}
}

void test_domain_create()
{
TS_ASSERT_THROWS(Mantid::API::FunctionDomain d(0),std::invalid_argument);
TS_ASSERT_THROWS(Mantid::API::FunctionDomain d(-10),std::length_error);
TS_ASSERT_THROWS_NOTHING(Mantid::API::FunctionDomain d(1),std::invalid_argument);
}

};
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/CurveFitting/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set ( SRC_FILES
src/Gaussian1D.cpp
src/GaussianLinearBG1D.cpp
src/GenericFit.cpp
src/NewFit.cpp
src/IkedaCarpenterPV.cpp
src/LevenbergMarquardtMinimizer.cpp
src/Linear.cpp
Expand Down Expand Up @@ -65,6 +66,7 @@ set ( INC_FILES
inc/MantidCurveFitting/Gaussian1D.h
inc/MantidCurveFitting/GaussianLinearBG1D.h
inc/MantidCurveFitting/GenericFit.h
inc/MantidCurveFitting/NewFit.h
inc/MantidCurveFitting/IFuncMinimizer.h
inc/MantidCurveFitting/IkedaCarpenterPV.h
inc/MantidCurveFitting/LevenbergMarquardtMinimizer.h
Expand Down Expand Up @@ -96,6 +98,7 @@ set ( TEST_FILES
test/ConvolutionTest.h
test/ExpDecayTest.h
test/FitTest.h
test/NewFitTest.h
test/FuncMinimizerFactoryTest.h
test/FunctionFactoryTest.h
test/FunctionTest.h
Expand Down

0 comments on commit 2971e0e

Please sign in to comment.