Hi Sean, On Tue, Nov 1, 2016 at 1:39 PM, Sean Fackler <swfack...@lbl.gov> wrote:
> Dear Matt, > > I’ve been working to implement Larch functions as a Python library. During > the implementation I found a number of things I needed to do including: > > You can use Larch functions from Python, of course. Normally, you'd do something like import larch from larch_plugins.xafs import pre_edge, mback > 1. Identifiying a functions’ python callable name, i.e. _group as a python > callable function instead of group as the larch function. > I'm not sure I understand. You shouldn't need "a function's python callable name", you should just need the function. Maybe I misunderstand. If you need a larch Group, you should be able to do import larch agroup = larch.Group(name='mygroupname', xdata = range(100), label='hello') > > 2. The need to pass '_larch = mylarch’ in the said function or I get the > 'AttributeError: 'NoneType' object has no attribute ‘symtable’ ‘ > > Yes, many of the larch plugin functions either require or are much happier with an instance of a larch session passed in as the '_larch' argument. It's kind of a feature ;). > 3. The need to run the script through the Python console as oppose to > running as a script. > > I'm not sure I understand what this means. You should be able to run a python program from any environment. > You can see my sample script with data attached. Keep in mind I am a > Python novice. So for point 3 in particular *I don’t understand the > difference between running some selected code in the Python console and > running the whole script in the shell *(I am using PyCharm CE). I checked > my Python interpreter with sys.executable (path) and sys.version_info > (version) which are the same between the console and interpreter which were > initial issues I found online. Is the interpreter somehow not seeing the > xraylarch library? > Hmm, that doesn't make a lot of sense to me either. What errors do you get when you run your script? I don't use PyCharm, so maybe that's not seeing all of the modules from anaconda? Is PyCharm seeing your anaconda distribution? A few comments on your script: a) there should be no need to do a os.chdir() to any folder, especially not to source code folders. b) doing from xxx import * is bound to lead to confusion. Import what you need, and don't import what you don't need. Finally: 1. Is there an easier way to use the larch functions as a python > library? > Is the above suggestion better? > 2. Is a larch group basically a python dictionary? > Actually, it's basically an empty class: class Group: def __init__(self, **kws): .... mygroup = Group() mygroup.x = 1 mygroup.y = 'a string' even in more detail, it's an empty class. In most cases it would probably be OK to substitute almost any class instance as a Group. In Larch, I tend to make as many things as possible "group-like" so that accessing elements is easy. > If so, this could be made clearer in the documentation. I am interested to > contribute to the documentation if that’s of interest/help. > > Sure! The docs are definitely in need of some serious work. > I am running MacOS Sierra 10.12.1 on a mid-2015 15" MacBook Pro with > Python 2.7. > > Ron and Alpha: Maybe you have some ideas to the above points? > > Thanks everyone for any help. > > Sean > > The attached modified version of your script works for me from a Terminal (The fit's not very good, yet, but it did run). On Mac OSX with anaconda, you probably have to run this as "pythonw import_fit.py" (note: pythonw, not python). Hope that helps, --Matt
import os import sys import numpy as np import matplotlib.pyplot as plt import larch from larch import Interpreter, Group from larch.fitting import guess, minimize from larch_plugins.math.lineshapes import gaussian from larch_plugins.xafs import pre_edge, mback import pandas as pd def rdin(filename): scandata_f = pd.read_csv(filename, sep='\t', skiprows=12) if not ("Counter 0" in scandata_f.columns): scandata_f = pd.read_csv(filename, sep='\t', skiprows=8) # TrajScan files need 8 header lines somehow? print scandata_f.columns if not ("Counter 0" in scandata_f.columns): print ("Problem with header. skipping 12 or 10 lines did not make it. Check input file.") return None return scandata_f def prepare_scan(scandata_f, datacounter="Counter 3", reference_counter='Counter 2'): # Preparing Scan (normalization) if 'Counter 4' in scandata_f.columns: clockname = 'Counter 4' elif 'Counter 6' in scandata_f.columns: clockname = 'Counter 6' else: print("No counter for clock found (looked for 'Counter 4' and 'Counter 6'). Defaulting to 'Counter 0'.") clockname = 'Counter 0' scandata_f["I_Norm0"] = scandata_f[datacounter].astype(float) / scandata_f[reference_counter].astype(float) scandata_f["I_Normt"] = scandata_f[datacounter].astype(float) / scandata_f[clockname].astype(float) scandata_f["Energy"] = scandata_f["Energy"].round(1) # scandata_f["Z"] = scandata_f["Z"].round(2) return scandata_f scandata_f = rdin("TrajScan21930_swf.txt") prepare_scan(scandata_f) mylarch = Interpreter() mdat = scandata_f mdat.x = mdat.Energy mdat.y = mdat.I_Norm0 # create a group of fit parameters params = Group(off=guess(0), amp=guess(5, min=0), cen=guess(535), wid=guess(1, min=0)) # Need an edge value for the first guess for the center of the # guassian: 'cen='. Can use the edge-finder for that init = params.off + params.amp * gaussian(mdat.x, params.cen, params.wid) # define objective function for fit residual def resid(p, data): return data.y - (p.off + p.amp * gaussian(data.x, p.cen, p.wid)) # perform fit minimize(resid, params, args=(mdat,), _larch=mylarch) # make final array final = params.off + params.amp * \ gaussian(mdat.x, params.cen, params.wid) # plot results plt.plot(mdat.x, mdat.y) plt.plot(mdat.x, init) plt.plot(mdat.x, final) plt.show()
_______________________________________________ Ifeffit mailing list Ifeffit@millenia.cars.aps.anl.gov http://millenia.cars.aps.anl.gov/mailman/listinfo/ifeffit Unsubscribe: http://millenia.cars.aps.anl.gov/mailman/options/ifeffit