/** Calls Gaussian1D as a child algorithm to fit the offset peak in a spectrum * * @param s :: The Workspace Index to fit * @param isAbsolbute :: Whether to calculate an absolute offset * @return The calculated offset value */ double GetDetectorOffsets::fitSpectra(const int64_t s, bool isAbsolbute) { // Find point of peak centre const auto &yValues = inputW->y(s); auto it = std::max_element(yValues.cbegin(), yValues.cend()); const double peakHeight = *it; const double peakLoc = inputW->x(s)[it - yValues.begin()]; // Return if peak of Cross Correlation is nan (Happens when spectra is zero) // Pixel with large offset will be masked if (std::isnan(peakHeight)) return (1000.); IAlgorithm_sptr fit_alg; try { // set the ChildAlgorithm no to log as this will be run once per spectra fit_alg = createChildAlgorithm("Fit", -1, -1, false); } catch (Exception::NotFoundError &) { g_log.error("Can't locate Fit algorithm"); throw; } auto fun = createFunction(peakHeight, peakLoc); fit_alg->setProperty("Function", fun); fit_alg->setProperty("InputWorkspace", inputW); fit_alg->setProperty<int>( "WorkspaceIndex", static_cast<int>(s)); // TODO what is the right thing to do here? fit_alg->setProperty("StartX", m_Xmin); fit_alg->setProperty("EndX", m_Xmax); fit_alg->setProperty("MaxIterations", 100); IFunction_sptr fun_ptr = createFunction(peakHeight, peakLoc); fit_alg->setProperty("Function", fun_ptr); fit_alg->executeAsChildAlg(); std::string fitStatus = fit_alg->getProperty("OutputStatus"); // Pixel with large offset will be masked if (fitStatus != "success") return (1000.); // std::vector<double> params = fit_alg->getProperty("Parameters"); API::IFunction_sptr function = fit_alg->getProperty("Function"); double offset = function->getParameter(3); // params[3]; // f1.PeakCentre offset = -1. * offset * m_step / (m_dreference + offset * m_step); // factor := factor * (1+offset) for d-spacemap conversion so factor cannot be // negative if (isAbsolbute) { // translated from(DIdeal - FittedPeakCentre)/(FittedPeakCentre) // given by Matt Tucker in ticket #10642 offset += (m_dideal - m_dreference) / m_dreference; } return offset; }
/** Fit background function */ void ProcessBackground::fitBackgroundFunction(std::string bkgdfunctiontype) { // Get background type and create bakground function BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(bkgdfunctiontype); int bkgdorder = getProperty("OutputBackgroundOrder"); bkgdfunction->setAttributeValue("n", bkgdorder); if (bkgdfunctiontype == "Chebyshev") { double xmin = m_outputWS->readX(0).front(); double xmax = m_outputWS->readX(0).back(); g_log.information() << "Chebyshev Fit range: " << xmin << ", " << xmax << "\n"; bkgdfunction->setAttributeValue("StartX", xmin); bkgdfunction->setAttributeValue("EndX", xmax); } g_log.information() << "Fit selected background " << bkgdfunctiontype << " to data workspace with " << m_outputWS->getNumberHistograms() << " spectra." << "\n"; // Fit input (a few) background pionts to get initial guess API::IAlgorithm_sptr fit; try { fit = this->createChildAlgorithm("Fit", 0.9, 1.0, true); } catch (Exception::NotFoundError &) { g_log.error() << "Requires CurveFitting library." << std::endl; throw; } g_log.information() << "Fitting background function: " << bkgdfunction->asString() << "\n"; double startx = m_lowerBound; double endx = m_upperBound; fit->setProperty("Function", boost::dynamic_pointer_cast<API::IFunction>(bkgdfunction)); fit->setProperty("InputWorkspace", m_outputWS); fit->setProperty("WorkspaceIndex", 0); fit->setProperty("MaxIterations", 500); fit->setProperty("StartX", startx); fit->setProperty("EndX", endx); fit->setProperty("Minimizer", "Levenberg-MarquardtMD"); fit->setProperty("CostFunction", "Least squares"); fit->executeAsChildAlg(); // Get fit status and chi^2 std::string fitStatus = fit->getProperty("OutputStatus"); bool allowedfailure = (fitStatus.find("cannot") < fitStatus.size()) && (fitStatus.find("tolerance") < fitStatus.size()); if (fitStatus.compare("success") != 0 && !allowedfailure) { g_log.error() << "ProcessBackground: Fit Status = " << fitStatus << ". Not to update fit result" << std::endl; throw std::runtime_error("Bad Fit"); } const double chi2 = fit->getProperty("OutputChi2overDoF"); g_log.information() << "Fit background: Fit Status = " << fitStatus << ", chi2 = " << chi2 << "\n"; // Get out the parameter names API::IFunction_sptr funcout = fit->getProperty("Function"); TableWorkspace_sptr outbkgdparws = boost::make_shared<TableWorkspace>(); outbkgdparws->addColumn("str", "Name"); outbkgdparws->addColumn("double", "Value"); TableRow typerow = outbkgdparws->appendRow(); typerow << bkgdfunctiontype << 0.; vector<string> parnames = funcout->getParameterNames(); size_t nparam = funcout->nParams(); for (size_t i = 0; i < nparam; ++i) { TableRow newrow = outbkgdparws->appendRow(); newrow << parnames[i] << funcout->getParameter(i); } TableRow chi2row = outbkgdparws->appendRow(); chi2row << "Chi-square" << chi2; g_log.information() << "Set table workspace (#row = " << outbkgdparws->rowCount() << ") to OutputBackgroundParameterTable. " << "\n"; setProperty("OutputBackgroundParameterWorkspace", outbkgdparws); // Set output workspace const MantidVec &vecX = m_outputWS->readX(0); const MantidVec &vecY = m_outputWS->readY(0); FunctionDomain1DVector domain(vecX); FunctionValues values(domain); funcout->function(domain, values); MantidVec &dataModel = m_outputWS->dataY(1); MantidVec &dataDiff = m_outputWS->dataY(2); for (size_t i = 0; i < dataModel.size(); ++i) { dataModel[i] = values[i]; dataDiff[i] = vecY[i] - dataModel[i]; } return; }