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@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@johan-Latitude-E6430:~/misc/larch/pd_metal_python$
________________________________
From: ifeffit-bounces@millenia.cars.aps.anl.gov [ifeffit-bounces@millenia.cars.aps.anl.gov] on behalf of Matt Newville [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 mailto:johan.nilsson@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.iohttp://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