I have been working on plotting time varying functions in Python as my most recent project, and would love input on optimization, proper Tkinter form, and anything that stands out like a sore thumb.To get technical details out of the way, this code has been tested and works on my home box running Linux Mint 18 (4.4.0-21-generic kernel) with Python 3.5.2. It uses matplotlib, numpy, sympy, and Tkinter. The code supplied will be verbatim what I currently have, saved as 3 separate files. The import structure is definitely something I need clarification on!For use, one can switch between graphs stored via the dropdown box and clicking the 'Make' button. New graphs can be entered by typing in first an initial function (in numpy format, such as np.sin(x)) varying in space (x), and a varying function (eg np.sin(x+i)), varying in space (x) and time (i), and pressing the respective add button. Time progression can be stopped and started via two buttons.dictionaries.pyfrom sympy import *from sympy.parsing.sympy_parser import parse_exprimport Tkinter as TkThese dictionaries serve the purpose of storing the space varying andtime varying functions to be plotted.initFuncts = {0: '(np.exp(-0.5 * x ** 2) +'                 '2 * x * np.exp(-0.5 * x ** 2)) ** 2',              1: 'x**2'}varyFuncts = {0: '((1 / (4 * np.pi)) ** (1 / 4)) * '                 '((np.exp(-0.5 * x ** 2) * np.cos(0.5 * i) + '                 '2 * x * np.exp(-0.5 * x ** 2) *'                 'np.cos(1.5 * i)) ** 2)',              1: 'x**2 + np.cos(i)'}def addInitFunct(textField, options, strings):    initFuncts[len(initFuncts)] = textField.get()    expr = parse_expr(initFuncts[len(initFuncts)-1].replace('np.', ''))        options.children['menu'].delete(0, 'end')    strings.set('')    for key in initFuncts:        options.children['menu'].add_command(            label=str(key),            command=Tk._setit(strings, str(key)))def addVaryFunct(textField):    varyFuncts[len(varyFuncts)] = textField.get()animationObj.pyfrom matplotlib.backends.backend_tkagg import FigureCanvasTkAggimport Tkinter as Tk, numpy as npimport matplotlib.pyplot as plt, matplotlib.animation as animationimport dictionaries as dictsclass animationObj:    def __init__(self, mainframe, num, x, timeString):                Create instance of animationObj class, enabling the animation of        matplotlib based figures.        Keyword arguments:        mainframe -- the frame the animation will appear in        num -- the function number in the dictionaries        x -- spacial range of the animation        timeString -- string which will report current time to user                self._master = mainframe  # set frame        self.timeString, self.num, self.x = timeString, num, x        self.fig = plt.Figure()  # create pyplot figure        # add figure to canvas and connect canvas to frame        self.canvas = FigureCanvasTkAgg(self.fig, master=self._master)        # get widget then pack        self.tkwidget = self.canvas.get_tk_widget()        self.tkwidget.pack()        # add subplot to actually animate on        self.ax = self.fig.add_subplot(111)        # generate initial plot, note the syntax: 'self.line,', comma        # after variable means returning as a tuple        self.line, = self.ax.plot(self.x,                                  eval(dicts.initFuncts[self.num]))        # set bounds on plot        self.ax.axis([-6, 6, -5, 5])        # animate the animation        self.ani = animation.FuncAnimation(self.fig, self.animate,                                           np.arange(0, 200, 0.01),                                           interval=1, blit=False)    def animate(self, i):                Animation function which executes every 'interval given in the        FuncAnimation instantiation.        Keyword arguments:        i -- the current time                # must create a (not technically called this...) 'local global'        # version of x because set_ydata expects a global variable x        x = self.x        self.timeString.set('t = ' + '{:3.2f}'.format(i))  # report time        # generate plot at next time interval        self.line.set_ydata(eval(dicts.varyFuncts[self.num]))        # return line tuple        return self.line,    def stopIt(self):        Pause the current animation shown.        self.ani.event_source.stop()    def startIt(self):        Resume the current animation shown.        self.ani.event_source.start()    def removeIt(self):        Remove the current animation from the window.        self.tkwidget.pack_forget()        self.ani.event_source.stop()    def addIt(self, num):                Add a new plot to the plotting window.        Keyword arguments:        num -- the function number in the dictionaries                if (num in dicts.initFuncts) and (num in dicts.varyFuncts):            self.removeIt()  # remove old plot            x = self.x  # same as before, expects a global x            i = 0  # reset time to zero            self.num = int(num)  # update instance variable            #reinitialize all needed components            self.fig = plt.Figure()            self.canvas = FigureCanvasTkAgg(self.fig, master=self._master)            self.tkwidget = self.canvas.get_tk_widget()            self.tkwidget.pack()            self.ax = self.fig.add_subplot(111)            self.line, = self.ax.plot(self.x,                                      eval(dicts.initFuncts[self.num]))            self.ax.axis([-6, 6, -5, 5])            self.ani = animation.FuncAnimation(self.fig, self.animate,                                               np.arange(0, 200, 0.01),                                               interval=1, blit=False)main.pyimport Tkinter as Tkimport numpy as npimport animationObjimport dictionariesdef _quit(mast):        Quits the entire application.    Keyword arguments:    mast -- the root Tk instance        mast.quit()    mast.destroy()root = Tk.Tk()  # root Tk instancet1 = Tk.Toplevel(root)t2 = Tk.Toplevel(root)  # Tk Toplevel instance to separate windows# add frames to windowsf1 = Tk.Frame(t1)f2 = Tk.Frame(t2)f = Tk.Frame(root)label1 = Tk.Label(f, text=Superposition State).pack()# set each frames' geometryt2.geometry(%dx%d+%d+%d % (250, 300, 650, 625))t1.geometry(%dx%d+%d+%d % (250, 300, 650, 300))root.geometry(%dx%d+%d+%d % (500, 500, 150, 300))# drop down menuoptions = Tk.StringVar()options.set('0')w = Tk.OptionMenu(f1, options, '0', '1')w.pack(side=Tk.BOTTOM)# string to display timetimeString = Tk.StringVar()timeString.set('t = 0')l = Tk.Label(f1, textvariable=timeString, font=(Courier, 24))# make and pack quit buttonbutton = Tk.Button(master=f1, text='Quit',                   command=lambda: _quit(root), height=2)button.pack(side=Tk.BOTTOM)# pack time stringl.pack(side=Tk.TOP)x = np.arange(-6, 6, 0.005)  # range of x valuesaniObj = animationObj.animationObj(f, 0, x, timeString)# other buttonsbutton3 = Tk.Button(master=f1, text='Make',                    command=lambda: aniObj.addIt(int(options.get())), height=2)stopIt = Tk.Button(master=f1, text='Stop', command=aniObj.stopIt, height=1)startIt = Tk.Button(master=f1, text='Start',                    command=aniObj.startIt, height=1)# pack framesf.pack()f1.pack()f2.pack()# pack buttonsbutton3.pack(side=Tk.BOTTOM)stopIt.pack(side=Tk.LEFT)startIt.pack(side=Tk.LEFT)e = Tk.Entry(f2)button4 = Tk.Button(master=f2, text='Add Initial Function',                    command=lambda: dictionaries.addInitFunct(e, w, options),                    height=1)button5 = Tk.Button(master=f2, text='Add Varying Function', command=lambda:                    dictionaries.addVaryFunct(e), height=1)button4.pack(side=Tk.BOTTOM)button5.pack(side=Tk.BOTTOM)e.pack(side=Tk.TOP)# execute main loop on base instanceroot.mainloop()Again I would like to thank any advice and criticisms offered up in advance!
Function Plotter GUI in Tkinter and Matplotlib
python;gui;tkinter;matplotlib;sympy
There are a lot of PEP 8 issues in your code. I recommend reading through that document. It is recommend to avoid using eval, as it makes your code harder to maintain and has lots of security issues. Instead, it is better to represent your expressions symbolically with SymPy, then use sympy.lambdify to convert them to numerical functions. So for instance, your initFuncts could be (by the way, if your dict keys are just 0 and 1, why not just use a list?) could beimport sympy as symx = sym.symbols('x')initFuncts = [(sym.exp(-x**2/2) + 2*x*sym.exp(-x**2/2))**2, x**2](I've also cleaned up the spaces, and used rational numbers instead of floats).Then you could convert this to a numpy function later with lambdify. For example, f = lambdify(x, initFuncts[0], 'numpy')creates a function f which evaluates the first expression as a NumPy function.