Skip to content

Commit

Permalink
Re #5851. Added the tests. Moved the validator to Kernel.
Browse files Browse the repository at this point in the history
  • Loading branch information
mantid-roman committed Sep 21, 2012
1 parent 5c48103 commit 96240db
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/CurveFitting/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ set ( INC_FILES
inc/MantidCurveFitting/SimplexMinimizer.h
inc/MantidCurveFitting/SpecialFunctionSupport.h
inc/MantidCurveFitting/SplineBackground.h
inc/MantidCurveFitting/StartsWithValidator.h
inc/MantidCurveFitting/StaticKuboToyabe.h
inc/MantidCurveFitting/SteepestDescentMinimizer.h
inc/MantidCurveFitting/StretchExp.h
Expand All @@ -166,6 +165,7 @@ set ( TEST_FILES
ChebyshevTest.h
CompositeFunctionTest.h
ConvolutionTest.h
DampingMinimizerTest.h
DeltaFunctionTest.h
DiffSphereTest.h
EndErfcTest.h
Expand Down
6 changes: 3 additions & 3 deletions Code/Mantid/Framework/CurveFitting/src/Fit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include "MantidCurveFitting/CostFuncFitting.h"
#include "MantidCurveFitting/FitMW.h"
#include "MantidCurveFitting/MultiDomainCreator.h"
#include "MantidCurveFitting/StartsWithValidator.h"

#include "MantidAPI/FuncMinimizerFactory.h"
#include "MantidAPI/IFuncMinimizer.h"
Expand All @@ -29,6 +28,7 @@
#include "MantidKernel/Matrix.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/StartsWithValidator.h"

#include <boost/lexical_cast.hpp>
#include <gsl/gsl_errno.h>
Expand Down Expand Up @@ -110,7 +110,7 @@ namespace CurveFitting
auto it = std::find(minimizerOptions.begin(), minimizerOptions.end(), "Levenberg-Marquardt");
minimizerOptions.erase( it );
}
minimizerProperty->replaceValidator( Kernel::IValidator_sptr(new StartsWithValidator(minimizerOptions)) );
minimizerProperty->replaceValidator( Kernel::IValidator_sptr(new Kernel::StartsWithValidator(minimizerOptions)) );
}

void Fit::setFunction()
Expand Down Expand Up @@ -297,7 +297,7 @@ namespace CurveFitting
std::vector<std::string> minimizerOptions = API::FuncMinimizerFactory::Instance().getKeys();

declareProperty("Minimizer","Levenberg-Marquardt",
Kernel::IValidator_sptr(new StartsWithValidator(minimizerOptions)),
Kernel::IValidator_sptr(new Kernel::StartsWithValidator(minimizerOptions)),
"The minimizer method applied to do the fit, default is Levenberg-Marquardt");

std::vector<std::string> costFuncOptions = API::CostFunctionFactory::Instance().getKeys();
Expand Down
262 changes: 262 additions & 0 deletions Code/Mantid/Framework/CurveFitting/test/DampingMinimizerTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#ifndef CURVEFITTING_DAMPINGTEST_H_
#define CURVEFITTING_DAMPINGTEST_H_

#include <cxxtest/TestSuite.h>

#include "MantidCurveFitting/CostFuncLeastSquares.h"
#include "MantidCurveFitting/DampingMinimizer.h"
#include "MantidCurveFitting/UserFunction.h"
#include "MantidAPI/FunctionDomain1D.h"
#include "MantidAPI/FunctionValues.h"
#include "MantidCurveFitting/BoundaryConstraint.h"

#include <sstream>

using namespace Mantid;
using namespace Mantid::CurveFitting;
using namespace Mantid::API;

class DampingMinimizerTest : public CxxTest::TestSuite
{
public:

void test_Gaussian()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.setParameter("h",3.3);
dataMaker.setParameter("s",0.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
fun->setParameter("a",1.);
fun->setParameter("b",2.);
fun->setParameter("h",3.);
fun->setParameter("s",0.1);

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);

DampingMinimizer s;
s.initialize(costFun);
TS_ASSERT( s.existsProperty("Damping") );
double damping = s.getProperty("Damping");
TS_ASSERT_EQUALS( damping, 0.0 );

TS_ASSERT(s.minimize());
TS_ASSERT_DELTA(costFun->val(),0.0,0.0001);
TS_ASSERT_DELTA(fun->getParameter("a"),1.1,0.001);
TS_ASSERT_DELTA(fun->getParameter("b"),2.2,0.001);
TS_ASSERT_DELTA(fun->getParameter("h"),3.3,0.001);
TS_ASSERT_DELTA(fun->getParameter("s"),0.2,0.001);
TS_ASSERT_EQUALS(s.getError(),"success");
}

