File: extra_exafs.py

package info (click to toggle)
python-extranormal3 0.0.3-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 108 kB
  • sloc: python: 450; makefile: 3
file content (179 lines) | stat: -rw-r--r-- 6,096 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env python3
#######################################

import sys
import os
import os.path

import logging
# ------------------------ logging levels ------------------------------------
logging.basicConfig(level= logging.DEBUG,
                    format='%(module)s.%(funcName)s: %(levelname)-7s: %(message)s')  
config_log = logging.INFO
# ----------------------------------------------------------------------------

import numpy
from scipy import optimize, interpolate

from extranormal3 import curved_tools

#------------
K_step = 0.05
K_max_margin = 1
#------------

def get_idx_bounds(ene, sample_edge, ek_start, ek_end):
    
    E_bounds = True    
    
    if E_bounds:
        logging.debug('Emin = '+ str(ek_start) +', Emax = '+ str(ek_end))
        
        rel_Ebounds = True if sample_edge > ek_start else False        
        logging.debug('In get_idx_bounds: ABSOLUTE values for energy bounds are given')
        '''
        if not rel_Ebounds:  # get them relative
            e_start = e_start - edge
            e_end = e_end - edge
            rel_Ebounds = True
        '''
        if rel_Ebounds:
            start_idx = min(ene.searchsorted(sample_edge + ek_start), len(ene)-10)
            end_idx = min(ene.searchsorted(sample_edge + ek_end), len(ene)-1)
        else: 
            start_idx = min(ene.searchsorted(ek_start), len(ene)-10)
            end_idx = min(ene.searchsorted(ek_end), len(ene)-1)
        
        logging.debug(' Idx bounds: '+ str(start_idx) +' and '+ str(end_idx))
        
    else:  # k2energy
        logging.debug(' K bounds given: '+ str(ek_start) +', '+ str(ek_end))
        
        e_start = ek_start**2/0.2625
        e_end = ek_end**2/0.2625            
        logging.debug(" E bounds: "+ str(e_start) +', '+ str(e_end))
        
        start_idx = ene.searchsorted(sample_edge + e_start)
        if ene[start_idx]- (sample_edge + e_start) > (sample_edge + e_start) - ene[start_idx-1]:
            start_idx -= 1
        
        end_idx = min(ene.searchsorted(sample_edge + e_end), len(ene)-1)            
        logging.debug(' Idx bounds: '+ str(start_idx) +' and '+ str(end_idx))
        
    return start_idx, end_idx
    

def get_K_points(ene, sample_edge, start_idx, end_idx):
    '''
    should be called just ones
    '''
    if ene[start_idx] < sample_edge:
        raise Exception(' Invalid index when converting E to K')
    
    E_points = ene[start_idx:end_idx]
    K_points = numpy.sqrt(0.2625 * (E_points-sample_edge))
    nb_points = int((K_points[-1] - K_points[0])/K_step)
    K_interp = numpy.array([K_points[0] + K_step*i for i in range(nb_points)])
    
    return K_interp, K_points


def polynomial(k_points, mu_in_bounds, k_interp, I_jump, poly_deg, kweight, 
               plot=False):
    
    if I_jump == 0.:
        raise Exception(' Intensity jump at edge cannot aqual to zero')
        
    mu_calc = interpolate.interp1d(k_points, mu_in_bounds, 'linear', bounds_error=False, fill_value=0.)
    mu_interp = mu_calc(k_interp)
    
    '''
    fit_sigma = [k_interp[-1]**kweight for i in range(20)]
    fit_sigma = fit_sigma + [1./k_interp[i]**kweight for i in range(20, len(k_interp))]
    '''
    bkg_polynomial = optimize.curve_fit(curved_tools.poly_calc, k_interp, mu_interp, 
                                        [1.,]*poly_deg+[mu_interp[0]], 
                                        sigma=1./k_interp**kweight
                                        #sigma=fit_sigma
                                        )[0]
                                        
    bkg = numpy.polyval(bkg_polynomial, k_interp)
    
    if plot:
        import pylab
        pylab.plot(k_interp, bkg)
        
    chi_vals = (mu_interp - bkg)/I_jump
    
    return chi_vals, bkg
        
                    
#class NoJunpsEx(Exception): pass
    
def extract_all(energies, abs_data, edge, I_jumps, e_start, e_end,
                poly_deg, kweight, m):
    '''
    *** This function is applicable to the interpolated data ***
    
    data : data[0] = energies, data[1:] = absorbance columns
    '''
    if any([len(energies) != len(vals) for vals in abs_data]):
        raise Exception(' Invalid data format')
            
    if len(I_jumps) != len(abs_data):
        raise Exception(' Invalid data format or inconsistent meta data')
        #raise NoJunpsEx(' Invalid data format or inconsistent meta data')
        
    '''
    rel_Ebounds = True if edge > e_start else False
        
    if not rel_Ebounds:  # get them relative
        e_start = e_start - edge
        e_end = e_end - edge
        rel_Ebounds = True
    '''
    
    #  e_start, e_end are for the moment ABSOLUTE (not relative to Edge)
    start_idx, end_idx = get_idx_bounds(energies, edge, e_start, e_end)  
    
    k_interp, k_points = get_K_points(energies, edge, start_idx, end_idx) 
    logging.debug(' Kmin = '+ str(k_points[0]) +',  Kmax = '+ str(k_points[-1]))
    
    '''
    end_idx = min(energies.searchsorted(edge + e_end), len(energies)-1)
    kmax_extra = numpy.sqrt(0.2625 * (energies[end_idx] - edge))
    '''
    kmax_extra = k_points[-1]
    
    if poly_deg <= 0:
        poly_deg = min(9, int(numpy.round(kmax_extra/2.)))
        print ('Auto defined poly_deg = '+ str(poly_deg))
    
    if kweight <= 0:
        if kmax_extra >=16:
            kweight = 3
        elif 12 < kmax_extra < 16:
            kweight = 2
        elif kmax_extra < 12:
            kweight =1
        print ('Auto defined kweight = '+ str(kweight))
        
    otvet = [polynomial(k_points, abs_data[i][start_idx: end_idx], k_interp, I_jumps[i], poly_deg, kweight)
             for i in range(len(abs_data))]
    
    exafs_list = []
    Km_exafs_list = []
    bkgr_list = []
    for tuple_instance in otvet:
        exafs_list.append(tuple_instance[0])
        Km_exafs_list.append((k_interp**m)*tuple_instance[0])
        bkgr_list.append(tuple_instance[1])

    exafs = numpy.array(exafs_list)
    Km_exafs= numpy.array(Km_exafs_list)
    bkgr = numpy.array(bkgr_list)
        
    return Km_exafs, exafs, bkgr