Coverage for /Users/Newville/Codes/xraylarch/larch/xrf/xrf_peak.py: 22%
73 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
1#!/usr/bin/env python
2"""
3provide xrf_peak() function to create an XRF_Peak.
4This is a Larch group representing a Peak in an XRF Spectrum.
6 group = xrf_peak()
8"""
9import numpy as np
10from scipy.interpolate import UnivariateSpline
12from xraydb import xray_line
14from larch import Group
15from ..fitting import Parameter, isParameter, param_value
16from ..math import gaussian, lorentzian, voigt, pvoigt
18class XRFPeak(Group):
19 def __init__(self, name=None, shape='gaussian',
20 amplitude=1, center=0, sigma=1,
21 sigma_params=None, **kws):
22 kwargs = {'name': name}
23 kwargs.update(kws)
24 self.amplitude = amplitude
25 self.center = center
26 self.sigma = sigma
27 Group.__init__(self)
28 self.name = name
29 if name is not None:
30 self._define(name, shape=shape,
31 sigma_params=sigma_params)
33 def _define(self, name, shape='gaussian', sigma_params=None):
34 self.shape = shape
35 if name is None:
36 return
37 try:
38 elem, line = [w.title() for w in name.split()]
39 except:
40 return
41 if line == 'Ka': line='Ka1'
43 dat = xray_line(elem, line)
44 if dat is not None:
45 ecenter = dat.energy
46 if self.center is None:
47 self.center = Parameter(name='center', value=ecenter,
48 vary=False)
50 if sigma_params is not None:
51 if len(sigma_params) == 2 and self.sigma is None:
52 if isParameter(sigma_params[0]):
53 sigma_params = (sigma_params[0].name,
54 sigma_params[1].name)
55 expr = "%s + %s * %f" % (sigma_params[0],
56 sigma_params[1],
57 ecenter)
58 self.sigma = Parameter(name='sigma', expr=expr)
60 def __repr__(self):
61 if self.name is not None:
62 return '<XRFPeak Group: %s>' % self.name
63 return '<XRFPeak Group (unknown)>'
65 def __copy__(self):
66 return XRFPeak(name=self.name)
68 def __deepcopy__(self, memo):
69 return XRFPeak(filename=self.ename)
72 def _peakparams(self, paramgroup=None, **kws):
73 """evaluate peak parameter values """
74 # sigma, amplitude, center
75 out = []
76 for parname in ('amplitude', 'sigma', 'center'):
77 val = getattr(self, parname)
78 if parname in kws:
79 if kws[parname] is not None:
80 val = kws[parname]
81 if isinstance(val, str):
82 thispar = Parameter(expr=val)
83 setattr(self, parname, thispar)
84 val = getattr(self, parname)
85 out.append(param_value(val))
86 return out
88 def calc_peak(self, x, amplitude=None, center=None, sigma=None,
89 shape=None, **kws):
90 """
91 calculate peak function for x values, write to 'counts' attribute
92 """
93 (amp, sigma, center) = self._peakparams(amplitude=amplitude,
94 center=center,
95 sigma=sigma)
96 fcn = gaussian
97 if shape is None:
98 shape = self.shape
99 if shape.lower().startswith('loren'):
100 fcn = lorentzian
101 elif shape.lower().startswith('voig'):
102 fcn = voigt
103 elif shape.lower().startswith('pvoig'):
104 fcn = pvoigt
106 self.counts = amp*fcn(x, cen=center, sigma=sigma)
109def xrf_peak(name=None, amplitude=1, sigma=0.1, center=None,
110 shape='gaussian', sigma_params=None, **kws):
111 """create an XRF Peak
113 Parameters:
114 -----------
115 name: name of peak -- may be used for auto-setting center
116 'Fe Ka1', 'Pb Lb1', etc
117 amplitude:
118 center:
119 sigma:
120 shape peak shape (gaussian, voigt, lorentzian)
122 For all the options described as **value or parameter** either a
123 numerical value or a Parameter (as created by param()) can be given.
125 Returns:
126 ---------
127 an XRFPeak Group.
129 """
130 return XRFPeak(name=name, amplitude=amplitude, sigma=sigma, center=center,
131 shape=shape, sigma_params=sigma_params)