From f49bebf1a22b2a1c1ed7bac0a0f5969747455bc9 Mon Sep 17 00:00:00 2001 From: Michael Wedel Date: Tue, 5 May 2015 08:47:55 +0200 Subject: [PATCH] Refs #11674. Checkpointing work --- .../Framework/CurveFitting/CMakeLists.txt | 3 + .../PoldiCalibrationProfile.h | 69 +++++++++++++++++++ .../src/PoldiCalibrationProfile.cpp | 68 ++++++++++++++++++ .../test/PoldiCalibrationProfileTest.h | 44 ++++++++++++ .../PoldiSpectrumCalibrationFunction.h | 4 +- .../PoldiSpectrumDomainFunction.h | 6 +- .../Framework/SINQ/src/PoldiFitPeaks2D.cpp | 20 ++++-- .../PoldiSpectrumCalibrationFunction.cpp | 24 ++++--- .../PoldiSpectrumDomainFunction.cpp | 14 ++-- 9 files changed, 229 insertions(+), 23 deletions(-) create mode 100644 Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PoldiCalibrationProfile.h create mode 100644 Code/Mantid/Framework/CurveFitting/src/PoldiCalibrationProfile.cpp create mode 100644 Code/Mantid/Framework/CurveFitting/test/PoldiCalibrationProfileTest.h diff --git a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt index c60bcf76181e..10c891e27a7a 100644 --- a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt +++ b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt @@ -75,6 +75,7 @@ set ( SRC_FILES src/PawleyFunction.cpp src/PeakParameterFunction.cpp src/PlotPeakByLogValue.cpp + src/PoldiCalibrationProfile.cpp src/Polynomial.cpp src/ProcessBackground.cpp src/ProductFunction.cpp @@ -193,6 +194,7 @@ set ( INC_FILES inc/MantidCurveFitting/PawleyFunction.h inc/MantidCurveFitting/PeakParameterFunction.h inc/MantidCurveFitting/PlotPeakByLogValue.h + inc/MantidCurveFitting/PoldiCalibrationProfile.h inc/MantidCurveFitting/Polynomial.h inc/MantidCurveFitting/ProcessBackground.h inc/MantidCurveFitting/ProductFunction.h @@ -302,6 +304,7 @@ set ( TEST_FILES PawleyFunctionTest.h PeakParameterFunctionTest.h PlotPeakByLogValueTest.h + PoldiCalibrationProfileTest.h PolynomialTest.h ProcessBackgroundTest.h ProductFunctionTest.h diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PoldiCalibrationProfile.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PoldiCalibrationProfile.h new file mode 100644 index 000000000000..bc3dded5a618 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/PoldiCalibrationProfile.h @@ -0,0 +1,69 @@ +#ifndef MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTION_H_ +#define MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTION_H_ + +#include "MantidCurveFitting/Gaussian.h" + +namespace Mantid { +namespace CurveFitting { + +/** PoldiCalibrationProfile + + Instrument parameters at POLDI are calibrated using an additional parameter + that changes the slope of Bragg lines in the POLDI 2D data. If the + instrument is calibrated properly, the parameter is 0. + + Since silicon powder is used as standard, peak profiles are always Gaussian, + so the Gaussian function from this module is re-used. The additional + parameter depends on 2theta, so it can only be used in conjunction with the + PoldiSpectrumCalibrationFunction in the SINQ module. If used otherwise + it will behave like Gaussian with an additional parameter that does nothing. + + @author Michael Wedel, Paul Scherrer Institut - SINQ + @date 04/05/2015 + + Copyright © 2015 PSI-NXMM + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + File change history is stored at: + Code Documentation is available at: +*/ +class DLLExport PoldiCalibrationProfile : public Gaussian { +public: + ~PoldiCalibrationProfile() {} + + std::string name() const { return "PoldiCalibrationProfile"; } + + double centre() const; + + void functionLocal(double *out, const double *xValues, + const size_t nData) const; + void functionDerivLocal(API::Jacobian *out, const double *xValues, + const size_t nData); + + // void functionDerivLocal(API::Jacobian *out, const double *xValues, const + // size_t nData); + +protected: + double getAbsoluteShift() const; + + void init(); +}; + +} // namespace CurveFitting +} // namespace Mantid + +#endif /* MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTION_H_ */ diff --git a/Code/Mantid/Framework/CurveFitting/src/PoldiCalibrationProfile.cpp b/Code/Mantid/Framework/CurveFitting/src/PoldiCalibrationProfile.cpp new file mode 100644 index 000000000000..cea06bdf3c5d --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/src/PoldiCalibrationProfile.cpp @@ -0,0 +1,68 @@ +#include "MantidCurveFitting/PoldiCalibrationProfile.h" +#include "MantidAPI/FunctionFactory.h" + +namespace Mantid { +namespace CurveFitting { + +using namespace API; + +DECLARE_FUNCTION(PoldiCalibrationProfile) + +void PoldiCalibrationProfile::functionLocal(double *out, const double *xValues, + const size_t nData) const { + + const double height = getParameter("Height"); + const double peakCentre = getParameter("PeakCentre"); + const double shift = getAbsoluteShift(); + const double realCentre = peakCentre + peakCentre * shift; + + const double weight = pow(1 / getParameter("Sigma"), 2); + + for (size_t i = 0; i < nData; i++) { + double diff = xValues[i] - realCentre; + out[i] = height * exp(-0.5 * diff * diff * weight); + } +} + +void PoldiCalibrationProfile::functionDerivLocal(Jacobian *out, + const double *xValues, + const size_t nData) { + const double height = getParameter("Height"); + const double peakCentre = getParameter("PeakCentre"); + const double shift = getAbsoluteShift(); + const double realCentre = peakCentre + peakCentre * shift; + + const double weight = pow(1 / getParameter("Sigma"), 2); + const double factor = getAttribute("DeltaTheta").asDouble() / 1000.0; + + for (size_t i = 0; i < nData; i++) { + double diff = xValues[i] - realCentre; + double e = exp(-0.5 * diff * diff * weight); + double b = e * height * diff * weight; + out->set(i, 0, e); + out->set(i, 1, b * (1.0 + shift)); + out->set(i, 2, -0.5 * diff * diff * height * + e); // derivative with respect to weight not sigma + out->set(i, 3, b * factor * peakCentre); + } +} + +double PoldiCalibrationProfile::centre() const { + return getParameter("PeakCentre") + + getParameter("PeakCentre") * getAbsoluteShift(); +} + +double PoldiCalibrationProfile::getAbsoluteShift() const { + return getParameter("Slope") * 1.e-3 * getAttribute("DeltaTheta").asDouble(); +} + +/// Initialize Gaussian parameters and declare additional parameter. +void PoldiCalibrationProfile::init() { + Gaussian::init(); + + declareParameter("Slope"); + declareAttribute("DeltaTheta", IFunction::Attribute(0.0)); +} + +} // namespace CurveFitting +} // namespace Mantid diff --git a/Code/Mantid/Framework/CurveFitting/test/PoldiCalibrationProfileTest.h b/Code/Mantid/Framework/CurveFitting/test/PoldiCalibrationProfileTest.h new file mode 100644 index 000000000000..41193e131b43 --- /dev/null +++ b/Code/Mantid/Framework/CurveFitting/test/PoldiCalibrationProfileTest.h @@ -0,0 +1,44 @@ +#ifndef MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTIONTEST_H_ +#define MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTIONTEST_H_ + +#include + +#include "MantidCurveFitting/PoldiCalibrationProfile.h" + +using namespace Mantid::CurveFitting; +using namespace Mantid::API; + +class PoldiCalibrationProfileTest : public CxxTest::TestSuite { +public: + // This pair of boilerplate methods prevent the suite being created statically + // This means the constructor isn't called when running other tests + static PoldiCalibrationProfileTest *createSuite() { + return new PoldiCalibrationProfileTest(); + } + static void destroySuite(PoldiCalibrationProfileTest *suite) { delete suite; } + + void testParameters() { + PoldiCalibrationProfile fn; + fn.initialize(); + + Gaussian gaussian; + gaussian.initialize(); + + TS_ASSERT_EQUALS(fn.nParams(), gaussian.nParams() + 1); + } + + void testDerivatives() { + PoldiCalibrationProfile fn; + fn.initialize(); + + fn.setParameter("Height", 2.0); + fn.setParameter("PeakCentre", 1.1); + fn.setParameter("Sigma", 0.01); + fn.setParameter("Slope", 0.001); + fn.setAttribute("DeltaTheta", IFunction::Attribute(0.01)); + + + } +}; + +#endif /* MANTID_CURVEFITTING_POLDICALIBRATIONFUNCTIONTEST_H_ */ diff --git a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumCalibrationFunction.h b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumCalibrationFunction.h index 1d188fc5b78b..52ae599bd352 100644 --- a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumCalibrationFunction.h +++ b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumCalibrationFunction.h @@ -43,7 +43,9 @@ class MANTID_SINQ_DLL PoldiSpectrumCalibrationFunction } protected: - virtual getPeakCenter(const Poldi2DHelper_sptr &poldi2DHelper) const; + void init(); + + void functionModificationHook(const Poldi2DHelper_sptr &poldi2DHelper) const; }; } // namespace Poldi diff --git a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumDomainFunction.h b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumDomainFunction.h index 179e66b0e509..1d4f4d84088b 100644 --- a/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumDomainFunction.h +++ b/Code/Mantid/Framework/SINQ/inc/MantidSINQ/PoldiUtilities/PoldiSpectrumDomainFunction.h @@ -42,7 +42,7 @@ struct MANTID_SINQ_DLL Poldi2DHelper { /// Default constructor Poldi2DHelper() : dFractionalOffsets(), dOffsets(), domain(), values(), factors(), - deltaD(), deltaTwoTheta(), minTOFN() {} + deltaD(), deltaTwoTheta(), tofFactor(), minTOFN() {} /// Transforms the chopper slit offsets for a given 2theta/distance pair. void setChopperSlitOffsets(double distance, double sinTheta, double deltaD, @@ -96,6 +96,7 @@ struct MANTID_SINQ_DLL Poldi2DHelper { double deltaD; double deltaTwoTheta; + double tofFactor; int minTOFN; }; @@ -260,7 +261,8 @@ class MANTID_SINQ_DLL PoldiSpectrumDomainFunction protected: virtual void init(); - virtual double getPeakCenter(const Poldi2DHelper_sptr &poldi2DHelper) const; + virtual void + functionModificationHook(const Poldi2DHelper_sptr &poldi2DHelper) const; void initializeParametersFromWorkspace( const DataObjects::Workspace2D_const_sptr &workspace2D); diff --git a/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp b/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp index 38fa55e16789..1634d42f0571 100644 --- a/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp +++ b/Code/Mantid/Framework/SINQ/src/PoldiFitPeaks2D.cpp @@ -463,14 +463,14 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks( boost::shared_ptr peakFunction = boost::dynamic_pointer_cast( FunctionFactory::Instance().createFunction( - "PoldiSpectrumDomainFunction")); + "PoldiSpectrumCalibrationFunction")); if (!peakFunction) { throw std::invalid_argument( "Cannot process null pointer poldi function."); } - peakFunction->setDecoratedFunction(profileFunctionName); + //peakFunction->setDecoratedFunction(profileFunctionName); IPeakFunction_sptr wrappedProfile = boost::dynamic_pointer_cast( @@ -483,6 +483,12 @@ Poldi2DFunction_sptr PoldiFitPeaks2D::getFunctionIndividualPeaks( } mdFunction->addFunction(peakFunction); + + if (i > 0) { + std::string paramName = + "f" + boost::lexical_cast(i) + ".Slope"; + mdFunction->tie(paramName, paramName + "=f0.Slope"); + } } return mdFunction; @@ -1166,6 +1172,12 @@ void PoldiFitPeaks2D::exec() { // The FitFunction is used to generate... IFunction_sptr fitFunction = getFunction(fitAlgorithm); + for (size_t i = 0; i < fitFunction->nParams(); ++i) { + std::cout << i << " " << fitFunction->parameterName(i) << " " + << fitFunction->getParameter(i) << " " << fitFunction->getError(i) + << std::endl; + } + // ...a calculated 1D-spectrum... MatrixWorkspace_sptr outWs1D = get1DSpectrum(fitFunction, ws); @@ -1173,8 +1185,8 @@ void PoldiFitPeaks2D::exec() { std::vector integralPeaks = getCountPeakCollections(fitFunction); - for(size_t i = 0; i < peakCollections.size(); ++i) { - assignMillerIndices(peakCollections[i], integralPeaks[i]); + for (size_t i = 0; i < peakCollections.size(); ++i) { + assignMillerIndices(peakCollections[i], integralPeaks[i]); } // Get the calculated 2D workspace diff --git a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumCalibrationFunction.cpp b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumCalibrationFunction.cpp index ca1c0f681408..71243757524d 100644 --- a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumCalibrationFunction.cpp +++ b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumCalibrationFunction.cpp @@ -1,21 +1,25 @@ #include "MantidSINQ/PoldiUtilities/PoldiSpectrumCalibrationFunction.h" +#include "MantidAPI/FunctionFactory.h" -namespace Mantid -{ -namespace Poldi -{ +namespace Mantid { +namespace Poldi { -PoldiSpectrumCalibrationFunction::PoldiSpectrumCalibrationFunction() : - PoldiSpectrumDomainFunction() -{ +using namespace API; -} +DECLARE_FUNCTION(PoldiSpectrumCalibrationFunction) -PoldiSpectrumCalibrationFunction::getPeakCenter(const Poldi2DHelper_sptr &poldi2DHelper) const -{ +PoldiSpectrumCalibrationFunction::PoldiSpectrumCalibrationFunction() + : PoldiSpectrumDomainFunction() {} +void PoldiSpectrumCalibrationFunction::init() { + setDecoratedFunction("PoldiCalibrationProfile"); } +void PoldiSpectrumCalibrationFunction::functionModificationHook( + const Poldi2DHelper_sptr &poldi2DHelper) const { + m_profileFunction->setAttribute( + "DeltaTheta", IFunction::Attribute(poldi2DHelper->deltaTwoTheta / 2.0)); +} } // namespace Poldi } // namespace Mantid diff --git a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumDomainFunction.cpp b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumDomainFunction.cpp index 8f221a169043..53edf36c18c4 100644 --- a/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumDomainFunction.cpp +++ b/Code/Mantid/Framework/SINQ/src/PoldiUtilities/PoldiSpectrumDomainFunction.cpp @@ -60,10 +60,12 @@ void PoldiSpectrumDomainFunction::function1DSpectrum( Poldi2DHelper_sptr helper = m_2dHelpers[index]; if (helper) { + functionModificationHook(helper); + int domainSize = static_cast(domain.size()); double fwhm = m_profileFunction->fwhm(); - double centre = getPeakCenter(helper); + double centre = m_profileFunction->centre(); double dWidth = 2.0 * fwhm; double dCalcMin = centre - dWidth; @@ -116,10 +118,12 @@ void PoldiSpectrumDomainFunction::functionDeriv1DSpectrum( Poldi2DHelper_sptr helper = m_2dHelpers[index]; if (helper) { + functionModificationHook(helper); + size_t domainSize = domain.size(); double fwhm = m_profileFunction->fwhm(); - double centre = getPeakCenter(helper); + double centre = m_profileFunction->centre(); double dWidth = 2.0 * fwhm; double dCalcMin = centre - dWidth; @@ -185,11 +189,9 @@ IPeakFunction_sptr PoldiSpectrumDomainFunction::getProfileFunction() const { /// Does nothing. void PoldiSpectrumDomainFunction::init() {} -/// Returns the centre parameter of the decorated profile function. -double PoldiSpectrumDomainFunction::getPeakCenter( +void PoldiSpectrumDomainFunction::functionModificationHook( const Poldi2DHelper_sptr &poldi2DHelper) const { - UNUSED_ARG(poldi2DHelper) - return m_profileFunction->centre(); + UNUSED_ARG(poldi2DHelper) } /**