def autobk(energy, mu, rbkg=1, nknots=None, group=None, e0=None, kmin=0, kmax=None, kw=1, dk=0, win=None, vary_e0=True, chi_std=None, nfft=2048, kstep=0.05, _larch=None): if _larch is None: raise Warning("cannot calculate autobk spline -- larch broken?") # get array indices for rkbg and e0: irbkg, ie0 rgrid = np.pi/(kstep*nfft) if rbkg < 2*rgrid: rbkg = 2*rgrid irbkg = int(1.01 + rbkg/rgrid) if e0 is None: e0 = find_e0(energy, mu, group=group, _larch=_larch) ie0 = _index_nearest(energy, e0) # save ungridded k (kraw) and grided k (kout) # and ftwin (*k-weighting) for FT in residual kraw = np.sqrt(ETOK*(energy[ie0:] - e0)) if kmax is None: kmax = max(kraw) kout = kstep * np.arange(int(1.01+kmax/kstep)) ftwin = kout**kw * ftwindow(kout, xmin=kmin, xmax=kmax, window=win, dx=dk) # calc k-value and initial guess for y-values of spline params nspline = max(4, min(60, 2*int(rbkg*(kmax-kmin)/np.pi) + 1)) spl_y = np.zeros(nspline) spl_k = np.zeros(nspline) for i in range(nspline): q = kmin + i*(kmax-kmin)/(nspline - 1) ik = _index_nearest(kraw, q) i1 = min(len(kraw)-1, ik + 5) i2 = max(0, ik - 5) spl_k[i] = kraw[ik] spl_y[i] = (2*mu[ik] + mu[i1] + mu[i2] ) / 4.0 # get spline represention: knots, coefs, order=3 # coefs will be varied in fit. knots, coefs, order = splrep(spl_k, spl_y) # set fit parameters from initial coefficients fparams = Parameters() for i, v in enumerate(coefs): fparams.add("c%i" % i, value=v, vary=i<len(spl_y)) fitkws = dict(knots=knots, order=order, kraw=kraw, mu=mu[ie0:], irbkg=irbkg, kout=kout, ftwin=ftwin, nfft=nfft) # do fit fit = Minimizer(__resid, fparams, fcn_kws=fitkws) fit.leastsq() # write final results coefs = [p.value for p in fparams.values()] bkg, chi = spline_eval(kraw, mu[ie0:], knots, coefs, order, kout) obkg = np.zeros(len(mu)) obkg[:ie0] = mu[:ie0] obkg[ie0:] = bkg if _larch.symtable.isgroup(group): setattr(group, 'bkg', obkg) setattr(group, 'chie', mu-obkg) setattr(group, 'k', kout) setattr(group, 'chi', chi)
def fft(self, k, chi): if self.kwin_array is None: self.kwin_array = ftwindow(k, xmin=self.kmin, xmax=self.kmax, dx=self.dk, dx2=self.dk2, window=self.window) cchi = zeros(self.nfft, dtype='complex128') cchi[0:len(chi)] = chi out = fft(cchi * self.kwin_array * k**self.kw) return self.kstep*sqrt(pi) * out[:self.nfft/2]
def ffti(self, chir): " reverse FT -- meant to be used internally" self.make_karrays() if self.rwin is None: self.rwin = ftwindow(self.r_, xmin=self.rmin, xmax=self.rmax, dx=self.dr, dx2=self.dr2, window=self.rwindow) cx = chir * self.rwin[:len(chir)] * self.r_[:len(chir)]**self.rw, return xafsift_fast(cx, kstep=self.kstep, nfft=self.nfft)
def ifft(self, r, chir): if self.rwin_array is None: self.rwin_array = ftwindow(r, xmin=self.rmin, xmax=self.rmax, dx=self.dr, dx2=self.dr2, window=self.rwindow) cchir = zeros(self.nfft, dtype='complex128') cchir[0:len(chir)] = chir out = ifft(cchir * self.rwin_array * r**self.rw) return sqrt(pi)/(2*self.kstep) * out[:self.nfft/2]
def fftf(self, chi, kweight=None): """ forward FT -- meant to be used internally. chi must be on self.k_ grid""" self.make_karrays() if self.kwin is None: self.kwin = ftwindow(self.k_, xmin=self.kmin, xmax=self.kmax, dx=self.dk, dx2=self.dk2, window=self.window) if kweight is None: kweight = self.get_kweight() cx = chi * self.kwin[:len(chi)] * self.k_[:len(chi)]**kweight return xafsft_fast(cx, kstep=self.kstep, nfft=self.nfft)
def fft(self, k, chi): if self.kwin_array is None: self.kwin_array = ftwindow(k, xmin=self.kmin, xmax=self.kmax, dx=self.dk, dx2=self.dk2, window=self.window) cchi = zeros(self.nfft, dtype='complex128') cchi[0:len(chi)] = chi out = fft(cchi * self.kwin_array * k**self.kw) return self.kstep * sqrt(pi) * out[:self.nfft / 2]
def ifft(self, r, chir): if self.rwin_array is None: self.rwin_array = ftwindow(r, xmin=self.rmin, xmax=self.rmax, dx=self.dr, dx2=self.dr2, window=self.rwindow) cchir = zeros(self.nfft, dtype='complex128') cchir[0:len(chir)] = chir out = ifft(cchir * self.rwin_array * r**self.rw) return sqrt(pi) / (2 * self.kstep) * out[:self.nfft / 2]
def autobk(energy, mu, rbkg=1, nknots=None, group=None, e0=None, kmin=0, kmax=None, kw=1, dk=0, win=None, vary_e0=True, chi_std=None, nfft=2048, kstep=0.05, _larch=None): if _larch is None: raise Warning("cannot calculate autobk spline -- larch broken?") # get array indices for rkbg and e0: irbkg, ie0 rgrid = np.pi / (kstep * nfft) if rbkg < 2 * rgrid: rbkg = 2 * rgrid irbkg = int(1.01 + rbkg / rgrid) if e0 is None: e0 = find_e0(energy, mu, group=group, _larch=_larch) ie0 = _index_nearest(energy, e0) # save ungridded k (kraw) and grided k (kout) # and ftwin (*k-weighting) for FT in residual kraw = np.sqrt(ETOK * (energy[ie0:] - e0)) if kmax is None: kmax = max(kraw) kout = kstep * np.arange(int(1.01 + kmax / kstep)) ftwin = kout**kw * ftwindow(kout, xmin=kmin, xmax=kmax, window=win, dx=dk) # calc k-value and initial guess for y-values of spline params nspline = max(4, min(60, 2 * int(rbkg * (kmax - kmin) / np.pi) + 1)) spl_y = np.zeros(nspline) spl_k = np.zeros(nspline) for i in range(nspline): q = kmin + i * (kmax - kmin) / (nspline - 1) ik = _index_nearest(kraw, q) i1 = min(len(kraw) - 1, ik + 5) i2 = max(0, ik - 5) spl_k[i] = kraw[ik] spl_y[i] = (2 * mu[ik] + mu[i1] + mu[i2]) / 4.0 # get spline represention: knots, coefs, order=3 # coefs will be varied in fit. knots, coefs, order = splrep(spl_k, spl_y) # set fit parameters from initial coefficients fparams = Parameters() for i, v in enumerate(coefs): fparams.add("c%i" % i, value=v, vary=i < len(spl_y)) fitkws = dict(knots=knots, order=order, kraw=kraw, mu=mu[ie0:], irbkg=irbkg, kout=kout, ftwin=ftwin, nfft=nfft) # do fit fit = Minimizer(__resid, fparams, fcn_kws=fitkws) fit.leastsq() # write final results coefs = [p.value for p in fparams.values()] bkg, chi = spline_eval(kraw, mu[ie0:], knots, coefs, order, kout) obkg = np.zeros(len(mu)) obkg[:ie0] = mu[:ie0] obkg[ie0:] = bkg if _larch.symtable.isgroup(group): setattr(group, 'bkg', obkg) setattr(group, 'chie', mu - obkg) setattr(group, 'k', kout) setattr(group, 'chi', chi)
def autobk(energy, mu, group=None, rbkg=1, nknots=None, e0=None, edge_step=None, kmin=0, kmax=None, kweight=1, dk=0, win='hanning', k_std=None, chi_std=None, nfft=2048, kstep=0.05, pre_edge_kws=None, debug=False, _larch=None, **kws): """Use Autobk algorithm to remove XAFS background Options are: rbkg -- distance out to which the chi(R) is minimized """ if _larch is None: raise Warning("cannot calculate autobk spline -- larch broken?") if 'kw' in kws: kweight = kws['kw'] energy = remove_dups(energy) # if e0 or edge_step are not specified, get them, either from the # passed-in group or from running pre_edge() if edge_step is None: if _larch.symtable.isgroup(group) and hasattr(group, 'edge_step'): edge_step = group.edge_step if e0 is None: if _larch.symtable.isgroup(group) and hasattr(group, 'e0'): e0 = group.e0 if e0 is None or edge_step is None: # need to run pre_edge: pre_kws = dict(nnorm=3, nvict=0, pre1=None, pre2=-50., norm1=100., norm2=None) if pre_edge_kws is not None: pre_kws.update(pre_edge_kws) edge_step, e0 = pre_edge(energy, mu, group=group, _larch=_larch, **pre_kws) # get array indices for rkbg and e0: irbkg, ie0 ie0 = index_nearest(energy, e0) rgrid = np.pi/(kstep*nfft) if rbkg < 2*rgrid: rbkg = 2*rgrid irbkg = int(1.01 + rbkg/rgrid) # save ungridded k (kraw) and grided k (kout) # and ftwin (*k-weighting) for FT in residual kraw = np.sqrt(ETOK*(energy[ie0:] - e0)) if kmax is None: kmax = max(kraw) kout = kstep * np.arange(int(1.01+kmax/kstep), dtype='float64') # interpolate provided chi(k) onto the kout grid if chi_std is not None and k_std is not None: chi_std = np.interp(kout, k_std, chi_std) ftwin = kout**kweight * ftwindow(kout, xmin=kmin, xmax=kmax, window=win, dx=dk) # calc k-value and initial guess for y-values of spline params nspline = max(4, min(60, 2*int(rbkg*(kmax-kmin)/np.pi) + 1)) spl_y = np.zeros(nspline) spl_k = np.zeros(nspline) spl_e = np.zeros(nspline) for i in range(nspline): q = kmin + i*(kmax-kmin)/(nspline - 1) ik = index_nearest(kraw, q) i1 = min(len(kraw)-1, ik + 5) i2 = max(0, ik - 5) spl_k[i] = kraw[ik] spl_e[i] = energy[ik+ie0] spl_y[i] = (2*mu[ik+ie0] + mu[i1+ie0] + mu[i2+ie0] ) / 4.0 # get spline represention: knots, coefs, order=3 # coefs will be varied in fit. knots, coefs, order = splrep(spl_k, spl_y) # set fit parameters from initial coefficients ncoefs = len(coefs) params = Group() for i in range(ncoefs): name = FMT_COEF % i p = Parameter(coefs[i], name=name, vary=i<len(spl_y)) p._getval() setattr(params, name, p) initbkg, initchi = spline_eval(kraw, mu[ie0:], knots, coefs, order, kout) fitkws = dict(ncoefs=len(coefs), chi_std=chi_std, knots=knots, order=order, kraw=kraw, mu=mu[ie0:], irbkg=irbkg, kout=kout, ftwin=ftwin, nfft=nfft) # do fit fit = Minimizer(__resid, params, fcn_kws=fitkws, _larch=_larch, toler=1.e-4) fit.leastsq() # write final results coefs = [getattr(params, FMT_COEF % i) for i in range(ncoefs)] bkg, chi = spline_eval(kraw, mu[ie0:], knots, coefs, order, kout) obkg = np.zeros(len(mu)) obkg[:ie0] = mu[:ie0] obkg[ie0:] = bkg if _larch.symtable.isgroup(group): group.bkg = obkg group.chie = (mu-obkg)/edge_step group.k = kout group.chi = chi/edge_step if debug: group.spline_params = params ix_bkg = np.zeros(len(mu)) ix_bkg[:ie0] = mu[:ie0] ix_bkg[ie0:] = initbkg group.init_bkg = ix_bkg group.init_chi = initchi/edge_step group.spline_e = spl_e group.spline_y = np.array([coefs[i] for i in range(nspline)]) group.spline_yinit = spl_y