358 lines
9.7 KiB
Python
358 lines
9.7 KiB
Python
import os, math
|
|
from Tkinter import *
|
|
from Cantera import *
|
|
|
|
from SpeciesInfo import SpeciesInfo
|
|
from Cantera import rxnpath
|
|
import webbrowser
|
|
|
|
_CUTOFF = 1.e-15
|
|
_ATOL = 1.e-15
|
|
_RTOL = 1.e-7
|
|
|
|
class KineticsFrame(Frame):
|
|
def __init__(self,master):
|
|
Frame.__init__(self,master)
|
|
self.config(relief=FLAT, bd=4)
|
|
self.top = self.master.top
|
|
self.controls=Frame(self)
|
|
self.hide = IntVar()
|
|
self.hide.set(0)
|
|
self.comp = IntVar()
|
|
self.comp.set(2)
|
|
self.controls.grid(column=1,row=0,sticky=W+E+N)
|
|
self.makeControls()
|
|
mf = self.master
|
|
|
|
def makeControls(self):
|
|
Radiobutton(self.controls,text='Creation Rates',
|
|
variable=self.comp,value=0,
|
|
command=self.show).grid(column=0,row=0,sticky=W)
|
|
Radiobutton(self.controls,text='Destruction Rates',
|
|
variable=self.comp,value=1,
|
|
command=self.show).grid(column=0,row=1,sticky=W)
|
|
Radiobutton(self.controls,text='Net Production Rates',
|
|
variable=self.comp,value=2,
|
|
command=self.show).grid(column=0,row=2,sticky=W)
|
|
|
|
def show(self):
|
|
mf = self.master
|
|
mf.active = self
|
|
c = self.comp.get()
|
|
mix = self.top.mix
|
|
g = mix.g
|
|
if c == 0:
|
|
mf.var.set("Creation Rates")
|
|
#mf.data = spdict(mix.g, mix.moles())
|
|
mf.comp = g.creationRates()
|
|
|
|
elif c == 1:
|
|
mf.var.set("Destruction Rates")
|
|
#mf.data = spdict(mix.g,mix.mass())
|
|
mf.comp = g.destructionRates()
|
|
|
|
elif c == 2:
|
|
mf.var.set("Net Production Rates")
|
|
mf.comp = g.netProductionRates()
|
|
#mf.data = spdict(mix,mix,mf.comp)
|
|
|
|
for s in mf.variable.keys():
|
|
try:
|
|
k = g.speciesIndex(s)
|
|
if mf.comp[k] > _CUTOFF or -mf.comp[k] > _CUTOFF:
|
|
mf.variable[s].set(mf.comp[k])
|
|
else:
|
|
mf.variable[s].set(0.0)
|
|
except:
|
|
pass
|
|
|
|
class SpeciesKineticsFrame(Frame):
|
|
def __init__(self,master,top):
|
|
Frame.__init__(self,master)
|
|
self.config(relief=GROOVE, bd=4)
|
|
self.top = top
|
|
self.top.kinetics = self
|
|
self.g = self.top.mix.g
|
|
self.entries=Frame(self)
|
|
self.var = StringVar()
|
|
self.var.set("Net Production Rates")
|
|
self.names = self.top.mix.speciesNames()
|
|
self.nsp = len(self.names)
|
|
self.comp = [0.0]*self.nsp
|
|
self.makeControls()
|
|
self.makeEntries()
|
|
self.entries.bind('<Double-l>',self.minimize)
|
|
self.ctype = 0
|
|
|
|
def makeControls(self):
|
|
self.c = KineticsFrame(self)
|
|
#self.rr = ReactionKineticsFrame(self, self.top)
|
|
self.c.grid(column=1,row=0,sticky=E+W+N+S)
|
|
#self.rr.grid(column=0,row=1,sticky=E+W+N+S)
|
|
|
|
def show(self):
|
|
self.c.show()
|
|
|
|
def redo(self):
|
|
self.update()
|
|
self.entries.destroy()
|
|
self.entries=Frame(self)
|
|
self.makeEntries()
|
|
|
|
def minimize(self,Event=None):
|
|
self.c.hide.set(1)
|
|
self.redo()
|
|
self.c.grid_forget()
|
|
self.entries.bind("<Double-1>",self.maximize)
|
|
|
|
def maximize(self,Event=None):
|
|
self.c.hide.set(0)
|
|
self.redo()
|
|
self.c.grid(column=1,row=0,sticky=E+W+N+S)
|
|
self.entries.bind("<Double-1>",self.minimize)
|
|
|
|
def up(self, x):
|
|
self.update()
|
|
|
|
def makeEntries(self):
|
|
self.entries.grid(row=0,column=0,sticky=W+N+S+E)
|
|
self.entries.config(relief=FLAT,bd=4)
|
|
DATAKEYS = self.top.species
|
|
self.variable = {}
|
|
|
|
n=0
|
|
ncol = 3
|
|
col = 0
|
|
row = 60
|
|
|
|
for sp in DATAKEYS:
|
|
s = sp
|
|
k = s.index
|
|
if row > 15:
|
|
row = 0
|
|
col = col + 2
|
|
l = Label(self.entries,text='Species')
|
|
l.grid(column=col,row=row,sticky=E+W)
|
|
e1 = Entry(self.entries)
|
|
e1.grid(column=col+1,row=row,sticky=E+W)
|
|
e1['textvariable'] = self.var
|
|
e1.config(state=DISABLED)
|
|
e1.config(bg='lightyellow',relief=RIDGE)
|
|
row = row + 1
|
|
|
|
spname = s.name
|
|
val = self.comp[k]
|
|
if not self.c.hide.get() or val: showit = 1
|
|
else: showit = 0
|
|
|
|
l=SpeciesInfo(self.entries,species=s,
|
|
text=spname,relief=FLAT,justify=RIGHT,
|
|
fg='darkblue')
|
|
entry1 = Entry(self.entries)
|
|
self.variable[spname] = DoubleVar()
|
|
self.variable[spname].set(self.comp[k])
|
|
entry1['textvariable']=self.variable[spname]
|
|
entry1.bind('<Any-Leave>',self.up)
|
|
if showit:
|
|
l.grid(column= col ,row=row,sticky=E)
|
|
entry1.grid(column=col+1,row=row)
|
|
n=n+1
|
|
row = row + 1
|
|
entry1.config(state=DISABLED,bg='lightgray')
|
|
|
|
|
|
class ReactionKineticsFrame(Frame):
|
|
def __init__(self,vis,top):
|
|
self.master = Toplevel()
|
|
self.master.protocol("WM_DELETE_WINDOW",self.hide)
|
|
self.vis = vis
|
|
Frame.__init__(self,self.master)
|
|
self.config(relief=GROOVE, bd=4)
|
|
self.top = top
|
|
self.g = self.top.mix.g
|
|
nr = self.g.nReactions()
|
|
self.eqs=Text(self,width=40,height=nr)
|
|
self.data = []
|
|
for i in range(4):
|
|
self.data.append(Text(self,width=15,height=nr))
|
|
|
|
for n in range(nr):
|
|
s = self.g.reactionEqn(n)
|
|
self.eqs.insert(END,s+'\n')
|
|
self.eqs.grid(column=0,row=1,sticky=W+E+N)
|
|
for i in range(4):
|
|
self.data[i].grid(column=i+1,row=1,sticky=W+E+N)
|
|
Label(self, text='Reaction').grid(column=0,row=0,sticky=W+E+N)
|
|
Label(self, text='Fwd ROP').grid(column=1,row=0,sticky=W+E+N)
|
|
Label(self, text='Rev ROP').grid(column=2,row=0,sticky=W+E+N)
|
|
Label(self, text='Net ROP').grid(column=3,row=0,sticky=W+E+N)
|
|
Label(self, text='Kp').grid(column=4,row=0,sticky=W+E+N)
|
|
# Button(self, text='View Reaction Paths', command=self.viewRxnPaths).grid(column=0,row=2,sticky=W+E+N)
|
|
self.grid(column=0,row=0)
|
|
self.hide()
|
|
|
|
def hide(self):
|
|
# self.vis.set(0)
|
|
self.master.withdraw()
|
|
|
|
def show(self):
|
|
v = self.vis.get()
|
|
#if v == 0:
|
|
# self.hide()
|
|
# return
|
|
|
|
self.master.deiconify()
|
|
nr = self.g.nReactions()
|
|
frop = self.g.fwdRatesOfProgress()
|
|
rrop = self.g.revRatesOfProgress()
|
|
kp = self.g.equilibriumConstants()
|
|
self.data[0].delete(1.0,END)
|
|
self.data[1].delete(1.0,END)
|
|
self.data[2].delete(1.0,END)
|
|
self.data[3].delete(1.0,END)
|
|
for n in range(nr):
|
|
s = '%12.5e \n' % (frop[n],)
|
|
self.data[0].insert(END,s)
|
|
s = '%12.5e \n' % (rrop[n],)
|
|
self.data[1].insert(END,s)
|
|
s = '%12.5e \n' % (frop[n] - rrop[n],)
|
|
self.data[2].insert(END,s)
|
|
s = '%12.5e \n' % (kp[n],)
|
|
self.data[3].insert(END,s)
|
|
|
|
|
|
class ReactionPathFrame(Frame):
|
|
|
|
def __init__(self,top):
|
|
self.master = Toplevel()
|
|
self.master.protocol("WM_DELETE_WINDOW",self.hide)
|
|
#self.vis = vis
|
|
Frame.__init__(self,self.master)
|
|
self.config(relief=GROOVE, bd=4)
|
|
self.grid(column=0,row=0)
|
|
self.top = top
|
|
self.g = self.top.mix.g
|
|
self.el = IntVar()
|
|
self.el.set(0)
|
|
self.thresh = DoubleVar()
|
|
|
|
scframe = Frame(self)
|
|
self.sc = Scale(scframe,variable = self.thresh,
|
|
orient='horizontal',digits=3,length=300,resolution=0.01)
|
|
self.sc.config(cnf={'from':-6,'to':0})
|
|
Label(scframe,text='log10 Threshold').grid(column=0,row=0)
|
|
self.sc.grid(row=0,column=1,columnspan=10)
|
|
self.sc.bind('<ButtonRelease-1>',self.show)
|
|
scframe.grid(row=3,column=0,columnspan=10)
|
|
|
|
enames = self.g.elementNames()
|
|
self.nel = len(enames)
|
|
|
|
i = 1
|
|
eframe = Frame(self)
|
|
Label(eframe,text='Element').grid(column=0,row=0,sticky=W)
|
|
for e in enames:
|
|
Radiobutton(eframe,text=e,
|
|
variable=self.el,value=i-1,
|
|
command=self.show).grid(column=i,row=0,sticky=W)
|
|
i += 1
|
|
eframe.grid(row=0,column=0)
|
|
|
|
self.detailed = IntVar()
|
|
Checkbutton(self, text = 'Show details', variable=self.detailed,
|
|
command=self.show).grid(column=1,row=0)
|
|
self.net = IntVar()
|
|
Checkbutton(self, text = 'Show net flux',
|
|
variable=self.net,
|
|
command=self.show).grid(column=2,row=0)
|
|
self.local = StringVar()
|
|
Label(self,text='Species').grid(column=1,row=1,sticky=E)
|
|
sp = Entry(self, textvariable=self.local,
|
|
width=15)
|
|
sp.grid(column=2,row=1)
|
|
sp.bind('<Any-Leave>',self.show)
|
|
|
|
self.b = rxnpath.PathBuilder(self.g)
|
|
|
|
self.fmt = StringVar()
|
|
self.fmt.set('svg')
|
|
i = 1
|
|
fmtframe = Frame(self)
|
|
fmtframe.config(relief=GROOVE, bd=4)
|
|
self.browser = IntVar()
|
|
Checkbutton(fmtframe, text = 'Display in Web Browser',
|
|
variable=self.browser,
|
|
command=self.show).grid(column=0,columnspan=6,row=0)
|
|
Label(fmtframe,text='Format').grid(column=0,row=1,sticky=W)
|
|
for e in ['svg', 'png', 'gif', 'jpg']:
|
|
Radiobutton(fmtframe,text=e,
|
|
variable=self.fmt,value=e,
|
|
command=self.show).grid(column=i,row=1,sticky=W)
|
|
i += 1
|
|
fmtframe.grid(row=5,column=0,columnspan=10,sticky=E+W)
|
|
|
|
self.cv = Canvas(self,relief=SUNKEN,bd=1)
|
|
self.cv.grid(column=0,row=4,sticky=W+E+N,columnspan=10)
|
|
|
|
pframe = Frame(self)
|
|
pframe.config(relief=GROOVE, bd=4)
|
|
self.dot = StringVar()
|
|
self.dot.set('dot -Tgif rxnpath.dot > rxnpath.gif')
|
|
Label(pframe,text='DOT command:').grid(column=0,row=0,sticky=W)
|
|
Entry(pframe,width=60,textvariable=self.dot).grid(column=0,
|
|
row=1,sticky=W)
|
|
pframe.grid(row=6,column=0,columnspan=10,sticky=E+W)
|
|
|
|
self.thresh.set(-2.0)
|
|
self.hide()
|
|
|
|
def hide(self):
|
|
#self.vis.set(0)
|
|
self.master.withdraw()
|
|
|
|
def show(self,e=None):
|
|
|
|
self.master.deiconify()
|
|
el = self.g.elementName(self.el.get())
|
|
det = 'false'
|
|
if self.detailed.get() == 1: det = 'true'
|
|
flow = 'one_way'
|
|
if self.net.get() == 1: flow = 'net'
|
|
self.d = rxnpath.PathDiagram(arrow_width=-2,
|
|
flow_type=flow,
|
|
detailed = det,
|
|
threshold=math.pow(10.0,
|
|
self.thresh.get()))
|
|
node = self.local.get()
|
|
try:
|
|
k = self.g.speciesIndex(node)
|
|
self.d.displayOnly(k)
|
|
except:
|
|
self.d.displayOnly()
|
|
|
|
self.b.build(element = el, diagram = self.d,
|
|
dotfile = 'rxnpath.dot', format = 'dot')
|
|
self.b.build(element = el, diagram = self.d,
|
|
dotfile = 'rxnpath.txt', format = 'plain')
|
|
|
|
if self.browser.get() == 1:
|
|
fmt = self.fmt.get()
|
|
os.system('dot -T'+fmt+' rxnpath.dot > rxnpath.'+fmt)
|
|
webbrowser.open('rxnpath.'+fmt)
|
|
try:
|
|
self.cv.delete(self.image)
|
|
except:
|
|
pass
|
|
else:
|
|
os.system(self.dot.get())
|
|
self.rp = PhotoImage(file='rxnpath.gif')
|
|
try:
|
|
self.cv.delete(self.image)
|
|
except:
|
|
pass
|
|
self.cv.configure(width=self.rp.width(),
|
|
height=self.rp.height())
|
|
|
|
self.image = self.cv.create_image(0,0,anchor=NW,
|
|
image=self.rp)
|
|
|