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

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. 

5 

6 group = xrf_peak() 

7 

8""" 

9import numpy as np 

10from scipy.interpolate import UnivariateSpline 

11 

12from xraydb import xray_line 

13 

14from larch import Group 

15from ..fitting import Parameter, isParameter, param_value 

16from ..math import gaussian, lorentzian, voigt, pvoigt 

17 

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) 

32 

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' 

42 

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) 

49 

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) 

59 

60 def __repr__(self): 

61 if self.name is not None: 

62 return '<XRFPeak Group: %s>' % self.name 

63 return '<XRFPeak Group (unknown)>' 

64 

65 def __copy__(self): 

66 return XRFPeak(name=self.name) 

67 

68 def __deepcopy__(self, memo): 

69 return XRFPeak(filename=self.ename) 

70 

71 

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 

87 

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 

105 

106 self.counts = amp*fcn(x, cen=center, sigma=sigma) 

107 

108 

109def xrf_peak(name=None, amplitude=1, sigma=0.1, center=None, 

110 shape='gaussian', sigma_params=None, **kws): 

111 """create an XRF Peak 

112 

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) 

121 

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. 

124 

125 Returns: 

126 --------- 

127 an XRFPeak Group. 

128 

129 """ 

130 return XRFPeak(name=name, amplitude=amplitude, sigma=sigma, center=center, 

131 shape=shape, sigma_params=sigma_params)