Hello Matt,
Thank you for providing the examples. I tried to to write my own script based on your examples and things appear to be working fine until I get to the point where I want to run feffit, then I get the traceback I've pasted here below. I've attached an archive with the script and the data, do you have any idea what the problem is here?
Best regards,
Johan
***@johan-Latitude-E6430:~/misc/larch/pd_metal_python$ python pd_metal_python.py
Traceback (most recent call last):
File "pd_metal_python.py", line 49, in <module>
out = feffit(pars, dset, _larch=mylarch)
File "/usr/local/lib/python2.7/dist-packages/larch/__init__.py", line 38, in wrapper
return fcn(*args, **keywords)
File "/home/johan/.larch/plugins/xafs/feffit.py", line 411, in feffit
fit.leastsq()
File "/usr/local/lib/python2.7/dist-packages/larch/fitting/minimizer.py", line 398, in leastsq
lsout = leastsq(self.__residual, self.vars, **lskws)
File "/usr/local/lib/python2.7/dist-packages/larch/fitting/minimizer.py", line 222, in leastsq
shape = _check_func('leastsq', 'func', func, x0, args, n)
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 19, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/usr/local/lib/python2.7/dist-packages/larch/fitting/minimizer.py", line 325, in __residual
return self.userfcn(self.paramgroup, *self.userargs, **self.userkws)
File "/home/johan/.larch/plugins/xafs/feffit.py", line 399, in _resid
return concatenate([d._residual() for d in datasets])
File "/home/johan/.larch/plugins/xafs/feffit.py", line 266, in _residual
_larch=self._larch, group=self.model)
File "/usr/local/lib/python2.7/dist-packages/larch/__init__.py", line 38, in wrapper
return fcn(*args, **keywords)
File "/home/johan/.larch/plugins/xafs/feffdat.py", line 447, in _ff2chi
path._calc_chi(k=k, kstep=kstep, kmax=kmax)
File "/home/johan/.larch/plugins/xafs/feffdat.py", line 333, in _calc_chi
if self._larch.symtable._sys.paramGroup is not None:
AttributeError: 'NoneType' object has no attribute 'symtable'
***@johan-Latitude-E6430:~/misc/larch/pd_metal_python$
________________________________
From: ifeffit-***@millenia.cars.aps.anl.gov [ifeffit-***@millenia.cars.aps.anl.gov] on behalf of Matt Newville [***@cars.uchicago.edu]
Sent: 01 October 2015 06:16
To: XAFS Analysis using Ifeffit
Subject: Re: [Ifeffit] Problems importing larch plugins to python
Hi Johan,
On Wed, Sep 30, 2015 at 10:53 AM, Johan Nilsson <***@chalmers.se<mailto:***@chalmers.se>> wrote:
Hello Matt,
I was able to import pre_edge, autobk, and xftf without problems. Is it possible to import feff paths and do a fit to exafs data in a python script? I was able to do
larch.enable_plugins()
from larch_plugins.xafs import feffdat
path1 = feffdat.feffpath('feff0001.dat')
but I could not figure out how to get the feffit_transform and feffit_dataset functions to work. Before I upgraded I was able to use those two in a python script but I was not able to get the feffit function to run to do the actual fit.
Sorry, the use from python is not as well documented as it should be. A larch script for a simple use of feffit would be:
## simple feffit in larch
# read chi(k)
cu_data = read_ascii('../xafsdata/cu.chi', labels='k, chi')
# define fitting parameter group
pars = group(amp = param(1, vary=True),
del_e0 = param(0.1, vary=True),
sig2 = param(0.002, vary=True),
del_r = param(0., vary=True) )
# define a Feff Path, give expressions for Path Parameters
path1 = feffpath('feffcu01.dat',
s02 = 'amp',
e0 = 'del_e0',
sigma2 = 'sig2',
deltar = 'del_r')
# set tranform / fit ranges
trans = feffit_transform(kmin=3, kmax=17, kw=2, dk=4,
window='kaiser', rmin=1.4, rmax=3.0)
# define dataset to include data, pathlist, transform
dset = feffit_dataset(data=cu_data, pathlist=[path1], transform=trans)
# perform fit
out = feffit(pars, dset)
# print result
print feffit_report(out)
###########################################
Translating that into pure Python would be:
## simple feffit in python
import larch
from larch import Group, Parameter
from larch_plugins.io<http://larch_plugins.io> import read_ascii
from larch_plugins.xafs import FeffPathGroup
from larch_plugins.xafs.feffit import (TransformGroup, FeffitDataSet,
feffit, feffit_report)
#create larch session
session = larch.Interpreter()
# read chi(k)
cu_data = read_ascii('../xafsdata/cu.chi', labels='k, chi', _larch=session)
# define fitting parameter group
pars = larch.Group(amp = Parameter(1, vary=True),
del_e0 = Parameter(0.1, vary=True),
sig2 = Parameter(0.002, vary=True),
del_r = Parameter(0., vary=True) )
# define a Feff Path, give expressions for Path Parameters
path1 = FeffPathGroup('feffcu01.dat',
s02 = 'amp',
e0 = 'del_e0',
sigma2 = 'sig2',
deltar = 'del_r', _larch=session)
# set tranform / fit ranges
trans = TransformGroup(kmin=3, kmax=17, kw=2, dk=4,
window='kaiser', rmin=1.4, rmax=3.0, _larch=session)
# define dataset to include data, pathlist, transform
dset = FeffitDataSet(data=cu_data, pathlist=[path1],
transform=trans, _larch=session)
# perform fit
out = feffit(pars, dset, _larch=session)
# print result
print feffit_report(out, _larch=session)
##################################################
So, it's FeffPathGroup, TransformGroup and FeffitDataSet that you were looking for -- python classes, with the corresponding larch functione just return an instance of these classes. And you have to pass in a '_larch=session'
to all of these classes and fnctions, as these all assume they can read/write to the session-wide larch symbol table (and, while fitting, they actually do). Yeah, a couple of these might be possible to eliminate, and it's not how you'd do it in pure python, but you'd probably build a Feffit class, and be passing around 'self', which is really not so different from "reference to global state".
Anyway, it is doable in non-larch Python. Suggestions for improvement welcome!
--Matt