Mantid
Loading...
Searching...
No Matches
ComptonPeakProfile.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
12
13#include <cmath>
14
16
17using namespace CurveFitting::Algorithms;
18
19DECLARE_FUNCTION(ComptonPeakProfile)
20
21namespace {
23const char *WSINDEX_NAME = "WorkspaceIndex";
24const char *MASS_NAME = "Mass";
25const char *VOIGT_CUT_OFF = "VoigtEnergyCutOff";
26
27const char *AMP_PARAM = "Intensity";
28const char *POS_PARAM = "Position";
29const char *WIDTH_PARAM = "SigmaGauss";
30
32const double MASS_TO_MEV = 0.5 * PhysicalConstants::NeutronMass / PhysicalConstants::meV;
33const double STDDEV_TO_FWHM = 0.5 * std::sqrt(std::log(4.0));
35} // namespace
36
38 : API::ParamFunction(), API::IFunction1D(), m_wsIndex(0), m_mass(0.0), m_voigtCutOff(5000.), m_gauss(), m_voigt(),
39 m_efixed(0.0), m_hwhmLorentz(0.0) {}
40
42std::string ComptonPeakProfile::name() const { return "ComptonPeakProfile"; }
43
51void ComptonPeakProfile::function1D(double *out, const double *xValues, const size_t nData) const {
52 double amp(getParameter(0)), pos(getParameter(1)), gaussSigma(getParameter(2));
53
54 if (m_efixed < m_voigtCutOff) {
55 double gaussFWHM(getParameter(2) * STDDEV_TO_FWHM), lorentzFWHM(2.0 * m_hwhmLorentz);
56 m_voigt->setParameter(0, amp);
57 m_voigt->setParameter(1, pos);
58 m_voigt->setParameter(2, lorentzFWHM);
59 m_voigt->setParameter(3, gaussFWHM);
60 m_voigt->functionLocal(out, xValues, nData);
61 const double norm = 1.0 / (0.5 * M_PI * lorentzFWHM);
62 using std::placeholders::_1;
63 std::transform(out, out + nData, out, std::bind(std::multiplies<double>(), _1, norm));
64 } else {
65 double sigmaTotalSq = m_hwhmLorentz * m_hwhmLorentz + gaussSigma * gaussSigma;
66 // Our gaussian isn't normalised by the width. Here we set the height to
67 // amp/(2*sigma^2) so that it will be normalised correctly
68 m_gauss->setParameter(0, 0.5 * amp / M_PI / sigmaTotalSq);
69 m_gauss->setParameter(1, pos);
70 m_gauss->setParameter(2, sqrt(sigmaTotalSq));
71 m_gauss->functionLocal(out, xValues, nData);
72 }
73}
74
75/*
76 * Creates the internal caches
77 */
79 // Voigt & Gaussian
80
81 using namespace Mantid::API;
82 m_gauss = std::dynamic_pointer_cast<IPeakFunction>(FunctionFactory::Instance().createFunction("Gaussian"));
83 m_voigt = std::dynamic_pointer_cast<IPeakFunction>(FunctionFactory::Instance().createFunction("Voigt"));
84}
85
91void ComptonPeakProfile::setWorkspace(std::shared_ptr<const API::Workspace> ws) {
92 auto workspace = std::dynamic_pointer_cast<const API::MatrixWorkspace>(ws);
93 if (!workspace) {
94 throw std::invalid_argument("ComptonPeakProfile expected an object of type MatrixWorkspace, type=" + ws->id());
95 }
96
98 m_efixed = detpar.efixed;
99
100 // Recoil time
101 const double sth = sin(detpar.theta);
102 const double distFact = (cos(detpar.theta) + sqrt(m_mass * m_mass - sth * sth)) / (m_mass + 1.0);
103 const double ei = detpar.efixed / pow(distFact, 2.0);
104 const double v1 = std::sqrt(detpar.efixed / MASS_TO_MEV);
105 const double k1 = std::sqrt(detpar.efixed / PhysicalConstants::E_mev_toNeutronWavenumberSq);
106 const double v2 = std::sqrt(ei / MASS_TO_MEV);
107 const double trec = detpar.l1 / v1 + detpar.l2 / v2;
108
109 // Compute lorentz width due to in Y due to spread in energy hwhm_lorentz
110 const auto &det = workspace->spectrumInfo().detector(m_wsIndex);
111 const auto &pmap = workspace->constInstrumentParameters();
112 const double dELorentz = ConvertToYSpace::getComponentParameter(det, pmap, "hwhm_lorentz");
113 double yplus(0.0), yminus(0.0), dummy(0.0);
114 detpar.efixed += dELorentz;
115 ConvertToYSpace::calculateY(yplus, dummy, dummy, m_mass, trec, k1, v1, detpar);
116 detpar.efixed -= 2.0 * dELorentz;
117 ConvertToYSpace::calculateY(yminus, dummy, dummy, m_mass, trec, k1, v1, detpar);
118 // lorentzian width
119 m_hwhmLorentz = 0.5 * (yplus - yminus);
120}
121
123 declareParameter(AMP_PARAM, 1.0, "Intensity parameter");
124 declareParameter(POS_PARAM, 1.0, "Peak position parameter");
125 declareParameter(WIDTH_PARAM, 1.0, "Width parameter");
126}
127
129 declareAttribute(WSINDEX_NAME, IFunction::Attribute(static_cast<int>(m_wsIndex)));
132}
133
138void ComptonPeakProfile::setAttribute(const std::string &name, const Attribute &value) {
139 IFunction::setAttribute(name, value); // Make sure the base-class stores it
140 if (name == WSINDEX_NAME)
141 m_wsIndex = static_cast<size_t>(value.asInt());
142 else if (name == MASS_NAME)
143 m_mass = value.asDouble();
144 else if (name == VOIGT_CUT_OFF)
145 m_voigtCutOff = value.asDouble();
146}
147
148} // namespace Mantid::CurveFitting::Functions
double value
The value of the point.
Definition: FitMW.cpp:51
#define DECLARE_FUNCTION(classname)
Macro for declaring a new type of function to be used with the FunctionFactory.
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
This is a specialization of IFunction for functions of one real argument.
Definition: IFunction1D.h:43
Attribute is a non-fitting parameter.
Definition: IFunction.h:282
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
Definition: IFunction.cpp:1418
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
Definition: IFunction.cpp:1409
Implements the part of IFunction interface dealing with parameters.
Definition: ParamFunction.h:33
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
double getParameter(size_t i) const override
Get i-th parameter.
static DetectorParams getDetectorParameters(const API::MatrixWorkspace_const_sptr &ws, const size_t index)
Creates a POD struct containing the required detector parameters for this spectrum.
static double getComponentParameter(const Geometry::IComponent &det, const Geometry::ParameterMap &pmap, const std::string &name)
Retrieve a component parameter.
static void calculateY(double &yspace, double &qspace, double &ei, const double mass, const double tsec, const double k1, const double v1, const DetectorParams &detpar)
Convert single time value to Y,Q & Ei values.
void setAttribute(const std::string &name, const Attribute &value) override
std::shared_ptr< API::IPeakFunction > m_gauss
Gaussian function for lower-energy peaks.
std::shared_ptr< API::IPeakFunction > m_voigt
Voigt function for higher-energy peaks.
void setWorkspace(std::shared_ptr< const API::Workspace > ws) override
Cache a copy of the workspace pointer and pull out the parameters.
void declareAttributes() override
Override to declare function attributes.
ComptonPeakProfile()
Default constructor required for factory.
double m_hwhmLorentz
Calculated value of lorentz width.
void declareParameters() override
Override to declare function parameters.
void setUpForFit() override
Ensure the object is ready to be fitted.
std::string name() const override
A string identifier for this function.
double m_voigtCutOff
Below this value a Voigt is used for profile approximation.
void function1D(double *out, const double *xValues, const size_t nData) const override
Calculates the value of the function for each x value and stores in the given output array.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static constexpr double E_mev_toNeutronWavenumberSq
Transformation coefficient to transform neutron energy into neutron wavevector: K-neutron[m^-10] = sq...
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double meV
1 meV in Joules.
Generate a tableworkspace to store the calibration results.
Simple data structure to store nominal detector values It avoids some functions taking a huge number ...
double theta
scattering angle in radians
double l1
source-sample distance in metres
double l2
sample-detector distance in metres