/** Creates PoldiPeak-objects from peak position iterators * * In this method, PoldiPeak objects are created from the raw peak position *data and the original x-data. Estimates for peak height and FWHM * provided along with the position. * * @param baseListStart :: Starting iterator of the vector which the peak *positions refer to. * @param peakPositions :: List with peakPositions. * @param xData :: Vector with x-values of the correlation spectrum. * @return Vector with PoldiPeak objects constructed from the raw peak position *data. */ std::vector<PoldiPeak_sptr> PoldiPeakSearch::getPeaks(const MantidVec::const_iterator &baseListStart, const MantidVec::const_iterator &baseListEnd, std::list<MantidVec::const_iterator> peakPositions, const MantidVec &xData, const Unit_sptr &unit) const { std::vector<PoldiPeak_sptr> peakData; peakData.reserve(peakPositions.size()); for (std::list<MantidVec::const_iterator>::const_iterator peak = peakPositions.begin(); peak != peakPositions.end(); ++peak) { size_t index = std::distance(baseListStart, *peak); double xDataD = getTransformedCenter(xData[index], unit); double fwhmEstimate = getFWHMEstimate(baseListStart, baseListEnd, *peak, xData); UncertainValue fwhm(fwhmEstimate / xData[index]); PoldiPeak_sptr newPeak = PoldiPeak::create( MillerIndices(), UncertainValue(xDataD), UncertainValue(**peak), fwhm); peakData.push_back(newPeak); } return peakData; }
/** * Fit peak without background i.e, with background removed * inspired from FitPowderDiffPeaks.cpp * copied from PoldiPeakDetection2.cpp * @param workspaceindex :: indice of the row to use @param center :: gaussian parameter - center @param sigma :: gaussian parameter - width @param height :: gaussian parameter - height @param startX :: fit range - start X value @param endX :: fit range - end X value @returns A boolean status flag, true for fit success, false else */ bool ConvertEmptyToTof::doFitGaussianPeak(int workspaceindex, double ¢er, double &sigma, double &height, double startX, double endX) { g_log.debug("Calling doFitGaussianPeak..."); // 1. Estimate sigma = sigma * 0.5; // 2. Use factory to generate Gaussian auto temppeak = API::FunctionFactory::Instance().createFunction("Gaussian"); auto gaussianpeak = boost::dynamic_pointer_cast<API::IPeakFunction>(temppeak); gaussianpeak->setHeight(height); gaussianpeak->setCentre(center); gaussianpeak->setFwhm(sigma); // 3. Constraint double centerleftend = center - sigma * 0.5; double centerrightend = center + sigma * 0.5; std::ostringstream os; os << centerleftend << " < PeakCentre < " << centerrightend; auto *centerbound = API::ConstraintFactory::Instance().createInitialized( gaussianpeak.get(), os.str(), false); gaussianpeak->addConstraint(centerbound); g_log.debug("Calling createChildAlgorithm : Fit..."); // 4. Fit API::IAlgorithm_sptr fitalg = createChildAlgorithm("Fit", -1, -1, true); fitalg->initialize(); fitalg->setProperty( "Function", boost::dynamic_pointer_cast<API::IFunction>(gaussianpeak)); fitalg->setProperty("InputWorkspace", m_inputWS); fitalg->setProperty("WorkspaceIndex", workspaceindex); fitalg->setProperty("Minimizer", "Levenberg-MarquardtMD"); fitalg->setProperty("CostFunction", "Least squares"); fitalg->setProperty("MaxIterations", 1000); fitalg->setProperty("Output", "FitGaussianPeak"); fitalg->setProperty("StartX", startX); fitalg->setProperty("EndX", endX); // 5. Result bool successfulfit = fitalg->execute(); if (!fitalg->isExecuted() || !successfulfit) { // Early return due to bad fit g_log.warning() << "Fitting Gaussian peak for peak around " << gaussianpeak->centre() << '\n'; return false; } // 6. Get result center = gaussianpeak->centre(); height = gaussianpeak->height(); double fwhm = gaussianpeak->fwhm(); return fwhm > 0.0; }
/// Returns the integral intensity of the peak function, using the peak radius /// to determine integration borders. double IPeakFunction::intensity() const { double x0 = centre(); double dx = fabs(s_peakRadius * fwhm()); PeakFunctionIntegrator integrator; IntegrationResult result = integrator.integrate(*this, x0 - dx, x0 + dx); if (!result.success) { return 0.0; } return result.result; }
/// Creates a PoldiPeak from the given profile function/hkl pair. PoldiPeak_sptr PoldiFitPeaks2D::getPeakFromPeakFunction(IPeakFunction_sptr profileFunction, const V3D &hkl) { // Use EstimatePeakErrors to calculate errors of FWHM and so on IAlgorithm_sptr errorAlg = createChildAlgorithm("EstimatePeakErrors"); errorAlg->setProperty( "Function", boost::dynamic_pointer_cast<IFunction>(profileFunction)); errorAlg->setPropertyValue("OutputWorkspace", "Errors"); errorAlg->execute(); double centre = profileFunction->centre(); double fwhmValue = profileFunction->fwhm(); ITableWorkspace_sptr errorTable = errorAlg->getProperty("OutputWorkspace"); double centreError = errorTable->cell<double>(0, 2); double fwhmError = errorTable->cell<double>(2, 2); UncertainValue d(centre, centreError); UncertainValue fwhm(fwhmValue, fwhmError); UncertainValue intensity; bool useIntegratedIntensities = getProperty("OutputIntegratedIntensities"); if (useIntegratedIntensities) { double integratedIntensity = profileFunction->intensity(); double integratedIntensityError = errorTable->cell<double>(3, 2); intensity = UncertainValue(integratedIntensity, integratedIntensityError); } else { double height = profileFunction->height(); double heightError = errorTable->cell<double>(1, 2); intensity = UncertainValue(height, heightError); } // Create peak with extracted parameters and supplied hkl PoldiPeak_sptr peak = PoldiPeak::create(MillerIndices(hkl), d, intensity, UncertainValue(1.0)); peak->setFwhm(fwhm, PoldiPeak::FwhmRelation::AbsoluteD); return peak; }
/** * Gaussian fit to determine peak position if no user position given. * * @return :: detector position of the peak: Gaussian fit and position * of the maximum (serves as start value for the optimization) */ double LoadILLReflectometry::reflectometryPeak() { if (!isDefault("BeamCentre")) { return getProperty("BeamCentre"); } size_t startIndex; size_t endIndex; std::tie(startIndex, endIndex) = fitIntegrationWSIndexRange(*m_localWorkspace); IAlgorithm_sptr integration = createChildAlgorithm("Integration"); integration->initialize(); integration->setProperty("InputWorkspace", m_localWorkspace); integration->setProperty("OutputWorkspace", "__unused_for_child"); integration->setProperty("StartWorkspaceIndex", static_cast<int>(startIndex)); integration->setProperty("EndWorkspaceIndex", static_cast<int>(endIndex)); integration->execute(); MatrixWorkspace_sptr integralWS = integration->getProperty("OutputWorkspace"); IAlgorithm_sptr transpose = createChildAlgorithm("Transpose"); transpose->initialize(); transpose->setProperty("InputWorkspace", integralWS); transpose->setProperty("OutputWorkspace", "__unused_for_child"); transpose->execute(); integralWS = transpose->getProperty("OutputWorkspace"); rebinIntegralWorkspace(*integralWS); // determine initial height: maximum value const auto maxValueIt = std::max_element(integralWS->y(0).cbegin(), integralWS->y(0).cend()); const double height = *maxValueIt; // determine initial centre: index of the maximum value const size_t maxIndex = std::distance(integralWS->y(0).cbegin(), maxValueIt); const double centreByMax = static_cast<double>(maxIndex); g_log.debug() << "Peak maximum position: " << centreByMax << '\n'; // determine sigma const auto &ys = integralWS->y(0); auto lessThanHalfMax = [height](const double x) { return x < 0.5 * height; }; using IterType = HistogramData::HistogramY::const_iterator; std::reverse_iterator<IterType> revMaxValueIt{maxValueIt}; auto revMinFwhmIt = std::find_if(revMaxValueIt, ys.crend(), lessThanHalfMax); auto maxFwhmIt = std::find_if(maxValueIt, ys.cend(), lessThanHalfMax); std::reverse_iterator<IterType> revMaxFwhmIt{maxFwhmIt}; if (revMinFwhmIt == ys.crend() || maxFwhmIt == ys.cend()) { g_log.warning() << "Couldn't determine fwhm of beam, using position of max " "value as beam center.\n"; return centreByMax; } const double fwhm = static_cast<double>(std::distance(revMaxFwhmIt, revMinFwhmIt) + 1); g_log.debug() << "Initial fwhm (full width at half maximum): " << fwhm << '\n'; // generate Gaussian auto func = API::FunctionFactory::Instance().createFunction("CompositeFunction"); auto sum = boost::dynamic_pointer_cast<API::CompositeFunction>(func); func = API::FunctionFactory::Instance().createFunction("Gaussian"); auto gaussian = boost::dynamic_pointer_cast<API::IPeakFunction>(func); gaussian->setHeight(height); gaussian->setCentre(centreByMax); gaussian->setFwhm(fwhm); sum->addFunction(gaussian); func = API::FunctionFactory::Instance().createFunction("LinearBackground"); func->setParameter("A0", 0.); func->setParameter("A1", 0.); sum->addFunction(func); // call Fit child algorithm API::IAlgorithm_sptr fit = createChildAlgorithm("Fit"); fit->initialize(); fit->setProperty("Function", boost::dynamic_pointer_cast<API::IFunction>(sum)); fit->setProperty("InputWorkspace", integralWS); fit->setProperty("StartX", centreByMax - 3 * fwhm); fit->setProperty("EndX", centreByMax + 3 * fwhm); fit->execute(); const std::string fitStatus = fit->getProperty("OutputStatus"); if (fitStatus != "success") { g_log.warning("Fit not successful, using position of max value.\n"); return centreByMax; } const auto centre = gaussian->centre(); g_log.debug() << "Sigma: " << gaussian->fwhm() << '\n'; g_log.debug() << "Estimated peak position: " << centre << '\n'; return centre; }