Coverage for /Users/Newville/Codes/xraylarch/larch/xrf/xrf_bgr.py: 8%

40 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-09 10:08 -0600

1""" 

2Methods for fitting background in energy dispersive xray spectra 

3 

4""" 

5import numpy as np 

6from .mca import isLarchMCAGroup 

7 

8def xrf_background(energy, counts=None, group=None, width=None, exponent=2, **kws): 

9 """fit background for XRF spectra. 

10 

11 xrf_background(energy, counts=None, group=None, exponent=2) 

12 

13 Arguments 

14 --------- 

15 energy array of energies OR an MCA group. If an MCA group, 

16 it will be used to give ``counts`` and ``mca`` arguments 

17 counts array of XRF counts (or MCA.counts) 

18 group group for outputs 

19 

20 width full width (in keV) of the concave down polynomials when its 

21 value is ~1% of max counts. Default width is (energy range)/4.0 

22 exponent power of polynomial used. Default is 2, should be even. 

23 

24 Outputs (written to group) 

25 ------- 

26 bgr background array 

27 bgr_info dictionary of parameters used to calculate background 

28 """ 

29 if isLarchMCAGroup(energy): 

30 group = energy 

31 energy = group.energy 

32 if counts is None: 

33 counts = group.counts 

34 

35 nchans = len(counts) 

36 slope = energy[1] - energy[0] 

37 if width is None: 

38 width = max(energy)/4.0 

39 

40 tcounts = 1.0 * counts 

41 tcounts[np.where(tcounts<1.e-12)] = 1.e-12 

42 

43 bgr = 0*counts 

44 

45 # use 99% percentile of counts as height at which 

46 # the polynomial should have full width = width 

47 max_count = np.percentile(tcounts, [99])[0] 

48 indices = np.linspace(-nchans, nchans, 2*nchans+1) * (2.0 * slope / width) 

49 polynom = 0.01 * max_count * indices**exponent 

50 polynom = np.compress((polynom <= max_count), polynom) 

51 max_index = int(len(polynom)/2 - 1) 

52 nx = int(len(polynom)/2) 

53 

54 ch0 = np.arange(nchans) + 1 - nx 

55 ch0[np.where(ch0 < 0)] = 0 

56 

57 ch1 = np.arange(nchans) + nx 

58 ch1[np.where(ch1 > nchans)] = nchans 

59 

60 ix1 = np.linspace(nx-1, nx-nchans, nchans, dtype='i4') 

61 ix1[np.where(ix1 < 0)] = 0 

62 

63 ix2 = np.linspace(nx+nchans-1, nx, nchans, dtype='i4') 

64 ix2[np.where(ix2 > (2*nx-1))] = 2*nx-1 

65 

66 for chan in range(nchans-1): 

67 c0, c1, i0, i1 = ch0[chan], ch1[chan], ix1[chan], ix2[chan] 

68 offset = tcounts[chan] - polynom[i0:i1] 

69 tmax = offset + min(tcounts[c0:c1] - offset) 

70 bgr[c0:c1] = np.maximum(bgr[c0:c1], tmax) 

71 

72 bgr[np.where(bgr < 0)] = 0.0 

73 bgr[np.where(counts < 1)] = 0.0 

74 

75 if group is not None: 

76 group.bgr = bgr 

77 group.bgr_info = dict(width=width, exponent=exponent) 

78 return bgr