/** * Converts normalized peak intensities to count based integral intensities * * This operation is the opposite of getNormalizedPeakCollection and is used * to convert the intensities back to integral intensities. * * @param peakCollection :: PoldiPeakCollection with normalized intensities * @return PoldiPeakCollection with integral intensities */ PoldiPeakCollection_sptr PoldiFitPeaks2D::getCountPeakCollection( const PoldiPeakCollection_sptr &peakCollection) const { if (!peakCollection) { throw std::invalid_argument( "Cannot proceed with invalid PoldiPeakCollection."); } if (!m_timeTransformer) { throw std::invalid_argument("Cannot proceed without PoldiTimeTransformer."); } PoldiPeakCollection_sptr countPeakCollection = boost::make_shared<PoldiPeakCollection>(PoldiPeakCollection::Integral); countPeakCollection->setProfileFunctionName( peakCollection->getProfileFunctionName()); // Get crystal data into new peak collection assignCrystalData(countPeakCollection, peakCollection); for (size_t i = 0; i < peakCollection->peakCount(); ++i) { PoldiPeak_sptr peak = peakCollection->peak(i); double calculatedIntensity = m_timeTransformer->calculatedTotalIntensity(peak->d()); PoldiPeak_sptr countPeak = peak->clone(); countPeak->setIntensity(peak->intensity() * calculatedIntensity); countPeakCollection->addPeak(countPeak); } return countPeakCollection; }
/** * Returns a Poldi2DFunction that encapsulates individual peaks * * This function takes all peaks from the supplied peak collection and * generates an IPeakFunction of the type given in the name parameter, wraps * them in a Poldi2DFunction and returns it. * * @param profileFunctionName :: Profile function name. * @param peakCollection :: Peak collection with peaks to be used in the fit. * @return :: A Poldi2DFunction with peak profile functions. */ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks( std::string profileFunctionName, const PoldiPeakCollection_sptr &peakCollection) const { auto mdFunction = boost::make_shared<Poldi2DFunction>(); for (size_t i = 0; i < peakCollection->peakCount(); ++i) { PoldiPeak_sptr peak = peakCollection->peak(i); boost::shared_ptr<PoldiSpectrumDomainFunction> peakFunction = boost::dynamic_pointer_cast<PoldiSpectrumDomainFunction>( FunctionFactory::Instance().createFunction( "PoldiSpectrumDomainFunction")); if (!peakFunction) { throw std::invalid_argument( "Cannot process null pointer poldi function."); } peakFunction->setDecoratedFunction(profileFunctionName); IPeakFunction_sptr wrappedProfile = boost::dynamic_pointer_cast<IPeakFunction>( peakFunction->getProfileFunction()); if (wrappedProfile) { wrappedProfile->setCentre(peak->d()); wrappedProfile->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD)); wrappedProfile->setIntensity(peak->intensity()); } mdFunction->addFunction(peakFunction); } return mdFunction; }
IFunction_sptr PoldiFitPeaks1D2::getPeakProfile(const PoldiPeak_sptr &poldiPeak) const { IPeakFunction_sptr clonedProfile = boost::dynamic_pointer_cast<IPeakFunction>( FunctionFactory::Instance().createFunction(m_profileTemplate)); clonedProfile->setCentre(poldiPeak->q()); clonedProfile->setFwhm(poldiPeak->fwhm(PoldiPeak::AbsoluteQ)); clonedProfile->setHeight(poldiPeak->intensity()); return clonedProfile; }
void PoldiPeakSummary::storePeakSummary(TableRow tableRow, const PoldiPeak_sptr &peak) const { UncertainValue q = peak->q(); UncertainValue d = peak->d(); tableRow << MillerIndicesIO::toString(peak->hkl()) << UncertainValueIO::toString(q) << UncertainValueIO::toString(d) << d.error() / d.value() * 1e3 << UncertainValueIO::toString(peak->fwhm(PoldiPeak::Relative) * 1e3) << UncertainValueIO::toString(peak->intensity()); }
/** * Returns a Poldi2DFunction that encapsulates a PawleyFunction * * This function creates a PawleyFunction using the supplied profile function * name and the crystal system as well as initial cell from the input * properties of the algorithm and wraps it in a Poldi2DFunction. * * The cell is refined using LatticeFunction to get better starting values. * * Because the peak intensities are integral at this step but PawleyFunction * expects peak heights, a profile function is created and * setIntensity/height-methods are used to convert. * * @param profileFunctionName :: Profile function name for PawleyFunction. * @param peakCollection :: Peak collection with peaks to be used in the fit. * @return :: A Poldi2DFunction with a PawleyFunction. */ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionPawley( std::string profileFunctionName, const PoldiPeakCollection_sptr &peakCollection) { auto mdFunction = boost::make_shared<Poldi2DFunction>(); boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction = boost::dynamic_pointer_cast<PoldiSpectrumPawleyFunction>( FunctionFactory::Instance().createFunction( "PoldiSpectrumPawleyFunction")); if (!poldiPawleyFunction) { throw std::invalid_argument("Could not create pawley function."); } poldiPawleyFunction->setDecoratedFunction("PawleyFunction"); IPawleyFunction_sptr pawleyFunction = poldiPawleyFunction->getPawleyFunction(); pawleyFunction->setProfileFunction(profileFunctionName); // Extract crystal system from peak collection PointGroup_sptr pointGroup = peakCollection->pointGroup(); if (!pointGroup) { throw std::invalid_argument("Can not initialize pawley function properly - " "peaks do not have point group."); } std::string latticeSystem = getLatticeSystemFromPointGroup(pointGroup); pawleyFunction->setLatticeSystem(latticeSystem); UnitCell cell = peakCollection->unitCell(); // Extract unit cell from peak collection pawleyFunction->setUnitCell(getRefinedStartingCell( unitCellToStr(cell), latticeSystem, peakCollection)); IPeakFunction_sptr pFun = boost::dynamic_pointer_cast<IPeakFunction>( FunctionFactory::Instance().createFunction(profileFunctionName)); for (size_t i = 0; i < peakCollection->peakCount(); ++i) { PoldiPeak_sptr peak = peakCollection->peak(i); pFun->setCentre(peak->d()); pFun->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD)); pFun->setIntensity(peak->intensity()); pawleyFunction->addPeak(peak->hkl().asV3D(), peak->fwhm(PoldiPeak::AbsoluteD), pFun->height()); } pawleyFunction->fix(pawleyFunction->parameterIndex("f0.ZeroShift")); mdFunction->addFunction(poldiPawleyFunction); return mdFunction; }
/** Scales the intensities of all peaks in the collection by the supplied *scattering contribution * * This method scales intensities of peaks contained in the supplied *PoldiPeakCollection * (if it's a null-pointer, the method throws an std::invalid_argument *exception). The original * intensity is multiplied by the contribution factor. * * @param peakCollection :: PoldiPeakCollection with expected peaks of one *phase. * @param contribution :: Scattering contribution of that material. */ void PoldiIndexKnownCompounds::scaleIntensityEstimates( const PoldiPeakCollection_sptr &peakCollection, double contribution) const { if (!peakCollection) { throw std::invalid_argument( "Cannot assign intensities to invalid PoldiPeakCollection."); } size_t peakCount = peakCollection->peakCount(); for (size_t i = 0; i < peakCount; ++i) { PoldiPeak_sptr peak = peakCollection->peak(i); peak->setIntensity(peak->intensity() * contribution); } }
size_t PoldiIndexKnownCompounds::getMaximumIntensityPeakIndex( const PoldiPeakCollection_sptr &peakCollection) const { double maxInt = 0.0; size_t maxIndex = 0; for (size_t i = 0; i < peakCollection->peakCount(); ++i) { PoldiPeak_sptr currentPeak = peakCollection->peak(i); double currentInt = currentPeak->intensity(); if (currentInt > maxInt) { maxInt = currentInt; maxIndex = i; } } return maxIndex; }
IFunction_sptr PoldiFitPeaks1D::getPeakProfile(const PoldiPeak_sptr &poldiPeak) const { IPeakFunction_sptr clonedProfile = boost::dynamic_pointer_cast<IPeakFunction>( FunctionFactory::Instance().createFunction(m_profileTemplate)); clonedProfile->setCentre(poldiPeak->q()); clonedProfile->setFwhm(poldiPeak->fwhm(PoldiPeak::AbsoluteQ)); clonedProfile->setHeight(poldiPeak->intensity()); IFunction_sptr clonedBackground = m_backgroundTemplate->clone(); auto totalProfile = boost::make_shared<CompositeFunction>(); totalProfile->initialize(); totalProfile->addFunction(clonedProfile); totalProfile->addFunction(clonedBackground); if (!m_profileTies.empty()) { totalProfile->addTies(m_profileTies); } return totalProfile; }
/** * Return peak collection with integrated peaks * * This method takes a PoldiPeakCollection where the intensity is represented * by the maximum. Then it takes the profile function stored in the peak * collection, which must be the name of a registered * IPeakFunction-implementation. The parameters height and fwhm are assigned, * centre is set to 0 to avoid problems with the parameter transformation for * the integration from -inf to inf. The profiles are integrated using * a PeakFunctionIntegrator to the precision of 1e-10. * * The original peak collection is not modified, a new instance is created. * * @param rawPeakCollection :: PoldiPeakCollection * @return PoldiPeakCollection with integrated intensities */ PoldiPeakCollection_sptr PoldiFitPeaks2D::getIntegratedPeakCollection( const PoldiPeakCollection_sptr &rawPeakCollection) const { if (!rawPeakCollection) { throw std::invalid_argument( "Cannot proceed with invalid PoldiPeakCollection."); } if (!isValidDeltaT(m_deltaT)) { throw std::invalid_argument("Cannot proceed with invalid time bin size."); } if (!m_timeTransformer) { throw std::invalid_argument( "Cannot proceed with invalid PoldiTimeTransformer."); } if (rawPeakCollection->intensityType() == PoldiPeakCollection::Integral) { /* Intensities are integral already - don't need to do anything, * except cloning the collection, to make behavior consistent, since * integrating also results in a new peak collection. */ return rawPeakCollection->clone(); } /* If no profile function is specified, it's not possible to get integrated * intensities at all and we try to use the one specified by the user * instead. */ std::string profileFunctionName = rawPeakCollection->getProfileFunctionName(); if (!rawPeakCollection->hasProfileFunctionName()) { profileFunctionName = getPropertyValue("PeakProfileFunction"); } std::vector<std::string> allowedProfiles = FunctionFactory::Instance().getFunctionNames<IPeakFunction>(); if (std::find(allowedProfiles.begin(), allowedProfiles.end(), profileFunctionName) == allowedProfiles.end()) { throw std::runtime_error( "Cannot integrate peak profiles with invalid profile function."); } PoldiPeakCollection_sptr integratedPeakCollection = boost::make_shared<PoldiPeakCollection>(PoldiPeakCollection::Integral); integratedPeakCollection->setProfileFunctionName(profileFunctionName); // Preserve unit cell, point group assignCrystalData(integratedPeakCollection, rawPeakCollection); for (size_t i = 0; i < rawPeakCollection->peakCount(); ++i) { PoldiPeak_sptr peak = rawPeakCollection->peak(i); IPeakFunction_sptr profileFunction = boost::dynamic_pointer_cast<IPeakFunction>( FunctionFactory::Instance().createFunction(profileFunctionName)); profileFunction->setHeight(peak->intensity()); profileFunction->setFwhm(peak->fwhm(PoldiPeak::AbsoluteD)); PoldiPeak_sptr integratedPeak = peak->clone(); integratedPeak->setIntensity(UncertainValue(profileFunction->intensity())); integratedPeakCollection->addPeak(integratedPeak); } return integratedPeakCollection; }
bool PoldiPeakSearch::isLessThanMinimum(PoldiPeak_sptr peak) { return peak->intensity().value() <= m_minimumPeakHeight; }
bool PoldiFitPeaks1D2::peakIsAcceptable(const PoldiPeak_sptr &peak) const { return peak->intensity() > 0 && peak->fwhm(PoldiPeak::Relative) < m_maxRelativeFwhm && peak->fwhm(PoldiPeak::Relative) > 0.001; }