-
Notifications
You must be signed in to change notification settings - Fork 122
/
PseudoVoigt.cpp
92 lines (69 loc) · 2.8 KB
/
PseudoVoigt.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "MantidCurveFitting/Functions/PseudoVoigt.h"
#include "MantidAPI/FunctionFactory.h"
#include "MantidCurveFitting/Constraints/BoundaryConstraint.h"
#include <cmath>
namespace Mantid {
namespace CurveFitting {
namespace Functions {
using namespace CurveFitting;
using namespace Constraints;
using namespace API;
DECLARE_FUNCTION(PseudoVoigt)
void PseudoVoigt::functionLocal(double *out, const double *xValues,
const size_t nData) const {
double h = getParameter("Height");
double x0 = getParameter("PeakCentre");
double f = getParameter("FWHM");
double gFraction = getParameter("Mixing");
double lFraction = 1.0 - gFraction;
// Lorentzian parameter gamma...fwhm/2
double g = f / 2.0;
double gSquared = g * g;
// Gaussian parameter sigma...fwhm/(2*sqrt(2*ln(2)))...gamma/sqrt(2*ln(2))
double sSquared = gSquared / (2.0 * M_LN2);
for (size_t i = 0; i < nData; ++i) {
double xDiffSquared = (xValues[i] - x0) * (xValues[i] - x0);
out[i] = h * (gFraction * exp(-0.5 * xDiffSquared / sSquared) +
(lFraction * gSquared / (xDiffSquared + gSquared)));
}
}
void PseudoVoigt::functionDerivLocal(Jacobian *out, const double *xValues,
const size_t nData) {
double h = getParameter("Height");
double x0 = getParameter("PeakCentre");
double f = getParameter("FWHM");
double gFraction = getParameter("Mixing");
double lFraction = 1.0 - gFraction;
// Lorentzian parameter gamma...fwhm/2
double g = f / 2.0;
double gSquared = g * g;
// Gaussian parameter sigma...fwhm/(2*sqrt(2*ln(2)))...gamma/sqrt(2*ln(2))
double sSquared = gSquared / (2.0 * M_LN2);
for (size_t i = 0; i < nData; ++i) {
double xDiff = (xValues[i] - x0);
double xDiffSquared = xDiff * xDiff;
double expTerm = exp(-0.5 * xDiffSquared / sSquared);
double lorentzTerm = gSquared / (xDiffSquared + gSquared);
out->set(i, 0, h * (expTerm - lorentzTerm));
out->set(i, 1, gFraction * expTerm + lFraction * lorentzTerm);
out->set(i, 2, h * xDiff * (gFraction * expTerm / sSquared +
lFraction * lorentzTerm * 2.0 /
(xDiffSquared + gSquared)));
out->set(i, 3, h * (gFraction * expTerm * xDiffSquared / sSquared / f +
lFraction * lorentzTerm *
(1.0 / g - g / (xDiffSquared + gSquared))));
}
}
void PseudoVoigt::init() {
declareParameter("Mixing", 1.0);
declareParameter("Height");
declareParameter("PeakCentre");
declareParameter("FWHM");
BoundaryConstraint *mixingConstraint =
new BoundaryConstraint(this, "Mixing", 0.0, 1.0, true);
mixingConstraint->setPenaltyFactor(1e9);
addConstraint(mixingConstraint);
}
} // namespace Functions
} // namespace CurveFitting
} // namespace Mantid