# Least Squares Routine

from spdirvars import *
from spglobalfuncs import *
import spplotter
from Numeric import *
from Tkinter import *
from Ifeffit import *
import Pmw
import Tix
import tkFileDialog
import tkMessageBox
import tkSimpleDialog
import os
import math
import types
from string import *

#root=Tix.Tk()
#root.title("Least Squares Fitting Mod")
#Pmw.initialise(root)

if os.name=='nt':os.sep='/'
filepath=os.getcwd()+os.sep
pm='+/-'

iffc=Ifeffit(screen_echo=1)
iffc.ifeffit("load mnexafsfit.iff")


###############################################################
##
## Main Least Square Fitter Program Class
##
###############################################################

def remundsc(text):
    return replace(text,'_','')

class DefCParams:
    def __init__(self,master,big,fname):
        f=Frame(master)
        f.pack(side=TOP,padx=2,pady=0,fill=Y)
        self.fname=fname
        self.big=big
        if fname=='init':
            lt=''
            self.active=0
        else:
            lt=fname
            self.active=1
        self.lab=Label(f,text=lt,relief=GROOVE,bd=2,width=30,justify=CENTER,font="Arial 10")
        self.lab.pack(side=TOP,fill=X,padx=2,pady=4)
        #component parameters are frac and eshift
        w=10
        self.frac=Pmw.EntryField(f,labelpos='w',entry_width=w,label_text='Frac: ',value=0,validate='real',modifiedcommand=self.clicktochange)
        self.eshift=Pmw.EntryField(f,labelpos='w',entry_width=w,label_text='EShift: ',label_fg='dark grey',entry_bg='light grey',value=0,validate='real',entry_state=DISABLED)
        self.frac.pack(side=TOP,padx=2,pady=10)
        self.eshift.pack(side=TOP,padx=2,pady=10)
        Pmw.alignlabels((self.frac,self.eshift),sticky=E)

    def clicktochange(self, *arg):
        #link to big=filelist
        if self.fname!='init':
            self.big.item_configure(self.fname,2,text=str(self.frac.get()))
        
class DefFParams:
    def __init__(self,master,fname,flist):
        f=Frame(master)
        f.pack(side=TOP,padx=2,pady=0)
        funceqns=('y=Ax+B','y=Ax2+Bx+C','Amp/Xoff/FWHM/Yoff','Amp/Xoff/FWHM/Yoff','Amp/Xoff/FWHM/Yoff/fLorz','y=A atan((x-B)/C)+D','y=A erfc((x-B)/C)+D','y=A erf((x-B)/C)+D','y=A exp((x-B)/C)+D','y=A ln((x-B)/C)+D')
        feqn={}
        for i in range(10):
            feqn.update({flist[i]:funceqns[i]})
        numparam=[2,3,4,4,5,6,6,6,6,6]
        if fname=='init':
            lt=''
            etext=''
            self.active=0
            self.np=0
        else:
            lt=fname
            ftype=fname[:rfind(fname,' ')]
            etext=feqn[ftype]
            self.active=1
            self.np=numparam[flist.index(ftype)]
        self.lab=Label(f,text=lt,relief=GROOVE,bd=2,width=30,justify=CENTER,font="Arial 10")
        self.lab.pack(side=TOP,fill=X,padx=2,pady=2)
        l=Label(f,text=etext,bd=2,justify=CENTER)
        l.pack(side=TOP,fill=X,padx=2,pady=2)
        #function parameters, dependent on function!
        w=10
        #2params=linear (AB)
        #3params=quad (ABC)
        #4params=guass,lorenz,atan,erfc,erf,exp,log (ABCW)
        #5params=pvoight (ABCWF)
        self.entlab=('A: ','B: ','C: ','D: ')
        if self.np==4 or self.np==5:
            self.entlab=('Amp: ','x0: ','FWHM: ','Off: ','F-Ltz: ')
        if self.np==6:
            self.np=4
        #init wids
        self.entlist=['','','','','']
        self.butvar=['','','','','']
        widlist=[]
        for i in range(self.np):
            fsub=Frame(f)
            fsub.pack(side=TOP,padx=2,pady=2)
            self.entlist[i]=Pmw.EntryField(fsub,labelpos='w',entry_width=w,label_text=self.entlab[i],value=0,validate='real')
            self.entlist[i].pack(side=LEFT,padx=2,pady=1)
            widlist.append(self.entlist[i])
            self.butvar[i]=StringVar()
            but=Checkbutton(fsub,text='',variable=self.butvar[i],onvalue='guess',offvalue='set')
            but.select()
            but.pack(side=LEFT,padx=3,pady=1)
        Pmw.alignlabels(widlist,sticky=E)
        
