From 492aff6d156bc1f4a38c8bffef85609c2996ad29 Mon Sep 17 00:00:00 2001 From: Michael Wedel <michael.wedel@psi.ch> Date: Wed, 11 Mar 2015 16:54:27 +0100 Subject: [PATCH] Refs #11043. Correcting parameter behavior, adding peaks. --- .../inc/MantidCurveFitting/PawleyFunction.h | 22 +++++- .../CurveFitting/src/PawleyFunction.cpp | 78 ++++++++++++++++--- .../CurveFitting/test/PawleyFunctionTest.h | 36 +++++++-- 3 files changed, 118 insertions(+), 18 deletions(-) diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h index 948dd31ac10..f7b795c8209 100644 --- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PawleyFunction.h @@ -5,6 +5,7 @@ #include "MantidAPI/CompositeFunction.h" #include "MantidAPI/FunctionParameterDecorator.h" #include "MantidAPI/IFunction1D.h" +#include "MantidAPI/IPeakFunction.h" #include "MantidAPI/ParamFunction.h" #include "MantidGeometry/Crystal/PointGroup.h" @@ -26,6 +27,14 @@ public: Geometry::PointGroup::CrystalSystem getCrystalSystem() const; Geometry::UnitCell getUnitCellFromParameters() const; + std::string getProfileFunctionName() const { + return getAttribute("ProfileFunction").asString(); + } + + std::string getProfileFunctionCenterParameterName() const { + return m_profileFunctionCenterParameterName; + } + void function(const API::FunctionDomain &domain, API::FunctionValues &values) const; void functionDeriv(const API::FunctionDomain &domain, @@ -34,12 +43,16 @@ public: protected: void init(); + void setProfileFunction(const std::string &profileFunction); void setCrystalSystem(const std::string &crystalSystem); void createCrystalSystemParameters( Geometry::PointGroup::CrystalSystem crystalSystem); + void setCenterParameterNameFromFunction( + const API::IPeakFunction_sptr &profileFunction); Geometry::PointGroup::CrystalSystem m_crystalSystem; + std::string m_profileFunctionCenterParameterName; }; typedef boost::shared_ptr<PawleyParameterFunction> PawleyParameterFunction_sptr; @@ -82,6 +95,7 @@ typedef boost::shared_ptr<PawleyParameterFunction> PawleyParameterFunction_sptr; class PawleyFunction : public API::IFunction1D, public API::FunctionParameterDecorator { public: + PawleyFunction(); virtual ~PawleyFunction() {} std::string name() const { return "PawleyFunction"; } @@ -94,10 +108,12 @@ public: const size_t nData); void functionDeriv(const API::FunctionDomain &domain, API::Jacobian &jacobian) { - calNumericalDeriv(domain, jacobian); + calNumericalDeriv(domain, jacobian); } - void addPeak(); + void addPeak(const Kernel::V3D &hkl, double centre, double fwhm, + double height); + API::IPeakFunction_sptr getPeak(size_t i) const; protected: void init(); @@ -106,6 +122,8 @@ protected: API::CompositeFunction_sptr m_compositeFunction; PawleyParameterFunction_sptr m_pawleyParameterFunction; API::CompositeFunction_sptr m_peakProfileComposite; + + std::vector<Kernel::V3D> m_hkls; }; } // namespace CurveFitting } // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp b/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp index d729affefce..6fbed58fa98 100644 --- a/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp +++ b/Code/Mantid/Framework/CurveFitting/src/PawleyFunction.cpp @@ -14,12 +14,15 @@ using namespace API; using namespace Geometry; PawleyParameterFunction::PawleyParameterFunction() - : ParamFunction(), m_crystalSystem(PointGroup::Triclinic) {} + : ParamFunction(), m_crystalSystem(PointGroup::Triclinic), + m_profileFunctionCenterParameterName() {} void PawleyParameterFunction::setAttribute(const std::string &attName, const Attribute &attValue) { if (attName == "CrystalSystem") { setCrystalSystem(attValue.asString()); + } else if (attName == "ProfileFunction") { + setProfileFunction(attValue.asString()); } ParamFunction::setAttribute(attName, attValue); @@ -81,15 +84,21 @@ void PawleyParameterFunction::init() { declareAttribute("CrystalSystem", IFunction::Attribute("Triclinic")); declareAttribute("ProfileFunction", IFunction::Attribute("Gaussian")); - declareParameter("a", 1.0); - declareParameter("b", 1.0); - declareParameter("c", 1.0); + setCrystalSystem("Triclinic"); + setProfileFunction("Gaussian"); +} - declareParameter("Alpha", 90.0); - declareParameter("Beta", 90.0); - declareParameter("Gamma", 90.0); +void PawleyParameterFunction::setProfileFunction( + const std::string &profileFunction) { + IPeakFunction_sptr peakFunction = boost::dynamic_pointer_cast<IPeakFunction>( + FunctionFactory::Instance().createFunction(profileFunction)); - declareParameter("ZeroShift", 0.0); + if (!peakFunction) { + throw std::invalid_argument("PawleyFunction can only use IPeakFunctions to " + "calculate peak profiles."); + } + + setCenterParameterNameFromFunction(peakFunction); } void @@ -166,6 +175,19 @@ void PawleyParameterFunction::createCrystalSystemParameters( declareParameter("ZeroShift", 0.0); } +void PawleyParameterFunction::setCenterParameterNameFromFunction( + const IPeakFunction_sptr &profileFunction) { + m_profileFunctionCenterParameterName.clear(); + if (profileFunction) { + m_profileFunctionCenterParameterName = + profileFunction->getCentreParameterName(); + } +} + +PawleyFunction::PawleyFunction() + : FunctionParameterDecorator(), m_compositeFunction(), + m_pawleyParameterFunction(), m_peakProfileComposite(), m_hkls() {} + void PawleyFunction::setCrystalSystem(const std::string &crystalSystem) { m_pawleyParameterFunction->setAttributeValue("CrystalSystem", crystalSystem); m_compositeFunction->checkFunction(); @@ -174,6 +196,23 @@ void PawleyFunction::setCrystalSystem(const std::string &crystalSystem) { void PawleyFunction::setProfileFunction(const std::string &profileFunction) { m_pawleyParameterFunction->setAttributeValue("ProfileFunction", profileFunction); + + // At this point PawleyParameterFunction guarantees that it's an IPeakFunction + for (size_t i = 0; i < m_peakProfileComposite->nFunctions(); ++i) { + IPeakFunction_sptr oldFunction = boost::dynamic_pointer_cast<IPeakFunction>( + m_peakProfileComposite->getFunction(i)); + + IPeakFunction_sptr newFunction = boost::dynamic_pointer_cast<IPeakFunction>( + FunctionFactory::Instance().createFunction( + m_pawleyParameterFunction->getProfileFunctionName())); + + newFunction->setCentre(oldFunction->centre()); + newFunction->setFwhm(oldFunction->fwhm()); + newFunction->setHeight(oldFunction->height()); + + m_peakProfileComposite->replaceFunction(i, newFunction); + } + m_compositeFunction->checkFunction(); } @@ -191,9 +230,26 @@ void PawleyFunction::functionDeriv1D(API::Jacobian *out, const double *xValues, UNUSED_ARG(nData); } -void PawleyFunction::addPeak() { - m_peakProfileComposite->addFunction( - FunctionFactory::Instance().createFunction("Gaussian")); +void PawleyFunction::addPeak(const Kernel::V3D &hkl, double centre, double fwhm, + double height) { + m_hkls.push_back(hkl); + + IPeakFunction_sptr peak = boost::dynamic_pointer_cast<IPeakFunction>( + FunctionFactory::Instance().createFunction( + m_pawleyParameterFunction->getProfileFunctionName())); + + peak->setCentre(centre); + peak->setFwhm(fwhm); + peak->setHeight(height); + + m_peakProfileComposite->addFunction(peak); + + m_compositeFunction->checkFunction(); +} + +IPeakFunction_sptr PawleyFunction::getPeak(size_t i) const { + return boost::dynamic_pointer_cast<IPeakFunction>( + m_peakProfileComposite->getFunction(i)); } void PawleyFunction::init() { diff --git a/Code/Mantid/Framework/CurveFitting/test/PawleyFunctionTest.h b/Code/Mantid/Framework/CurveFitting/test/PawleyFunctionTest.h index 0086d7a9c69..7942404e49e 100644 --- a/Code/Mantid/Framework/CurveFitting/test/PawleyFunctionTest.h +++ b/Code/Mantid/Framework/CurveFitting/test/PawleyFunctionTest.h @@ -263,14 +263,40 @@ public: } void testPawleyFunctionSetCrystalSystem() { - PawleyFunction fn; - fn.initialize(); + PawleyFunction fn; + fn.initialize(); + + TS_ASSERT_EQUALS(fn.nParams(), 7); + + fn.setCrystalSystem("Cubic"); + + TS_ASSERT_EQUALS(fn.nParams(), 2); + } + + void testPawleyFunctionAddPeak() { + PawleyFunction fn; + fn.initialize(); + + TS_ASSERT_EQUALS(fn.nParams(), 7); + + fn.addPeak(V3D(), 2.0, 3.0, 4.0); + + TS_ASSERT_EQUALS(fn.nParams(), 10); + } + + void testPawleyFunctionSetProfileFunction() { + PawleyFunction fn; + fn.initialize(); + + TS_ASSERT_EQUALS(fn.nParams(), 7); + + fn.addPeak(V3D(), 2.0, 3.0, 4.0); - TS_ASSERT_EQUALS(fn.nParams(), 7); + TS_ASSERT_EQUALS(fn.nParams(), 10); - fn.setCrystalSystem("Cubic"); + fn.setProfileFunction("PseudoVoigt"); - TS_ASSERT_EQUALS(fn.nParams(), 2); + TS_ASSERT_EQUALS(fn.nParams(), 11); } private: -- GitLab