def setUp(self): self.param1 = Parameter(name='a', value=2.0, vary=True, min=0) self.param2 = Parameter(name='b', expr='sqrt(x/2)') self.group1 = Group(a=1.030405, label='a string', opts={ 'a': 1, 'b': 2 }, x=np.linspace(0, 10, 21), y=np.sqrt(np.arange(3) / 5.)) self.group2 = Group(par1=Parameter(name='p1', value=3.0, min=0.0, vary=False), par2=Parameter(name='p2', value=1.0, vary=True), sub=Group(label='a label', x=np.linspace(0, 10, 21))) self.group3 = Group(par1=Parameter(name='p1', value=3.0, min=0.0), dx={ 'a': 1.3 + 0.2j, 'blist': [1, 2, 3.0], 'tup': (0, None) })
def _define(self, name, shape='gaussian', sigma_params=None): self.shape = shape if name is None: return try: elem, line = [w.title() for w in name.split()] except: return if line == 'Ka': line = 'Ka1' dat = xray_line(elem, line, _larch=self._larch) if dat is not None: ecenter = dat[0] if self.center is None: self.center = Parameter(name='center', value=ecenter, vary=False, _larch=self._larch) if sigma_params is not None: if len(sigma_params) == 2 and self.sigma is None: if isParameter(sigma_params[0]): sigma_params = (sigma_params[0].name, sigma_params[1].name) expr = "%s + %s * %f" % (sigma_params[0], sigma_params[1], ecenter) self.sigma = Parameter(name='sigma', expr=expr, _larch=self._larch)
def __init__(self, parent=None, size=(-1, -1)): wx.Frame.__init__(self, parent, -1, 'Parameter Panel Test', size=size, style=wx.DEFAULT_FRAME_STYLE) panel = GridPanel(self) name1 = 'peak1_amp' param1 = Parameter(value=99.0, vary=True, min=0, name=name1) name2 = 'peak1_cen' param2 = Parameter(value=1.23, vary=True, min=0.5, max=2.0, name=name2) p1 = ParameterPanel(panel, param1) p2 = ParameterPanel(panel, param2) panel.AddText(" %s: " % name1, style=LEFT) panel.Add(p1, style=LEFT) panel.NewRow() panel.AddText(" %s: " % name2, style=LEFT) panel.Add(p2, style=LEFT) panel.pack() self.createMenus() self.SetSize((400, 90)) self.Show() self.Raise()
def __init__(self, parent=None, size=(-1, -1)): wx.Frame.__init__(self, parent, -1, 'Parameter Panel Test', size=size, style=wx.DEFAULT_FRAME_STYLE) panel = GridPanel(self) param1 = Parameter(value=99.0, vary=True, min=0, name='peak1_amplitude') param2 = Parameter(value=110.2, vary=True, min=100, max=120, name='peak1_center') param3 = Parameter(value=1.23, vary=True, min=0.5, max=2.0, name='peak1_sigma') panel.Add(ParameterPanel(panel, param1, show_name=True), style=LEFT) # panel.NewRow() panel.Add(ParameterPanel(panel, param2, show_name=True), style=LEFT) panel.Add(ParameterPanel(panel, param3, show_name=True), style=LEFT) panel.pack() self.createMenus() self.SetSize((700, 200)) self.Show() self.Raise()
def fitpeaks_page(self): "create row for filters parameters" mca = self.parent.mca self.wids.peaks = [] p = GridPanel(self) p.AddManyText((' ROI Name', 'Fit?', 'Center', 'Sigma', 'Amplitude'), style=CEN) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) offset, slope = self.mca.offset, self.mca.slope for iroi, roi in enumerate(self.mca.rois): try: cenval, ecen, fwhm, ampval, _x = self.mca.init_calib[roi.name] except KeyError: continue sigval = 0.4 * fwhm mincen = offset + slope * (roi.left - 4 * roi.bgr_width) maxcen = offset + slope * (roi.right + 4 * roi.bgr_width) pname = roi.name.replace(' ', '').lower() ampnam = '%s_amp' % pname cennam = '%s_cen' % pname signam = '%s_sig' % pname sigexpr = "%s + %s*%s +%s*%s**2" % (self.gsig_offset, self.gsig_slope, cennam, self.gsig_quad, cennam) p_amp = Parameter(value=ampval, vary=True, min=0, name=ampnam) p_sig = Parameter(value=sigval, expr=sigexpr, min=0, name=signam) p_cen = Parameter(value=cenval, vary=False, name=cennam, min=mincen, max=maxcen) setattr(self.paramgroup, ampnam, p_amp) setattr(self.paramgroup, cennam, p_cen) setattr(self.paramgroup, signam, p_sig) _use = Check(p, label='use', default=True) _cen = ParameterPanel(p, p_cen, precision=3) _sig = ParameterPanel(p, p_sig, precision=3) _amp = ParameterPanel(p, p_amp, precision=2) self.wids.peaks.append((_use, _cen, _sig, _amp)) p.AddText(' %s' % roi.name, newrow=True, style=LEFT) p.Add(_use, style=wx.ALIGN_CENTER) p.Add(_cen) p.Add(_sig) p.Add(_amp) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) p.pack() return p
def decode4js(obj): """ return decoded Python object from encoded object. """ out = obj if isinstance(obj, dict): classname = obj.pop('__class__', None) if classname is None: return obj elif classname == 'Complex': out = obj['value'][0] + 1j*obj['value'][1] elif classname in ('List', 'Tuple'): out = [] for item in obj['value']: out.append(decode4js(item)) if classname == 'Tuple': out = tuple(out) elif classname == 'Array': if obj['__dtype__'].startswith('complex'): re = np.fromiter(obj['value'][0], dtype='double') im = np.fromiter(obj['value'][1], dtype='double') out = re + 1j*im else: out = np.fromiter(obj['value'], dtype=obj['__dtype__']) out.shape = obj['__shape__'] elif classname in ('Dict', 'Parameter', 'Group'): out = {} for key, val in obj.items(): out[key] = decode4js(val) if classname == 'Parameter': out = Parameter(**out) elif classname == 'Group': out = Group(**out) return out
def get_component(val): if isinstance(val, h5py.Group): ltype = val.attrs.get('larchtype', None) if ltype == 'group': me = make_group(val) for skey, sval in val.items(): setattr(me, skey, get_component(sval)) return me elif ltype == 'parameter': kws = json.loads(val['json'].value) if kws['expr'] is not None: kws.pop('val') kws['_larch'] = _larch return Parameter(**kws) elif ltype in ('list', 'tuple'): me = [] for skey, sval in val.items(): me.append(get_component(sval)) if ltype == 'tuple': me = tuple(me) return me elif ltype == 'dict': me = {} for skey, sval in val.items(): me[skey] = get_component(sval) return me elif isinstance(val, h5py.Dataset): return val.value
def _pathparams(self, paramgroup=None, **kws): """evaluate path parameter value """ # degen, s02, e0, ei, deltar, sigma2, third, fourth if (paramgroup is not None and self._larch.symtable.isgroup(paramgroup)): self._larch.symtable._sys.paramGroup = paramgroup self._larch.symtable._fix_searchGroups() # put 'reff' and '_feffdat' into the paramGroup so that # 'reff' can be used in constraint expressions and # '_feffdat' can be used inside Debye and Eins functions stable = self._larch.symtable if stable.isgroup(stable._sys.paramGroup): stable._sys.paramGroup.reff = self._feffdat.reff stable._sys.paramGroup._feffdat = self._feffdat out = [] for param in ('degen', 's02', 'e0', 'ei', 'deltar', 'sigma2', 'third', 'fourth'): val = getattr(self, param) if param in kws: if kws[param] is not None: val = kws[param] if isinstance(val, six.string_types): thispar = Parameter(expr=val, _larch=self._larch) #if isinstance(thispar, Parameter): # thispar = thispar.value setattr(self, param, thispar) val = getattr(self, param) out.append(param_value(val)) return out
def _peakparams(self, paramgroup=None, **kws): """evaluate peak parameter values """ # sigma, amplitude, center out = [] for parname in ('amplitude', 'sigma', 'center'): val = getattr(self, parname) if parname in kws: if kws[parname] is not None: val = kws[parname] if isinstance(val, six.string_types): thispar = Parameter(expr=val, _larch=self._larch) setattr(self, parname, thispar) val = getattr(self, parname) out.append(param_value(val)) return out
def filters_page(self): "create row for filters parameters" mca = self.parent.mca self.wids.filters = [] p = GridPanel(self, itemstyle=LEFT) bx = Button(p, 'Customize Filter List', size=(150, -1), action=self.onEditFilters) bx.Disable() p.AddManyText( (' filter', 'material', 'density (gr/cm^3)', 'thickness (mm)'), style=CEN) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) for i in range(4): _mat = Choice(p, choices=self.Filter_Materials, default=0, size=(125, -1), action=partial(self.onFilterMaterial, index=i)) _den = FloatCtrl(p, value=0, minval=0, maxval=30, precision=4, size=(75, -1)) pnam = 'filter%i_thickness' % (i + 1) param = Parameter(value=0.0, vary=False, min=0, name=pnam) setattr(self.paramgroup, pnam, param) _len = ParameterPanel(p, param, precision=4) self.wids.filters.append((_mat, _den, _len)) p.AddText(' %i ' % (i + 1), newrow=True) p.Add(_mat) p.Add(_den, style=wx.ALIGN_CENTER) p.Add(_len) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) p.AddText(' ', newrow=True) p.Add(bx, dcol=3) p.pack() return p
def spline_rep(x, y, group=None, name='spl1', _larch=None): """create a spline representation for an (x, y) data set to be evaluated with spline_eval(), with pars = spline_rep(x, y) pars = group() spline_rep(x, y, group=pars) ynew = spline_eval(xnew, pars) arguments: ------------ x 1-d array for x y 1-d array for y name name for spline params and subgroup ['spl1'] group optional group to use to hold spline parameters returns: -------- group containing spline representation, which will include len(x)+2 parameters (named 'spl1_c0' ... 'spl1_cN+1') and a subgroup 'spl1_details' notes: ------ in order to hold multiple splines in a single parameter group, the ``name`` argument must be different for each spline representation, and passed to spline_eval() """ if group is None: group = Group() knots, coefs, order = splrep(x, y) dgroup = Group(knots=knots, order=order, coefs=coefs) setattr(group, "{:s}_details".format(name), dgroup) for i, val in enumerate(coefs[2:-2]): pname = "{:s}_c{:d}".format(name, i) p = Parameter(value=val, name=pname, vary=True) #, _larch=_larch) setattr(group, pname, p) return group
def _peakparams(self, paramgroup=None, **kws): """evaluate peak parameter values """ # sigma, amplitude, center if (paramgroup is not None and self._larch.symtable.isgroup(paramgroup)): self._larch.symtable._sys.paramGroup = paramgroup self._larch.symtable._fix_searchGroups() out = [] for parname in ('amplitude', 'sigma', 'center'): val = getattr(self, parname) if parname in kws: if kws[parname] is not None: val = kws[parname] if isinstance(val, (str, unicode)): thispar = Parameter(expr=val, _larch=self._larch) setattr(self, parname, thispar) val = getattr(self, parname) out.append(param_value(val)) return out
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'UO2.chik'), _larch=self._larch) gds = Group(amp = Parameter(1, vary=True, _larch=self._larch), enot = Parameter(1e-7, vary=True, _larch=self._larch), sso = Parameter(0.003, vary=True, _larch=self._larch), dro = Parameter(1e-7, vary=True, _larch=self._larch), _larch=self._larch ) if not firstshell: gds.ssu = Parameter(0.003, vary=True, _larch=self._larch) gds.sso2 = Parameter(0.003, vary=True, _larch=self._larch) gds.dru = Parameter(1e-7, vary=True, _larch=self._larch) gds.dro2 = Parameter(1e-7, vary=True, _larch=self._larch) gds.nu = Parameter(12, vary=True, _larch=self._larch) gds.no2 = Parameter(expr='2*nu', _larch=self._larch) paths = list() paths.append(feffpath(realpath(join(folder, "feff0001.dat")), # 1st shell O SS s02 = 'amp', e0 = 'enot', sigma2 = 'sso', deltar = 'dro', _larch=self._larch)) if not firstshell: # paths.append(feffpath(realpath(join(folder, "feff0002.dat")), # triangle in first shell # s02 = 'amp', # e0 = 'enot', # sigma2 = 'sso*(1+sqrt(3))**2', # deltar = 'dro*(1+sqrt(3))/2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0003.dat")), # 2nd shell U SS degen = 1, s02 = 'amp*nu', e0 = 'enot', sigma2 = 'ssu', deltar = 'dru', _larch=self._larch)) # paths.append(feffpath(realpath(join(folder, "feff0004.dat")), # 1st shell, longer triangle # s02 = 'amp', # e0 = 'enot', # sigma2 = 'sso*(1+sqrt(2/3))**2', # deltar = '(1+sqrt(2/3))*dro', _larch=self._larch)) # paths.append(feffpath(realpath(join(folder, "feff0005.dat")), # 1st shell, longer U-O-U triangle # degen = 1, # s02 = 'amp*nu', # e0 = 'enot', # sigma2 = 'sso*ssu/2', # deltar = '(1+sqrt(2/3))*dro', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0006.dat")), # 3rd shell O SS degen = 1, s02 = 'amp*no2', e0 = 'enot', sigma2 = 'sso2', deltar = 'dro2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0007.dat")), # 1st shell, non-forward linear through absorber s02 = 'amp', e0 = 'enot', sigma2 = '2*sso2', deltar = '2*dro2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0008.dat")), # 1st shell forward through absorber s02 = 'amp', e0 = 'enot', sigma2 = '2*sso', deltar = '2*dro', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0009.dat")), # rattle in 1st shell s02 = 'amp', e0 = 'enot', sigma2 = '2*sso', deltar = '2*dro', _larch=self._larch)) rx = 4.3 if firstshell: rx = 2.5 trans = feffit_transform(kmin=3, kmax=11, kw=(2,1,3), dk=1, window='hanning', rmin=1.25, rmax=rx, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag+offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to '+self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag+offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells='_1st' write_ascii(join(self.folder, fittest, "fit_"+which+shells+".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_"+which+shells+".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_'+which+shells+'.gp'), 'w') as inp: inp.write(renderer.render_path( 'plot.mustache', # gnuplot mustache file {'material': 'UO2', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 11, 'rmin': 1.25, 'rmax': rx, 'offset': 0.75, } )) return fit
def settings_page(self): "create fit and background settings" mca = self.parent.mca conf = self.parent.conf wids = self.wids width = getattr(mca, 'bgr_width', 4) compr = getattr(mca, 'bgr_compress', 2) expon = getattr(mca, 'bgr_exponent', 2) p = GridPanel(self, itemstyle=LEFT) wids.bgr_use = Check(p, label='Fit Background-Subtracted Spectra', default=True) wids.bgr_width = FloatCtrl(p, value=width, minval=0, maxval=10, precision=1, size=(70, -1)) wids.bgr_compress = Choice(p, choices=['1', '2', '4', '8', '16'], size=(70, -1), default=1) wids.bgr_exponent = Choice(p, choices=['2', '4', '6'], size=(70, -1), default=0) sopts = {'vary': True, 'precision': 5} sig_offset = Parameter(value=0.050, name=self.gsig_offset, vary=True) sig_slope = Parameter(value=0.005, name=self.gsig_slope, vary=True) sig_quad = Parameter(value=0.000, name=self.gsig_quad, vary=False) setattr(self.paramgroup, self.gsig_offset, sig_offset) setattr(self.paramgroup, self.gsig_slope, sig_slope) setattr(self.paramgroup, self.gsig_quad, sig_quad) wids.sig_offset = ParameterPanel(p, sig_offset, vary=True, precision=5) wids.sig_slope = ParameterPanel(p, sig_slope, vary=True, precision=5) wids.sig_quad = ParameterPanel(p, sig_quad, vary=False, precision=5) wids.xray_en = FloatCtrl(p, value=20.0, size=(70, -1), minval=0, maxval=1000, precision=3) wids.fit_emin = FloatCtrl(p, value=conf.e_min, size=(70, -1), minval=0, maxval=1000, precision=3) wids.fit_emax = FloatCtrl(p, value=conf.e_max, size=(70, -1), minval=0, maxval=1000, precision=3) wids.flyield_use = Check( p, label='Account for Absorption, Fluorescence Efficiency') p.AddText(' General Settings ', colour='#880000', dcol=3) p.AddText(' X-ray Energy (keV): ', newrow=True) p.Add(wids.xray_en) p.AddText(' Min Energy (keV): ', newrow=True) p.Add(wids.fit_emin) p.AddText(' Max Energy (keV): ', newrow=False) p.Add(wids.fit_emax) wids.det_mat = Choice(p, choices=self.Detector_Materials, size=(55, -1), default=0) wids.det_thk = FloatCtrl(p, value=0.40, size=(70, -1), minval=0, maxval=100, precision=3) wids.det_use = Check(p, label='Account for Detector Thickness') p.AddText(' Detector Material: ', newrow=True) p.Add(wids.det_mat) p.AddText(' Thickness (mm): ', newrow=False) p.Add(wids.det_thk) p.Add(wids.det_use, dcol=4, newrow=True) p.Add(wids.flyield_use, dcol=4, newrow=True) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) p.AddText(' Energy Dependence of Peak Width:', colour='#880000', newrow=True, dcol=2) # p.AddText(' ', newrow=True) p.AddText(' sigma = offset + slope * Energy + quad * Energy^2 (keV)', dcol=3) p.AddText(' Offset: ', newrow=True) p.Add(wids.sig_offset, dcol=3) p.AddText(' Slope: ', newrow=True) p.Add(wids.sig_slope, dcol=3) p.AddText(' Quad: ', newrow=True) p.Add(wids.sig_quad, dcol=3) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) p.AddText(" Background Parameters: ", colour='#880000', dcol=2, newrow=True) p.Add(wids.bgr_use, dcol=2) p.AddText(" Exponent:", newrow=True) p.Add(wids.bgr_exponent) p.AddText(" Energy Width (keV): ", newrow=False) p.Add(wids.bgr_width) p.AddText(" Compression: ", newrow=True) p.Add(wids.bgr_compress) p.Add(Button(p, 'Show Background', size=(130, -1), action=self.onShowBgr), dcol=2) p.Add(HLine(p, size=(600, 3)), dcol=5, newrow=True) p.pack() return p
def do_fit(self, which): if which == 'testrun': folder = self.testrun else: folder = self.baseline data = read_xdi(join(self.path, 'NiO.chik'), _larch=self._larch) if hasattr(data, 'wavenumber'): data.k = data.wavenumber gds = Group( amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(0.01, vary=True, _larch=self._larch), alpha=Parameter(0.0001, vary=True, _larch=self._larch), sso=Parameter(0.003, vary=True, _larch=self._larch), ssni=Parameter(0.003, vary=True, _larch=self._larch), sso2=Parameter(0.003, vary=True, _larch=self._larch), #sso3 = Parameter(0.003, vary=True, _larch=self._larch), ssni2=Parameter(0.003, vary=True, _larch=self._larch), #ssni3 = Parameter(0.003, vary=True, _larch=self._larch), #ssni4 = Parameter(0.003, vary=True, _larch=self._larch), _larch=self._larch) paths = list() paths.append( feffpath( realpath(join(folder, "feff0001.dat")), # 1st shell O SS s02='amp', e0='enot', sigma2='sso', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0002.dat")), # 2nd shell Ni SS s02='amp', e0='enot', sigma2='ssni', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0003.dat")), # O-O triangle s02='amp', e0='enot', sigma2='1.5*sso', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0004.dat")), # O-Ni triangle s02='amp', e0='enot', sigma2='sso+ssni', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0005.dat")), # 3rd shell O SS s02='amp', e0='enot', sigma2='sso2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0006.dat")), # 4th shell Ni SS s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0007.dat")), # O-O non-forward linear s02='amp', e0='enot', sigma2='sso*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0008.dat")), # O-Ni forward scattering s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0009.dat")), # O-O forward through absorber s02='amp', e0='enot', sigma2='sso*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0010.dat")), # O-Ni-O double forward s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) trans = feffit_transform(kmin=3, kmax=15.938, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.5, rmax=4.2, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = 0.6 * max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, win=2, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', win=2, _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', win=2, _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', win=2, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if return fit
def mback(energy, mu, group=None, order=3, z=None, edge='K', e0=None, emin=None, emax=None, whiteline=None, leexiang=False, tables='chantler', fit_erfc=False, return_f1=False, _larch=None): """ Match mu(E) data for tabulated f''(E) using the MBACK algorithm and, optionally, the Lee & Xiang extension Arguments: energy, mu: arrays of energy and mu(E) order: order of polynomial [3] group: output group (and input group for e0) z: Z number of absorber edge: absorption edge (K, L3) e0: edge energy emin: beginning energy for fit emax: ending energy for fit whiteline: exclusion zone around white lines leexiang: flag to use the Lee & Xiang extension tables: 'chantler' (default) or 'cl' fit_erfc: True to float parameters of error function return_f1: True to put the f1 array in the group Returns: group.f2: tabulated f2(E) group.f1: tabulated f1(E) (if return_f1 is True) group.fpp: matched data group.mback_params: Group of parameters for the minimization References: * MBACK (Weng, Waldo, Penner-Hahn): http://dx.doi.org/10.1086/303711 * Lee and Xiang: http://dx.doi.org/10.1088/0004-637X/702/2/970 * Cromer-Liberman: http://dx.doi.org/10.1063/1.1674266 * Chantler: http://dx.doi.org/10.1063/1.555974 """ order = int(order) if order < 1: order = 1 # set order of polynomial if order > MAXORDER: order = MAXORDER ### implement the First Argument Group convention energy, mu, group = parse_group_args(energy, members=('energy', 'mu'), defaults=(mu, ), group=group, fcn_name='mback') if len(energy.shape) > 1: energy = energy.squeeze() if len(mu.shape) > 1: mu = mu.squeeze() group = set_xafsGroup(group, _larch=_larch) if e0 is None: # need to run find_e0: e0 = xray_edge(z, edge, _larch=_larch)[0] if e0 is None: e0 = group.e0 if e0 is None: find_e0(energy, mu, group=group) ### theta is an array used to exclude the regions <emin, >emax, and ### around white lines, theta=0.0 in excluded regions, theta=1.0 elsewhere (i1, i2) = (0, len(energy) - 1) if emin is not None: i1 = index_of(energy, emin) if emax is not None: i2 = index_of(energy, emax) theta = np.ones(len(energy)) # default: 1 throughout theta[0:i1] = 0 theta[i2:-1] = 0 if whiteline: pre = 1.0 * (energy < e0) post = 1.0 * (energy > e0 + float(whiteline)) theta = theta * (pre + post) if edge.lower().startswith('l'): l2 = xray_edge(z, 'L2', _larch=_larch)[0] l2_pre = 1.0 * (energy < l2) l2_post = 1.0 * (energy > l2 + float(whiteline)) theta = theta * (l2_pre + l2_post) ## this is used to weight the pre- and post-edge differently as ## defined in the MBACK paper weight1 = 1 * (energy < e0) weight2 = 1 * (energy > e0) weight = np.sqrt(sum(weight1)) * weight1 + np.sqrt(sum(weight2)) * weight2 ## get the f'' function from CL or Chantler if tables.lower() == 'chantler': f1 = f1_chantler(z, energy, _larch=_larch) f2 = f2_chantler(z, energy, _larch=_larch) else: (f1, f2) = f1f2(z, energy, edge=edge, _larch=_larch) group.f2 = f2 if return_f1: group.f1 = f1 n = edge if edge.lower().startswith('l'): n = 'L' params = Group( s=Parameter(1, vary=True, _larch=_larch), # scale of data xi=Parameter(50, vary=fit_erfc, min=0, _larch=_larch), # width of erfc em=Parameter(xray_line(z, n, _larch=_larch)[0], vary=False, _larch=_larch), # erfc centroid e0=Parameter(e0, vary=False, _larch=_larch), # abs. edge energy ## various arrays need by the objective function en=energy, mu=mu, f2=group.f2, weight=weight, theta=theta, leexiang=leexiang, _larch=_larch) if fit_erfc: params.a = Parameter(1, vary=True, _larch=_larch) # amplitude of erfc else: params.a = Parameter(0, vary=False, _larch=_larch) # amplitude of erfc for i in range(order): # polynomial coefficients setattr(params, 'c%d' % i, Parameter(0, vary=True, _larch=_larch)) fit = Minimizer(match_f2, params, _larch=_larch, toler=1.e-5) fit.leastsq() eoff = energy - params.e0.value normalization_function = params.a.value * erfc( (energy - params.em.value) / params.xi.value) + params.c0.value for i in range(MAXORDER): j = i + 1 attr = 'c%d' % j if hasattr(params, attr): normalization_function = normalization_function + getattr( getattr(params, attr), 'value') * eoff**j group.fpp = params.s * mu - normalization_function group.mback_params = params
def do_fit(self, which, firstshell=False, fittest='baseline'): firstshell = False # no 1st shell fit for this material if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'uranyl.chik'), _larch=self._larch) gds = Group( amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(1e-7, vary=True, _larch=self._larch), #enot = Parameter(1e-7, vary=True, _larch=self._larch, min=0, max=13), enoteq=Parameter(expr='enot', _larch=self._larch), deloax=Parameter(1e-7, vary=True, _larch=self._larch), deloeq=Parameter(1e-7, vary=True, _larch=self._larch), sigoax=Parameter(0.003, vary=True, _larch=self._larch), sigoeq=Parameter(0.003, vary=True, _larch=self._larch), nax=Parameter(2.0, vary=False, _larch=self._larch), neq=Parameter(6, vary=False, _larch=self._larch), #, min=0, max=12), _larch=self._larch) paths = list() paths.append( feffpath( realpath(join(folder, "feff0001.dat")), # axial oxygen degen=1, s02='amp*nax', e0='enot', sigma2='sigoax', deltar='deloax', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0003.dat")), # equatorial oxygen degen=1, s02='amp*neq', e0='enoteq', sigma2='sigoeq', deltar='deloeq', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0008.dat")), # axial oxygen, rattle degen=1, s02='amp*nax', e0='enot', sigma2='sigoax*4', deltar='deloax*2', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0009.dat")), # axial oxygen, non-forward degen=1, s02='amp*nax', e0='enot', sigma2='sigoax', deltar='deloax*2', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0010.dat")), # axial oxygen, forward degen=1, s02='amp*nax', e0='enot', sigma2='sigoax', deltar='deloax*2', _larch=self._larch)) trans = feffit_transform(kmin=3, kmax=11, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.0, rmax=3.2, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, win=2, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', win=2, _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', win=2, _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', win=2, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells = '_1st' write_ascii(join(self.folder, fittest, "fit_" + which + ".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_" + which + ".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_' + which + '.gp'), 'w') as inp: inp.write( renderer.render_path( 'plot.mustache', # gnuplot mustache file { 'material': 'uranyl', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 11, 'rmin': 1.0, 'rmax': 3.2, 'offset': 1, })) return fit
def autobk(energy, mu=None, 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, nclamp=4, clamp_lo=1, clamp_hi=1, calc_uncertainties=True, err_sigma=1, _larch=None, **kws): """Use Autobk algorithm to remove XAFS background Parameters: ----------- energy: 1-d array of x-ray energies, in eV, or group mu: 1-d array of mu(E) group: output group (and input group for e0 and edge_step). rbkg: distance (in Ang) for chi(R) above which the signal is ignored. Default = 1. e0: edge energy, in eV. If None, it will be determined. edge_step: edge step. If None, it will be determined. pre_edge_kws: keyword arguments to pass to pre_edge() nknots: number of knots in spline. If None, it will be determined. kmin: minimum k value [0] kmax: maximum k value [full data range]. kweight: k weight for FFT. [1] dk: FFT window window parameter. [0] win: FFT window function name. ['hanning'] nfft: array size to use for FFT [2048] kstep: k step size to use for FFT [0.05] k_std: optional k array for standard chi(k). chi_std: optional chi array for standard chi(k). nclamp: number of energy end-points for clamp [2] clamp_lo: weight of low-energy clamp [1] clamp_hi: weight of high-energy clamp [1] calc_uncertaintites: Flag to calculate uncertainties in mu_0(E) and chi(k) [True] err_sigma: sigma level for uncertainties in mu_0(E) and chi(k) [1] Output arrays are written to the provided group. Follows the 'First Argument Group' convention. """ msg = _larch.writer.write if 'kw' in kws: kweight = kws.pop('kw') if len(kws) > 0: msg('Unrecognized a:rguments for autobk():\n') msg(' %s\n' % (', '.join(kws.keys()))) return energy, mu, group = parse_group_args(energy, members=('energy', 'mu'), defaults=(mu, ), group=group, fcn_name='autobk') if len(energy.shape) > 1: energy = energy.squeeze() if len(mu.shape) > 1: mu = mu.squeeze() 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() group = set_xafsGroup(group, _larch=_larch) if edge_step is None and isgroup(group, 'edge_step'): edge_step = group.edge_step if e0 is None and isgroup(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) pre_edge(energy, mu, group=group, _larch=_larch, **pre_kws) if e0 is None: e0 = group.e0 if edge_step is None: edge_step = group.edge_step if e0 is None or edge_step is None: msg('autobk() could not determine e0 or edge_step!: trying running pre_edge first\n' ) return # get array indices for rkbg and e0: irbkg, ie0 ie0 = index_of(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 enpe = energy[ie0:] - e0 kraw = np.sign(enpe) * np.sqrt(ETOK * abs(enpe)) if kmax is None: kmax = max(kraw) else: kmax = max(0, min(max(kraw), kmax)) kout = kstep * np.arange(int(1.01 + kmax / kstep), dtype='float64') iemax = min(len(energy), 2 + index_of(energy, e0 + kmax * kmax / ETOK)) - 1 # 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) # pre-load FT window 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 nspl = max(4, min(128, 2 * int(rbkg * (kmax - kmin) / np.pi) + 1)) spl_y, spl_k, spl_e = np.zeros(nspl), np.zeros(nspl), np.zeros(nspl) for i in range(nspl): q = kmin + i * (kmax - kmin) / (nspl - 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 params = Group() for i in range(len(coefs)): 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[:iemax - ie0 + 1], mu[ie0:iemax + 1], knots, coefs, order, kout) # do fit fit = Minimizer(__resid, params, _larch=_larch, toler=1.e-4, fcn_kws=dict(ncoefs=len(coefs), chi_std=chi_std, knots=knots, order=order, kraw=kraw[:iemax - ie0 + 1], mu=mu[ie0:iemax + 1], irbkg=irbkg, kout=kout, ftwin=ftwin, kweight=kweight, nfft=nfft, nclamp=nclamp, clamp_lo=clamp_lo, clamp_hi=clamp_hi)) fit.leastsq() # write final results coefs = [getattr(params, FMT_COEF % i) for i in range(len(coefs))] bkg, chi = spline_eval(kraw[:iemax - ie0 + 1], mu[ie0:iemax + 1], knots, coefs, order, kout) obkg = np.copy(mu) obkg[ie0:ie0 + len(bkg)] = bkg # outputs to group group = set_xafsGroup(group, _larch=_larch) group.bkg = obkg group.chie = (mu - obkg) / edge_step group.k = kout group.chi = chi / edge_step # now fill in 'autobk_details' group params.init_bkg = np.copy(mu) params.init_bkg[ie0:ie0 + len(bkg)] = initbkg params.init_chi = initchi / edge_step params.knots_e = spl_e params.knots_y = np.array([coefs[i] for i in range(nspl)]) params.init_knots_y = spl_y params.nfev = params.fit_details.nfev params.kmin = kmin params.kmax = kmax group.autobk_details = params # uncertainties in mu0 and chi: can be fairly slow. if calc_uncertainties: nchi = len(chi) nmue = iemax - ie0 + 1 redchi = params.chi_reduced covar = params.covar / redchi jac_chi = np.zeros(nchi * nspl).reshape((nspl, nchi)) jac_bkg = np.zeros(nmue * nspl).reshape((nspl, nmue)) cvals, cerrs = [], [] for i in range(len(coefs)): par = getattr(params, FMT_COEF % i) cvals.append(getattr(par, 'value', 0.0)) cdel = getattr(par, 'stderr', 0.0) if cdel is None: cdel = 0.0 cerrs.append(cdel / 2.0) cvals = np.array(cvals) cerrs = np.array(cerrs) # find derivatives by hand! _k = kraw[:nmue] _m = mu[ie0:iemax + 1] for i in range(nspl): cval0 = cvals[i] cvals[i] = cval0 + cerrs[i] bkg1, chi1 = spline_eval(_k, _m, knots, cvals, order, kout) cvals[i] = cval0 - cerrs[i] bkg2, chi2 = spline_eval(_k, _m, knots, cvals, order, kout) cvals[i] = cval0 jac_chi[i] = (chi1 - chi2) / (2 * cerrs[i]) jac_bkg[i] = (bkg1 - bkg2) / (2 * cerrs[i]) dfchi = np.zeros(nchi) dfbkg = np.zeros(nmue) for i in range(nspl): for j in range(nspl): dfchi += jac_chi[i] * jac_chi[j] * covar[i, j] dfbkg += jac_bkg[i] * jac_bkg[j] * covar[i, j] prob = 0.5 * (1.0 + erf(err_sigma / np.sqrt(2.0))) dchi = t.ppf(prob, nchi - nspl) * np.sqrt(dfchi * redchi) dbkg = t.ppf(prob, nmue - nspl) * np.sqrt(dfbkg * redchi) group.delta_chi = dchi group.delta_bkg = 0.0 * mu group.delta_bkg[ie0:ie0 + len(dbkg)] = dbkg
def do_fit(self, which): if which == 'testrun': folder = self.testrun else: folder = self.baseline data = read_xdi(join(self.path, 'UO2.chik'), _larch=self._larch) gds = Group(amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(0.01, vary=True, _larch=self._larch), sso=Parameter(0.003, vary=True, _larch=self._larch), ssu=Parameter(0.003, vary=True, _larch=self._larch), sso2=Parameter(0.003, vary=True, _larch=self._larch), dro=Parameter(0.0001, vary=True, _larch=self._larch), dru=Parameter(0.0001, vary=True, _larch=self._larch), dro2=Parameter(0.0001, vary=True, _larch=self._larch), nu=Parameter(12, vary=True, _larch=self._larch), no2=Parameter(expr='2*nu', _larch=self._larch), _larch=self._larch) paths = list() paths.append( feffpath( realpath(join(folder, "feff0001.dat")), # 1st shell O SS s02='amp', e0='enot', sigma2='sso', deltar='dro', _larch=self._larch)) # paths.append(feffpath(realpath(join(folder, "feff0002.dat")), # triangle in first shell # s02 = 'amp', # e0 = 'enot', # sigma2 = 'sso*1.5', # deltar = 'dro*(1+sqrt(2))/2', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0003.dat")), # 2nd shell U SS degen=1, s02='amp*nu', e0='enot', sigma2='ssu', deltar='dru', _larch=self._larch)) # paths.append(feffpath(realpath(join(folder, "feff0004.dat")), # 1st shell, longer triangle # s02 = 'amp', # e0 = 'enot', # sigma2 = '2*sso', # deltar = '2*dro', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0006.dat")), # 3rd shell O SS degen=1, s02='amp*no2', #s02 = 'amp*nu*2', e0='enot', sigma2='sso2', deltar='dro2', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0007.dat") ), # 1st shell, non-forward linear through absorber s02='amp', e0='enot', sigma2='sso2', deltar='dro2', _larch=self._larch)) paths.append( feffpath( realpath(join( folder, "feff0008.dat")), # 1st shell forward through absorber s02='amp', e0='enot', sigma2='2*sso', deltar='2*dro', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0009.dat")), # rattle in 1st shell s02='amp', e0='enot', sigma2='2*sso', deltar='2*dro', _larch=self._larch)) trans = feffit_transform(kmin=3, kmax=11, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.25, rmax=4.3, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, win=2, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', win=2, _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', win=2, _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', win=2, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if return fit
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'NiO.chik'), _larch=self._larch) if hasattr(data, 'wavenumber'): data.k = data.wavenumber gds = Group(amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(1e-7, vary=True, _larch=self._larch), sso=Parameter(0.003, vary=True, _larch=self._larch), _larch=self._larch) if firstshell: gds.delr = Parameter(1e-7, vary=True, _larch=self._larch) dr1param = 'delr' else: gds.alpha = Parameter(1e-7, vary=True, _larch=self._larch) gds.ssni = Parameter(0.003, vary=True, _larch=self._larch) gds.sso2 = Parameter(0.003, vary=True, _larch=self._larch) #gds.sso3 = Parameter(0.003, vary=True, _larch=self._larch) gds.ssni2 = Parameter(0.003, vary=True, _larch=self._larch) #gds.ssni3 = Parameter(0.003, vary=True, _larch=self._larch) #gds.ssni4 = Parameter(0.003, vary=True, _larch=self._larch) dr1param = 'alpha*reff' paths = list() paths.append( feffpath( realpath(join(folder, "feff0001.dat")), # 1st shell O SS s02='amp', e0='enot', sigma2='sso', deltar=dr1param, _larch=self._larch)) if not firstshell: paths.append( feffpath( realpath(join(folder, "feff0002.dat")), # 2nd shell Ni SS s02='amp', e0='enot', sigma2='ssni', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0003.dat")), # O-O triangle s02='amp', e0='enot', sigma2='1.5*sso', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0004.dat")), # O-Ni triangle s02='amp', e0='enot', sigma2='sso+ssni/2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0005.dat")), # 3rd shell O SS s02='amp', e0='enot', sigma2='sso2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0006.dat")), # 4th shell Ni SS s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0007.dat")), # O-O non-forward linear s02='amp', e0='enot', sigma2='sso*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0008.dat")), # O-Ni forward scattering s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0009.dat")), # O-O forward through absorber s02='amp', e0='enot', sigma2='sso*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0011.dat")), # O-Ni-O double forward s02='amp', e0='enot', sigma2='ssni2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath( join(folder, "feff0010.dat") ), # O-O rattle (the order of 10 and 11 is different in Demeter's pathfinder!) s02='amp', e0='enot', sigma2='sso*4', deltar='alpha*reff', _larch=self._larch)) rx = 4.2 if firstshell: rx = 1.95 trans = feffit_transform(kmin=3, kmax=15.938, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.0, rmax=rx, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = 0.6 * max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells = '_1st' write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_' + which + shells + '.gp'), 'w') as inp: inp.write( renderer.render_path( 'plot.mustache', # gnuplot mustache file { 'material': 'NiO', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 15.938, 'rmin': 1.0, 'rmax': rx, 'offset': 1, })) return fit
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'bromoadamantane.chik'), _larch=self._larch) gds = Group(amp = Parameter(0.9, vary=True, _larch=self._larch), enot = Parameter(4.01, vary=True, _larch=self._larch), delr = Parameter(1e-7 , vary=True, units='AA', decimals=3, _larch=self._larch), ss = Parameter(0.003, vary=True, units='AA^2', _larch=self._larch), c3 = Parameter(1e-7, vary=False, _larch=self._larch), _larch=self._larch ) if not firstshell: gds.brc = Parameter(expr = '1.9521+delr', units='AA', _larch=self._larch) #gds.phir = Parameter(109.29960 * 3.141592653589793 / 180, vary=False, _larch=self._larch) gds.cc = Parameter(1.53780, vary=False, _larch=self._larch) #gds.tanbeta = Parameter(expr = '(brc+cc)*tan(phir/2) / (brc-cc)', _larch=self._larch) #gds.beta = Parameter(expr = 'atan(tanbeta)', _larch=self._larch) #gds.brc2 = Parameter(expr = '(brc-cc)*cos(phir/2)/cos(beta)', units='AA', _larch=self._larch) gds.drh = Parameter(0.04, vary=True, units='AA', decimals=3, _larch=self._larch) gds.ssh = Parameter(0.005, vary=True, units='AA^2', _larch=self._larch) gds.ss2 = Parameter(expr = 'ss*(brc2/brc)**2', units ='AA^2', _larch=self._larch) gds.drc = Parameter(0.04, vary=True, units='AA', decimals=3, _larch=self._larch) gds.brc2 = Parameter(expr = '2.8565+drc', units='AA', decimals=3, _larch=self._larch) paths = list() paths.append(feffpath(realpath(join(folder, "feff0001.dat")), s02 = 'amp', e0 = 'enot', sigma2 = 'ss', deltar = 'delr', third = 'c3', _larch=self._larch)) if not firstshell: paths.append(feffpath(realpath(join(folder, "feff0002.dat")), s02 = 'amp', e0 = 'enot', sigma2 = 'ss2', #deltar = 'brc2-2.8565', deltar = 'drc',_larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0003.dat")), s02 = 'amp', e0 = 'enot', sigma2 = 'ssh', deltar = 'drh', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0004.dat")), s02 = 'amp', e0 = 'enot', sigma2 = '(ss+ss2)/2', deltar = '(brc+brc2+cc)/2 - 3.173', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0005.dat")), s02 = 'amp', e0 = 'enot', sigma2 = '(ss+ss2)/2', deltar = '(brc+brc2+cc)/2 - 3.173', _larch=self._larch)) rx = 3 if firstshell: rx = 1.83 trans = feffit_transform(kmin=3, kmax=11, kw=(2,1,3), dk=1, window='hanning', rmin=1, rmax=3, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag+offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to '+self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag+offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells='_1st' write_ascii(join(self.folder, fittest, "fit_"+which+shells+".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_"+which+shells+".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest,'fit_'+which+shells+'.gp'), 'w') as inp: inp.write(renderer.render_path( 'plot.mustache', # gnuplot mustache file {'material': 'bromoadamantane', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 13, 'rmin': 1, 'rmax': rx, 'offset': 0.2, } )) return fit
def do_fit(self, which): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, 'baseline', which)) #endif print '>>>>>> %s' % folder data = read_xdi(join(self.path, 'Copper.chik'), _larch=self._larch) gds = Group(amp=Parameter(1, vary=True), enot=Parameter(1e-7, vary=True), thetad=Parameter(500, vary=True), temp=Parameter(10, vary=False), alpha=Parameter(1e-7, vary=True), ss1=Parameter(0.003, vary=True), _larch=self._larch) paths = list() for index in range(1, 14): nnnn = realpath(join(folder, "feff%4.4d.dat" % index)) if not exists(nnnn): continue #end if if index > 1: sigsqr = 'sigma2_debye(temp, thetad)' else: sigsqr = 'ss1' #end if paths.append( feffpath(nnnn, s02='amp', e0='enot', sigma2=sigsqr, deltar='alpha*reff', _larch=self._larch)) #end for trans = feffit_transform(kmin=3, kmax=16, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.7, rmax=5.1, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, win=2, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', win=2, _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', win=2, _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', win=2, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if return fit
def add_param(self, name, value=0, vary=True, **kws): if self._larch is not None: self._larch.symtable._sys.paramGroup = self.params p = Parameter(value=value, name=name, vary=vary, _larch=self._larch, **kws) setattr(self.params, name, p)
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'Copper.chik'), _larch=self._larch) gds = Group(amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(1e-7, vary=True, _larch=self._larch), ss1=Parameter(0.003, vary=True, _larch=self._larch), _larch=self._larch) if firstshell: gds.delr = Parameter(1e-7, vary=True, _larch=self._larch) dr1param = 'delr' else: gds.thetad = Parameter(500, vary=True, _larch=self._larch) gds.temp = Parameter(10, vary=False, _larch=self._larch) gds.alpha = Parameter(1e-7, vary=True, _larch=self._larch) dr1param = 'alpha*reff' imax = 16 if firstshell: imax = 2 paths = list() for index in range(1, imax): nnnn = realpath(join(folder, "feff%4.4d.dat" % index)) if not exists(nnnn): continue #end if if index > 1: sigsqr = 'sigma2_debye(temp, thetad)' else: sigsqr = 'ss1' #end if paths.append( feffpath(nnnn, s02='amp', e0='enot', sigma2=sigsqr, deltar=dr1param, _larch=self._larch)) #end for rx = 5.0 if firstshell: rx = 2.8 trans = feffit_transform(kmin=3, kmax=15, kw=(2, 1, 3), dk=1, window='hanning', rmin=1, rmax=rx, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells = '_1st' write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_' + which + shells + '.gp'), 'w') as inp: inp.write( renderer.render_path( 'plot.mustache', # gnuplot mustache file { 'material': 'Copper', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 15, 'rmin': 1, 'rmax': rx, 'offset': 2, })) return fit
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'BaZrO3.chik'), _larch=self._larch) gds = Group(amp = Parameter(0.95, vary=True, _larch=self._larch), enot = Parameter(1e-7, vary=True, _larch=self._larch), sso = Parameter(0.003, vary=True, _larch=self._larch), czr = Parameter(0., vary=False, _larch=self._larch), _larch=self._larch ) if firstshell: gds.delr = Parameter(1e-7, vary=True, _larch=self._larch) dr1param = 'delr' else: gds.alpha = Parameter(0.00001, vary=True, _larch=self._larch) gds.ssba = Parameter(0.003, vary=True, _larch=self._larch) gds.sszr = Parameter(0.003, vary=True, _larch=self._larch) gds.eba = Parameter(1e-7, vary=True, _larch=self._larch) gds.ezr = Parameter(1e-7, vary=True, _larch=self._larch) #gds.eba = Parameter(expr='enot', _larch=self._larch) #gdsezr = Parameter(expr='enot', _larch=self._larch) gds.sso2 = Parameter(0.003, vary=True, _larch=self._larch) dr1param = 'alpha*reff' paths = list() paths.append(feffpath(realpath(join(folder, "feff0001.dat")), s02 = 'amp', deltar = dr1param, e0 = 'enot', sigma2 = 'sso', _larch=self._larch)) if not firstshell: paths.append(feffpath(realpath(join(folder, "feff0002.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso*1.5', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0003.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'eba', sigma2 = 'ssba', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0004.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'ezr', sigma2 = 'sszr', third = 'czr', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0005.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso*2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0006.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = '(enot+ezr)/2', sigma2 = 'sszr', third = 'czr', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0007.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso*2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0009.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = '(2*enot+ezr)/3', sigma2 = 'sszr', third = 'czr', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0008.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso*4', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0011.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = '(enot+eba)/2', sigma2 = 'ssba+sso', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0012.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso2', _larch=self._larch)) paths.append(feffpath(realpath(join(folder, "feff0013.dat")), s02 = 'amp', deltar = 'alpha*reff', e0 = 'enot', sigma2 = 'sso+sso2', _larch=self._larch)) rx = 4.5 if firstshell: rx = 1.95 trans = feffit_transform(kmin=3, kmax=14.5, kw=(2,1,3), dk=1, window='hanning', rmin=1.2, rmax=rx, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag+offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to '+self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag+offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells='_1st' write_ascii(join(self.folder, fittest, "fit_"+which+shells+".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_"+which+shells+".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_'+which+shells+'.gp'), 'w') as inp: inp.write(renderer.render_path( 'plot.mustache', # gnuplot mustache file {'material': 'BaZrO3', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 14.5, 'rmin': 1.2, 'rmax': rx, 'offset': 1, } )) return fit
def do_fit(self, which): if which == 'testrun': folder = self.testrun else: folder = self.baseline #end if data = read_xdi(join(self.path, 'bromoadamantane.chik'), _larch=self._larch) gds = Group(amp=Parameter(1.021, vary=True, _larch=self._larch), enot=Parameter(4.01, vary=True, _larch=self._larch), delr=Parameter(-0.007, vary=True, _larch=self._larch), brc=Parameter(expr='1.9521+delr', _larch=self._larch), ss=Parameter(0.003, vary=True, _larch=self._larch), phir=Parameter(109.29960 * 3.141592653589793 / 180, vary=False, _larch=self._larch), cc=Parameter(1.53780, vary=False, _larch=self._larch), tanbeta=Parameter(expr='(brc+cc)*tan(phir/2) / (brc-cc)', _larch=self._larch), beta=Parameter(expr='atan(tanbeta)', _larch=self._larch), brc2=Parameter(expr='(brc-cc)*cos(phir/2)/cos(beta)', _larch=self._larch), drh=Parameter(0.04, vary=True, _larch=self._larch), ssh=Parameter(0.005, vary=True, _larch=self._larch), ss2=Parameter(expr='ss*(brc2/brc)**2', _larch=self._larch), c3=Parameter(-0.0007, vary=True, _larch=self._larch), _larch=self._larch) paths = list() paths.append( feffpath(realpath(join(folder, "feff0001.dat")), s02='amp', e0='enot', sigma2='ss', deltar='delr', third='c3', _larch=self._larch)) paths.append( feffpath(realpath(join(folder, "feff0002.dat")), s02='amp', e0='enot', sigma2='ss2', deltar='brc2-2.8565', _larch=self._larch)) paths.append( feffpath(realpath(join(folder, "feff0003.dat")), s02='amp', e0='enot', sigma2='ssh', deltar='drh', _larch=self._larch)) paths.append( feffpath(realpath(join(folder, "feff0004.dat")), s02='amp', e0='enot', sigma2='(ss+ss2)/2', deltar='(brc+brc2+cc)/2 - 3.173', _larch=self._larch)) paths.append( feffpath(realpath(join(folder, "feff0005.dat")), s02='amp', e0='enot', sigma2='(ss+ss2)/2', deltar='(brc+brc2+cc)/2 - 3.173', _larch=self._larch)) trans = feffit_transform(kmin=2.5, kmax=13, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.25, rmax=3, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, win=2, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', win=2, _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', win=2, _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', win=2, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if return fit
def pre_edge(energy, mu=None, group=None, e0=None, step=None, nnorm=3, nvict=0, pre1=None, pre2=-50, norm1=100, norm2=None, make_flat=True, _larch=None): """pre edge subtraction, normalization for XAFS This performs a number of steps: 1. determine E0 (if not supplied) from max of deriv(mu) 2. fit a line of polymonial to the region below the edge 3. fit a polymonial to the region above the edge 4. extrapolae the two curves to E0 to determine the edge jump Arguments ---------- energy: array of x-ray energies, in eV, or group (see note) mu: array of mu(E) group: output group e0: edge energy, in eV. If None, it will be determined here. step: edge jump. If None, it will be determined here. pre1: low E range (relative to E0) for pre-edge fit pre2: high E range (relative to E0) for pre-edge fit nvict: energy exponent to use for pre-edg fit. See Note norm1: low E range (relative to E0) for post-edge fit norm2: high E range (relative to E0) for post-edge fit nnorm: degree of polynomial (ie, nnorm+1 coefficients will be found) for post-edge normalization curve. Default=3 (quadratic), max=5 make_flat: boolean (Default True) to calculate flattened output. Returns ------- None The following attributes will be written to the output group: e0 energy origin edge_step edge step norm normalized mu(E) flat flattened, normalized mu(E) pre_edge determined pre-edge curve post_edge determined post-edge, normalization curve dmude derivative of mu(E) (if the output group is None, _sys.xafsGroup will be written to) Notes ----- 1 nvict gives an exponent to the energy term for the fits to the pre-edge and the post-edge region. For the pre-edge, a line (m * energy + b) is fit to mu(energy)*energy**nvict over the pre-edge region, energy=[e0+pre1, e0+pre2]. For the post-edge, a polynomial of order nnorm will be fit to mu(energy)*energy**nvict of the post-edge region energy=[e0+norm1, e0+norm2]. 2 If the first argument is a Group, it must contain 'energy' and 'mu'. If it exists, group.e0 will be used as e0. See First Argrument Group in Documentation """ energy, mu, group = parse_group_args(energy, members=('energy', 'mu'), defaults=(mu, ), group=group, fcn_name='pre_edge') if len(energy.shape) > 1: energy = energy.squeeze() if len(mu.shape) > 1: mu = mu.squeeze() pre_dat = preedge(energy, mu, e0=e0, step=step, nnorm=nnorm, nvict=nvict, pre1=pre1, pre2=pre2, norm1=norm1, norm2=norm2) group = set_xafsGroup(group, _larch=_larch) e0 = pre_dat['e0'] norm = pre_dat['norm'] norm1 = pre_dat['norm1'] norm2 = pre_dat['norm2'] # generate flattened spectra, by fitting a quadratic to .norm # and removing that. flat = norm ie0 = index_nearest(energy, e0) p1 = index_of(energy, norm1 + e0) p2 = index_nearest(energy, norm2 + e0) if p2 - p1 < 2: p2 = min(len(energy), p1 + 2) if make_flat and p2 - p1 > 4: enx, mux = remove_nans2(energy[p1:p2], norm[p1:p2]) # enx, mux = (energy[p1:p2], norm[p1:p2]) fpars = Group(c0=Parameter(0, vary=True), c1=Parameter(0, vary=True), c2=Parameter(0, vary=True), en=enx, mu=mux) fit = Minimizer(flat_resid, fpars, _larch=_larch, toler=1.e-5) try: fit.leastsq() except (TypeError, ValueError): pass fc0, fc1, fc2 = fpars.c0.value, fpars.c1.value, fpars.c2.value flat_diff = fc0 + energy * (fc1 + energy * fc2) flat = norm - flat_diff + flat_diff[ie0] flat[:ie0] = norm[:ie0] group.e0 = e0 group.norm = norm group.flat = flat group.dmude = np.gradient(mu) / np.gradient(energy) group.edge_step = pre_dat['edge_step'] group.pre_edge = pre_dat['pre_edge'] group.post_edge = pre_dat['post_edge'] group.pre_edge_details = Group() group.pre_edge_details.pre1 = pre_dat['pre1'] group.pre_edge_details.pre2 = pre_dat['pre2'] group.pre_edge_details.nnorm = pre_dat['nnorm'] group.pre_edge_details.norm1 = pre_dat['norm1'] group.pre_edge_details.norm2 = pre_dat['norm2'] group.pre_edge_details.pre_slope = pre_dat['precoefs'][0] group.pre_edge_details.pre_offset = pre_dat['precoefs'][1] for i in range(MAX_NNORM): if hasattr(group, 'norm_c%i' % i): delattr(group, 'norm_c%i' % i) for i, c in enumerate(pre_dat['norm_coefs']): setattr(group.pre_edge_details, 'norm_c%i' % i, c) return
def autobk(energy, mu=None, 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, nclamp=4, clamp_lo=1, clamp_hi=1, calc_uncertainties=False, _larch=None, **kws): """Use Autobk algorithm to remove XAFS background Parameters: ----------- energy: 1-d array of x-ray energies, in eV, or group mu: 1-d array of mu(E) group: output group (and input group for e0 and edge_step). rbkg: distance (in Ang) for chi(R) above which the signal is ignored. Default = 1. e0: edge energy, in eV. If None, it will be determined. edge_step: edge step. If None, it will be determined. pre_edge_kws: keyword arguments to pass to pre_edge() nknots: number of knots in spline. If None, it will be determined. kmin: minimum k value [0] kmax: maximum k value [full data range]. kweight: k weight for FFT. [1] dk: FFT window window parameter. [0] win: FFT window function name. ['hanning'] nfft: array size to use for FFT [2048] kstep: k step size to use for FFT [0.05] k_std: optional k array for standard chi(k). chi_std: optional chi array for standard chi(k). nclamp: number of energy end-points for clamp [2] clamp_lo: weight of low-energy clamp [1] clamp_hi: weight of high-energy clamp [1] calc_uncertaintites: Flag to calculate uncertainties in mu_0(E) and chi(k) [False] Output arrays are written to the provided group. Follows the 'First Argument Group' convention. """ msg = _larch.writer.write if 'kw' in kws: kweight = kws.pop('kw') if len(kws) > 0: msg('Unrecognized a:rguments for autobk():\n') msg(' %s\n' % (', '.join(kws.keys()))) return energy, mu, group = parse_group_args(energy, members=('energy', 'mu'), defaults=(mu, ), group=group, fcn_name='autobk') 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() group = set_xafsGroup(group, _larch=_larch) if edge_step is None and isgroup(group, 'edge_step'): edge_step = group.edge_step if e0 is None and isgroup(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) pre_edge(energy, mu, group=group, _larch=_larch, **pre_kws) if e0 is None: e0 = group.e0 if edge_step is None: edge_step = group.edge_step if e0 is None or edge_step is None: msg('autobk() could not determine e0 or edge_step!: trying running pre_edge first\n' ) return # get array indices for rkbg and e0: irbkg, ie0 ie0 = index_of(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 enpe = energy[ie0:] - e0 kraw = np.sign(enpe) * np.sqrt(ETOK * abs(enpe)) if kmax is None: kmax = max(kraw) else: kmax = max(0, min(max(kraw), kmax)) kout = kstep * np.arange(int(1.01 + kmax / kstep), dtype='float64') iemax = min(len(energy), 2 + index_of(energy, e0 + kmax * kmax / ETOK)) - 1 # 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) # pre-load FT window 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 nspl = max(4, min(128, 2 * int(rbkg * (kmax - kmin) / np.pi) + 1)) spl_y, spl_k, spl_e = np.zeros(nspl), np.zeros(nspl), np.zeros(nspl) for i in range(nspl): q = kmin + i * (kmax - kmin) / (nspl - 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 params = Group() for i in range(len(coefs)): 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[:iemax - ie0 + 1], mu[ie0:iemax + 1], knots, coefs, order, kout) # do fit fit = Minimizer(__resid, params, _larch=_larch, toler=1.e-4, fcn_kws=dict(ncoefs=len(coefs), chi_std=chi_std, knots=knots, order=order, kraw=kraw[:iemax - ie0 + 1], mu=mu[ie0:iemax + 1], irbkg=irbkg, kout=kout, ftwin=ftwin, kweight=kweight, nfft=nfft, nclamp=nclamp, clamp_lo=clamp_lo, clamp_hi=clamp_hi)) fit.leastsq() # write final results coefs = [getattr(params, FMT_COEF % i) for i in range(len(coefs))] bkg, chi = spline_eval(kraw[:iemax - ie0 + 1], mu[ie0:iemax + 1], knots, coefs, order, kout) obkg = np.copy(mu) obkg[ie0:ie0 + len(bkg)] = bkg # outputs to group group = set_xafsGroup(group, _larch=_larch) group.bkg = obkg group.chie = (mu - obkg) / edge_step group.k = kout group.chi = chi / edge_step # now fill in 'autobk_details' group params.init_bkg = np.copy(mu) params.init_bkg[ie0:ie0 + len(bkg)] = initbkg params.init_chi = initchi / edge_step params.knots_e = spl_e params.knots_y = np.array([coefs[i] for i in range(nspl)]) params.init_knots_y = spl_y params.nfev = params.fit_details.nfev params.kmin = kmin params.kmax = kmax group.autobk_details = params # uncertainties in mu0 and chi: fairly slow!! if HAS_UNCERTAIN and calc_uncertainties: vbest, vstd = [], [] for n in fit.var_names: par = getattr(params, n) vbest.append(par.value) vstd.append(par.stderr) uvars = uncertainties.correlated_values(vbest, params.covar) # uncertainty in bkg (aka mu0) # note that much of this is working around # limitations in the uncertainty package that make it # 1. take an argument list (not array) # 2. work on returned scalars (but not arrays) # 3. not handle kw args and *args well (so use # of global "index" is important here) nkx = iemax - ie0 + 1 def my_dsplev(*args): coefs = np.array(args) return splev(kraw[:nkx], [knots, coefs, order])[index] fdbkg = uncertainties.wrap(my_dsplev) dmu0 = [fdbkg(*uvars).std_dev() for index in range(len(bkg))] group.delta_bkg = np.zeros(len(mu)) group.delta_bkg[ie0:ie0 + len(bkg)] = np.array(dmu0) # uncertainty in chi (see notes above) def my_dchi(*args): coefs = np.array(args) b, chi = spline_eval(kraw[:nkx], mu[ie0:iemax + 1], knots, coefs, order, kout) return chi[index] fdchi = uncertainties.wrap(my_dchi) dchi = [fdchi(*uvars).std_dev() for index in range(len(kout))] group.delta_chi = np.array(dchi) / edge_step
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif dmt = read_xdi(join(self.path, 'dmt.chik'), _larch=self._larch) mmt = read_xdi(join(self.path, 'mmt.chik'), _larch=self._larch) gds = Group(amp=Parameter(0.9, vary=True, _larch=self._larch), enot=Parameter(1e-7, vary=True, _larch=self._larch), delr_c=Parameter(1e-7, vary=True, _larch=self._larch), ss_c=Parameter(0.003, vary=True, _larch=self._larch), delr_cl=Parameter(1e-7, vary=True, _larch=self._larch), ss_cl=Parameter(0.003, vary=True, _larch=self._larch), _larch=self._larch) paths_dmt = list() paths_dmt.append( feffpath(realpath(join(folder, "feff0001.dat")), degen=2, s02='amp', e0='enot', sigma2='ss_c', deltar='delr_c', _larch=self._larch)) paths_dmt.append( feffpath(realpath(join(folder, "feff0002.dat")), degen=2, s02='amp', e0='enot', sigma2='ss_cl', deltar='delr_cl', _larch=self._larch)) paths_mmt = list() paths_mmt.append( feffpath(realpath(join(folder, "feff0001.dat")), degen=1, s02='amp', e0='enot', sigma2='ss_c', deltar='delr_c', _larch=self._larch)) paths_mmt.append( feffpath(realpath(join(folder, "feff0002.dat")), degen=3, s02='amp', e0='enot', sigma2='ss_cl', deltar='delr_cl', _larch=self._larch)) trans = feffit_transform(kmin=3, kmax=13, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.25, rmax=3, _larch=self._larch) dset = [ feffit_dataset(data=dmt, pathlist=paths_dmt, transform=trans, _larch=self._larch), feffit_dataset(data=mmt, pathlist=paths_mmt, transform=trans, _larch=self._larch) ] fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = max(dset[0].data.chir_mag) / 2 _newplot(dset[0].data.r, dset[0].data.chir_mag + offset, xmax=5, win=1, xlabel=r'$R \rm\,(\AA)$', label='dimethyltin', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset[0].model.r, dset[0].model.chir_mag + offset, label='fit', win=1, _larch=self._larch) _plot(dset[0].data.r, dset[0].data.chir_re, label='dimethyltin', win=1, _larch=self._larch) _plot(dset[0].model.r, dset[0].model.chir_re, label='fit', win=1, _larch=self._larch) _plot(dset[1].data.r, dset[1].data.chir_mag + 7 * offset, label='monomethyltin', win=1, _larch=self._larch) _plot(dset[1].model.r, dset[1].model.chir_mag + 7 * offset, label='fit', win=1, _larch=self._larch) _plot(dset[1].data.r, dset[1].data.chir_re + 6 * offset, label='monomethyltin', win=1, _larch=self._larch) _plot(dset[1].model.r, dset[1].model.chir_re + 6 * offset, label='fit', win=1, _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells = '_1st' write_ascii(join(self.folder, fittest, "fit_" + which + ".k"), dset.data[0].k, dset.data[0].chi, dset.model[0].chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_" + which + ".r"), dset.data[0].r, dset.data[0].chir_mag, dset.model[0].chir_mag, dset.data[0].chir_re, dset.model[0].chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_' + which + '.gp'), 'w') as inp: inp.write( renderer.render_path( 'plot.mustache', # gnuplot mustache file { 'material': 'methyltin', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 13, 'rmin': 1.25, 'rmax': 3, 'offset': 1, })) return fit
def do_fit(self, which, firstshell=False, fittest='baseline'): if which == 'testrun': folder = self.testrun elif which == 'baseline': folder = self.baseline else: folder = realpath(join(self.folder, fittest, which)) #endif data = read_xdi(join(self.path, 'FeS2.chik'), _larch=self._larch) gds = Group(amp=Parameter(1, vary=True, _larch=self._larch), enot=Parameter(1e-7, vary=True, _larch=self._larch), ss=Parameter(0.003, vary=True, _larch=self._larch), _larch=self._larch) if firstshell: gds.delr = Parameter(1e-7, vary=True, _larch=self._larch) dr1param = 'delr' else: gds.alpha = Parameter(1e-7, vary=True, _larch=self._larch) gds.ss2 = Parameter(0.003, vary=True, _larch=self._larch) gds.ss3 = Parameter(expr='ss2', _larch=self._larch) gds.ssfe = Parameter(0.003, vary=True, _larch=self._larch) dr1param = 'alpha*reff' paths = list() paths.append( feffpath( realpath(join(folder, "feff0001.dat")), # 1st shell S SS s02='amp', e0='enot', sigma2='ss', deltar=dr1param, _larch=self._larch)) if not firstshell: paths.append( feffpath( realpath(join(folder, "feff0002.dat")), # 2nd shell S SS s02='amp', e0='enot', sigma2='ss2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0003.dat")), # 3rd shell S SS s02='amp', e0='enot', sigma2='ss3', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0004.dat")), # 4th shell Fe SS s02='amp', e0='enot', sigma2='ssfe', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0005.dat")), # S-S triangle s02='amp', e0='enot', sigma2='ss*1.5', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0006.dat")), # S-Fe triangle s02='amp', e0='enot', sigma2='ss/2+ssfe', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0012.dat")), # S-S non-forward linear s02='amp', e0='enot', sigma2='ss*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0013.dat")), # S-S forward scattering s02='amp', e0='enot', sigma2='ss*2', deltar='alpha*reff', _larch=self._larch)) paths.append( feffpath( realpath(join(folder, "feff0014.dat")), # S-S rattle s02='amp', e0='enot', sigma2='ss*4', deltar='alpha*reff', _larch=self._larch)) rx = 4.2 if firstshell: rx = 2.3 trans = feffit_transform(kmin=3, kmax=12.956, kw=(2, 1, 3), dk=1, window='hanning', rmin=1.2, rmax=rx, _larch=self._larch) dset = feffit_dataset(data=data, pathlist=paths, transform=trans, _larch=self._larch) fit = feffit(gds, dset, _larch=self._larch) if self.doplot: offset = 0.6 * max(dset.data.chir_mag) _newplot(dset.data.r, dset.data.chir_mag + offset, xmax=8, xlabel=r'$R \rm\,(\AA)$', label='data', ylabel=r'$|\chi(R)| \rm\,(\AA^{-3})$', title='Fit to ' + self.folder, show_legend=True, _larch=self._larch) _plot(dset.model.r, dset.model.chir_mag + offset, label='fit', _larch=self._larch) _plot(dset.data.r, dset.data.chir_re, label='data', _larch=self._larch) _plot(dset.model.r, dset.model.chir_re, label='fit', _larch=self._larch) #end if if self.verbose: print feffit_report(fit, _larch=self._larch) #end if shells = '' if firstshell: shells = '_1st' write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".k"), dset.data.k, dset.data.chi, dset.model.chi, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) write_ascii(join(self.folder, fittest, "fit_" + which + shells + ".r"), dset.data.r, dset.data.chir_mag, dset.model.chir_mag, dset.data.chir_re, dset.model.chir_re, labels="r data_mag fit_mag data_re fit_re", _larch=self._larch) renderer = pystache.Renderer() with open(join(self.folder, fittest, 'fit_' + which + shells + '.gp'), 'w') as inp: inp.write( renderer.render_path( 'plot.mustache', # gnuplot mustache file { 'material': 'FeS2', 'model': which, 'fittest': fittest, 'shells': shells, 'kmin': 3, 'kmax': 12.956, 'rmin': 1.2, 'rmax': rx, 'offset': 1, })) return fit