class EdgeFit:
    global lastreaddir,lastsavedir
    def __init__(self,master,root):
        #efwin=root.efwin=Toplevel(root)
        #efwin.title("Least Squares Fitting Dialog")
        #efwin.protocol("WM_DELETE_WINDOW", self.closemod)
        self.root=root
        self.efwin=efwin=master
        #change focus...
        efwin.focus_set()
        #GUI for fitting window...
        #create menu for fitting window
        menubar=Pmw.MenuBar(efwin)
        #file menu
        menubar.addmenu('File','')
        menubar.addmenuitem('File','command',label='Open Data',command=self.menuopen)
        menubar.addmenuitem('File','separator')
        menubar.addmenuitem('File','command',label='Edit Default Directories',command=self.callchangedefdirs)
        menubar.addmenuitem('File','separator')
        menubar.addmenuitem('File','command',label='Close',command=self.closemod)
        menubar.addmenuitem('File','command',label='Quit',command=root.quit)
        menubar.addmenu('Save','')
        menubar.addmenuitem('Save','command',label='Fit Data',command=self.savefitdata)
        menubar.addmenuitem('Save','command',label='Residuals',command=self.saveresdata)
        menubar.addmenu('Workspace','')
        menubar.addmenuitem('Workspace','command',label='Save Workspace',command=self.saveallvars)
        menubar.addmenuitem('Workspace','command',label='Load Workspace',command=self.loadallvars)
        menubar.addmenu('Interpolate','')
        self.nointerp=IntVar()
        menubar.addmenuitem('Interpolate','checkbutton',label='Turn Off Interpolation',variable=self.nointerp)
        self.XRDinterp=IntVar()
        menubar.addmenuitem('Interpolate','checkbutton',label='XRD Q-Spacing',variable=self.XRDinterp)
        menubar.addmenu('Self Abs','')
        menubar.addmenuitem('Self Abs','command',label='Do 10 Cycles',command=self.repeatselfabs)
        menubar.addmenu('Help','',side=RIGHT)
        menubar.addmenuitem('Help','command',label='About SixPack',command=self.callprogramabout)
        menubar.addmenuitem('Help','separator')
        #menubar.addmenuitem('Help','command',label='IFEFFIT Command Line',command=RunIFEFFITCmdLine)           
        menubar.grid(row=0,columnspan=20,sticky=W+E)
        #create toolbar space
        toolbar=Frame(efwin, relief=SUNKEN,borderwidth=2)
        b=Button(toolbar,text="Fit",width=6,command=self.fitdatcomp,bg="red", fg="white")
        b.pack(side=LEFT,padx=2,pady=2)
        b=Button(toolbar,text="Construct",width=8,command=self.makefitdat,bg="red", fg="white")
        b.pack(side=LEFT,padx=2,pady=2)
        b=Button(toolbar,text="Plot",width=6,command=self.plotcomp,bg="darkblue", fg="white")
        b.pack(side=LEFT,padx=2,pady=2)
        #display
        toolbar.grid(row=1,columnspan=20,sticky=W+E)
        #first area for data file
        filebar=Frame(efwin, relief=SUNKEN,bd=2)
        self.fileentry=Pmw.EntryField(filebar, label_text="Data File:",labelpos=W,validate=None,entry_width=80)
        self.fileentry.pack(side=LEFT,padx=5,pady=2,fill=X)
        b=Button(filebar,bitmap="@"+filepath+"xbms"+os.sep+"openfolder.xbm",command=self.fileme,height=21,width=30,bg='lightyellow')
        b.pack(side=LEFT,padx=2,pady=2)
        b=Button(filebar,text="Load",bg='darkgreen',fg='snow',width=7,command=self.load_data_file)
        b.pack(side=LEFT,padx=2,pady=2)
        filebar.grid(row=2,columnspan=15,rowspan=1,sticky=W+E+N+S)
        #Add fitting components frame in notebook format
        compwin=Frame(efwin,relief=SUNKEN,bd=2)
        l=Label(compwin,text="Fitting Components",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        #add notebook
        compnb=Pmw.NoteBook(compwin)
        if sys.platform == 'win32':
            compnb.configure(hull_background="SystemButtonFace")
        else:
            compnb.configure(hull_background="#d4d0c8")
        compnb.recolorborders()        
        compnb.pack(fill="both",expand=1)
        #file components page
        comppage=compnb.add('Components')
        s1=Frame(comppage)
        wd=20
        b=Button(s1,text="Add Comp",bg='steel blue',fg='snow',width=wd,command=self.addcomp)
        b.pack(side=TOP,padx=2,pady=2)
        b=Button(s1,text="Add Many Comps",bg='dark blue',fg='snow',width=wd,command=self.addmanycomp)
        b.pack(side=TOP,padx=2,pady=2)
        b=Button(s1,text="Reload Comps",bg='darkgreen',fg='snow',width=wd,command=self.reloadallcomp)
        b.pack(side=TOP,padx=2,pady=2)
        b=Button(s1,text="Remove Comp",bg='red',fg='snow',width=wd,command=self.removecomp)
        b.pack(side=TOP,padx=2,pady=2)
        b=Button(s1,text="Clear All",bg='brown',fg='snow',width=wd,command=self.clearcomplist)
        b.pack(side=TOP,padx=2,pady=2)
        s1.pack(side=LEFT,padx=2,pady=2)
        #tree for component list
        filwin=Frame(comppage)
        filwin.pack(side=LEFT,padx=2,pady=2)
        #add btree legend
        l=Label(filwin,text='Component                            Frac. ',anchor=W)
        l.pack(side=TOP,padx=2,pady=2)
        #add btree internals to components
        ftree=Tix.ScrolledHList(filwin,options='hlist.columns 3')
        self.filelist=ftree.hlist
        self.filelist.config(separator='#',width=45, height=16, drawbranch=0, indent=0, itemtype=Tix.TEXT,
                            command=self.choosecomp,browsecmd=self.selectcomp)
        self.filelist.column_width(2,chars=10)
        self.filelist.column_width(1,chars=30)
        self.filelist.column_width(0,chars=3)
        ftree.pack(side=TOP,fill=BOTH,expand=1,padx=2,pady=2)
        #notebook for component parameters
        sf=Frame(comppage)
        sf.pack(side=RIGHT,fill=BOTH)
        l=Label(sf,text="Component Parameters",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        self.compdes=Pmw.NoteBook(sf,tabpos=None)
        if sys.platform == 'win32':
            self.compdes.configure(hull_background="SystemButtonFace")
        else:
            self.compdes.configure(hull_background="#d4d0c8")
        self.compdes.recolorborders()
        self.compwidlist=[]
        self.compwidref={}
        self.initaddcomp()
        self.compdes.pack(side=TOP,padx=2,pady=2,fill=BOTH,expand=1)
        self.compdes.setnaturalsize()
        #functions page
        funcpage=compnb.add('Functions')
        s0=Frame(funcpage)
        s1=Frame(s0)
        s2=Frame(s0)
        wd=20
        b=Button(s1,text="Add Func",bg='steel blue',fg='snow',width=wd,command=self.addfunc)
        b.pack(side=TOP,padx=2,pady=2)
        self.allfuncs=['Linear','Quadratic','Gaussian','Lorentz','Voigt','atan','Erfc','Erf','exp','log']
        self.funccount=[0,0,0,0,0,0,0,0,0,0]
        self.funcbox=Pmw.ComboBox(s2,label_text='Functions: ',labelpos=W,scrolledlist_items=self.allfuncs,
                                  listheight=120,entryfield_entry_width=10,history=0)
        self.funcbox.selectitem(self.allfuncs[0])
        self.funcbox.pack(side=TOP,fill=X,padx=2,pady=3)
        b=Button(s1,text="Remove Func",bg='red',fg='snow',width=wd,command=self.removefunc)
        b.pack(side=TOP,padx=2,pady=2)
        b=Button(s1,text="Clear All",bg='brown',fg='snow',width=wd,command=self.clearfunclist)
        b.pack(side=TOP,padx=2,pady=2)
        s0.pack(side=LEFT,padx=2,pady=2)
        s1.pack(side=TOP,padx=2,pady=2)
        s2.pack(side=TOP,padx=2,pady=2)
        #tree for function list
        #add btree internals to components
        ftree=Tix.ScrolledHList(funcpage,options='hlist.columns 2')
        self.funclist=ftree.hlist
        self.funclist.config(separator='#',width=30, height=16, drawbranch=0, indent=0, itemtype=Tix.TEXT,
                             command=self.choosefunc,browsecmd=self.selectfunc)
        self.funclist.column_width(1,chars=20)
        self.funclist.column_width(0,chars=3)
        ftree.pack(side=LEFT,fill=BOTH,expand=1,padx=2,pady=2)
        #notebook for component parameters
        sf=Frame(funcpage)
        sf.pack(side=RIGHT,fill=BOTH)
        l=Label(sf,text="Function Parameters",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        self.funcdes=Pmw.NoteBook(sf,tabpos=None)
        if sys.platform == 'win32':
            self.funcdes.configure(hull_background="SystemButtonFace")
        else:
            self.funcdes.configure(hull_background="#d4d0c8")
        self.funcdes.recolorborders()
        self.funcwidlist=[]
        self.funcwidref={}
        self.initaddfunc()
        self.funcdes.pack(side=RIGHT,padx=2,pady=2,fill=BOTH,expand=1)
        self.funcdes.setnaturalsize()
        #results page
        respage=compnb.add('Results')
        self.restext=Pmw.ScrolledText(respage,hscrollmode='none',vscrollmode='static',label_text="Results of all fitted parameters",
                                      labelpos=N,borderframe=1,text_font="Courier 9",
                                      usehullsize=1,hull_height=250,hull_width=600) 
        self.restext.pack(padx=2,pady=0)
        compnb.setnaturalsize()        
        compwin.grid(row=3,rowspan=13,columnspan=15,sticky=W+E+N+S) 
        #add special features
        #add fluo correction
        feat=Frame(efwin,relief=SUNKEN,bd=2)
        l=Label(feat,text="Special Features",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        p10=Frame(feat,relief=GROOVE,bd=1)
        p11=Frame(p10)
        p12=Frame(p10)
        but=Button(p10,text="SA to Fit",width=8,command=self.selfabsfit,bg="goldenrod")
        but2=Button(p10,text="Fit to SA",width=8,command=self.fittoselfabs,bg="LemonChiffon3")
        lab=Label(p10,text="Fluorescence Self Abs Corr, D = (D/r) * muKa / (1 - (D/r))")
        but.pack(side=LEFT,padx=2,pady=2)
        but2.pack(side=LEFT,padx=2,pady=2)
        lab.pack(side=LEFT,padx=10,pady=2)
        self.mukent=Pmw.EntryField(p11,label_text="muKa:",labelpos=W,validate='real',entry_width=10,value="2")
        self.mukent.pack(side=TOP,padx=14,pady=1)
        self.deltamuk=Label(p11,text=pm,anchor=W,width=8)
        self.deltamuk.pack(side=TOP,padx=14,pady=1)
        self.ffent=Pmw.EntryField(p12,label_text="Ints. Ratio:",labelpos=W,validate='real',entry_width=10,value="2")
        self.ffent.pack(side=TOP,padx=2,pady=1)
        self.deltaff=Label(p12,text=pm,anchor=W,width=8)
        self.deltaff.pack(side=TOP,padx=1,pady=1)
        p10.pack(side=TOP,padx=2,pady=2,fill=X)
        p12.pack(side=RIGHT,padx=2,pady=2)
        p11.pack(side=RIGHT,padx=2,pady=2)
        #add Eshift slider
        p20=Frame(feat,relief=GROOVE,bd=1)
        p20.pack(side=TOP,padx=2,pady=2,fill=X)
        self.dateshift=DoubleVar()
        self.dateshift.set(0)
        self.slide=Scale(p20,label="Data Energy Shift (if enabled)",state=DISABLED,variable=self.dateshift,from_=-5, to=5,orient=HORIZONTAL,resolution=0.01,length=500,troughcolor='light slate grey',fg='dark grey')
        self.slide.pack(side=TOP,padx=2,pady=2)
        feat.grid(row=16,rowspan=8,columnspan=15,sticky=W+E+N+S)        
        #Add fit parameters list
        fitpwin=Frame(efwin,relief=SUNKEN,bd=2)
        l=Label(fitpwin,text="Fit Parameters",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        self.xmin=Pmw.EntryField(fitpwin,label_text="xmin:",labelpos=W,validate='real',entry_width=5,value='')
        self.xmax=Pmw.EntryField(fitpwin,label_text="xmax:",labelpos=W,validate='real',entry_width=5,value='')
        self.xwt=Pmw.EntryField(fitpwin,label_text="x-weight:",labelpos=W,validate='real',entry_width=5,value='0')
        self.xmin.pack(fill=X,expand=1,padx=15,pady=3)
        self.xmax.pack(fill=X,expand=1,padx=15,pady=3)
        self.xwt.pack(fill=X,expand=1,padx=15,pady=3)
        Pmw.alignlabels([self.xmin,self.xmax,self.xwt])
        self.fpos=IntVar()
        cb=Checkbutton(fitpwin,text="Non-negative Fit?",variable=self.fpos,anchor=W)
        cb.pack(fill=X,padx=8,pady=4)
        self.sumone=IntVar()
        cb=Checkbutton(fitpwin,text="Sum comps to one?",variable=self.sumone,anchor=W)
        cb.pack(fill=X,padx=8,pady=4)
        self.stowt=Pmw.EntryField(fitpwin,label_text="     Chisq wt STone:",labelpos=W,validate='real',entry_width=7,value='1000')
        self.stowt.pack(fill=X,expand=1,padx=16,pady=3)
        #self.efloat=IntVar()
        #cb=Checkbutton(fitpwin,text="Allow Component E to float?",variable=self.efloat,anchor=W)
        #cb.pack(fill=X,padx=8,pady=4)
        self.edfloat=IntVar()
        cb=Checkbutton(fitpwin,text="Allow Data E to float?",variable=self.edfloat,anchor=W,command=self.changestate)
        cb.pack(fill=X,padx=8,pady=4)
        fitpwin.grid(row=2,column=16,columnspan=4,rowspan=10,sticky=W+E+N+S)
        #add plot options list
        plotpwin=Frame(efwin,relief=SUNKEN,bd=2)
        l=Label(plotpwin,text="Plot Options",relief=RAISED,bd=2)
        l.pack(side=TOP,fill=X,padx=2,pady=4)
        self.plottypes=Pmw.RadioSelect(plotpwin, buttontype='checkbutton',orient='vertical',labelpos=W)
        self.plottypes.pack(side=TOP,padx=5,pady=5)
        for text in ('Data','Fit','SA Corrected','E Shifted','Residuals','Waterfall'):
            self.plottypes.add(text)
        self.plottypes.invoke('Data')
        plotpwin.grid(row=12,column=16,columnspan=4,rowspan=12,sticky=W+E+N+S) 
        #Fit Quality Bar
        bar=Frame(efwin, relief=SUNKEN,bd=2)
        l=Label(bar,text="Chi Sq: ",anchor=W)
        self.ChiSq=Label(bar,text="",width=25,anchor=W)
        l.pack(side=LEFT,padx=2,pady=2)
        self.ChiSq.pack(side=LEFT,padx=2,pady=2)
        m=Label(bar,text="Red Chi Sq: ",anchor=W)
        self.ChiSqR=Label(bar,text="",width=25,anchor=W)
        m.pack(side=LEFT,padx=2,pady=2)
        self.ChiSqR.pack(side=LEFT,padx=2,pady=2)
        n=Label(bar,text="Comp Sum: ",anchor=W)
        self.Csum=Label(bar,text="",width=25,anchor=W)
        n.pack(side=LEFT,padx=2,pady=2)
        self.Csum.pack(side=LEFT,padx=2,pady=2)
        bar.grid(row=24,columnspan=20,sticky=W+E)
        #Status Bar
        self.status=Label(efwin,text="",bd=2,relief=RAISED,anchor=W,fg='blue')
        self.status.grid(row=25,columnspan=20,sticky=W+E)
        setstatus(self.status,"Ready")
        self.mstat=0
        self.abscor=0
        self.fitabsc=0
        self.autolimit=0
        self.dataname=''
        #error window
        self.box=Pmw.MessageDialog(root,title='File Error',defaultbutton=0,message_text='Wrong type of parameter file chosen!',
                 iconpos='n',icon_bitmap='warning')
        self.box.iconname('File Error')
        self.box.withdraw()

    def closemod(self):
        self.root.deiconify()
        self.efwin.destroy()

    def callprogramabout(self):
        programabout(self.root)

    def callchangedefdirs(self):        
        global lastsavedir,lastreaddir
        s=changedefdirs(self.efwin)
        lastreaddir=s.newdir
        lastsavedir=s.newdir
        
    def changestate(self):
        if self.edfloat.get()==1:
            self.slide.config(state=NORMAL,fg='black')
        if self.edfloat.get()==0:
            self.dateshift.set(0)
            self.slide.config(state=DISABLED,fg='dark grey')
        self.slide.update()

    def fileme(self):
        fileget(self.efwin,self.fileentry)

    def load_data_file(self):
        self.dataname=trimdirext(self.fileentry.get())
        dn=self.dataname
        if self.dataname=='':
            tkMessageBox.showwarning(title="File Error",message="Missing data file name",parent=self.efwin)
        else:
            if self.xmin.get()=='' or self.xmax.get()=='':
                if tkMessageBox.askokcancel(title="Parameter Error",message="Missing x-limits\nAuto-load limits from data file?",parent=self.efwin):
                    self.autolimit=1
                else:
                    return
            iffc.ifeffit("read_data(file="+self.fileentry.get()+", group="+self.dataname+",label='xr yr')")
            setstatus(self.status,"Data file "+self.dataname+" loaded!")
            #autoload limits if requested...
            if self.autolimit==1:
                iffc.ifeffit("xa=floor("+dn+".xr)")
                iffc.ifeffit("xb=ceil("+dn+".xr)")
                entry_replace(self.xmin,str(iffc.get_scalar("xa")))
                entry_replace(self.xmax,str(iffc.get_scalar("xb")))
                self.xmin.checkentry()
                self.xmax.checkentry()
                self.autolimit=0
            #interpolate data
            #0.1eV for XANES, 0.05A-1 for EXAFS
            if self.nointerp.get()==0:
                if self.XRDinterp.get()==1:
                    #XRD
                    iffc.ifeffit(dn+".x=range("+self.xmin.get()+","+self.xmax.get()+",0.005)")
                    iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
                    self.egrid=0.005
                else:
                    if iffc.get_scalar("floor("+dn+".x)")>100:
                        #XANES
                        iffc.ifeffit(dn+".x=range("+self.xmin.get()+"-10,"+self.xmax.get()+"+10,0.1)")
                        iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
                        self.egrid=0.1
                    else:
                        #EXAFS
                        iffc.ifeffit(dn+".x=range("+self.xmin.get()+","+self.xmax.get()+",0.05)")
                        iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
                        self.egrid=0.05
            else:
                iffc.ifeffit(dn+".x="+dn+".xr")
                iffc.ifeffit(dn+".y="+dn+".yr")
            #do x-weighting if necessary
            iffc.ifeffit("doxwt "+dn+" "+self.xwt.get())
                
    def menuopen(self):
        self.fileme()
        self.load_data_file()

    def initaddcomp(self):
        fname="init"
        new=self.compdes.add(fname)
        new.p=DefCParams(new,self.filelist,fname)
        self.compwidref.update({fname:new})
        self.compwidlist.append(fname)

    def initaddfunc(self):
        fname="init"
        new=self.funcdes.add(fname)
        new.p=DefFParams(new,fname,self.allfuncs)
        self.funcwidref.update({fname:new})
        self.funcwidlist.append(fname)

    def addcomp(self):
        global lastreaddir
        if self.xmin.get()=='' or self.xmax.get()=='':
            tkMessageBox.showwarning(title="Parameter Error",message="Cannot open component file\nPlease fill in missing x-limit entries",parent=self.efwin)
            return
        #get file name
        infile=ask_for_file([("chi files","*.chi"),("mu files","*.mu"),("all files","*")],lastreaddir)
        #if valid...
        if infile !='':
            sdir=rfind(infile,os.sep)
            lastreaddir=infile[:sdir]
            self.compload(infile)

    def addfunc(self):
        #get current func name
        ftype=self.funcbox.get()
        #add appropriate number        
        find=self.allfuncs.index(ftype)
        fnum=self.funccount[find]+1
        self.funccount[find]=fnum
        fname=ftype+' '+str(fnum)
        #place entries in tree
        self.funclist.add(fname,text='X',state=NORMAL)
        self.funclist.item_create(fname,1,text=fname)
        self.funclist.selection_clear()
        self.funclist.selection_set(fname)
        #create page
        new=self.funcdes.add(fname)
        self.funcdes.selectpage(fname)
        new.p=DefFParams(new,fname,self.allfuncs)
        self.funcwidref.update({fname:new})
        self.funcwidlist.append(fname)

    def addmanycomp(self):
        global lastreaddir
        if self.xmin.get()=='' or self.xmax.get()=='':
            tkMessageBox.showwarning(title="Parameter Error",message="Cannot open component files\nPlease fill in missing x-limit entries",parent=self.efwin)
            return
        self.multifd=Tix.ExFileSelectDialog(self.root)
        if lastreaddir!='':
            lastreaddir=replace(lastreaddir,'/','\\')
            self.multifd.fsbox.config(directory=lastreaddir)
        self.multifd.fsbox.filelist.listbox.configure(selectmode=MULTIPLE)
        #setup ok button...
        self.multifd.fsbox.ok.configure(command=self.getmultilist)        
        self.multifd.popup()

    def getmultilist(self):
        global lastreaddir
        multfn=self.multifd.fsbox.filelist.listbox.curselection()
        multdlist=self.multifd.fsbox.filelist.listbox.get(0,END)
        curdir=self.multifd.fsbox.dir.entry.get()
        lastreaddir=curdir
        self.multifd.popdown()
        if multfn !=():
            for sel in multfn:
                curfil=multdlist[int(sel)]
                fulpath=curdir+os.sep+curfil
                #get file data
                self.compload(fulpath)

    def clearcomplist(self):
        #kill pages
        for pg in self.compwidlist:
            #clear memory in IFEFFIT
            dn=replace(pg,'.','_')
            iffc.ifeffit('erase @group='+dn)
            self.compdes.delete(remundsc(pg))
        #reset all
        self.compwidlist=[]
        self.compwidref={}
        self.filelist.delete_all()                    
        #reinit
        self.initaddcomp()

    def clearfunclist(self):
        #kill pages
        for pg in self.funcwidlist:
            #remove memory from IFEFFIT
            dn=replace(pg,' ','_')
            iffc.ifeffit('erase @group='+dn)
            wid=self.funcwidref[pg]
            for var in wid.p.entlist:
                if var!='':
                    ind=wid.p.entlist.index(var)
                    iffc.ifeffit('erase '+dn+str(ind))
            self.funcdes.delete(pg)
        #reset all
        self.funcwidlist=[]
        self.funcwidref={}
        self.funclist.delete_all()                    
        self.funccount=[0,0,0,0,0,0,0,0,0,0]
        #reinit
        self.initaddfunc()      

    def removecomp(self):
        cur=self.filelist.info_selection()
        if cur != ():
            cur=cur[0]            
            #remove all associated vars
            ind=self.compwidlist.index(cur)
            self.compwidlist.remove(cur)
            self.filelist.delete_entry(cur)
            self.compdes.delete(remundsc(cur))
            del self.compwidref[cur]
            #clear memory in IFEFFIT
            dn=replace(cur,'.','_')
            iffc.ifeffit('erase @group='+dn)
            #reselect
            if len(self.compwidlist)==1:
                self.filelist.selection_clear()
                self.compdes.selectpage('init')
            else:
                if ind==1:ind=2
                new=self.compwidlist[ind-1]
                self.filelist.selection_set(new)
                self.selectcomp()            

    def removefunc(self):
        cur=self.funclist.info_selection()
        if cur != ():
            cur=cur[0]            
            #remove memory from IFEFFIT
            dn=replace(cur,' ','_')
            iffc.ifeffit('erase @group='+dn)
            wid=self.funcwidref[cur]
            for var in wid.p.entlist:
                if var!='':
                    ind=wid.p.entlist.index(var)
                    iffc.ifeffit('erase '+dn+str(ind))
            #remove all associated vars
            ind=self.funcwidlist.index(cur)
            self.funcwidlist.remove(cur)
            self.funclist.delete_entry(cur)
            self.funcdes.delete(cur)
            del self.funcwidref[cur]
            #reselect
            if len(self.funcwidlist)==1:
                self.funclist.selection_clear()
                self.funcdes.selectpage('init')
            else:
                if ind==1:ind=2
                new=self.funcwidlist[ind-1]
                self.funclist.selection_set(new)
                self.selectfunc()            

    def reloadallcomp(self):
        #store path list in temp variable
        tpath=[]
        for np in self.compwidlist:
            #select new sample
            if np!='init':
                dat=self.compwidref.get(np)
                tpath.append(dat.path)
        #kill all data
        self.clearcomplist()
        #reload files
        for fn in tpath:
            self.compload(fn)

    def compload(self,infile):
        #load component into Ifeffit
        fname=trimdir(infile)
        #place entries in tree
        self.filelist.add(fname,text='X',state=NORMAL)
        self.filelist.item_create(fname,1,text=fname)
        self.filelist.item_create(fname,2,text='0')
        self.filelist.selection_clear()
        self.filelist.selection_set(fname)
        #create page
        new=self.compdes.add(remundsc(fname))
        self.compdes.selectpage(remundsc(fname))
        new.p=DefCParams(new,self.filelist,fname)
        new.path=infile
        self.compwidref.update({fname:new})
        self.compwidlist.append(fname)
        #load into IFEFFIT
        dn=replace(fname,'.','_')
        #load file
        iffc.ifeffit("read_data(file="+infile+",group="+dn+",label='xr yr')")
        #interpolate components
        #0.1eV for XANES, 0.05A-1 for EXAFS
        if self.nointerp.get()==0:
            if self.XRDinterp.get()==1:
                #XRD
                iffc.ifeffit(dn+".x=range("+self.xmin.get()+","+self.xmax.get()+",0.005)")
                iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
                self.egrid=0.005
            else:            
                if iffc.get_scalar("floor("+dn+".x)")>100:
                    #XANES
                    iffc.ifeffit(dn+".x=range("+self.xmin.get()+"-10,"+self.xmax.get()+"+10,0.1)")
                    iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
                else:
                    #EXAFS
                    iffc.ifeffit(dn+".x=range("+self.xmin.get()+","+self.xmax.get()+",0.05)")
                    iffc.ifeffit(dn+".y=splint("+dn+".xr,"+dn+".yr,"+dn+".x)")
        else:
            iffc.ifeffit(dn+".x="+dn+".xr")
            iffc.ifeffit(dn+".y="+dn+".yr")
        #do x-weighting if necessary
        iffc.ifeffit("doxwt "+dn+" "+self.xwt.get())
        setstatus(self.status,"Component file "+infile+" loaded")            

    def selectcomp(self, *args):
        #get data
        cur=self.filelist.info_selection()
        if cur==():
            return
        cur=cur[0]
        self.compdes.selectpage(remundsc(cur))

    def selectfunc(self, *args):
        #get data
        cur=self.funclist.info_selection()
        if cur==():
            return
        cur=cur[0]
        self.funcdes.selectpage(cur)
 
    def choosecomp(self, *args):
        cur=args[0]
        self.compdes.selectpage(remundsc(cur))
        wid=self.compwidref[cur].p
        if wid.active==0:
            #turn on
            wid.active=1
            self.filelist.item_configure(cur,0,text='X')
            blacktext=Tix.DisplayStyle(Tix.TEXT,fg='black',bg='white',selectforeground='white',refwindow=self.efwin)
            for i in range(3):
                self.filelist.item_configure(cur,i,style=blacktext)
        else:
            #turn off
            wid.active=0
            self.filelist.item_configure(cur,0,text=' ')
            greytext=Tix.DisplayStyle(Tix.TEXT,fg='grey',bg='white',selectforeground='grey',refwindow=self.efwin)
            for i in range(3):
                self.filelist.item_configure(cur,i,style=greytext)

    def choosefunc(self, *args):
        cur=args[0]
        self.funcdes.selectpage(cur)
        wid=self.funcwidref[cur].p
        if wid.active==0:
            #turn on
            wid.active=1
            self.funclist.item_configure(cur,0,text='X')
            blacktext=Tix.DisplayStyle(Tix.TEXT,fg='black',bg='white',selectforeground='white',refwindow=self.efwin)
            for i in range(2):
                self.funclist.item_configure(cur,i,style=blacktext)
        else:
            #turn off
            wid.active=0
            self.funclist.item_configure(cur,0,text=' ')
            greytext=Tix.DisplayStyle(Tix.TEXT,fg='grey',bg='white',selectforeground='grey',refwindow=self.efwin)
            for i in range(2):
                self.funclist.item_configure(cur,i,style=greytext)

    def sp_plot(self,new,gx,gy,xlab,ylab,title,xmin,xmax,key):
        xdat=iffc.get_array(gx)
        ydat=iffc.get_array(gy)
        if new==1: spplotter.SPPlotter(self.root,cmd="new",lt=key,xd=xdat,yd=ydat,xt=xlab,yt=ylab,
                                       title=title,xmin=xmin,xmax=xmax)
        if new==0: spplotter.SPPlotter(self.root,cmd="stack",lt=key,xd=xdat,yd=ydat,xt=xlab,yt=ylab,
                                       title=title,xmin=xmin,xmax=xmax)

    def plotcomp(self):
        #Plot component fits -- choose plot type
        ptypes=self.plottypes.getcurselection()
        xm1=self.xmin.get()
        xm2=self.xmax.get()
        newg=1
        for typ in ptypes:
            if typ=='Data':
                dn=self.dataname
                self.sp_plot(newg,dn+".x",dn+".y_xw","x","y",dn,xm1,xm2,"Data")
                newg=0
            if typ=='Fit':
                self.sp_plot(newg,"fit.x","fit.y","x","y","Fit",xm1,xm2,"Fit")
                newg=0
            if typ=='SA Corrected':
                dn=self.dataname
                self.sp_plot(newg,dn+".x",dn+".say","x","y",dn,xm1,xm2,"SACorr")
                newg=0
            if typ=='E Shifted':
                dn=self.dataname
                self.sp_plot(newg,dn+".x",dn+".yes","x","y",dn,xm1,xm2,"Eshift")
                newg=0
            if typ=='Residuals':
                dn=self.dataname
                self.sp_plot(newg,dn+".x",dn+".diff","x","y",dn,xm1,xm2,"Resid")
                newg=0
            if typ=='Waterfall':
                #plot waterfall
                dn=self.dataname
                for name in self.compwidlist:
                    #plot that component
                    wid=self.compwidref[name]
                    cn=replace(name,'.','_')
                    if wid.p.active==1:
                        iffc.ifeffit("set(temp.cf="+cn+".y_xw*"+wid.p.frac.get()+")")
                        self.sp_plot(newg,dn+".x","temp.cf","x","y",dn,xm1,xm2,name)
                        newg=0
                #plot functions
                for name in self.funcwidlist:
                    wid=self.funcwidref[name]
                    cn=replace(name,' ','_')
                    if wid.p.active==1:
                        self.sp_plot(newg,dn+".x",cn+".y","x","y",dn,xm1,xm2,name)
                        newg=0
        setstatus(self.status,"Plots complete")

    def defallfuncs(self,setvar):
        #define functions in IFEFFIT
        dn=self.dataname
        iffc.ifeffit("set(const.x=ones(npts("+dn+".x)))")
        for name in self.funcwidlist:
            wid=self.funcwidref[name]
            ftype=name[:rfind(name,' ')]
            fn=replace(name,' ','_')
            #define variables
            for var in wid.p.entlist:
                if var!='':
                    ind=wid.p.entlist.index(var)
                    varcmd=wid.p.butvar[ind].get()
                    if wid.p.active==0:varcmd='set'
                    if setvar==1:varcmd='set'
                    iffc.ifeffit(varcmd+'('+fn+str(ind)+'='+var.get()+')')
            #define function
            if ftype==self.allfuncs[0]: #linear
                iffc.ifeffit('def('+fn+'.y='+fn+'0*'+dn+'.x+'+fn+'1*const.x)')
            elif ftype==self.allfuncs[1]: #quadratic
                iffc.ifeffit('def('+fn+'.y='+fn+'0*'+dn+'.x**2+'+fn+'1*'+dn+'.x+'+fn+'2*const.x)')
            elif ftype==self.allfuncs[2]: #gauss
                iffc.ifeffit('def('+fn+'.y='+fn+'0*gauss('+dn+'.x,'+fn+'1,'+fn+'2)+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[3]: #lorentz
                iffc.ifeffit('def('+fn+'.y='+fn+'0*loren('+dn+'.x,'+fn+'1,'+fn+'2)+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[4]: #voight
                iffc.ifeffit('def('+fn+'.y='+fn+'0*pvoight('+dn+'.x,'+fn+'1,'+fn+'2,'+fn+'4)+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[5]: #atan
                iffc.ifeffit('def('+fn+'.y='+fn+'0*atan(('+dn+'.x-'+fn+'1)/('+fn+'2))+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[6]: #erfc
                iffc.ifeffit('def('+fn+'.y='+fn+'0*erfc(('+dn+'.x-'+fn+'1)/('+fn+'2))+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[7]: #erf
                iffc.ifeffit('def('+fn+'.y='+fn+'0*erf(('+dn+'.x-'+fn+'1)/('+fn+'2))+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[8]: #exp
                iffc.ifeffit('def('+fn+'.y='+fn+'0*exp(('+dn+'.x-'+fn+'1)/('+fn+'2))+'+fn+'3*const.x)')
            elif ftype==self.allfuncs[9]: #log
                iffc.ifeffit('def('+fn+'.y='+fn+'0*ln(('+dn+'.x-'+fn+'1)/('+fn+'2))+'+fn+'3*const.x)')

    def makefitdat(self):
        #Make fit construction from components
        if self.dataname=='':
            print 'ERROR: No Data File loaded'
            return
        dn=self.dataname
        #consider any eshifting of components...
        #construct using %ages
        iffc.ifeffit("set(fit.y=zeros(npts("+dn+".y)))")
        iffc.ifeffit("set(fit.x="+dn+".x)")
        for name in self.compwidlist:
            #add component to total
            wid=self.compwidref[name]
            if wid.p.active==1:
                cn=replace(name,'.','_')
                iffc.ifeffit("set(fit.y=fit.y+"+cn+".y_xw*"+wid.p.frac.get()+")")
        #redefine function defs
        self.defallfuncs(0)     
        #add function terms!
        for name in self.funcwidlist:
            #add active funcs to total too
            wid=self.funcwidref[name]
            if wid.p.active==1:
                cn=replace(name,' ','_')
                iffc.ifeffit("set(fit.y=fit.y+"+cn+".y)")
        #calcualte residuals, e-shifting, and self absorption if needed
        if self.edfloat.get()==0:
            iffc.ifeffit("set(des=0)")
            iffc.ifeffit("set("+dn+".yes="+dn+".y_xw)")
        if self.edfloat.get()==1:
            #shift E and define new data...
            iffc.ifeffit("set(des="+str(self.dateshift.get())+")")
            iffc.ifeffit("set(new.x=range("+self.xmin.get()+"-des,"+self.xmax.get()+"-des,"+str(self.egrid)+"))")
            iffc.ifeffit("set("+dn+".yes=splint("+dn+".x,"+dn+".y_xw,new.x))")            
        if self.abscor==0:
            iffc.ifeffit("set("+dn+".diff="+dn+".yes-fit.y)")
        if self.abscor==1:
            iffc.ifeffit("set(muka="+self.mukent.get()+",rat="+self.ffent.get()+")")            
            iffc.ifeffit("set("+dn+".say=(muka*"+dn+".yes/rat)/(1-("+dn+".yes/rat)))")
            iffc.ifeffit("set("+dn+".diff="+dn+".say-fit.y)")
        if self.mstat==0:
            setstatus(self.status,"Fit constructed from fractions provided")
        self.mstat=0

    def fitdatcomp(self):
        #Main fitting routine    #consider eshift for components!
        dn=self.dataname
        #set guesses and def's for components 
        minterm="fit.y="
        sumterm="sumres=(0"
        for name in self.compwidlist:
            wid=self.compwidref[name]
            cn=replace(name,'.','_')
            if wid.p.active==1:
                iffc.ifeffit("guess(frac"+cn+"="+wid.p.frac.get()+")")
                if self.fpos.get()==0:
                    minterm=minterm+"+frac"+cn+"*"+cn+".y_xw"
                    sumterm=sumterm+"+frac"+cn
                if self.fpos.get()==1:
                    iffc.ifeffit("def(pos"+cn+"=abs(frac"+cn+"))")
                    minterm=minterm+"+pos"+cn+"*"+cn+".y_xw"
                    sumterm=sumterm+"+pos"+cn
            if wid.p.active==0:
                iffc.ifeffit("def(frac"+cn+"=0)")
                iffc.ifeffit("def(pos"+cn+"=0)")
        #redefine function defs
        self.defallfuncs(0)     
        #add function terms!
        for name in self.funcwidlist:
            #add active funcs to total too
            wid=self.funcwidref[name]
            fn=replace(name,' ','_')
            if wid.p.active==1:
                minterm=minterm+"+"+fn+".y"
        #shift energy scale of data if needed
        if self.edfloat.get()==0:
            iffc.ifeffit("set(des=0)")
            iffc.ifeffit("set("+dn+".yes="+dn+".y_xw)")
        if self.edfloat.get()==1:
            iffc.ifeffit("guess(des="+str(self.dateshift.get())+")")
            iffc.ifeffit("def(new.x=range("+self.xmin.get()+"-des,"+self.xmax.get()+"-des,"+str(self.egrid)+"))")
            iffc.ifeffit("def("+dn+".yes=splint("+dn+".x,"+dn+".y_xw,new.x))")
        #construct mimization
        #consider sum to one constraint -- not real, but close!
        sumterm=sumterm+")"
        iffc.ifeffit("def("+sumterm+")")
        sumtermres="sumtermres=(1-sumres)*"+self.stowt.get()
        iffc.ifeffit("def("+sumtermres+")")
        iffc.ifeffit("def("+minterm+")")
        if self.fitabsc==0:
            iffc.ifeffit("def(fit.resid=fit.y-"+dn+".yes)")
        if self.fitabsc==1:
            iffc.ifeffit("def(muka="+self.mukent.get()+",rat="+self.ffent.get()+")") 
            iffc.ifeffit("def("+dn+".say=(muka*"+dn+".yes/rat)/(1-("+dn+".yes/rat)))")
            iffc.ifeffit("def(fit.resid=fit.y-"+dn+".say)")            
        #call minimize
        if self.sumone.get()==0:
            iffc.ifeffit("minimize(fit.resid,x="+dn+".x,xmin="+self.xmin.get()+",xmax="+self.xmax.get()+")")
        if self.sumone.get()==1:
            iffc.ifeffit("minimize(fit.resid,x="+dn+".x,xmin="+self.xmin.get()+",xmax="+self.xmax.get()+",restraint=sumtermres)")            
        #report fitting quality parameters in status bar
        setstatus_d(self.Csum,iffc.get_scalar("sumres"),5)
        setstatus_d(self.ChiSq,iffc.get_scalar("chi_square"),5)
        setstatus_d(self.ChiSqR,iffc.get_scalar("chi_reduced"),8)
        #report values in entryfields
        for name in self.compwidlist:
            wid=self.compwidref[name]
            cn=replace(name,'.','_')
            if wid.p.active==1:
                if self.fpos.get()==0:
                    entry_replace_d(wid.p.frac,iffc.get_scalar("frac"+cn),5)
                    #setstatus_d(name.deltapct,pm+str(iffc.get_scalar("delta_cf"+str(cnum))),5)
                if self.fpos.get()==1:
                    entry_replace_d(wid.p.frac,iffc.get_scalar("pos"+cn),5)
                    #setstatus_d(name.deltapct,pm+str(iffc.get_scalar("delta_cp"+str(cnum))),5)
                wid.p.big.item_configure(wid.p.fname,2,text=str(wid.p.frac.get()))
        for name in self.funcwidlist:
            wid=self.funcwidref[name]
            fn=replace(name,' ','_')
            if wid.p.active==1:
                for var in wid.p.entlist:
                    if var!='':
                        ind=wid.p.entlist.index(var)
                        entry_replace_d(var,iffc.get_scalar(fn+str(ind)),8)
        if self.edfloat.get()==1:
            self.dateshift.set(iffc.get_scalar("des"))  
        setstatus(self.status,"Fit completed!")
        self.mstat=1
        if self.fitabsc==1: self.abscor=1
        if self.fitabsc==0: self.abscor=0
        self.makefitdat()
        #call result reporter
        self.reportresults(self.abscor)
        self.fitabsc=0

    def reportresults(self,saval):
        #clear page
        self.restext.clear()
        #header
        self.restext.insert(END,"File: "+self.fileentry.get()+'\n\n')
        #print chisquare and R-value
        line="Chi-Sq: "+str(iffc.get_scalar('chi_square'))+"\t\tRed Chi-Sq: "+str(iffc.get_scalar('chi_reduced'))
        self.restext.insert(END,line+'\n')
        #print energyt shift if needed
        if self.edfloat.get()==1:
            line='\nData shifted in energy by: '+str(self.dateshift.get())+' eV'
            self.restext.insert(END,line+'\n')
        #print SA values if needed
        if saval==1:
            line="\nMuKa:  \t\t"+str(self.clipresults(iffc.get_scalar("muka")))+" +/- "+str(self.clipresults(iffc.get_scalar("delta_muka")))+'\n'
            self.restext.insert(END,line)
            line="Ratio: \t\t"+str(self.clipresults(iffc.get_scalar("rat")))+" +/- "+str(self.clipresults(iffc.get_scalar("delta_rat")))+'\n'
            self.restext.insert(END,line)            
        #print list of components
        self.restext.insert(END,'\nCOMPONENT COMPOSITIONS\n\n')
        for name in self.compwidlist:
            wid=self.compwidref[name]
            cn=replace(name,'.','_')
            if wid.p.active==1:
                line=name+'\t\t'+str(self.clipresults(abs(iffc.get_scalar("frac"+cn))))+' +/- '+str(self.clipresults(iffc.get_scalar("delta_frac"+cn)))+'\n'
                self.restext.insert(END,line)
        self.restext.insert(END,"Component Sum\t\t"+str(iffc.get_scalar("sumres"))+'\n')
        #print list of functions        
        self.restext.insert(END,'\nFUNCTION VALUES\n')
        for name in self.funcwidlist:
            wid=self.funcwidref[name]
            fn=replace(name,' ','_')
            if wid.p.active==1:
                self.restext.insert(END,'\n'+name+'\n')
                for var in wid.p.entlist:
                    if var!='':
                        ind=wid.p.entlist.index(var)
                        varcmd=wid.p.butvar[ind].get()
                        if varcmd=='guess':
                            line='\t'+wid.p.entlab[ind]+'\t\t'+str(self.clipresults(iffc.get_scalar(fn+str(ind))))+' +/- '+str(self.clipresults(iffc.get_scalar("delta_"+fn+str(ind))))+'\n'
                        if varcmd=='set':
                            line='\t'+wid.p.entlab[ind]+'\t\t'+str(self.clipresults(iffc.get_scalar(fn+str(ind))))+'\n'
                        self.restext.insert(END,line)
        #end
                        
    def clipresults(self,v):
        dig=8
        val=str(v)
        decind=rfind(val,'.')
        eind=rfind(val,"e")
        if eind==-1:
            if decind>dig:
                val=val[:decind+2]
            else:
                val=val[:dig]
        else:
            val=val[:4]+val[eind:len(val)]        
        return val
    
    def repeatselfabs(self):
        for r in range(1,11):
            self.fittoselfabs()
            setstatus(self.status,"Self absorpion fit "+str(r)+" completed!")
            self.selfabsfit()
            setstatus(self.status,"Fit "+str(r)+" to self abs corrections completed!")
        setstatus(self.status,"Self Absorption cycle fits completed.")
    
    def fittoselfabs(self):
        self.fitabsc=1
        self.fitdatcomp()        

    def selfabsfit(self):
        dn=self.dataname
        #set all components to set values
        iffc.ifeffit("set(fit.y=zeros(npts("+dn+".y)))")
        iffc.ifeffit("set(fit.x="+dn+".x)")
        for name in self.compwidlist:
            wid=self.compwidref[name]
            cn=replace(name,'.','_')
            #add components to total
            if wid.p.active==1:
                iffc.ifeffit("def(frac"+cn+"="+wid.p.frac.get()+")")
                iffc.ifeffit("set(fit.y=fit.y+frac"+cn+"*"+cn+".y_xw)")
            if wid.p.active==0:
                iffc.ifeffit("def(frac"+cn+"=0)")
                iffc.ifeffit("def(pos"+cn+"=0)")
        #redefine function defs -- using set terms
        self.defallfuncs(1)     
        #add function terms to total!
        for name in self.funcwidlist:
            wid=self.funcwidref[name]
            fn=replace(name,' ','_')
            if wid.p.active==1:
                iffc.ifeffit("set(fit.y=fit.y+"+fn+".y)")
        #shift energy scale of data if needed           
        if self.edfloat.get()==0:
            iffc.ifeffit("set(des=0)")
            iffc.ifeffit("set("+dn+".yes="+dn+".y_xw)")
        if self.edfloat.get()==1:
            #shift E and define new data...
            iffc.ifeffit("guess(des="+str(self.dateshift.get())+")")
            iffc.ifeffit("def(new.x=range("+self.xmin.get()+"-des,"+self.xmax.get()+"-des,"+str(self.egrid)+"))")
            iffc.ifeffit("def("+dn+".yes=splint("+dn+".x,"+dn+".y_xw,new.x))")
        #define new data.say=SAC factor
        iffc.ifeffit("guess(muka="+self.mukent.get()+",rat="+self.ffent.get()+")") 
        iffc.ifeffit("def("+dn+".say=(muka*"+dn+".yes/rat)/(1-("+dn+".yes/rat)))")
        iffc.ifeffit("def(fit.resid=fit.y-"+dn+".say)")
        #do fit on data
        iffc.ifeffit("minimize(fit.resid,x="+dn+".x,xmin="+self.xmin.get()+",xmax="+self.xmax.get()+")")  
        #report fitting quality parameters
        setstatus_d(self.Csum,iffc.get_scalar("sumres"),5)
        setstatus_d(self.ChiSq,iffc.get_scalar("chi_square"),5)
        setstatus_d(self.ChiSqR,iffc.get_scalar("chi_reduced"),5)
        #report values
        entry_replace_d(self.mukent,iffc.get_scalar("muka"),3)
        entry_replace_d(self.ffent,iffc.get_scalar("rat"),3)
        setstatus_d(self.deltamuk,pm+str(iffc.get_scalar("delta_muka")),4)
        setstatus_d(self.deltaff,pm+str(iffc.get_scalar("delta_rat")),4)
        if self.edfloat.get()==1:
            self.dateshift.set(iffc.get_scalar("des"))         
        setstatus(self.status,"Self absorpion fit completed!")
        self.mstat=1
        self.abscor=1
        self.makefitdat()
        #call result reporter
        self.reportresults(self.abscor)

    def savefitdata(self):
        global lastsavedir
        dn=self.dataname
        nfn=ask_save_file('',lastsavedir)
        self.efwin.focus_set()
        if nfn!="":
            sdir=rfind(nfn,os.sep)
            lastsavedir=nfn[:sdir]
            iffc.ifeffit("write_data(file="+nfn+".fit,"+dn+".x,"+dn+".y_xw,fit.y)")
            setstatus(self.status,"Fit data saved to "+nfn)        

    def saveresdata(self):
        global lastsavedir
        dn=self.dataname
        nfn=ask_save_file('',lastsavedir)
        self.efwin.focus_set()
        if nfn!="":
            sdir=rfind(nfn,os.sep)
            lastsavedir=nfn[:sdir]
            iffc.ifeffit("write_data(file="+nfn+".res,"+dn+".x,"+dn+".diff)")
            setstatus(self.status,"Data residuals saved to "+nfn)        

    def saveallvars(self):
        global lastsavedir
        #place all paths and varibles into a parameter file
        #get file name
        nfn=ask_save_file('',lastsavedir)
        self.efwin.focus_set()
        if nfn=="":
            setstatus(self.status,"Save parameters aborted")        
        else:
            sdir=rfind(nfn,os.sep)
            lastsavedir=nfn[:sdir]
            #open file
            #check for extension ending
            ext=rfind(nfn,".")
            if ext==-1:
                nfn=nfn+".prm"
            fid=open(nfn,"w")
            #save data-file parameters
            fid.write("EDGEPARAMS\n")
            #enter filename,xmin,xmax,fitting constraints
            fid.write(self.fileentry.get()+"\n")
            fid.write(self.xmin.get()+"\n")
            fid.write(self.xmax.get()+"\n")
            fid.write(self.xwt.get()+"\n")
            fid.write(str(self.fpos.get())+"\n")
            fid.write(str(self.sumone.get())+"\n")
            fid.write(self.stowt.get()+"\n")
            #fid.write(str(self.efloat.get())+"\n")
            fid.write(str(self.edfloat.get())+"\n")
            #save the number of components currently loaded
            fid.write(str(len(self.compwidlist)-1)+"\n")
            #save all parts of all components
            for name in self.compwidlist:
                if name!='init':
                    wid=self.compwidref[name]
                    fid.write(wid.path+"\n")
                    fid.write(str(wid.p.active)+"\n")
                    fid.write(str(wid.p.frac.get())+"\n")
            #save number of functions
            fid.write(str(len(self.funcwidlist)-1)+"\n")
            #save all parts of all functions                              
            for name in self.funcwidlist:
                if name!='init':
                    wid=self.funcwidref[name]
                    fid.write(str(name[:rfind(name,' ')])+"\n")  #function type
                    fid.write(str(wid.p.active)+"\n")
                    for var in wid.p.entlist:
                        if var!='':
                            ind=wid.p.entlist.index(var)
                            fid.write(str(wid.p.entlist[ind].get())+"\n")
                        else:
                            fid.write(''+"\n")
            #SA factors
            fid.write(self.mukent.get()+"\n")
            fid.write(self.ffent.get()+"\n")
            #E shifting
            fid.write(str(self.dateshift.get())+"\n")
            fid.write("END")
            fid.close()            
            setstatus(self.status,"Fit parameters saved to "+nfn)        

    def loadallvars(self):
        global lastreaddir
        #load paths and variables from files
        #get file name
        fn=ask_for_file([("parameter files","*.prm"),("all files","*")],lastreaddir,check=0)
        self.efwin.focus_set()
        if fn=="":
            setstatus(self.status,"Load parameters aborted")
        else:
            sdir=rfind(fn,os.sep)
            lastreaddir=fn[:sdir]
            #open file
            fid=open(fn,"r")
            param=fid.read()
            fid.close()
            #parse file...
            lp=split(param,'\n')
            ind=0
            new=lp[ind]
            if new=='FPARAMS' or new=='BSPARAMS':
                #wrong parameter file
                self.box.deiconify()
            if new=='EDGEPARAMS':
                #read data-file parameters
                ind=ind+1
                #read filename,xmin,xmax,fit contraints
                self.fileentry.setentry(lp[ind]);ind=ind+1                
                self.xmin.setentry(lp[ind]);ind=ind+1 
                self.xmax.setentry(lp[ind]);ind=ind+1 
                self.xwt.setentry(lp[ind]);ind=ind+1 
                self.fpos.set(int(lp[ind]));ind=ind+1
                self.sumone.set(int(lp[ind]));ind=ind+1
                self.stowt.setentry(lp[ind]);ind=ind+1 
                #self.efloat.set(int(lp[ind]));ind=ind+1
                self.edfloat.set(int(lp[ind]));ind=ind+1
                #read in number of components
                numcomp=int(lp[ind]);ind=ind+1
                #clear data and functions
                self.clearcomplist()
                self.clearfunclist()
                #read all components
                for x in range(numcomp):
                    path=lp[ind];ind=ind+1
                    cn=trimdir(path)
                    self.compload(path)
                    wid=self.compwidref[cn]
                    wid.p.active=int(lp[ind]);ind=ind+1
                    wid.p.frac.setentry(lp[ind]);ind=ind+1
                #read in number of functions
                numfunc=int(lp[ind]);ind=ind+1                    
                #read all functions
                for x in range(numfunc):
                    ftype=lp[ind];ind=ind+1      #function type
                    self.funcbox.selectitem(ftype)
                    self.addfunc()
                    find=self.allfuncs.index(ftype)
                    fnum=self.funccount[find]
                    fname=ftype+' '+str(fnum)
                    wid=self.funcwidref[fname]
                    wid.p.active=int(lp[ind]);ind=ind+1
                    for var in wid.p.entlist:
                        if var!='':
                            ix=wid.p.entlist.index(var)
                            wid.p.entlist[ix].setentry(lp[ind]);ind=ind+1
                        else:
                            ind=ind+1
                #read SA features
                self.mukent.setentry(lp[ind]);ind=ind+1                     
                self.ffent.setentry(lp[ind]);ind=ind+1 
                #read E shifting
                self.dateshift.set(atof(lp[ind]));ind=ind+1
            setstatus(self.status,"Parameter file read from "+fn)



#start event handler
#EdgeFit(root)
#root.mainloop()

