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
« 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
4"""
5import numpy as np
6from .mca import isLarchMCAGroup
8def xrf_background(energy, counts=None, group=None, width=None, exponent=2, **kws):
9 """fit background for XRF spectra.
11 xrf_background(energy, counts=None, group=None, exponent=2)
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
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.
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
35 nchans = len(counts)
36 slope = energy[1] - energy[0]
37 if width is None:
38 width = max(energy)/4.0
40 tcounts = 1.0 * counts
41 tcounts[np.where(tcounts<1.e-12)] = 1.e-12
43 bgr = 0*counts
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)
54 ch0 = np.arange(nchans) + 1 - nx
55 ch0[np.where(ch0 < 0)] = 0
57 ch1 = np.arange(nchans) + nx
58 ch1[np.where(ch1 > nchans)] = nchans
60 ix1 = np.linspace(nx-1, nx-nchans, nchans, dtype='i4')
61 ix1[np.where(ix1 < 0)] = 0
63 ix2 = np.linspace(nx+nchans-1, nx, nchans, dtype='i4')
64 ix2[np.where(ix2 > (2*nx-1))] = 2*nx-1
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)
72 bgr[np.where(bgr < 0)] = 0.0
73 bgr[np.where(counts < 1)] = 0.0
75 if group is not None:
76 group.bgr = bgr
77 group.bgr_info = dict(width=width, exponent=exponent)
78 return bgr