Newer
Older
Roman Tolchenov
committed
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/IPeakFunction.h"
#include "MantidAPI/Jacobian.h"
Roman Tolchenov
committed
#include "MantidKernel/Exception.h"
Roman Tolchenov
committed
#include "MantidKernel/ConfigService.h"
Roman Tolchenov
committed
Roman Tolchenov
committed
#include <boost/lexical_cast.hpp>
Roman Tolchenov
committed
#include <cmath>
namespace Mantid
{
namespace API
{
/** A Jacobian for individual functions
*/
class PartialJacobian1: public Jacobian
{
Jacobian* m_J; ///< pointer to the overall Jacobian
int m_iY0; ///< offset in the overall Jacobian for a particular function
public:
/** Constructor
Janik Zikovsky
committed
* @param J :: A pointer to the overall Jacobian
* @param iY0 :: The data offset for a particular function
Roman Tolchenov
committed
*/
Janik Zikovsky
committed
PartialJacobian1(Jacobian* J,int iY0):m_J(J),m_iY0(iY0)
Roman Tolchenov
committed
{}
/**
* Overridden Jacobian::set(...).
Janik Zikovsky
committed
* @param iY :: The index of the data point
* @param iP :: The parameter index of an individual function.
* @param value :: The derivative value
Roman Tolchenov
committed
*/
Anders Markvardsen
committed
void set(size_t iY, size_t iP, double value)
Roman Tolchenov
committed
{
m_J->set(m_iY0 + iY,iP,value);
}
Roman Tolchenov
committed
/**
* Overridden Jacobian::get(...).
* @param iY :: The index of the data point
* @param iP :: The parameter index of an individual function.
*/
Anders Markvardsen
committed
double get(size_t iY, size_t iP)
Roman Tolchenov
committed
{
return m_J->get(m_iY0 + iY,iP);
}
Roman Tolchenov
committed
};
Roman Tolchenov
committed
/// Default value for the peak radius
Roman Tolchenov
committed
int IPeakFunction::s_peakRadius = 5;
Roman Tolchenov
committed
/**
* Constructor. Sets peak radius to the value of curvefitting.peakRadius property
*/
IPeakFunction::IPeakFunction()
{
int peakRadius;
if ( Kernel::ConfigService::Instance().getValue("curvefitting.peakRadius",peakRadius) )
{
setPeakRadius(peakRadius);
}
}
Roman Tolchenov
committed
/**
* General implementation of the method for all peaks. Limits the peak evaluation to
* a certain number of FWHMs around the peak centre. The outside points are set to 0.
* Calls functionLocal() to compute the actual values
Janik Zikovsky
committed
* @param out :: Output function values
* @param xValues :: X values for data points
* @param nData :: Number of data points
Roman Tolchenov
committed
*/
void IPeakFunction::function1D(double* out, const double* xValues, const size_t nData)const
Roman Tolchenov
committed
{
double c = this->centre();
double dx = fabs(s_peakRadius*this->fwhm());
Roman Tolchenov
committed
int i0 = -1;
int n = 0;
for(size_t i = 0; i < nData; ++i)
Roman Tolchenov
committed
{
if (fabs(xValues[i] - c) < dx)
{
Roman Tolchenov
committed
++n;
}
else
{
out[i] = 0.0;
Roman Tolchenov
committed
}
}
if (i0 < 0 || n == 0) return;
this->functionLocal(out+i0, xValues+i0, n);
Roman Tolchenov
committed
}
/**
* General implementation of the method for all peaks. Calculates derivatives only
* for a range of x values limited to a certain number of FWHM around the peak centre.
* For the points outside the range all derivatives are set to 0.
* Calls functionDerivLocal() to compute the actual values
Janik Zikovsky
committed
* @param out :: Derivatives
* @param xValues :: X values for data points
* @param nData :: Number of data points
Roman Tolchenov
committed
*/
void IPeakFunction::functionDeriv1D(Jacobian* out, const double* xValues, const size_t nData)
Roman Tolchenov
committed
{
double c = this->centre();
double dx = fabs(s_peakRadius*this->fwhm());
Roman Tolchenov
committed
int i0 = -1;
int n = 0;
for(size_t i = 0; i < nData; ++i)
Roman Tolchenov
committed
{
if (fabs(xValues[i] - c) < dx)
{
if (i0 < 0) i0 = static_cast<int>(i);
Roman Tolchenov
committed
++n;
}
else
{
for(size_t ip = 0; ip < this->nParams(); ++ip)
Roman Tolchenov
committed
{
out->set(i,ip, 0.0);
}
}
}
if (i0 < 0 || n == 0) return;
PartialJacobian1 J(out,i0);
this->functionDerivLocal(&J,xValues+i0,n);
}
void IPeakFunction::setPeakRadius(const int& r)
{
if (r > 0)
{
s_peakRadius = r;
Roman Tolchenov
committed
std::string setting = boost::lexical_cast<std::string>(r);
Kernel::ConfigService::Instance().setString("curvefitting.peakRadius",setting);
Roman Tolchenov
committed
}
}
} // namespace API
} // namespace Mantid