Mantid
Loading...
Searching...
No Matches
ComptonProfile.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 +
13#include "MantidKernel/Logger.h"
15
16#include <gsl/gsl_poly.h>
17
19
20using namespace CurveFitting;
21using namespace CurveFitting::Algorithms;
22using namespace Mantid::API;
23
24namespace {
26// const char * WSINDEX_NAME = "WorkspaceIndex";
27const char *MASS_NAME = "Mass";
29} // namespace
30
32 : API::ParamFunction(), API::IFunction1D(), m_log("ComptonProfile"), m_wsIndex(0), m_startX(0.0), m_endX(0.0),
33 m_voigt(), m_resolutionFunction(std::dynamic_pointer_cast<VesuvioResolution>(
34 FunctionFactory::Instance().createFunction("VesuvioResolution"))),
35 m_yspace(), m_modQ(), m_e0(), m_mass(0.0) {}
36
37//-------------------------------------- Function evaluation
38//-----------------------------------------
39
48void ComptonProfile::function1D(double *out, const double *xValues, const size_t nData) const {
49 UNUSED_ARG(xValues); // Y-space values have already been pre-cached
50
51 this->massProfile(out, nData);
52
53 m_log.setEnabled(false);
54}
55
56/*
57 * Creates the internal caches
58 */
60
61 using namespace Mantid::API;
62 m_voigt = std::dynamic_pointer_cast<IPeakFunction>(FunctionFactory::Instance().createFunction("Voigt"));
63 m_resolutionFunction->setUpForFit();
64}
65
73void ComptonProfile::setMatrixWorkspace(std::shared_ptr<const API::MatrixWorkspace> workspace, size_t wsIndex,
74 double startX, double endX) {
75 auto inst = workspace->getInstrument();
76 auto sample = inst->getSample();
77 auto source = inst->getSource();
78 if (!sample || !source) {
79 throw std::invalid_argument("ComptonProfile - Workspace has no source/sample.");
80 }
82 m_wsIndex = wsIndex;
83 m_startX = startX;
84 m_endX = endX;
85
87}
88
90 const auto &spectrumInfo = m_workspace->spectrumInfo();
91 if (!spectrumInfo.hasDetectors(m_wsIndex)) {
92 throw std::invalid_argument("ComptonProfile - Workspace has no detector "
93 "attached to histogram at index " +
95 }
96
97 m_resolutionFunction->setAttributeValue("Mass", m_mass);
99
101 this->cacheYSpaceValues(m_workspace->points(m_wsIndex), detpar);
102}
103
104void ComptonProfile::cacheYSpaceValues(const HistogramData::Points &tseconds, const Algorithms::DetectorParams &detpar,
105 const ResolutionParams &respar) {
106 m_resolutionFunction->setAttributeValue("Mass", m_mass);
107 m_resolutionFunction->cacheResolutionComponents(detpar, respar);
108 this->cacheYSpaceValues(tseconds, detpar);
109}
110
115void ComptonProfile::cacheYSpaceValues(const HistogramData::Points &tseconds,
116 const Algorithms::DetectorParams &detpar) {
117
118 // ------ Fixed coefficients related to resolution & Y-space transforms
119 // ------------------
121 const double massToMeV = 0.5 * PhysicalConstants::NeutronMass / PhysicalConstants::meV; // Includes factor of 1/2
122
123 const double v1 = std::sqrt(detpar.efixed / massToMeV);
124 const double k1 = std::sqrt(detpar.efixed / mevToK);
125
126 // Calculate energy dependent factors and transform q to Y-space
127 const size_t nData = tseconds.size();
128
129 m_e0.resize(nData);
130 m_modQ.resize(nData);
131 m_yspace.resize(nData);
132 for (size_t i = 0; i < nData; ++i) {
133 const double tsec = tseconds[i];
134 ConvertToYSpace::calculateY(m_yspace[i], m_modQ[i], m_e0[i], m_mass, tsec, k1, v1, detpar);
135 }
136}
137
138void ComptonProfile::declareParameters() { declareParameter(MASS_NAME, 0.0, "Atomic mass (amu)"); }
139
140void ComptonProfile::setParameter(size_t i, const double &value, bool explicitlySet) {
141 ParamFunction::setParameter(i, value, explicitlySet);
142
143 // Mass parameter has changed, need to rebuild Y-space cache
144 if (i == parameterIndex(MASS_NAME) && m_mass != value) {
145 m_mass = value;
146 m_resolutionFunction->setAttributeValue("Mass", m_mass);
147
148 if (m_workspace)
149 buildCaches();
150 }
151}
152
164void ComptonProfile::voigtApproxDiff(std::vector<double> &voigtDiff, const std::vector<double> &yspace,
165 const double lorentzPos, const double lorentzAmp, const double lorentzWidth,
166 const double gaussWidth) const {
167 double miny(DBL_MAX), maxy(-DBL_MAX);
168 auto iend = yspace.end();
169 for (auto itr = yspace.begin(); itr != iend; ++itr) {
170 const double absy = std::abs(*itr);
171 if (absy < miny)
172 miny = absy;
173 else if (absy > maxy)
174 maxy = absy;
175 }
176 const double epsilon = (maxy - miny) / 1000.0;
177
178 // Compute: V = (voigt(y+2eps,...) - voigt(y-2eps,...) - 2*voigt(y+eps,...) +
179 // 2*(voigt(y-eps,...))/(2eps^3)
180
181 std::vector<double> ypmEps(yspace.size());
182 // y+2eps
183 using std::placeholders::_1;
184 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
185 std::bind(std::plus<double>(), _1, 2.0 * epsilon)); // Add 2 epsilon
186 m_resolutionFunction->voigtApprox(voigtDiff, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
187 // y-2eps
188 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
189 std::bind(std::minus<double>(), _1, 2.0 * epsilon)); // Subtract 2 epsilon
190 std::vector<double> tmpResult(yspace.size());
191 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
192 // Difference of first two terms - result is put back in voigtDiff
193 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::minus<double>());
194
195 // y+eps
196 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
197 std::bind(std::plus<double>(), _1, epsilon)); // Add epsilon
198 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
199 std::transform(tmpResult.begin(), tmpResult.end(), tmpResult.begin(),
200 std::bind(std::multiplies<double>(), _1, 2.0)); // times 2
201 // Difference with 3rd term - result is put back in voigtDiff
202 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::minus<double>());
203
204 // y-eps
205 std::transform(yspace.begin(), yspace.end(), ypmEps.begin(),
206 std::bind(std::minus<double>(), _1, epsilon)); // Subtract epsilon
207 m_resolutionFunction->voigtApprox(tmpResult, ypmEps, lorentzPos, lorentzAmp, lorentzWidth, gaussWidth);
208 std::transform(tmpResult.begin(), tmpResult.end(), tmpResult.begin(),
209 std::bind(std::multiplies<double>(), _1, 2.0)); // times 2
210 // Sum final term
211 std::transform(voigtDiff.begin(), voigtDiff.end(), tmpResult.begin(), voigtDiff.begin(), std::plus<double>());
212
213 // Finally divide by 2*eps^3
214 std::transform(voigtDiff.begin(), voigtDiff.end(), voigtDiff.begin(),
215 std::bind(std::divides<double>(), _1, 2.0 * std::pow(epsilon, 3)));
216}
217
218} // namespace Mantid::CurveFitting::Functions
double value
The value of the point.
Definition FitMW.cpp:51
IPeaksWorkspace_sptr workspace
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
This is a specialization of IFunction for functions of one real argument.
Definition IFunction1D.h:42
Implements the part of IFunction interface dealing with parameters.
void setParameter(size_t, const double &value, bool explicitlySet=true) override
Set i-th parameter.
size_t parameterIndex(const std::string &name) const override
Returns the index of parameter name.
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new 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 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.
virtual void massProfile(double *result, const size_t nData) const =0
Override to calculate the value of the profile for this mass and store in the given array.
std::vector< double > m_e0
Incident energies.
std::shared_ptr< const API::MatrixWorkspace > m_workspace
Current workspace.
void declareParameters() override
Declare parameters that will never participate in the fit.
std::shared_ptr< VesuvioResolution > m_resolutionFunction
Vesuvio resolution function.
ComptonProfile()
Default constructor required for factory.
void voigtApproxDiff(std::vector< double > &voigtDiff, const std::vector< double > &yspace, const double lorentzPos, const double lorentzAmp, const double lorentzWidth, const double gaussWidth) const
Compute Voigt function interpolated around the given values.
void setParameter(size_t i, const double &value, bool explicitlySet=true) override
Set i-th parameter.
void setMatrixWorkspace(std::shared_ptr< const API::MatrixWorkspace > workspace, size_t wsIndex, double startX, double endX) override
Cache a copy of the workspace pointer and pull out the parameters.
void buildCaches()
Initiate a Y-space value chache rebuild when workspace of mass are changed.
std::shared_ptr< API::IPeakFunction > m_voigt
Voigt function.
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.
void cacheYSpaceValues(const HistogramData::Points &tseconds, const Algorithms::DetectorParams &detpar, const ResolutionParams &respar)
Pre-calculate the Y-space values with specified resolution parameters.
size_t m_wsIndex
Current workspace index, required to access instrument parameters.
void setUpForFit() override
Ensure the object is ready to be fitted.
Calculate the resolution from a workspace of Vesuvio data using the mass & instrument definition.
void setEnabled(const bool enabled)
set if the logging is enabled
Definition Logger.cpp:90
Mantid::Kernel::SingletonHolder< FunctionFactoryImpl > FunctionFactory
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.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
Simple data structure to store nominal detector values It avoids some functions taking a huge number ...
Simple data structure to store resolution parameter values It avoids some functions taking a huge num...