1
2
3 """
4 Peaks and backgrounds.
5
6 Available peaks and backgrounds::
7
8 gauss, lorentz, voigt, quadratic
9 constant, linear
10
11 The functions are standardized to unit height at zero, but can be adjusted
12 with center, scale and width parameters.
13
14 Models corresponding to these use uppercase names. E.g.::
15
16 gauss(x, sigma=3, center=2, scale=4)
17
18 corresponds to::
19
20 m = Gauss(sigma=3, center=2, scale=4)
21 m(x)
22
23 The models define derivatives with respect to the parameters for the
24 individual evaluation points x. E.g.::
25
26 m.dsigma(x)
27 """
28
29 import numpy
30 from math import sqrt, pi
31
32
33 -def gauss(x, sigma=1, center=0, scale=1):
34 """
35 Gauss peak.
36
37 The formula used to calculate this is::
38
39 G(x) = exp( -0.5 (x-center)**2 / sigma**2 )
40
41 :Parameters:
42 sigma : real
43 The 1-sigma width of the Gaussian
44 center : real
45 Location of the center of the peak
46 scale : real
47 Value at the highest point of the peak
48
49 """
50 return scale*numpy.exp(-((numpy.asarray(x)-center)/sigma)**2)
51
52 -def lorentz(x, gamma=1, center=0, scale=1):
53 """
54 Lorentz peak.
55
56 The formula used to calculate this is::
57
58 L(x) = scale/pi gamma/((x-center)**2 + gamma**2)
59
60 :Parameters:
61 gamma : real
62 Half-width at half-maximum peak width
63 center : real
64 Location of the center of the peak
65 scale : real
66 Value at the highest point of the peak
67 """
68 return scale/numpy.pi * gamma/((x-center)**2 + gamma**2)
69
70 -def voigt(x, sigma=1, gamma=1, center=0, scale=1):
71 """
72 Voigt peak.
73
74 The voigt peak is the convolution of a Lorentz peak with a Gaussian peak.
75
76 The formula used to calculate this is::
77
78 z(x) = (x + 1j gamma) / (sqrt(2) sigma)
79 w(z) = exp(-z**2) erfc(-1j z) / (sqrt(2 pi) sigma)
80
81 V(x) = scale Re(w(z(x-center)))
82
83 :Parameters:
84 gamma : real
85 The half-width half-maximum of the Lorentzian
86 sigma : real
87 The 1-sigma width of the Gaussian, which is one standard deviation.
88 center : real
89 Location of the center of the peak
90 scale : real
91 Value at the highest point of the peak
92
93 Ref: W.I.F. David, J. Appl. Cryst. (1986). 19, 63-64
94
95 Note: adjusted to use stddev and HWHM rather than FWHM parameters
96 """
97
98 from scipy.special import wofz
99 z = (numpy.asarray(x)-center+1j*gamma)/(sigma*sqrt(2))
100 V = wofz(z)/(sqrt(2*pi)*sigma)
101 return scale*V.real
102
103 -def quadratic(x, width=1, center=0, scale=0):
104 """
105 Quadratic peak.
106
107 The formula used to calculate this is::
108
109 Q(x) = A ( 1 - ( (x - c)/w )**2 / 2 ) if |x-c| < w sqrt(2)
110 Q(x) = 0 otherwise
111
112 :Parameters:
113 width : real
114 The half-width half-maximum of the quadratic
115 center : real
116 Location of the center of the peak
117 scale : real
118 Value at the highest point of the peak
119 """
120 v = scale*(1 - ((numpy.asarray(x)-center)/width)**2/2)
121 v[v<0] = 0
122 return v
123
124 -def linear(x, center=0, scale=1):
125 """
126 Sloping background.
127
128 The background has unit height at zero.
129
130 The formula used to calculate this is::
131
132 S(x) = scale ( x - center + 1)
133
134 :Parameters:
135 center : real
136 Location of the zero crossing
137 scale : real
138 Slope of the line
139 """
140 return scale*(numpy.asarray(x) - center + 1)
141
143 """
144 Constant background.
145
146 The formula used to calculate this is::
147
148 C(x) = scale
149
150 :Parameters:
151 scale : real
152 Value at the highest point of the peak
153 """
154 return scale*numpy.ones(numpy.asarray(x).shape)
155
156
157
159 """Gauss peak: scale exp ( -0.5 (x-center)**2 / sigma**2 )"""
160 - def __init__(self, scale=1., center=0, sigma=1):
161 self.scale,self.center = scale,center
162 self.sigma = sigma
168 return self(x) * (x - self.center) / self.sigma**2
170 return self(x) * (x - self.center)**2 / self.sigma**3
171
173 """Lorentz peak (HWHM): scale/pi gamma/((x-center)**2 + gamma**2)"""
174 - def __init__(self, scale=1., center=0, gamma=1):
175 self.scale,self.center = scale,center
176 self.gamma = gamma
183 return self(x) * 2*(x-self.center)/((x-self.center)**2+self.gamma**2)
185 return self(x) * (1/self.gamma - self.gamma/((x-self.center)**2
186 + self.gamma**2))
187
189 """Voigt peak (HWHM,sigma): A [G(sigma) * L(gamma)](x-center)"""
190 - def __init__(self, scale=1, center=0, sigma=1, gamma=1):
191 self.scale,self.center = scale,center
192 self.sigma = sigma
193 self.gamma = gamma
195 return voigt(x, scale=self.scale, center=self.center,
196 sigma=self.sigma, gamma=self.gamma)
200
201 raise NotImplementedError
203
204 raise NotImplementedError
206
207 raise NotImplementedError
208
210 """Quadratic peak (HWHM): 1 - 1/2 ((x-c)/w)**2"""
211 - def __init__(self, scale=1, center=0, width=1):
212 self.scale, self.center = scale, center
213 self.width = width
220 v = self.scale/self.width**2 * (x-self.center)
221 v[abs(x-self.center) >= self.width*sqrt(2)] = 0
222 return v
224 v = self.scale/self.width**3 * (x-self.center)**2
225 v[abs(x-self.center) >= self.width*sqrt(2)] = 0
226 return v
227
229 """Linear background: scale (x - center + 1)"""
238
240 """Constant background: scale"""
247