import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg#, NavigationToolbar2TkAgg try: from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg as NavigationToolbar2TkAgg except: from matplotlib.backends.backend_tkagg import NavigationToolbar2T as NavigationToolbar2TkAgg #at some point NavigationToolbar2TkAgg deprecated import tkinter as tk from tkinter import Tk, Label, Button, Scale,Entry,Text,Toplevel,OptionMenu,StringVar, Frame import numpy as np from pisapy import ParetoUtil as PU import matplotlib.markers as mm import shutil import os class BeamOptGUI: def __init__(self,master): self.master=master self.InitialGui() def InitialGui(self): master=self.master ###Load some dictionaries/things to make them available globally self.FileDic=PU.MakeFileDic() self.ObjFile=self.FileDic['objectives_file'] self.ConFile=self.FileDic['constraints_file'] self.DecFile=self.FileDic['decision_variables_file'] self.OutFile=self.FileDic['outputfile'] self.ObjDic=PU.MakeObjDic(self.ObjFile) #these dictionaries are generic to all individuals self.ConDic=PU.MakeConDic(self.ConFile) self.DecDic=PU.MakeDecDic(self.DecFile) ####### self.GenFront=PU.GetAFront(1) #Front to get keywords but not values self.ObjName,self.ObjArray=PU.GetParetoFront() self.CurBeamlineX,self.CurBeamlineY=self.ObjName[0],self.ObjName[1] self.CurBeamlineXVals,self.CurBeamlineYVals=self.ObjArray[0],self.ObjArray[1] self.DecDicPlus={**self.DecDic,**{self.ObjName[0]:[]},**{self.ObjName[1]:[]}} #dictionary of decisions plus objective names (For choice menu) #self.master=master self.individual=[] self.PlotDic={} ###Make initla widgets##### self.Frame1=Frame(master) self.Frame1.grid(column=0,row=1,rowspan=2) self.close_button=Button(master, text="Close", command=master.quit) self.close_button.grid(row=0,column=0) self.xselect=StringVar() self.xselect.set(self.ObjName[0]) self.xmenu=OptionMenu(self.Frame1,self.xselect,*self.DecDicPlus) self.xmenu.pack() self.yselect=StringVar() self.yselect.set(self.ObjName[1]) self.ymenu=OptionMenu(self.Frame1,self.yselect,*self.DecDicPlus) self.ymenu.pack() self.update_button=Button(self.Frame1, text="Update", command=self.UpdateDecPlot) self.update_button.pack() self.MonitorClick=True ##Call some functions self.PlotDic={} self.PlotFront() self.MakePlot() def UpdateDecPlot(self): self.PlotDic={} #remove old plot points self.CurBeamlineX,self.CurBeamlineY=self.xselect.get(),self.yselect.get() self.CurBeamlineXVals=PU.GetParetoCol(self.OutFile,self.CurBeamlineX,self.GenFront) self.CurBeamlineYVals=PU.GetParetoCol(self.OutFile,self.CurBeamlineY,self.GenFront) self.PlotFront() #loads correct values to PlotDic if self.individual: x_closest=self.individual[self.CurBeamlineX][1] y=self.individual[self.CurBeamlineY][1] self.PlotDic['point']={'x':x_closest,'y':y,'linewidth':None,'linestyle':'None','marker':'x','color':'r'} self.MakePlot() def MakePlot(self): master=self.master PlotDic=self.PlotDic try: self.canvas.get_tk_widget().destroy() self.toolbar.destroy() self.toolbarFrame.get_tk_widget().destroy() except: pass figure1 = plt.Figure(figsize=(6,5), dpi=100) ax1 = figure1.add_subplot(111) xlabel=self.CurBeamlineX ylabel=self.CurBeamlineY for k in PlotDic: x=PlotDic[k]['x'] y=PlotDic[k]['y'] linewidth=PlotDic[k]['linewidth'] marker=PlotDic[k]['marker'] linestyle=PlotDic[k]['linestyle'] color=PlotDic[k]['color'] ax1.plot(x,y,marker=marker,linestyle=linestyle,color=color) ax1.set_xlabel(xlabel) ax1.set_ylabel(ylabel) if self.CurBeamlineX in self.DecDic or self.CurBeamlineY in self.DecDic: self.ModPlot4Dec(ax1) canvas = FigureCanvasTkAgg(figure1, master) canvas.get_tk_widget().grid(row=1, column=1,rowspan=3,columnspan=3) toolbarFrame = Frame(self.master) toolbarFrame.grid(row=0,column=1) toolbar = NavigationToolbar2TkAgg(canvas, toolbarFrame) ax1.format_coord = lambda x, y: '' toolbar.update() self.canvas=canvas self.toolbar=toolbar self.canvas.mpl_connect('button_press_event', self.go) def ModPlot4Dec(self,ax1): if self.CurBeamlineX in self.DecDic and self.CurBeamlineY in self.DecDic: xmin=self.DecDic[self.CurBeamlineX][0] xmax=self.DecDic[self.CurBeamlineX][1] updatex=True updatey=True if xmin==xmax: xmin,xmax=ax1.get_xlim() updatex=False ymin=self.DecDic[self.CurBeamlineY][0] ymax=self.DecDic[self.CurBeamlineY][1] if ymin==ymax: ymin,ymax=ax1.get_ylim() updatey=False if xmin>xmax: xmax,xmin=xmin,xmax if ymin>ymax: ymax,ymin=ymin,ymax ax1.set_ylim((ymin,ymax)) ax1.set_xlim((xmin,xmax)) if updatex==True: ax1.plot(np.linspace(xmin,xmin,10),np.linspace(ymin,ymax,10),'--',color='r') ax1.plot(np.linspace(xmax,xmax,10),np.linspace(ymin,ymax,10),'--',color='r') if updatey==True: ax1.plot(np.linspace(xmin,xmax,10),np.linspace(ymin,ymin,10),'--',color='r') ax1.plot(np.linspace(xmin,xmax,10),np.linspace(ymax,ymax,10),'--',color='r') if self.CurBeamlineX in self.DecDic and self.CurBeamlineY not in self.DecDic: xmin=self.DecDic[self.CurBeamlineX][0] xmax=self.DecDic[self.CurBeamlineX][1] updatex=True if xmin==xmax: xmin,xmax=ax1.get_xlim() updatex=False if xmin>xmax: xmax,xmin=xmin,xmax ax1.set_xlim((xmin,xmax)) ymin,ymax=ax1.get_ylim() if updatex==True: ax1.plot(np.linspace(xmin,xmin,10),np.linspace(ymin,ymax,10),'--',color='r') ax1.plot(np.linspace(xmax,xmax,10),np.linspace(ymin,ymax,10),'--',color='r') if self.CurBeamlineX not in self.DecDic and self.CurBeamlineY in self.DecDic: ymin=self.DecDic[self.CurBeamlineY][0] ymax=self.DecDic[self.CurBeamlineY][1] updatey=True if ymin==ymax: ymin,ymax=ax1.get_ylim() updatey=False if ymin>ymax: ymax,ymin=ymin,ymax ax1.set_ylim((ymin,ymax)) xmin,xmax=ax1.get_xlim() if updatey==True: ax1.plot(np.linspace(xmin,xmax,10),np.linspace(ymin,ymin,10),'--',color='r') ax1.plot(np.linspace(xmin,xmax,10),np.linspace(ymax,ymax,10),'--',color='r') def PlotFront(self): #ObjName,ObjArray=PU.GetParetoFront() x=self.CurBeamlineXVals y=self.CurBeamlineYVals self.PlotDic['Front']={'x':x,'y':y,'linewidth':None,'linestyle':'None','marker':'o','color':'b'} self.CurPlotList=['Front'] def PlotBeamLineDic(self): x=self.ResultDic[self.CurBeamlineX] y=self.ResultDic[self.CurBeamlineY] self.PlotDic['BeamLine']={'x':x,'y':y,'linewidth':2,'linestyle':'-','marker':None,'color':'g'} def clear(self): self.bar1.get_tk_widget().destroy() def go(self,event): x=event.xdata if event.dblclick and x!=None and self.MonitorClick==True: self.Table=Text(self.master,width=40,height=20,font=("Helvetica", 16)) self.Table.grid(row=0,column=4,rowspan=3,columnspan=3) self.run_button=Button(self.master,text='Run GPT',command=self.run) self.run_button.grid(row=0,column=2) individual=self.FindClosestIndividual(x) x_closest=individual[self.CurBeamlineX][1] y=individual[self.CurBeamlineY][1] self.PlotDic['point']={'x':x_closest,'y':y,'linewidth':None,'linestyle':'None','marker':'x','color':'r'} self.CurPlotList=self.CurPlotList+['point'] self.MakePlot() self.PrintIndividual(individual) self.individual=individual def FindClosestIndividual(self,x): OutFile=self.FileDic['outputfile'] Allx=PU.GetParetoCol(OutFile,self.CurBeamlineX,self.GenFront) ClosestFrontNumber=np.argmin(abs(x-np.asarray(Allx))) ClosestIndividual=PU.GetAFront(ClosestFrontNumber) return ClosestIndividual def PrintIndividual(self,individual): self.Table.delete(0.0,tk.END) IndStr='Displaying stats for Selected Individual\n' for k,v in individual.items(): if v!='C': if v[0]=='D': IndStr=IndStr+k+' '+v[0]+' '+ str(v[1])+"\n" if v[0]=='O': IndStr=IndStr+k+' '+v[0]+"\n" if v=='C': IndStr=IndStr+k+' C\n' self.Table.insert(tk.END,IndStr) def run(self): IndStr=self.Table.get(0.0,tk.END) FrontDic=self.UpDateIndividual(IndStr) self.popup("Enter a folder name") self.FileName=self.w.popvalue+'_individual.txt' PU.MakeFrontFileFromFront(self.FileName,FrontDic) self.runGPT() self.run_button.destroy() def runGPT(self): cwd=os.getcwd() Path2Parent='..' ParentDir=os.path.join(cwd,Path2Parent) SaveDirectory=self.w.popvalue os.system('rm -r '+os.path.join(cwd,SaveDirectory)) ###Make Front file###### FrontFile=self.FileName ###Copy template/tmp directory try:shutil.rmtree(os.path.join(cwd,'tmp')) except: pass try:shutil.rmtree(os.path.join(cwd,'template')) except: pass os.system('mkdir tmp') try:shutil.copytree(os.path.join(ParentDir,'template'),os.path.join(cwd,'template')) except: pass try:shutil.copyfile(os.path.join(ParentDir,'func_eval.py'),os.path.join(cwd,'func_eval.py')) except:pass #####execute func_eval for the selected point on the Pareto front os.system('python func_eval.py -f' +FrontFile+ ' -v 2 ') #run the front file try: shutil.rmtree(os.path.join(cwd,SaveDirectory)) except:pass shutil.copytree(os.path.join(cwd,'tmp'),os.path.join(cwd,SaveDirectory)) shutil.move(self.FileName,os.path.join(cwd,SaveDirectory,self.FileName)) self.ResultDic=self.MakeResultDic(os.path.join(cwd,SaveDirectory,'eval.0','gpt.tout.stat.txt')) self.PlotDic={} self.CurBeamlineX='s' self.CurBeamlineY='std_x' self.PlotBeamLineDic() self.MakePlot() self.xselect=StringVar() self.xselect.set(self.CurBeamlineX) self.Frame1.destroy() #destroy old frames and menus self.Frame1=Frame(self.master) self.xmenu.destroy() self.ymenu.destroy() self.update_button.destroy() self.Frame1.grid(column=0,row=1,rowspan=2) self.xmenu=OptionMenu(self.Frame1,self.xselect,*self.ResultDic) self.xmenu.pack() self.yselect=StringVar() self.yselect.set(self.CurBeamlineY) self.ymenu=OptionMenu(self.Frame1,self.yselect,*self.ResultDic) self.ymenu.pack() self.update_button=Button(self.Frame1, text="update", command=self.UpdateBeamLinePlot) self.update_button.pack() self.reset_button=Button(self.master, text='reset', command=self.Reset) self.reset_button.grid(row=0,column=2) self.MonitorClick=False def Reset(self): ##Destroy some things (Can not find automated way to do this?) self.Frame1.destroy() #destroy old frames and menus self.Frame1=Frame(self.master) self.xmenu.destroy() self.ymenu.destroy() self.update_button.destroy() self.Table.destroy() self.canvas.get_tk_widget().destroy() self.toolbar.destroy() self.reset_button.destroy() #'there is one more button and it must also be destroyed. Here, I can not self-terminate.... ##reset GUI self.InitialGui() def UpDateIndividual(self,IndStr): #IndStr should only contain decisions, not obj/cons FrontLine=IndStr.split('\n') FrontLine.pop(0) #removes top line of str FrontDic={} ind=0 FrontLine=[line for line in FrontLine if line] #remove any empty lines for line in FrontLine: line=line.split() if line[1]=='D': FrontDic[line[0]]=['D',float(line[2])] #if line[1]=='O': # FrontDic[line[0]]=['O',float(line[1])] #if line[1]=='C': # FrontDic[line[0]]='C' #for k in self.ObjDic: # FrontDic[k]=self.individual[k] self.individual={**self.individual,**FrontDic} return self.individual def UpdateBeamLinePlot(self): self.CurBeamlineX=self.xselect.get() self.CurBeamlineY=self.yselect.get() self.PlotBeamLineDic() self.MakePlot() def MakeColDic(self,ColStr): ColList=ColStr.split() ColDic={} ColNum=0 for Col in ColList: ColDic[Col]=ColNum ColNum=ColNum+1 return ColDic def MakeResultDic(self,File): ResultDic={} ReadingLine1=True with open(File,'r') as f: for line in f: if ReadingLine1==True: ColDic=self.MakeColDic(line) ReadingLine1=False for k in ColDic: ResultDic[k]=[] elif ReadingLine1==False: for k in ColDic: SplitLine=line.split() CurCol=ColDic[k] CurVar=ResultDic[k] CurVar.append(float(SplitLine[CurCol])) ResultDic[k]=CurVar return ResultDic def popup(self,Message): self.w=popupWindow(self.master,Message) self.master.wait_window(self.w.top) class popupWindow(object): def __init__(self,master,Message): top=self.top=Toplevel(master) self.l=Label(top,text=Message) self.l.pack() self.e=Entry(top) self.e.pack() self.b=Button(top,text='OK',command=self.cleanup) self.b.pack() def cleanup(self): self.popvalue=self.e.get() self.top.destroy() root = Tk() my_gui = BeamOptGUI(root) root.mainloop()