void test_Gaussian_with_damping()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.setParameter("h",3.3);
dataMaker.setParameter("s",0.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
fun->setParameter("a",1.);
fun->setParameter("b",2.);
fun->setParameter("h",3.);
fun->setParameter("s",0.1);

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);

DampingMinimizer s;
s.initialize(costFun);
s.setProperty( "Damping", 100.0 );
double damping = s.getProperty("Damping");
TS_ASSERT_EQUALS( damping, 100.0 );

TS_ASSERT(s.minimize());
TS_ASSERT_DELTA(costFun->val(),0.0,0.0002);
TS_ASSERT_DELTA(fun->getParameter("a"),1.0973,0.001);
TS_ASSERT_DELTA(fun->getParameter("b"),2.2200,0.001);
TS_ASSERT_DELTA(fun->getParameter("h"),3.2795,0.001);
TS_ASSERT_DELTA(fun->getParameter("s"),0.2014,0.001);
TS_ASSERT_EQUALS(s.getError(),"success");
}

void test_Gaussian_fixed()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.setParameter("h",3.3);
dataMaker.setParameter("s",0.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
fun->setParameter("a",1.);
fun->setParameter("b",2.);
fun->setParameter("h",3.);
fun->setParameter("s",0.1);
fun->fix(0);

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);
TS_ASSERT_EQUALS(costFun->nParams(),3);

DampingMinimizer s;
s.initialize(costFun);
TS_ASSERT(s.minimize());
TS_ASSERT_DELTA(costFun->val(),0.2,0.01);
TS_ASSERT_DELTA(fun->getParameter("a"),1.,0.000001);
TS_ASSERT_DELTA(fun->getParameter("b"),2.90,0.01);
TS_ASSERT_DELTA(fun->getParameter("h"),2.67,0.01);
TS_ASSERT_DELTA(fun->getParameter("s"),0.27,0.01);
TS_ASSERT_EQUALS(s.getError(),"success");
}


void test_Gaussian_tied()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.setParameter("h",3.3);
dataMaker.setParameter("s",0.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
fun->setParameter("a",1.);
fun->setParameter("b",2.);
fun->setParameter("h",3.);
fun->setParameter("s",0.1);
fun->tie("a","1");

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);
TS_ASSERT_EQUALS(costFun->nParams(),3);

DampingMinimizer s;
s.initialize(costFun);
TS_ASSERT(s.minimize());
TS_ASSERT_DELTA(costFun->val(),0.2,0.01);
TS_ASSERT_DELTA(fun->getParameter("a"),1.,0.000001);
TS_ASSERT_DELTA(fun->getParameter("b"),2.90,0.01);
TS_ASSERT_DELTA(fun->getParameter("h"),2.67,0.01);
TS_ASSERT_DELTA(fun->getParameter("s"),0.27,0.01);
TS_ASSERT_EQUALS(s.getError(),"success");
}

void test_Gaussian_tied_with_formula()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.setParameter("h",3.3);
dataMaker.setParameter("s",0.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b+h*exp(-s*x^2)");
fun->setParameter("a",1.);
fun->setParameter("b",2.);
fun->setParameter("h",3.);
fun->setParameter("s",0.1);
fun->tie("b","2*a+0.1");

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);
TS_ASSERT_EQUALS(costFun->nParams(),3);

DampingMinimizer s;
s.initialize(costFun);
TS_ASSERT(s.minimize());
TS_ASSERT_DELTA(costFun->val(),0.002,0.01);
double a = fun->getParameter("a");
TS_ASSERT_DELTA(a,1.0895,0.01);
TS_ASSERT_DELTA(fun->getParameter("b"),2*a+0.1,0.0001);
TS_ASSERT_DELTA(fun->getParameter("h"),3.23,0.01);
TS_ASSERT_DELTA(fun->getParameter("s"),0.207,0.001);
TS_ASSERT_EQUALS(s.getError(),"success");
}

