18#include <boost/math/distributions/chi_squared.hpp>
24constexpr double MAXCHISQUAREDIFFERENCE = 10.8276;
33 double chiSquared = 0.0;
34 double chiSquaredWeighted = 0.0;
37 chiSquaredWeighted, dof);
38 return chiSquaredWeighted - chi0;
63 std::vector<int> &freeParameters)
80 std::vector<double> originalParamValues(function->nParams());
81 for (
auto ip = 0u; ip < function->nParams(); ++ip) {
82 originalParamValues[ip] = function->getParameter(ip);
95 for (
auto ip = 0u; ip < function->nParams(); ++ip) {
96 function->setParameter(ip, originalParamValues[ip]);
111 base = std::make_shared<Functions::ChebfunBase>(10, lBound, rBound, 1e-4);
112 P = base->fit(*
this);
123 double diff0 = (*this)(0);
124 double bound = shift;
125 bool canDecrease =
true;
126 for (
size_t i = 0; i < 100; ++i) {
127 double diff = (*this)(bound);
129 bool isIncreasing =
fabs(bound) >
fabs(bound0) && diff > diff0;
143 if (diff > MAXCHISQUAREDIFFERENCE - 1) {
144 if (diff < MAXCHISQUAREDIFFERENCE) {
179const std::string ProfileChiSquared1D::name()
const {
return "ProfileChiSquared1D"; }
181int ProfileChiSquared1D::version()
const {
return 1; }
183const std::string ProfileChiSquared1D::summary()
const {
184 return "Profiles chi squared about its minimum to obtain parameter errors "
185 "for the input function.";
188void ProfileChiSquared1D::initConcrete() {
declareProperty(
"Output",
"",
"A base name for output workspaces."); }
190void ProfileChiSquared1D::execConcrete() {
200 boost::math::chi_squared chi2Dist(1);
201 std::array<double, 3> sigmas = {1, 2, 3};
202 std::array<double, 3> qvalues;
203 for (
size_t i = 0; i < sigmas.size(); i++) {
204 double pvalue = std::erf(sigmas[i] / sqrt(2));
206 qvalues[i] = boost::math::quantile(chi2Dist, pvalue);
210 std::vector<int> freeParameters;
211 for (
size_t ip = 0; ip < nParams; ++ip) {
213 freeParameters.push_back(
static_cast<int>(ip));
217 if (freeParameters.size() < 2) {
218 throw std::invalid_argument(
"Function must have 2 or more free parameters");
223 int workspaceIndex =
getProperty(
"WorkspaceIndex");
225 if (baseName.empty()) {
226 baseName =
"ProfileChiSquared1D";
229 "The name of the TableWorkspace in which to store the "
230 "pdfs of fit parameters");
236 auto nameColumn = errorsTable->addColumn(
"str",
"Parameter");
237 auto valueColumn = errorsTable->addColumn(
"double",
"Value");
238 auto minValueColumn = errorsTable->addColumn(
"double",
"Value at Min");
239 errorsTable->addColumn(
"double",
"Left Error (1-sigma)");
240 errorsTable->addColumn(
"double",
"Right Error (1-sigma)");
241 errorsTable->addColumn(
"double",
"Left Error (2-sigma)");
242 errorsTable->addColumn(
"double",
"Right Error (2-sigma )");
243 errorsTable->addColumn(
"double",
"Left Error (3-sigma)");
244 errorsTable->addColumn(
"double",
"Right Error (3-sigma )");
245 auto quadraticErrColumn = errorsTable->addColumn(
"double",
"Quadratic Error (1-sigma)");
246 errorsTable->setRowCount(freeParameters.size());
249 "The name of the TableWorkspace in which to store the "
250 "values and errors of fit parameters");
255 double chiSquared = 0.0;
256 double chiSquaredWeighted = 0.0;
263 double chi0 = chiSquaredWeighted;
267 pdfTable->setRowCount(
n);
268 const double fac = 1e-4;
270 for (
auto p = 0u; p < freeParameters.size(); ++p) {
272 int ip = freeParameters[p];
275 nameColumn->read(row, parName);
277 auto col1 = pdfTable->addColumn(
"double", parName);
278 col1->setPlotType(1);
280 auto col2 = pdfTable->addColumn(
"double", parName +
"_chi2");
281 col2->setPlotType(2);
283 auto col3 = pdfTable->addColumn(
"double", parName +
"_pdf");
284 col3->setPlotType(2);
287 double shift =
fabs(par0 * fac);
293 ChiSlice slice(
m_function, ip, inputws, workspaceIndex, *domain, *values, chi0, freeParameters);
307 std::vector<double> P, A;
308 auto base = slice.
makeApprox(lBound, rBound, P, A);
311 double dp = (rBound - lBound) /
static_cast<double>(
n);
312 for (
size_t i = 0; i <
n; ++i) {
313 double par = lBound + dp *
static_cast<double>(i);
314 double chi = base->eval(par, P);
315 col1->fromDouble(i, par0 + par);
316 col2->fromDouble(i, chi);
320 std::vector<double> AD;
323 base->derivative(A, AD);
325 std::vector<double> minima = base->roots(AD);
326 if (minima.empty()) {
327 minima.emplace_back(par0);
333 double chiMin = std::numeric_limits<double>::max();
334 double parMin = par0;
335 for (
double minimum : minima) {
336 double value = base->eval(minimum, P);
337 if (
value < chiMin) {
344 valueColumn->fromDouble(row, par0);
345 minValueColumn->fromDouble(row, par0 + parMin);
346 for (
size_t i = 0; i < qvalues.size(); i++) {
348 errorsTable->getColumn(3 + 2 * i)->fromDouble(row, rootsMin - parMin);
349 errorsTable->getColumn(4 + 2 * i)->fromDouble(row, rootsMax - parMin);
353 for (
size_t i = 0; i <
n; ++i) {
354 double chi = col2->toDouble(i);
355 col3->fromDouble(i, exp(-chi + chiMin));
364 for (
size_t i = 0; i < freeParameters.size(); ++i) {
365 int ip = freeParameters[i];
366 quadraticErrColumn->fromDouble(i, sqrt(V.
get(ip, ip)));
381 H.resize(nParams, nParams);
382 for (
size_t i = 0; i < nParams; ++i) {
383 for (
size_t j = i; j < nParams; ++j) {
385 for (
size_t k = 0; k < values->size(); ++k) {
386 double w = values->getFitWeight(k);
387 h += J.
get(k, i) * J.
get(k, j) * w * w;
402void ProfileChiSquared1D::unfixParameters() {
403 for (
size_t i = 0; i <
m_function->nParams(); ++i) {
412void ProfileChiSquared1D::refixParameters() {
420 std::vector<double> &coeffs,
double qvalue,
421 double rBound,
double lBound)
const {
426 auto Aold = coeffs[0];
428 coeffs[0] = Aold - qvalue;
429 std::vector<double> roots = approximation->roots(coeffs);
430 std::sort(roots.begin(), roots.end());
436 }
else if (roots.size() == 1) {
438 if (roots.front() < 0) {
439 roots.emplace_back(rBound);
441 roots.insert(roots.begin(), lBound);
443 }
else if (roots.size() > 2) {
445 auto smallest = roots.front();
446 auto biggest = roots.back();
452 return {roots[0], roots[1]};
#define DECLARE_ALGORITHM(classname)
double value
The value of the point.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
Base class that represents the domain of a function.
A class to store values calculated by a function.
This is an interface to a fitting function - a semi-abstarct class.
A property class for workspaces.
static void calcChiSquared(const API::IFunction &fun, size_t nParams, const API::FunctionDomain &domain, API::FunctionValues &values, double &chiSquared, double &chiSquaredWeighted, double &dof)
Caclculate the chi squared, weighted chi squared and the number of degrees of freedom.
Helper class to calculate the chi squared along a direction in the parameter space.
std::vector< int > m_freeParameters
int m_fixedParameterIndex
IFunction_sptr m_function
Functions::ChebfunBase_sptr makeApprox(double lBound, double rBound, std::vector< double > &P, std::vector< double > &A)
Make an approximation for this slice on an interval.
API::FunctionValues & m_values
The values.
MatrixWorkspace_sptr m_ws
ChiSlice(IFunction_sptr inputFunction, int fixedParameterIndex, API::MatrixWorkspace_sptr inputWS, int workspaceIndex, const API::FunctionDomain &domain, API::FunctionValues &values, double chi0, std::vector< int > &freeParameters)
Constructor.
double findBound(double shift)
Fiind a displacement in the parameter space from the initial point to a point where the PDF drops sig...
const API::FunctionDomain & m_domain
The domain.
double m_chi0
The chi squared at the minimum.
double operator()(double p)
Calculate the value of chi squared along the chosen direction at a distance from the minimum point.
EigenMatrix getCovarianceMatrix()
void unfixParameters()
Temporary unfix any fixed parameters.
std::tuple< double, double > getChiSquaredRoots(const Functions::ChebfunBase_sptr &approximation, std::vector< double > &coeffs, double qvalue, double rBound, double lBound) const
void refixParameters()
Restore the "fixed" status of previously unfixed paramters.
std::vector< size_t > m_fixedParameters
Cache indices of fixed parameters.
Two implementations of Jacobian.
double get(size_t iY, size_t iP) override
overwrite base method
A wrapper around Eigen::Matrix.
double get(size_t i, size_t j) const
Get an element.
void invert()
Invert this matrix.
static std::shared_ptr< ChebfunBase > bestFitAnyTolerance(double start, double end, FunctionType f, std::vector< double > &p, std::vector< double > &a, double maxA=0.0, double tolerance=0.0, size_t maxSize=0)
Find best fit with highest possible tolerance (to be used with noisy data).
A base class for fitting algorithms.
std::shared_ptr< API::IDomainCreator > m_domainCreator
Pointer to a domain creator.
std::shared_ptr< API::IFunction > m_function
Pointer to the fitting function.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
Manage the lifetime of a class intended to be a singleton.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< FunctionValues > FunctionValues_sptr
typedef for a shared pointer
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
std::shared_ptr< FunctionDomain > FunctionDomain_sptr
typedef for a shared pointer
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< ChebfunBase > ChebfunBase_sptr
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
@ Output
An output workspace.