Mantid
Loading...
Searching...
No Matches
EstimatePeakErrors.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 +
10
15#include "MantidAPI/TableRow.h"
17
19using namespace API;
20using namespace Kernel;
21using namespace std;
22
23// Subscription
24DECLARE_ALGORITHM(EstimatePeakErrors)
25
26//--------------------------------------------------------------------------------------------------------
27// Public members
28//--------------------------------------------------------------------------------------------------------
29
30
32
34const std::string EstimatePeakErrors::summary() const {
35 return "Calculates error estimates for peak parameters: "
36 "centre, height, FWHM and intensity.";
37}
38
39const std::string EstimatePeakErrors::name() const { return "EstimatePeakErrors"; }
40
41int EstimatePeakErrors::version() const { return 1; }
42
43const std::string EstimatePeakErrors::category() const { return "Optimization"; }
44
45//--------------------------------------------------------------------------------------------------------
46// Private members
47//--------------------------------------------------------------------------------------------------------
48namespace {
49
59EigenMatrix makeJacobian(IPeakFunction &peak, double &centre, double &height, double &fwhm, double &intensity) {
60 EigenMatrix jacobian(4, peak.nParams());
61 centre = peak.centre();
62 height = peak.height();
63 fwhm = peak.fwhm();
64 intensity = peak.intensity();
65 for (size_t ip = 0; ip < peak.nParams(); ++ip) {
66 double p = peak.getParameter(ip);
67 double dp = 1e-9;
68 if (p != 0.0) {
69 dp *= p;
70 }
71 peak.setParameter(ip, p + dp);
72 jacobian.set(0, ip, (peak.centre() - centre) / dp);
73 jacobian.set(1, ip, (peak.height() - height) / dp);
74 jacobian.set(2, ip, (peak.fwhm() - fwhm) / dp);
75 jacobian.set(3, ip, (peak.intensity() - intensity) / dp);
76 peak.setParameter(ip, p);
77 }
78 return jacobian;
79}
80
86void calculatePeakValues(IPeakFunction &peak, ITableWorkspace &results, const EigenMatrix &covariance,
87 const std::string &prefix) {
88 double centre, height, fwhm, intensity;
89 EigenMatrix J = makeJacobian(peak, centre, height, fwhm, intensity);
90 EigenMatrix JCJ = J * covariance * J.tr();
91
92 TableRow row = results.appendRow();
93 row << prefix + "Centre" << centre << sqrt(JCJ.get(0, 0));
94 row = results.appendRow();
95 row << prefix + "Height" << height << sqrt(JCJ.get(1, 1));
96 row = results.appendRow();
97 row << prefix + "FWHM" << fwhm << sqrt(JCJ.get(2, 2));
98 row = results.appendRow();
99 row << prefix + "Intensity" << intensity << sqrt(JCJ.get(3, 3));
100}
101} // namespace
102
104void EstimatePeakErrors::init() {
105
106 declareProperty(std::make_unique<FunctionProperty>("Function", Direction::InOut),
107 "Fitting function containing peaks. Must have a covariance "
108 "matrix attached.");
109
111 std::make_unique<API::WorkspaceProperty<API::ITableWorkspace>>("OutputWorkspace", "", Kernel::Direction::Output),
112 "The name of the TableWorkspace with the output values and errors.");
113}
114
116void EstimatePeakErrors::exec() {
117
118 IFunction_sptr function = getProperty("Function");
119
120 ITableWorkspace_sptr results = WorkspaceFactory::Instance().createTable("TableWorkspace");
121 results->addColumn("str", "Parameter");
122 results->addColumn("double", "Value");
123 results->addColumn("double", "Error");
124
125 auto matrix = function->getCovarianceMatrix();
126 if (!matrix) {
127 g_log.warning() << "Function doesn't have covariance matrix.\n";
128 setProperty("OutputWorkspace", results);
129 return;
130 }
131
132 auto *peak = dynamic_cast<IPeakFunction *>(function.get());
133
134 if (peak) {
135 EigenMatrix covariance(*matrix);
136 calculatePeakValues(*peak, *results, covariance, "");
137 } else {
138 auto *cf = dynamic_cast<CompositeFunction *>(function.get());
139 if (cf) {
140 size_t ip = 0;
141 for (size_t i = 0; i < cf->nFunctions(); ++i) {
142 IFunction *fun = cf->getFunction(i).get();
143 size_t np = fun->nParams();
144 peak = dynamic_cast<IPeakFunction *>(fun);
145 if (peak) {
146 std::string prefix = "f" + std::to_string(i) + ".";
147 EigenMatrix covariance(*matrix, ip, ip, np, np);
148 calculatePeakValues(*peak, *results, covariance, prefix);
149 }
150 ip += np;
151 }
152 } else {
153 g_log.warning() << "Function has no peaks.\n";
154 }
155 }
156
157 setProperty("OutputWorkspace", results);
158}
159
160} // namespace Mantid::CurveFitting::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double height
Definition: GetAllEi.cpp:155
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
A composite function is a function containing other functions.
virtual double height() const =0
Returns the height of the function.
virtual double centre() const =0
Returns the centre of the function, which may be something as simple as the centre of the fitting ran...
This is an interface to a fitting function - a semi-abstarct class.
Definition: IFunction.h:163
virtual size_t nParams() const =0
Total number of parameters.
virtual std::shared_ptr< IFunction > getFunction(size_t i) const
Returns the pointer to i-th child function.
Definition: IFunction.cpp:1363
An interface to a peak function, which extend the interface of IFunctionWithLocation by adding method...
Definition: IPeakFunction.h:51
virtual double fwhm() const =0
Returns the peak FWHM.
virtual double intensity() const
Returns the integral intensity of the peak.
void setParameter(const std::string &name, const double &value, bool explicitlySet=true) override
Override parent so that we may bust the cache when a parameter is set.
size_t nParams() const override
Total number of parameters.
Definition: ParamFunction.h:53
double getParameter(size_t i) const override
Get i-th parameter.
A property class for workspaces.
A wrapper around Eigen::Matrix.
Definition: EigenMatrix.h:33
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Output
An output workspace.
Definition: Property.h:54