Coverage for /Users/Newville/Codes/xraylarch/larch/xafs/feffdat.py: 83%
450 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
1#!/usr/bin/env python
2"""
3feffdat provides the following function related to
4reading and dealing with Feff.data files in larch:
6 path1 = read_feffdat('feffNNNN.dat')
8returns a Feff Group -- a special variation of a Group -- for
9the path represented by the feffNNNN.dat
11 group = ff2chi(paths)
13creates a group that contains the chi(k) for the sum of paths.
14"""
15import os
16import numpy as np
17from copy import deepcopy
18from scipy.interpolate import UnivariateSpline
19from lmfit import Parameters, Parameter
21from xraydb import atomic_mass, atomic_symbol
23from larch import Group, isNamedClass
24from larch.utils.strutils import fix_varname, b32hash
25from larch.fitting import group2params, dict2params, isParameter, param_value
26from .xafsutils import ETOK, ktoe, set_xafsGroup, gfmt
27from .sigma2_models import add_sigma2funcs
29SMALL_ENERGY = 1.e-6
31PATH_PARS = ('degen', 's02', 'e0', 'ei', 'deltar', 'sigma2', 'third', 'fourth')
32FDAT_ARRS = ('real_phc', 'mag_feff', 'pha_feff', 'red_fact',
33 'lam', 'rep', 'pha', 'amp', 'k')
35# values that will be available in calculations of Path Parameter values
36FEFFDAT_VALUES = ('reff', 'nleg', 'degen', 'rmass', 'rnorman',
37 'gam_ch', 'rs_int', 'vint', 'vmu', 'vfermi')
39class FeffDatFile(Group):
40 def __init__(self, filename=None, **kws):
41 kwargs = dict(name='feff.dat: %s' % filename)
42 kwargs.update(kws)
43 Group.__init__(self, **kwargs)
44 if filename not in ('', None) and os.path.exists(filename):
45 self._read(filename)
47 def __repr__(self):
48 if self.filename is not None:
49 return '<Feff.dat File Group: %s>' % self.filename
50 return '<Feff.dat File Group (empty)>'
52 def __copy__(self):
53 return FeffDatFile(filename=self.filename)
55 def __deepcopy__(self, memo):
56 return FeffDatFile(filename=self.filename)
58 @property
59 def reff(self): return self.__reff__
61 @reff.setter
62 def reff(self, val): pass
64 @property
65 def nleg(self): return self.__nleg__
67 @nleg.setter
68 def nleg(self, val): pass
70 @property
71 def rmass(self):
72 """reduced mass for a path"""
73 if self.__rmass is None:
74 rmass = 0
75 for atsym, iz, ipot, amass, x, y, z in self.geom:
76 rmass += 1.0/max(1., amass)
77 self.__rmass = 1./rmass
78 return self.__rmass
80 @rmass.setter
81 def rmass(self, val): pass
83 def _set_from_dict(self, **kws):
84 self.__rmass = None
85 for key, val in kws.items():
86 if key == 'rmass':
87 continue
88 elif key == 'reff':
89 key = '__reff__'
90 elif key == 'nleg':
91 key = '__nleg__'
92 elif key in FDAT_ARRS:
93 val = np.array(val)
94 setattr(self, key, val)
96 def __setstate__(self, state):
97 (self.filename, self.title, self.version, self.shell,
98 self.absorber, self.degen, self.__reff__, self.__nleg__,
99 self.rnorman, self.edge, self.gam_ch, self.exch, self.vmu, self.vfermi,
100 self.vint, self.rs_int, self.potentials, self.geom, self.__rmass,
101 self.k, self.real_phc, self.mag_feff, self.pha_feff,
102 self.red_fact, self.lam, self.rep, self.pha, self.amp) = state
104 self.k = np.array(self.k)
105 self.real_phc = np.array(self.real_phc)
106 self.mag_feff = np.array(self.mag_feff)
107 self.pha_feff = np.array(self.pha_feff)
108 self.red_fact = np.array(self.red_fact)
109 self.lam = np.array(self.lam)
110 self.rep = np.array(self.rep)
111 self.pha = np.array(self.pha)
112 self.amp = np.array(self.amp)
114 def __getstate__(self):
115 return (self.filename, self.title, self.version, self.shell,
116 self.absorber, self.degen, self.__reff__, self.__nleg__,
117 self.rnorman, self.edge, self.gam_ch, self.exch, self.vmu,
118 self.vfermi, self.vint, self.rs_int, self.potentials,
119 self.geom, self.__rmass, self.k.tolist(),
120 self.real_phc.tolist(), self.mag_feff.tolist(),
121 self.pha_feff.tolist(), self.red_fact.tolist(),
122 self.lam.tolist(), self.rep.tolist(), self.pha.tolist(),
123 self.amp.tolist())
126 def _read(self, filename):
127 try:
128 with open(filename, 'r') as fh:
129 lines = fh.readlines()
130 except:
131 print(f"Error reading Feff Data file '{filename}'")
132 return
133 self.filename = filename
134 mode = 'header'
135 self.potentials, self.geom = [], []
136 data = []
137 pcounter = 0
138 iline = 0
139 for line in lines:
140 iline += 1
141 line = line[:-1].strip()
142 if line.startswith('#'): line = line[1:]
143 line = line.strip()
144 if iline == 1:
145 self.title = line[:64].strip()
146 self.version = line[64:].strip()
147 continue
148 if line.startswith('k') and line.endswith('real[p]@#'):
149 mode = 'arrays'
150 continue
151 elif '----' in line[2:10]:
152 mode = 'path'
153 continue
154 #
155 if (mode == 'header' and
156 line.startswith('Abs') or line.startswith('Pot')):
157 words = line.replace('=', ' ').split()
158 ipot, z, rmt, rnm = (0, 0, 0, 0)
159 words.pop(0)
160 if line.startswith('Pot'):
161 ipot = int(words.pop(0))
162 iz = int(words[1])
163 rmt = float(words[3])
164 rnm = float(words[5])
165 if line.startswith('Abs'):
166 self.shell = words[6]
167 self.potentials.append((ipot, iz, rmt, rnm))
168 elif mode == 'header' and line.startswith('Gam_ch'):
169 words = line.replace('=', ' ').split(None, 2)
170 self.gam_ch = float(words[1])
171 self.exch = words[2]
172 elif mode == 'header' and line.startswith('Mu'):
173 words = line.replace('=', ' ').replace('eV', ' ').split()
174 self.vmu = float(words[1])
175 self.vfermi = ktoe(float(words[3]))
176 self.vint = float(words[5])
177 self.rs_int= float(words[7])
178 elif mode == 'path':
179 pcounter += 1
180 if pcounter == 1:
181 w = [float(x) for x in line.split()[:5]]
182 self.__nleg__ = int(w.pop(0))
183 self.degen, self.__reff__, self.rnorman, self.edge = w
184 elif pcounter > 2:
185 words = line.split()
186 xyz = ["%7.4f" % float(x) for x in words[:3]]
187 ipot = int(words[3])
188 iz = int(words[4])
189 if len(words) > 5:
190 lab = words[5]
191 else:
192 lab = atomic_symbol(iz)
193 amass = atomic_mass(iz)
194 geom = [lab, iz, ipot, amass] + xyz
195 if len(self.geom) == 0:
196 self.absorber = lab
197 self.geom.append(tuple(geom))
198 elif mode == 'arrays':
199 d = np.array([float(x) for x in line.split()])
200 if len(d) == 7:
201 data.append(d)
202 data = np.array(data).transpose()
203 self.k = data[0]
204 self.real_phc = data[1]
205 self.mag_feff = data[2]
206 self.pha_feff = data[3]
207 self.red_fact = data[4]
208 self.lam = data[5]
209 self.rep = data[6]
210 self.pha = data[1] + data[3]
211 self.amp = data[2] * data[4]
212 self.__rmass = None # reduced mass of path
215class FeffPathGroup(Group):
216 def __init__(self, filename=None, label='', feffrun='', s02=None, degen=None,
217 e0=None, ei=None, deltar=None, sigma2=None, third=None,
218 fourth=None, use=True, _feffdat=None, **kws):
219 kwargs = dict(filename=filename)
220 kwargs.update(kws)
221 Group.__init__(self, **kwargs)
223 self.filename = filename
224 self.feffrun = feffrun
225 self.label = label
226 self.use = use
227 self.params = None
228 self.spline_coefs = None
229 self.geom = []
230 self.shell = 'K'
231 self.absorber = None
232 self._feffdat = _feffdat
234 self.hashkey = 'p000'
235 self.k = None
236 self.chi = None
238 self.__def_degen = 1
240 if filename not in ('', None) and os.path.exists(filename):
241 self._feffdat = FeffDatFile(filename=filename)
243 if self._feffdat is not None:
244 self.create_spline_coefs()
245 self.geom = self._feffdat.geom
246 self.shell = self._feffdat.shell
247 self.absorber = self._feffdat.absorber
248 self.__def_degen = self._feffdat.degen
250 self.hashkey = self.__geom2label()
251 if self.label in ('', None):
252 self.label = self.hashkey
254 if feffrun in ('', None):
255 try:
256 dirname, fpfile = os.path.split(filename)
257 parent, folder = os.path.split(dirname)
258 self.feffrun = folder
259 except:
260 pass
262 self.init_path_params(degen=degen, s02=s02, e0=e0, ei=ei,
263 deltar=deltar, sigma2=sigma2, third=third,
264 fourth=fourth)
267 def init_path_params(self, degen=None, s02=None, e0=None, ei=None,
268 deltar=None, sigma2=None, third=None, fourth=None):
269 """set inital values/expressions for path parameters for Feff Path"""
270 self.degen = self.__def_degen if degen is None else degen
271 self.s02 = 1.0 if s02 is None else s02
272 self.e0 = 0.0 if e0 is None else e0
273 self.ei = 0.0 if ei is None else ei
274 self.deltar = 0.0 if deltar is None else deltar
275 self.sigma2 = 0.0 if sigma2 is None else sigma2
276 self.third = 0.0 if third is None else third
277 self.fourth = 0.0 if fourth is None else fourth
279 def __repr__(self):
280 if self.filename is not None:
281 return 'feffpath((no_file)'
282 return f'feffpath({self.filename})'
284 def __getstate__(self):
285 _feffdat_state = self._feffdat.__getstate__()
286 return (self.filename, self.label, self.feffrun, self.degen,
287 self.s02, self.e0, self.ei, self.deltar, self.sigma2,
288 self.third, self.fourth, self.use, _feffdat_state)
291 def __setstate__(self, state):
292 self.params = self.spline_coefs = self.k = self.chi = None
293 self.use = True
294 if len(state) == 12: # "use" was added after paths states were being saved
295 (self.filename, self.label, self.feffrun, self.degen,
296 self.s02, self.e0, self.ei, self.deltar, self.sigma2,
297 self.third, self.fourth, _feffdat_state) = state
298 elif len(state) == 13:
299 (self.filename, self.label, self.feffrun, self.degen,
300 self.s02, self.e0, self.ei, self.deltar, self.sigma2,
301 self.third, self.fourth, self.use, _feffdat_state) = state
303 self._feffdat = FeffDatFile()
304 self._feffdat.__setstate__(_feffdat_state)
306 self.create_spline_coefs()
308 self.geom = self._feffdat.geom
309 self.shell = self._feffdat.shell
310 self.absorber = self._feffdat.absorber
311 def_degen = self._feffdat.degen
313 self.hashkey = self.__geom2label()
314 if self.label in ('', None):
315 self.label = self.hashkey
318 def __geom2label(self):
319 """generate label by hashing path geometry"""
320 rep = [self._feffdat.degen, self._feffdat.shell, self.feffrun]
321 for atom in self.geom:
322 rep.extend(atom)
323 rep.append("%7.4f" % self._feffdat.reff)
324 s = "|".join([str(i) for i in rep])
325 return "p%s" % (b32hash(s)[:9].lower())
327 def pathpar_name(self, parname):
328 """
329 get internal name of lmfit Parameter for a path paramter, using Path's hashkey
330 """
331 return f'{parname}_{self.hashkey}'
333 def __copy__(self):
334 newpath = FeffPathGroup()
335 newpath.__setstate__(self.__getstate__())
336 return newpath
338 def __deepcopy__(self, memo):
339 newpath = FeffPathGroup()
340 newpath.__setstate__(self.__getstate__())
341 return newpath
344 @property
345 def reff(self): return self._feffdat.reff
347 @reff.setter
348 def reff(self, val): pass
350 @property
351 def nleg(self): return self._feffdat.nleg
353 @nleg.setter
354 def nleg(self, val): pass
356 @property
357 def rmass(self): return self._feffdat.rmass
359 @rmass.setter
360 def rmass(self, val): pass
362 def __repr__(self):
363 return f'<FeffPath Group label={self.label:s}, filename={self.filename:s}, use={self.use}>'
365 def create_path_params(self, params=None):
366 """
367 create Path Parameters within the current lmfit.Parameters namespace
368 """
369 if params is not None:
370 self.params = params
371 if self.params is None:
372 self.params = Parameters()
374 if (not isinstance(self.params, Parameters) and
375 isinstance(self.params, dict)):
376 self.params = dict2params(self.params)
378 if self.params._asteval.symtable.get('sigma2_debye', None) is None:
379 add_sigma2funcs(self.params)
380 if self.label is None:
381 self.label = self.__geom2label()
382 self.store_feffdat()
383 for pname in PATH_PARS:
384 val = getattr(self, pname)
385 attr = 'value'
386 if isinstance(val, str):
387 attr = 'expr'
388 kws = {'vary': False, attr: val}
389 parname = self.pathpar_name(pname)
390 self.params.add(parname, **kws)
391 self.params[parname].is_pathparam = True
393 def create_spline_coefs(self):
394 """pre-calculate spline coefficients for feff data"""
395 self.spline_coefs = {}
396 fdat = self._feffdat
397 self.spline_coefs['pha'] = UnivariateSpline(fdat.k, fdat.pha, s=0)
398 self.spline_coefs['amp'] = UnivariateSpline(fdat.k, fdat.amp, s=0)
399 self.spline_coefs['rep'] = UnivariateSpline(fdat.k, fdat.rep, s=0)
400 self.spline_coefs['lam'] = UnivariateSpline(fdat.k, fdat.lam, s=0)
402 def store_feffdat(self):
403 """stores data about this Feff path in the Parameters
404 symbol table for use as `reff` and in sigma2 calcs
405 """
406 if (not isinstance(self.params, Parameters) and
407 isinstance(self.params, dict)):
408 self.params = dict2params(self.params)
410 symtab = self.params._asteval.symtable
411 symtab['feffpath'] = self._feffdat
412 for attr in FEFFDAT_VALUES:
413 symtab[attr] = getattr(self._feffdat, attr)
416 def __path_params(self, **kws):
417 """evaluate path parameter value. Returns
418 (degen, s02, e0, ei, deltar, sigma2, third, fourth)
419 """
420 # put 'reff' and '_feffdat' into the symboltable so that
421 # they can be used in constraint expressions
422 self.store_feffdat()
423 if self.params is None:
424 self.create_path_params()
425 out = []
426 for pname in PATH_PARS:
427 val = kws.get(pname, None)
428 if val is None:
429 parname = self.pathpar_name(pname)
430 val = self.params[parname]._getval()
431 out.append(val)
432 return out
434 def path_paramvals(self, **kws):
435 (deg, s02, e0, ei, delr, ss2, c3, c4) = self.__path_params()
436 return dict(degen=deg, s02=s02, e0=e0, ei=ei, deltar=delr,
437 sigma2=ss2, third=c3, fourth=c4)
439 def report(self):
440 "return text report of parameters"
441 tmpvals = self.__path_params()
442 pathpars = {}
443 for pname in ('degen', 's02', 'e0', 'deltar',
444 'sigma2', 'third', 'fourth', 'ei'):
445 parname = self.pathpar_name(pname)
446 if parname in self.params:
447 pathpars[pname] = (self.params[parname].value,
448 self.params[parname].stderr)
450 out = [f" = Path '{self.label}' = {self.absorber} {self.shell} Edge",
451 f" feffdat file = {self.filename}, from feff run '{self.feffrun}'"]
452 geomlabel = ' geometry atom x y z ipot'
453 geomformat = ' %4s %s, %s, %s %d'
454 out.append(geomlabel)
456 for atsym, iz, ipot, amass, x, y, z in self.geom:
457 s = geomformat % (atsym, x, y, z, ipot)
458 if ipot == 0: s = "%s (absorber)" % s
459 out.append(s)
461 stderrs = {}
462 out.append(' {:7s}= {:s}'.format('reff',
463 gfmt(self._feffdat.reff)))
465 for pname in ('degen', 's02', 'e0', 'r',
466 'deltar', 'sigma2', 'third', 'fourth', 'ei'):
467 val = strval = getattr(self, pname, 0)
468 parname = self.pathpar_name(pname)
469 std = None
470 if pname == 'r':
471 parname = self.pathpar_name('deltar')
472 par = self.params.get(parname, None)
473 val = par.value + self._feffdat.reff
474 strval = 'reff + ' + getattr(self, 'deltar', 0)
475 std = par.stderr
476 else:
477 if pname in pathpars:
478 val, std = pathpars[pname]
479 else:
480 par = self.params.get(parname, None)
481 if par is not None:
482 val = par.value
483 std = par.stderr
485 if std is None or std <= 0:
486 svalue = gfmt(val)
487 else:
488 svalue = "{:s} +/-{:s}".format(gfmt(val), gfmt(std))
489 if pname == 's02':
490 pname = 'n*s02'
492 svalue = " {:7s}= {:s}".format(pname, svalue)
493 if isinstance(strval, str):
494 svalue = "{:s} := '{:s}'".format(svalue, strval)
496 if val == 0 and pname in ('third', 'fourth', 'ei'):
497 continue
498 out.append(svalue)
499 return '\n'.join(out)
501 def calc_chi_from_params(self, params, **kws):
502 "calculate chi(k) from Parameters, ParameterGroup, and/or kws for path parameters"
503 if isinstance(params, Parameters):
504 self.create_path_params(params=params)
505 else:
506 self.create_path_params(params=group2params(params))
507 self._calc_chi(**kws)
509 def _calc_chi(self, k=None, kmax=None, kstep=None, degen=None, s02=None,
510 e0=None, ei=None, deltar=None, sigma2=None,
511 third=None, fourth=None, debug=False, interp='cubic', **kws):
512 """calculate chi(k) with the provided parameters"""
513 fdat = self._feffdat
514 if fdat.reff < 0.05:
515 print('reff is too small to calculate chi(k)')
516 return
517 # make sure we have a k array
518 if k is None:
519 if kmax is None:
520 kmax = 30.0
521 kmax = min(max(fdat.k), kmax)
522 if kstep is None: kstep = 0.05
523 k = kstep * np.arange(int(1.01 + kmax/kstep), dtype='float64')
524 if not self.use:
525 self.k = k
526 self.p = k
527 self.chi = 0.0 * k
528 self.chi_imag = 0.0 * k
529 return
530 reff = fdat.reff
531 # get values for all the path parameters
532 (degen, s02, e0, ei, deltar, sigma2, third, fourth) = \
533 self.__path_params(degen=degen, s02=s02, e0=e0, ei=ei,
534 deltar=deltar, sigma2=sigma2,
535 third=third, fourth=fourth)
537 # create e0-shifted energy and k, careful to look for |e0| ~= 0.
538 en = k*k - e0*ETOK
539 if min(abs(en)) < SMALL_ENERGY:
540 try:
541 en[np.where(abs(en) < 1.5*SMALL_ENERGY)] = SMALL_ENERGY
542 except ValueError:
543 pass
544 # q is the e0-shifted wavenumber
545 q = np.sign(en)*np.sqrt(abs(en))
547 # lookup Feff.dat values (pha, amp, rep, lam)
548 if interp.startswith('lin'):
549 pha = np.interp(q, fdat.k, fdat.pha)
550 amp = np.interp(q, fdat.k, fdat.amp)
551 rep = np.interp(q, fdat.k, fdat.rep)
552 lam = np.interp(q, fdat.k, fdat.lam)
553 else:
554 pha = self.spline_coefs['pha'](q)
555 amp = self.spline_coefs['amp'](q)
556 rep = self.spline_coefs['rep'](q)
557 lam = self.spline_coefs['lam'](q)
559 if debug:
560 self.debug_k = q
561 self.debug_pha = pha
562 self.debug_amp = amp
563 self.debug_rep = rep
564 self.debug_lam = lam
566 # p = complex wavenumber, and its square:
567 pp = (rep + 1j/lam)**2 + 1j * ei * ETOK
568 p = np.sqrt(pp)
570 # the xafs equation:
571 cchi = np.exp(-2*reff*p.imag - 2*pp*(sigma2 - pp*fourth/3) +
572 1j*(2*q*reff + pha +
573 2*p*(deltar - 2*sigma2/reff - 2*pp*third/3) ))
575 cchi = degen * s02 * amp * cchi / (q*(reff + deltar)**2)
576 cchi[0] = 2*cchi[1] - cchi[2]
577 # outputs:
578 self.k = k
579 self.p = p
580 self.chi = cchi.imag
581 self.chi_imag = -cchi.real
585def path2chi(path, paramgroup=None, **kws):
586 """calculate chi(k) for a Feff Path,
587 optionally setting path parameter values
588 output chi array will be written to path group
590 Parameters:
591 ------------
592 path: a FeffPath Group
593 params: lmfit Parameters or larch ParameterGroup
594 kmax: maximum k value for chi calculation [20].
595 kstep: step in k value for chi calculation [0.05].
596 k: explicit array of k values to calculate chi.
598 Returns:
599 ---------
600 None - outputs are written to path group
602 """
603 if not isNamedClass(path, FeffPathGroup):
604 msg('%s is not a valid Feff Path' % path)
605 return
606 path.calc_chi_from_params(paramgroup, **kws)
609def ff2chi(paths, group=None, paramgroup=None, k=None, kmax=None,
610 kstep=0.05, **kws):
611 """sum chi(k) for a list of FeffPath Groups.
613 Parameters:
614 ------------
615 paths: a list of FeffPath Groups or dict of {label: FeffPathGroups}
616 paramgroup: a Parameter Group for calculating Path Parameters [None]
617 kmax: maximum k value for chi calculation [20].
618 kstep: step in k value for chi calculation [0.05].
619 k: explicit array of k values to calculate chi.
620 Returns:
621 ---------
622 group contain arrays for k and chi
624 This essentially calls path2chi() for each of the paths in the
625 `paths` and writes the resulting arrays to group.k and group.chi.
627 """
628 if isinstance(paramgroup, Parameters):
629 params = paramgroup
630 else:
631 params = group2params(paramgroup)
634 if isinstance(paths, (list, tuple)):
635 pathlist = paths
636 elif isinstance(paths, dict):
637 pathlist = list(paths.values())
638 else:
639 raise ValueErrror('paths must be list, tuple, or dict')
641 if len(pathlist) == 0:
642 return Group(k=np.linspace(0, 20, 401),
643 chi=np.zeros(401, dtype='float64'))
645 for path in pathlist:
646 if not isNamedClass(path, FeffPathGroup):
647 print(f"{path} is not a valid Feff Path")
648 return
649 path.create_path_params(params=params)
650 path._calc_chi(k=k, kstep=kstep, kmax=kmax)
651 k = pathlist[0].k[:]*1.0
652 out = np.zeros_like(k)
653 for path in pathlist:
654 out += path.chi
656 if group is None:
657 group = Group()
658 group.k = k
659 group.chi = out
660 return group
662def feffpath(filename='', label='', feffrun='', s02=None, degen=None,
663 e0=None,ei=None, deltar=None, sigma2=None, third=None,
664 fourth=None, use=True, **kws):
665 """create a Feff Path Group from a *feffNNNN.dat* file.
667 Parameters:
668 -----------
669 filename: name (full path of) *feffNNNN.dat* file
670 label: label for path [file name]
671 degen: path degeneracy, N [taken from file]
672 s02: S_0^2 value or parameter [1.0]
673 e0: E_0 value or parameter [0.0]
674 deltar: delta_R value or parameter [0.0]
675 sigma2: sigma^2 value or parameter [0.0]
676 third: c_3 value or parameter [0.0]
677 fourth: c_4 value or parameter [0.0]
678 ei: E_i value or parameter [0.0]
679 feffrun: label for Feff run [parent folder of Feff.dat file]
680 use : use in sum of paths [True]
682 For all the options described as **value or parameter** either a
683 numerical value or a Parameter (as created by param()) can be given.
685 Returns:
686 ---------
687 a FeffPath Group.
688 """
689 if filename != '' and not os.path.exists(filename):
690 raise ValueError(f"Feff Path file '{filename:s}' not found")
691 return FeffPathGroup(filename=filename, label=label, feffrun=feffrun,
692 s02=s02, degen=degen, e0=e0, ei=ei, deltar=deltar,
693 sigma2=sigma2, third=third, fourth=fourth, use=use)
695def use_feffpath(pathcache, label, degen=None, s02=None, e0=None,ei=None,
696 deltar=None, sigma2=None, third=None, fourth=None, use=True):
697 """use a copy of a Feff Path from a cache of feff paths - a simply dictionary
698 keyed by the path label, and to support in-memory paths, not read from feff.dat files
700 Parameters:
701 -----------
702 pathcache: dictionary of feff paths
703 label: label for path -- the dictionary key
704 degen: path degeneracy, N [taken from file]
705 s02: S_0^2 value or parameter [1.0]
706 e0: E_0 value or parameter [0.0]
707 deltar: delta_R value or parameter [0.0]
708 sigma2: sigma^2 value or parameter [0.0]
709 third: c_3 value or parameter [0.0]
710 fourth: c_4 value or parameter [0.0]
711 ei: E_i value or parameter [0.0]
712 use: whether to use path in sum [True]
713 """
714 path = deepcopy(pathcache[label])
715 path.use = use
716 path.init_path_params(s02=s02, degen=degen, e0=e0, ei=ei,
717 deltar=deltar, sigma2=sigma2, third=third,
718 fourth=fourth)
719 return path