void test_Linear_constrained()
{
API::FunctionDomain1D_sptr domain(new API::FunctionDomain1DVector(0.0,10.0,20));
API::FunctionValues mockData(*domain);
UserFunction dataMaker;
dataMaker.setAttributeValue("Formula","a*x+b");
dataMaker.setParameter("a",1.1);
dataMaker.setParameter("b",2.2);
dataMaker.function(*domain,mockData);

API::FunctionValues_sptr values(new API::FunctionValues(*domain));
values->setFitDataFromCalculated(mockData);
values->setFitWeights(1.0);

boost::shared_ptr<UserFunction> fun(new UserFunction);
fun->setAttributeValue("Formula","a*x+b");
fun->setParameter("a",1.);
fun->setParameter("b",2.);

BoundaryConstraint* constraint = new BoundaryConstraint(fun.get(),"a",0,0.5);

fun->addConstraint(constraint);

boost::shared_ptr<CostFuncLeastSquares> costFun(new CostFuncLeastSquares);
costFun->setFittingFunction(fun,domain,values);
TS_ASSERT_EQUALS(costFun->nParams(),2);

DampingMinimizer s;
s.initialize(costFun);
TS_ASSERT(s.minimize());

TS_ASSERT_DELTA( fun->getParameter("a"), 0.5, 0.1 );
TS_ASSERT_DELTA( fun->getParameter("b"), 5.0, 0.1 );
TS_ASSERT_EQUALS( s.getError(), "success" );
}

};

#endif /*CURVEFITTING_DAMPINGTEST_H_*/
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ set ( SRC_FILES
src/SignalChannel.cpp
src/SingletonHolder.cpp
src/SobolSequence.cpp
src/StartsWithValidator.cpp
src/Statistics.cpp
src/Strings.cpp
src/TestChannel.cpp
Expand Down Expand Up @@ -190,6 +191,7 @@ set ( INC_FILES
inc/MantidKernel/SignalChannel.h
inc/MantidKernel/SingletonHolder.h
inc/MantidKernel/SobolSequence.h
inc/MantidKernel/StartsWithValidator.h
inc/MantidKernel/Statistics.h
inc/MantidKernel/Strings.h
inc/MantidKernel/System.h
Expand Down Expand Up @@ -287,6 +289,7 @@ set ( TEST_FILES
RegexStringsTest.h
SignalChannelTest.h
SobolSequenceTest.h
StartsWithValidatorTest.h
StatisticsTest.h
StringsTest.h
TaskTest.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

namespace Mantid
{
namespace CurveFitting
namespace Kernel
{
/** StartsWithValidator is a validator that requires the value of a property to start with of one
/** StartsWithValidator is a validator that requires the value of a property to start with one
of the strings in a defined list of possibilities.
Copyright &copy; 2008-9 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
Expand All @@ -36,9 +36,14 @@ namespace CurveFitting
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
class StartsWithValidator : public Kernel::StringListValidator
class DLLExport StartsWithValidator : public Kernel::StringListValidator
{
public:
/**
* Default constructor.
* @param values :: A vector with the allowed values.
*/
StartsWithValidator():Kernel::StringListValidator(){}
/**
* Constructor.
* @param values :: A vector with the allowed values.
Expand All @@ -49,29 +54,18 @@ class StartsWithValidator : public Kernel::StringListValidator
* @param values :: A set with the allowed values.
*/
StartsWithValidator(const std::set<std::string>& values):Kernel::StringListValidator(values){}
/// Clone the validator
IValidator_sptr clone() const{ return boost::make_shared<StartsWithValidator>(*this); }
protected:
/** Checks if the string passed is in the list
/** Checks if the string passed starts with one from the list
* @param value :: The value to test
* @return "" if the value is on the list, or "The value does not start with any of the allowed values"
*/
std::string checkValidity(const std::string & value) const
{
for(auto it = m_allowedValues.begin(); it != m_allowedValues.end(); ++it )
{
if ( value.substr(0, it->size()) == *it )
{
return "";
}
}
if ( isEmpty(value) ) return "Select a value";
std::ostringstream os;
os << "The value \"" << value << "\" does not start with any of the allowed values";
return os.str();
}
std::string checkValidity(const std::string & value) const;

};

} // namespace CurveFitting
} // namespace Kernel
} // namespace Mantid

#endif /*MANTID_KERNEL_STARTSWITHVALIDATOR_H_*/

0 comments on commit 96240db

Please sign in to comment.