Commit 0c816246 authored by Roman Tolchenov's avatar Roman Tolchenov
Browse files

Fixing warnings in CurveFitting. Re #6485.

parent c906fa7b
......@@ -19,9 +19,9 @@ namespace API
Composite functions do not have their own parameters, they use parameters of the member functions.
Functions are added to a composite functions with addFunction method and can be retrieved with
getFinction(i) method. Function indices are defined by the order they are added. Parameter names
are formed from the member function's index and its parameter name: f<index>.\<name\>. For example,
are formed from the member function's index and its parameter name: f[index].[name]. For example,
name "f0.Sigma" would be given to the "Sigma" parameter of a Gaussian added first to the composite
function. If a member function is a composite function itself the same principle applies: 'f<index>.'
function. If a member function is a composite function itself the same principle applies: 'f[index].'
is prepended to a name, e.g. "f0.f1.Sigma".
The default implementation expects its member to use the same type of FunctionDomain. The domain
......@@ -68,8 +68,6 @@ public:
void setWorkspace(boost::shared_ptr<const Workspace> ws);
/// Function you want to fit to.
/// @param domain :: The input domain over which the function is to be calculated
/// @param values :: A storage object for the calculated values
virtual void function(const FunctionDomain& domain, FunctionValues& values)const;
/// Derivatives of function with respect to active parameters
virtual void functionDeriv(const FunctionDomain& domain, Jacobian& jacobian);
......
......@@ -63,19 +63,9 @@ namespace API
class MANTID_API_DLL ConstraintFactoryImpl : public Kernel::DynamicFactory<IConstraint>
{
public:
/**Creates an instance of a Constraint
* @param fun :: The function
* @param input :: The creation expression
* @param isDefault :: Flag to mark as default the value of an object associated with this reference: a tie or a constraint. (default=false)
* @return A pointer to the created Constraint
*/
/// Creates an instance of a Constraint
IConstraint* createInitialized(IFunction* fun, const std::string& input, bool isDefault = false) const;
/**Creates an instance of a Constraint
* @param fun :: The function
* @param expr :: The creation expression
* @param isDefault :: Flag to mark as default the value of an object associated with this reference: a tie or a constraint. (default=false)
* @return A pointer to the created Constraint
*/
/// Creates an instance of a Constraint
IConstraint* createInitialized(IFunction* fun, const Expression& expr, bool isDefault = false) const;
private:
......
......@@ -77,51 +77,32 @@ public:
/// @param i :: An index of a value 0 <= i < size()
double operator[](size_t i) const {return m_calculated[i];}
/// Add a number to a calculated value.
/// @param i :: An index of a value 0 <= i < size()
/// @param value :: The value to add at the index given
/// @param i :: An index of a value 0 <= i < size() to update.
/// @param value :: A value to add
void addToCalculated(size_t i, double value) {m_calculated[i] += value;}
/// Add other calculated values
FunctionValues& operator+=(const FunctionValues& values)
{
if (size() != values.size())
{
throw std::runtime_error("Cannot add values: sizes do not match");
}
values.add(getPointerToCalculated(0));
return *this;
}
FunctionValues& operator+=(const FunctionValues& values);
/// Multiply by other calculated values
FunctionValues& operator*=(const FunctionValues& values)
{
if (size() != values.size())
{
throw std::runtime_error("Cannot multiply values: sizes do not match");
}
values.multiply(getPointerToCalculated(0));
return *this;
}
/// Add other calculated values to these values starting with i.
void addToCalculated(size_t i, const FunctionValues& values)
{
if (i + size() < values.size())
{
throw std::runtime_error("Cannot add values: sizes do not match");
}
values.add(getPointerToCalculated(i));
}
/// set a fitting data value
FunctionValues& operator*=(const FunctionValues& values);
/// Add other calculated values with offset
void addToCalculated(size_t start, const FunctionValues& values);
/// Set a fitting data value
void setFitData(size_t i,double value);
/// Set all fitting data values
void setFitData(const std::vector<double>& values);
/// get a fitting data value
/// Get a fitting data value
double getFitData(size_t i) const;
/// set a fitting weight
/// Set a fitting weight
void setFitWeight(size_t i,double value);
/// Set all fitting weights.
void setFitWeights(const std::vector<double>& values);
/// Set all fitting weights to a number.
void setFitWeights(const double& value);
/// get a fitting weight
/// Get a fitting weight
double getFitWeight(size_t i) const;
/// Set all calculated values by copying them from another FunctionValues instance.
void setFitDataFromCalculated(const FunctionValues& values);
protected:
/// Copy calculated values to a buffer
......
......@@ -66,7 +66,7 @@ namespace Mantid
/// Toggle output of either just composite or composite + members
void separateCompositeMembersInOutput(const bool value);
/// declare properties that specify the dataset within the workspace to fit to.
/// Declare properties that specify the dataset within the workspace to fit to.
/// @param suffix :: A suffix to give to all new properties.
/// @param addProp :: If false don't actually declare new properties but do other stuff if needed
virtual void declareDatasetProperties(const std::string& suffix = "",bool addProp = true)
......@@ -84,13 +84,11 @@ namespace Mantid
boost::shared_ptr<API::IFunctionValues>& values,
size_t i0 = 0) = 0;
/**
* Create an output workspace filled with data simulated with the fitting function.
* @param baseName :: A prefix for the name of the output workspace
* @param function :: The function that will provide the calculated values
* @param domain :: The input domain over which the function is calculated
* @param values :: A result holder for results on the domain
*/
/// Create an output workspace filled with data simulated with the fitting function.
/// @param baseName :: Specifies the name of the output workspace
/// @param function :: A pointer to the fitting function
/// @param domain :: The domain containing x-values for the function
/// @param values :: A FunctionValues instance containing the fitting data
virtual void createOutputWorkspace(
const std::string& baseName,
API::IFunction_sptr function,
......@@ -99,6 +97,7 @@ namespace Mantid
{UNUSED_ARG(baseName);UNUSED_ARG(function);UNUSED_ARG(domain);UNUSED_ARG(values);}
/// Initialize the function
/// @param function :: A function to initialize.
virtual void initFunction(API::IFunction_sptr function);
/// Return the size of the domain to be created.
......
......@@ -133,7 +133,8 @@ void CompositeFunction::setWorkspace(boost::shared_ptr<const Workspace> ws)
}
/** Function you want to fit to.
* @param domain :: The buffer for writing the calculated values. Must be big enough to accept dataSize() values
* @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
{
......
......@@ -23,6 +23,13 @@ namespace Mantid
{
}
/**Creates an instance of a Constraint initialized using an expression
* @param fun :: The function
* @param input :: The creation expression, format depends on the constraint implementation. For BoundaryConstraint
* it is an inequality defining the boundaries for a parameter, eg: 0 < paramName < 1, paramName > 0, etc.
* @param isDefault :: Is this initialization a default one?
* @return A pointer to the created Constraint
*/
IConstraint* ConstraintFactoryImpl::createInitialized(IFunction* fun, const std::string& input, bool isDefault) const
{
Expression expr;
......@@ -30,6 +37,12 @@ namespace Mantid
return createInitialized(fun,expr,isDefault);
}
/** An overloaded method using Expression.
* @param fun :: The function
* @param expr :: A parsed initialization Expression.
* @param isDefault :: Is this initialization a default one?
* @return A pointer to the created Constraint
*/
IConstraint* ConstraintFactoryImpl::createInitialized(IFunction* fun, const Expression& expr, bool isDefault) const
{
IConstraint* c = 0;
......
......@@ -118,10 +118,56 @@ namespace API
std::transform(m_calculated.begin(),m_calculated.end(),to,to,std::multiplies<double>());
}
/**
* Add other calculated values to this.
* @param values :: An instance of FunctionValues to be added to this. Must have the same size to this.
* @return A reference to this values.
*/
FunctionValues& FunctionValues::operator+=(const FunctionValues& values)
{
if (size() != values.size())
{
throw std::runtime_error("Cannot add values: sizes do not match");
}
values.add(getPointerToCalculated(0));
return *this;
}
/**
* Multiply by other calculated values.
* @param values :: An instance of FunctionValues to multiply to this. Must have the same size to this.
* @return A reference to this values.
*/
FunctionValues& FunctionValues::operator*=(const FunctionValues& values)
{
if (size() != values.size())
{
throw std::runtime_error("Cannot multiply values: sizes do not match");
}
values.multiply(getPointerToCalculated(0));
return *this;
}
/**
* Add other calculated values to these values starting from some index.
* @param start :: A starting index for addition
* @param values :: An instance of FunctionValues to be added to this. The size mustn't exceed the number of
* values in this from start to the end.
* @return A reference to this values.
*/
void FunctionValues::addToCalculated(size_t start, const FunctionValues& values)
{
if (start + size() < values.size())
{
throw std::runtime_error("Cannot add values: sizes do not match");
}
values.add(getPointerToCalculated(start));
}
/**
* Set a fitting data value.
* @param i :: Index
* @param value :: Value
* @param i :: A value index
* @param value :: A new value to set.
*/
void FunctionValues::setFitData(size_t i,double value)
{
......@@ -133,8 +179,8 @@ namespace API
}
/**
* Set fitting data values.
* @param values :: Values for fitting
* Set all fitting data values.
* @param values :: A vector of values for fitting. Must have the same size as this.
*/
void FunctionValues::setFitData(const std::vector<double>& values)
{
......@@ -147,7 +193,7 @@ namespace API
/**
* Get a fitting data value
* @param i :: Index
* @param i :: A value index
*/
double FunctionValues::getFitData(size_t i) const
{
......@@ -160,8 +206,8 @@ namespace API
/**
* Set a fitting weight
* @param i :: Index
* @param value :: Value
* @param i :: A value index
* @param value :: A new value for the weight.
*/
void FunctionValues::setFitWeight(size_t i,double value)
{
......@@ -173,8 +219,8 @@ namespace API
}
/**
* Set fitting data values.
* @param values :: Values for fitting
* Set all fitting weights.
* @param values :: A vector of fitting weights. Must have the same size as this.
*/
void FunctionValues::setFitWeights(const std::vector<double>& values)
{
......@@ -197,7 +243,7 @@ namespace API
/**
* Get a fitting weight.
* @param i :: Index
* @param i :: A value index.
*/
double FunctionValues::getFitWeight(size_t i) const
{
......@@ -210,6 +256,7 @@ namespace API
/**
* Set fitting data copied from other FunctionValues' calculated values.
* @param values :: An instance of FunctionValues to copy the data from.
*/
void FunctionValues::setFitDataFromCalculated(const FunctionValues& values)
{
......
......@@ -35,9 +35,8 @@ namespace Mantid
* <LI> SScol -The variance of the column values in the peak for this time slice </LI>
* <LI> SSrow - The variance of the row values in the peak for this time slice </LI>
* <LI> SSrc - The covariance of the row and column values in the peak for this time slice </LI>
* </UL><P>
*/
/** There is one attribute, This must be specified.
* </UL>
* There is one attribute, This must be specified.
* <UL>
* <LI> CalcVariances - <UL>
* If true,calculates SScol, SSrow, and SSrc from the experimental data
......@@ -45,8 +44,7 @@ namespace Mantid
* If false, the parameters SScol, SSrow, and SSrc will be fit, unless
* tied. </UL> </LI>
* </UL>
*/
/**
*
* This is a bivariate function. The workspace must have three histograms of equal length.
* Histogram 0: Contains the experimental values for each x and y, along with their errors.
* Histogram 1: Contains the corresponding x value for the data in Histogram 0
......@@ -54,8 +52,7 @@ namespace Mantid
*
* @author Ruth Mikkelson, SNS ORNL
* @date 11/4/2011
*/
/**
*
Copyright &copy; 2011-12 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
This file is part of Mantid.
......
......@@ -258,10 +258,10 @@ namespace
/**
* Create an output workspace with the calculated values.
* @param basename :: specifies the name of the output workspace
* @function :: pointer to the fitting function
* @param domain :: The domain
* @param ivalues :: The values
* @param baseName :: Specifies the name of the output workspace
* @param function :: A Pointer to the fitting function
* @param domain :: The domain containing x-values for the function
* @param ivalues :: A API::FunctionValues instance containing the fitting data
*/
void FitMW::createOutputWorkspace(
const std::string& baseName,
......
......@@ -580,7 +580,12 @@ namespace CurveFitting
* 4. Use X0, I and S calculated by Gaussian, then use simulated annealing on A and B;
*
* Arguments
* @param chi2 : (output) chi square of the fit result
* @param peak :: A peak function.
* @param backgroundfunction :: A background function
* @param peakleftbound :: peak left bound
* @param peakrightbound :: peak right bound
* @param rightpeakparammap :: peakrightbound
* @param finalchi2 :: (output) chi square of the fit result
*
* Arguments:
* 1. leftdev, rightdev: search range for the peak from the estimatio (theoretical)
......@@ -1194,8 +1199,12 @@ namespace CurveFitting
//----------------------------------------------------------------------------------------------
/** Fit peak with trustful peak parameters
* @param leftbound: left boundary of the peak for fitting
* @param rightbound: right boundary of the peak for fitting
* @param peak :: A peak BackToBackExponential function
* @param backgroundfunction :: A background function
* @param leftbound :: left boundary of the peak for fitting
* @param rightbound :: right boundary of the peak for fitting
* @param chi2 :: The output chi squared
* @param annhilatedpeak :: (output) annhilatedpeak
*/
bool FitPowderDiffPeaks2::fitSinglePeakConfident(BackToBackExponential_sptr peak,
BackgroundFunction_sptr backgroundfunction,
......@@ -1441,8 +1450,10 @@ namespace CurveFitting
*
* Assumption: all peaks' parameters on centre and FWHM are close to the true value
*
* @param ileftpeak: index of the left most peak in the peak groups;
* @param irightpeak: index of the right most peak in the peak groups;
* @param ileftpeak :: index of the left most peak in the peak groups;
* @param irightpeak :: index of the right most peak in the peak groups;
* @param peakleftboundary :: left boundary of the peak for fitting (output)
* @param peakrightboundary :: right boundary of the peak for fitting (output)
*/
void FitPowderDiffPeaks2::calculatePeakFitBoundary(size_t ileftpeak, size_t irightpeak,
double& peakleftboundary, double& peakrightboundary)
......@@ -1495,7 +1506,8 @@ namespace CurveFitting
* 1. Peak parameters are set up to the peak function
* 2. Background is removed
*
* @param tof_h: Estimated/guessed center of the peak
* @param dataws :: The data workspace
* @param peakfunction :: An instance of the BackToBackExponential peak function
* @param guessedfwhm: Guessed fwhm in order to constain the peak. If negative, then no constraint
*/
std::pair<bool, double> FitPowderDiffPeaks2::doFitPeak(Workspace2D_sptr dataws,BackToBackExponential_sptr peakfunction,
......@@ -1638,10 +1650,12 @@ namespace CurveFitting
//----------------------------------------------------------------------------
/** Fit 1 peak by 1 minimizer of 1 call of minimzer (simple version)
* @param dataws
* @param workspaceindex
* @param minimzer
* @param iteration
* @param dataws :: A data aworkspace
* @param workspaceindex :: A histogram index
* @param peakfunction :: An instance of the BackToBackExponential function
* @param minimzername :: A name of the minimizer to use
* @param maxiteration :: A maximum number of iterations
* @param chi2 :: The chi squared value (output)
*
* Return
* 1. fit success?
......@@ -1779,6 +1793,13 @@ namespace CurveFitting
//----------------------------------------------------------------------------------------------
/** Fit 1 peak by using a sequential of minimizer
* @param dataws :: A data aworkspace
* @param workspaceindex :: A histogram index
* @param peakfunction :: An instance of the BackToBackExponential function
* @param minimzernames :: A vector of the minimizer names
* @param maxiterations :: A vector if maximum numbers of iterations
* @param dampfactors :: A vector of damping factors
* @param chi2 :: The chi squared value (output)
*/
bool FitPowderDiffPeaks2::doFit1PeakSequential(Workspace2D_sptr dataws, size_t workspaceindex,
BackToBackExponential_sptr peakfunction,
......@@ -1935,6 +1956,8 @@ namespace CurveFitting
//----------------------------------------------------------------------------------------------
/** Fit peaks with confidence in fwhm and etc.
* @param peaks :: A vector of instances of BackToBackExponential
* @param backgroundfunction :: An instance of BackgroundFunction
* @param gfwhm : guessed fwhm. If negative, then use the input value
*/
bool FitPowderDiffPeaks2::fitOverlappedPeaks(vector<BackToBackExponential_sptr> peaks,
......@@ -2143,6 +2166,7 @@ namespace CurveFitting
/** Use Le Bail method to estimate and set the peak heights
* @param dataws: workspace containing the background-removed data
* @param wsindex: workspace index of the data without background
* @param peaks :: A vector of instances of BackToBackExponential function
*/
void FitPowderDiffPeaks2::estimatePeakHeightsLeBail(Workspace2D_sptr dataws, size_t wsindex,
vector<BackToBackExponential_sptr> peaks)
......@@ -2850,7 +2874,11 @@ namespace CurveFitting
/** Generate a peak
*
* @param hklmap: a map containing one (HKL) entry
* @param parammap :: a map of parameters
* @param bk2bk2braggmap :: bk2bk2braggmap
* @param good :: (output) good
* @param hkl : (output) (HKL) of the peak generated.
* @param d_h :: (output) d_h
* @return : BackToBackExponential peak
*/
BackToBackExponential_sptr FitPowderDiffPeaks2::genPeak(map<string, int> hklmap, map<string, double> parammap,
......@@ -3340,6 +3368,11 @@ namespace CurveFitting
* (2) Peak is inside
* Algorithm: From the top. Get the maximum value. Calculate the half maximum value. Find the range of X
* @param dataws: data workspace containing peak data
* @param wsindex :: index of a histogram
* @param centre :: (output) peak centre
* @param height :: (output) peak height
* @param fwhm :: (output) peak FWHM
* @param errmsg :: (output) error message
*/
bool observePeakParameters(Workspace2D_sptr dataws, size_t wsindex, double& centre, double& height, double& fwhm,
string& errmsg)
......
/*WIKI*
This algorithm fits data in a [[Workspace]] with a function. The function and the initial values for its parameters are set with the Function property. The function must be compatible with the workspace.
Using the Minimizer property, Fit can be set to use different algorithms to perform the minimization. By default if the function's derivatives can be evaluated then Fit uses the GSL Levenberg-Marquardt minimizer. If the function's derivatives cannot be evaluated the GSL Simplex minimizer is used. Also, if one minimizer fails, for example the Levenberg-Marquardt minimizer, Fit may try its luck with a different minimizer. If this happens the user is notified about this and the Minimizer property is updated accordingly.
===Output===
Setting the Output property defines the names of the output workspaces. One of them is a [[TableWorkspace]] with the fitted parameter values. If the function's derivatives can be evaluated an additional TableWorkspace is returned containing correlation coefficients in %.
*WIKI*/
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidCurveFitting/GenericFit.h"
//#include "MantidCurveFitting/BoundaryConstraint.h"
#include "MantidCurveFitting/SimplexMinimizer.h"
#include "MantidAPI/FunctionProperty.h"
#include "MantidAPI/CompositeFunction.h"
#include "MantidAPI/IPeakFunction.h"
#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/TextAxis.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/Exception.h"
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <numeric>
#include <cmath>
#include <iomanip>
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/ListValidator.h"
namespace Mantid
{
namespace CurveFitting
{
// Register the class into the algorithm factory
DECLARE_ALGORITHM(GenericFit)
/// Sets documentation strings for this algorithm
void GenericFit::initDocs()
{
this->setWikiSummary("Fits a function to data in a Workspace ");
this->setOptionalMessage("Fits a function to data in a Workspace");
}
using namespace Kernel;
using API::WorkspaceProperty;
using API::Workspace;
using API::Axis;
using API::MatrixWorkspace;
using API::Algorithm;
using API::Progress;
using API::Jacobian;
///Destructor
GenericFit::~GenericFit()
{
//if (m_function) delete m_function;
}
/** Initialisation method
*/
void GenericFit::init()
{
declareProperty(new WorkspaceProperty<Workspace>("InputWorkspace","",Direction::Input), "Name of the input Workspace");
declareProperty("Input","","Workspace slicing parameters. Must be consistent with the Function type (see FitFunction::setWorkspace).");
declareProperty(new API::FunctionProperty("Function"));
auto mustBePositive = boost::make_shared<BoundedValidator<int> >();
mustBePositive->setLower(0);
declareProperty("MaxIterations", 500, mustBePositive,
"Stop after this number of iterations if a good fit is not found" );
declareProperty("OutputStatus","", Direction::Output);
declareProperty("OutputChi2overDoF",0.0, Direction::Output);
// Disable default gsl error handler (which is to call abort!)
gsl_set_error_handler_off();
declareProperty("Output","","If not empty OutputParameters TableWorksace and OutputWorkspace will be created.");
std::vector<std::string> minimizerOptions = FuncMinimizerFactory::Instance().getKeys();
declareProperty("Minimizer","Levenberg-Marquardt",boost::make_shared<StringListValidator>(minimizerOptions),
"The minimizer method applied to do the fit, default is Levenberg-Marquardt", Direction::InOut);
std::vector<std::string> costFuncOptions = API::CostFunctionFactory::Instance().getKeys();
declareProperty("CostFunction","Least squares",boost::make_shared<StringListValidator>(costFuncOptions),
"The cost function to be used for the fit, default is Least squares", Direction::InOut);
}
/** Executes the algorithm
*
* @throw runtime_error Thrown if algorithm cannot execute
*/
void GenericFit::exec()
{
// Try to retrieve optional properties
const int maxInterations = getProperty("MaxIterations");
Progress prog(this,0.0,1.0,maxInterations?maxInterations:1);
//std::string funIni = getProperty("Function");
//m_function.reset( API::FunctionFactory::Instance().createInitialized(funIni) );
m_function = getProperty("Function");
if (m_function.get() == NULL)
{
throw std::runtime_error("Function was not set.");
}
prog.report("Setting workspace");
API::Workspace_sptr ws = getProperty("InputWorkspace");
std::string input = getProperty("Input");
m_function->setWorkspace(ws,input,true);
prog.report("Setting minimizer");
// force initial parameters to satisfy constraints of function
m_function->setParametersToSatisfyConstraints();
// check if derivative defined in derived class
bool isDerivDefined = true;
try
</