310 throw std::runtime_error(
"The fitting function has no parameters to fit. "
311 "Add at least one fitting parameter to the function, or use the "
312 "EvaluateFunction algorithm to calculate the function values.");
316 bool isDerivDefined =
true;
317 gsl_matrix *M =
nullptr;
321 const double xValuesTest = 0;
329 isDerivDefined =
false;
335 const int maxInterations =
getProperty(
"MaxIterations");
341 const size_t numberOfSpectra = localworkspace->getNumberHistograms();
343 if (histNumber >=
static_cast<int>(numberOfSpectra)) {
344 g_log.
warning(
"Invalid Workspace index given, using first Workspace");
349 Mantid::HistogramData::HistogramX
const &XValues = localworkspace->x(histNumber);
350 Mantid::HistogramData::HistogramY
const &YValues = localworkspace->y(histNumber);
351 Mantid::HistogramData::HistogramE
const &YErrors = localworkspace->e(histNumber);
358 startX = XValues.front();
363 endX = XValues.back();
372 if (startX < XValues.front()) {
373 g_log.
warning(
"StartX out of range! Set to start of frame.");
374 startX = XValues.front();
378 for (m_minX = 0; XValues[m_minX + 1] < startX; ++m_minX) {
383 if (endX >= XValues.back() || endX < startX) {
384 g_log.
warning(
"EndX out of range! Set to end of frame");
385 endX = XValues.back();
386 m_maxX =
static_cast<int>(YValues.size());
388 for (m_maxX = m_minX; XValues[m_maxX] < endX; ++m_maxX) {
403 throw std::runtime_error(
"All parameters of the fitting function are fixed, there is nothing to fit. "
404 "Unfix at least one parameter, or use the EvaluateFunction algorithm to "
405 "calculate the function values.");
408 l_data.
n = m_maxX - m_minX;
411 throw std::runtime_error(
"The data set is empty.");
413 if (l_data.
n < l_data.
p) {
414 g_log.
error(
"Number of data points less than number of parameters to be fitted.");
415 throw std::runtime_error(
"Number of data points less than number of parameters to be fitted.");
417 l_data.
X =
new double[l_data.
n];
424 const bool isHistogram = localworkspace->isHistogramData();
425 for (
unsigned int i = 0; i < l_data.
n; ++i) {
427 l_data.
X[i] = 0.5 * (XValues[m_minX + i] + XValues[m_minX + i + 1]);
429 l_data.
X[i] = XValues[m_minX + i];
432 l_data.
Y = &YValues[m_minX];
435 for (
unsigned int i = 0; i < l_data.
n; ++i) {
436 if (YErrors[m_minX + i] <= 0.0) {
439 l_data.
sigmaData[i] = YErrors[m_minX + i];
455 for (
size_t i = 0; i <
nParams(); i++) {
459 for (
size_t i = 0; i <
nParams(); i++) {
465 gsl_vector *initFuncArg;
466 initFuncArg = gsl_vector_alloc(l_data.
p);
468 for (
size_t i = 0, j = 0; i <
nParams(); i++) {
475 gsl_multimin_function gslSimplexContainer;
476 gslSimplexContainer.n = l_data.
p;
478 gslSimplexContainer.params = &l_data;
482 gsl_multifit_function_fdf f;
492 const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
493 gsl_multifit_fdfsolver *s =
nullptr;
494 if (isDerivDefined) {
495 s = gsl_multifit_fdfsolver_alloc(T, l_data.
n, l_data.
p);
496 gsl_multifit_fdfsolver_set(s, &f, initFuncArg);
501 const gsl_multimin_fminimizer_type *simplexType = gsl_multimin_fminimizer_nmsimplex;
502 gsl_multimin_fminimizer *simplexMinimizer =
nullptr;
503 gsl_vector *simplexStepSize =
nullptr;
504 if (!isDerivDefined) {
505 simplexMinimizer = gsl_multimin_fminimizer_alloc(simplexType, l_data.
p);
506 simplexStepSize = gsl_vector_alloc(l_data.
p);
507 gsl_vector_set_all(simplexStepSize,
509 gsl_multimin_fminimizer_set(simplexMinimizer, &gslSimplexContainer, initFuncArg, simplexStepSize);
516 double finalCostFuncVal;
517 auto dof =
static_cast<double>(l_data.
n - l_data.
p);
521 Progress prog(
this, 0.0, 1.0, maxInterations);
522 if (isDerivDefined) {
526 status = gsl_multifit_fdfsolver_iterate(s);
531 status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
533 }
while (status == GSL_CONTINUE && iter < maxInterations);
535 double chi = gsl_blas_dnrm2(s->f);
536 finalCostFuncVal = chi * chi / dof;
539 for (
size_t i = 0, j = 0; i <
nParams(); i++)
545 status = gsl_multimin_fminimizer_iterate(simplexMinimizer);
550 double size = gsl_multimin_fminimizer_size(simplexMinimizer);
551 status = gsl_multimin_test_size(size, 1e-2);
553 }
while (status == GSL_CONTINUE && iter < maxInterations);
555 finalCostFuncVal = simplexMinimizer->fval / dof;
567 std::string reportOfFit = gsl_strerror(status);
570 <<
"Status = " << reportOfFit <<
"\n"
571 <<
"Chi^2/DoF = " << finalCostFuncVal <<
"\n";
578 setProperty(
"OutputChi2overDoF", finalCostFuncVal);
583 if (!output.empty()) {
586 gsl_matrix *covar(
nullptr);
587 std::vector<double> standardDeviations;
588 std::vector<double> sdExtended;
589 if (isDerivDefined) {
590 covar = gsl_matrix_alloc(l_data.
p, l_data.
p);
591#if GSL_MAJOR_VERSION < 2
592 gsl_multifit_covar(s->J, 0.0, covar);
594 gsl_matrix *J = gsl_matrix_alloc(l_data.
n, l_data.
p);
595 gsl_multifit_fdfsolver_jac(s, J);
596 gsl_multifit_covar(J, 0.0, covar);
601 for (
size_t i = 0; i <
nParams(); i++) {
602 sdExtended.emplace_back(1.0);
604 sdExtended[i] = sqrt(gsl_matrix_get(covar, iPNotFixed, iPNotFixed));
609 for (
size_t i = 0; i <
nParams(); i++)
611 standardDeviations.emplace_back(sdExtended[i]);
615 "The name of the TableWorkspace in which to store the final "
616 "covariance matrix");
617 setPropertyValue(
"OutputNormalisedCovarianceMatrix", output +
"_NormalisedCovarianceMatrix");
621 m_covariance->addColumn(
"str",
"Name");
622 std::vector<std::string> paramThatAreFitted;
623 for (
size_t i = 0; i <
nParams(); i++) {
630 for (
size_t i = 0; i < l_data.
p; i++) {
633 row << paramThatAreFitted[i];
634 for (
size_t j = 0; j < l_data.
p; j++) {
638 row << 100.0 * gsl_matrix_get(covar, i, j) /
639 sqrt(gsl_matrix_get(covar, i, i) * gsl_matrix_get(covar, j, j));
644 setProperty(
"OutputNormalisedCovarianceMatrix", m_covariance);
649 "The name of the TableWorkspace in which to store the "
650 "final fit parameters");
652 "Name of the output Workspace holding resulting simlated spectrum");
660 m_result->addColumn(
"str",
"Name");
661 m_result->addColumn(
"double",
"Value");
663 m_result->addColumn(
"double",
"Error");
665 firstRow <<
"Chi^2/DoF" << finalCostFuncVal;
667 for (
size_t i = 0; i <
nParams(); i++) {
670 if (isDerivDefined && l_data.
active[i]) {
672 row << sdExtended[i];
680 Mantid::HistogramData::HistogramX
const &inputX = inputWorkspace->x(iSpec);
681 Mantid::HistogramData::HistogramY
const &inputY = inputWorkspace->y(iSpec);
683 int histN = isHistogram ? 1 : 0;
687 ws->getAxis(0)->unit() = inputWorkspace->getAxis(0)->unit();
689 for (
int i = 0; i < 3; i++)
690 ws->mutableX(i).assign(inputX.begin() + m_minX, inputX.begin() + m_maxX + histN);
692 ws->mutableY(0).assign(inputY.begin() + m_minX, inputY.begin() + m_maxX);
694 auto &
Y = ws->mutableY(1);
695 auto &E = ws->mutableY(2);
697 auto lOut =
new double[l_data.
n];
705 for (
unsigned int i = 0; i < l_data.
n; i++) {
707 E[i] = l_data.
Y[i] -
Y[i];
712 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(ws));
715 gsl_matrix_free(covar);
721 gsl_multifit_fdfsolver_free(s);
723 gsl_vector_free(simplexStepSize);
724 gsl_multimin_fminimizer_free(simplexMinimizer);
731 gsl_vector_free(initFuncArg);