How to combine two subplots in one tkinter window? - python

I would like to display two matplotlib plots below each other in one tkinter window. I have needed two different codes so far. How can I combine the codes in one? I have created the desired result with powerpoint below. I have already tried it with subplot, unfortunately without success: plt.subplots(2,1, figsize=(20,10)) and plt.subplots(1,1, figsize=(20,10))
My first code:
# ___________________________________________________________________________
# Library
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
import numpy as np
# ___________________________________________________________________________
# Carwash Array
Carwash_km = np.array([1,4,500,1500,2800,2960,2700,5,2000,2000,3100,4000,4150,4150])
Carwash_cost = np.array([5,1000,1000,2100,3000,3150,3150,20,50,600,3500,3800,3960,3700])
# Fuel Array
Fuel_km = np.array([2,5,600,2600,3900,3970,3800,6,3000,3000,4200,5000,5260,5260])
Fuel_cost = np.array([6,2000,2000,3200,4000,4260,4260,30,60,700,4600,4900,4070,4800])
# Maintenance Array
Maintenance_km = np.array([0,3,400,400,1700,1850,1600,4,1000,1000,2000,3000,3040,3040])
Maintenance_cost = np.array([4,500,500,1000,2000,2040,2040,10,40,500,2400,2700,2850,2600])
# ___________________________________________________________________________
# Main
Vis = tk.Tk()
Vis.title("Main") # titel
# ___________________________________________________________________________
# Plot
fig, ax = plt.subplots(1, 1, figsize=(20,5), facecolor = "white")
Plot_Carwash_cost = plt.bar(Carwash_km, Carwash_cost,
bottom=0,
color="#BDD7EE",
ec="black",
width=100,
label="Carwash_cost")
Plot_Carwash_cost2 = plt.bar(Maintenance_km, -Maintenance_cost,
bottom=-0,
color="#C5E0B4",
ec="black",
width=100,
label="Maintenance_cost")
Plot_Fuel = plt.scatter(Fuel_km, Fuel_cost,
marker="^",
s=150,
color="#C00000",
edgecolors="black",
zorder=3,
label="Fuel_cost")
ax.spines["bottom"].set_position("zero")
ax.spines["top"].set_color("none")
ax.spines["right"].set_color("none")
ax.spines["left"].set_color("none")
ax.tick_params(axis="x", length=20)
_, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
ax.set_xlim(-15, xmax)
ax.set_ylim(ymin, ymax+10) # legend
ax.text(xmax, -5, "km", ha="right", va="top", size=14)
plt.legend(ncol=5, loc="upper left")
plt.tight_layout()
# ___________________________________________________________________________
# Canvas, Toolbar
canvas = FigureCanvasTkAgg(fig, master=Vis)
canvas.draw() # TK-Drawingarea
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)
toolbar = NavigationToolbar2Tk(canvas, Vis)
toolbar.update()
Vis.mainloop()
My second code:
# ___________________________________________________________________________
# Library
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
import numpy as np
# ___________________________________________________________________________
# 1 Array
Beg1 = np.array([1,4,500,1500,2800,2960,2700,5,2000,2000,3100,4000,4150,4150])
End1 = np.array([2,5,600,2600,3900,3970,3800,6,3000,3000,4200,5000,5260,5260])
# 2 Array
Beg2 = np.array([5,1000,1000,2100,3000,3150,3150,20,50,600,3500,3800,3960,3700])
End2 = np.array([6,2000,2000,3200,4000,4260,4260,30,60,700,4600,4900,4070,4800])
# 3 Array
Beg3 = np.array([0,3,400,400,1700,1850,1600,4,1000,1000,2000,3000,3040,3040])
End3 = np.array([4,500,500,1000,2000,2040,2040,10,40,500,2400,2700,2850,2600])
# ___________________________________________________________________________
# detail
Vis2 = tk.Tk()
Vis2.title("detail") # titel
# ___________________________________________________________________________
# Plot
fig, ax = plt.subplots(2, 1, figsize=(20,10), facecolor = "white")
Plot_1 = plt.barh(len(Beg1)+np.arange(len(Beg2)), End2-Beg2+500,
left=Beg2,
height=0.9,
color='red',
alpha=0.5)
Plot_2 = plt.barh(range(len(Beg1)), End1-Beg1,
left=Beg1,
height=0.9,
color='#BDD7EE')
Plot_3 = plt.barh(len(Beg1)+len(Beg2)+np.arange(len(Beg3)), End3-Beg3+500,
left=Beg3,
height=0.9,
color="#C5E0B4")
plt.tight_layout()
# ___________________________________________________________________________
# Canvas, Toolbar
canvas = FigureCanvasTkAgg(fig, master = Vis2)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)
toolbar = NavigationToolbar2Tk(canvas, Vis2)
toolbar.update()
Vis2.mainloop()

The short answer is to create two Frame widget, and have your FigureCanvasTkAgg master set to each Frame.
...
frame1 = tk.Frame(Vis)
frame2 = tk.Frame(Vis)
frame1.pack()
frame2.pack()
...
canvas = FigureCanvasTkAgg(fig, master = frame1)
...
canvas2 = FigureCanvasTkAgg(fig, master = frame2)
...
Vis.mainloop()
A better way is to create a class which inherits from Frame and handles the creation of Figure and NavigationToolBar. Depending on your need, it could be something like this:
from matplotlib.figure import Figure #use Figure instead of pyplot if you are embedding into tkinter
class GraphFrame(tk.Frame):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, master=self)
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.toolbar = NavigationToolbar2Tk(self.canvas, self)
self.toolbar.update()
Then you can easily create new plotting areas under the same root window Vis:
Vis = tk.Tk()
graph1 = GraphFrame(Vis)
graph1.pack()
graph1.ax.bar(Carwash_km, Carwash_cost, ...)
graph1.ax.bar(Maintenance_km, -Maintenance_cost, ...)
graph1.ax.scatter(Fuel_km, Fuel_cost, ...)
graph2 = GraphFrame(Vis)
graph2.pack()
graph2.ax.barh(...)
graph2.ax.barh(...)
graph2.ax.barh(...)
Vis.mainloop()

#excuse me
#in
class GraphFrame(tk.Frame):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.fig = Figure()
I think the correct sintax is :
class GraphFrame(tk.Frame):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.fig = plt.figure()
Am I right?

Related

How to run a function concurrently with matplotlib animation?

I am building a GUI that takes in sensor data from the raspberry pi and displays it onto a window via matplotlib animation. The code works fine, except when being run on raspberry pi, the matplotlib animation takes some time to execute, which momentarily blocks the sensor reading GetCPM that I'm interested in. How can I make both these programs run simultaneously without one clogging the other, I've tried the multiprocessing library, but I can't seem to get it to work.
Note: The sensor data that I'm plotting does not have to have a high sample rate, its the sensor that I'm displaying on label that does.
Here is my code
import matplotlib
matplotlib.use("TkAgg")
import numpy as np
import tkinter as tk
from tkinter import ttk
from tkinter import *
import math
import datetime as dt
import time
from collections import Counter
import random as rn
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import matplotlib.pyplot as plt
import threading as td
import multiprocessing as mp
from multiprocessing import Process, Queue
style.use('seaborn')
limit = np.array([5])
# Initialize Pressure Figure
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
x1, y1 = [], []
x2, y2 = [], []
TOT = []
CPM = 0
def GetValues(i, x, y, ax):
volts2 = rn.uniform(3,6)
x.append(dt.datetime.now().strftime('%H: %M: %S.%f'))
y.append(float(volts2))
x = x[-50:]
y = y[-50:]
ax.clear()
ax.plot(x, y, linewidth=1, color= 'k')
ax.fill_between(x, y, limit[0], where=(y > limit[0]), facecolor='forestgreen', alpha=0.7, interpolate=True)
ax.fill_between(x, y, limit[0], where=(y < limit[0]), facecolor='darkred', alpha=0.7, interpolate=True)
ax.set_xticklabels([])
def animate(i, x, y, ax):
volts = rn.uniform(2,8)
x.append(dt.datetime.now().strftime('%H: %M: %S.%f'))
y.append(float(volts))
x = x[-50:]
y = y[-50:]
ax.clear()
ax.plot(x, y, linewidth=1, color= 'k')
ax.fill_between(x, y, limit[0], where=(y > limit[0]), facecolor='forestgreen', alpha=0.7, interpolate=True)
ax.fill_between(x, y, limit[0], where=(y < limit[0]), facecolor='darkred', alpha=0.7, interpolate=True)
ax.set_xticklabels([])
def GetCPM():
global TOT, CPM
temp = 1
# Test Case
if temp == True:
TOT.append(True)
else:
TOT.append(False)
TOT = TOT[-2750:]
count = Counter(TOT)
CPM = count[True]
return CPM
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# If you want to customize the icon of the tk window, only accepts .ico
#tk.Tk.iconbitmap(self, default="iconname.ico")
tk.Tk.wm_title(self, "Pressure")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0,weight=1)
self.frames = {}
frame = GUI(container, self)
self.frames[GUI] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(GUI)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class GUI(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
canvas1 = FigureCanvasTkAgg(fig1, self)
canvas1.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
canvas2 = FigureCanvasTkAgg(fig2, self)
canvas2.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
#Initialize label as self.
lbl = tk.Label(self, font = ('Sans Serif', 40, 'bold'),
background = 'purple',
foreground = 'White')
lbl.place(relx=0.5, rely=0.5, anchor=CENTER)
def update():
ll = GetCPM()
lbl.config(text = "CPM = {}".format(ll))
print(dt.datetime.now().strftime('%H: %M: %S.%f'))
lbl.after(20, update)
update()
# interval determines the speed at which data is recorded, 1000 = 1 second
if __name__ == '__main__':
app = App()
t1 = mp.Process(target=GetCPM)
t1.start()
t1.join()
ani_1 = animation.FuncAnimation(fig1, animate, interval = 500,
fargs=(x1, y1, ax1))
ani_2 = animation.FuncAnimation(fig2, GetValues, interval = 500,
fargs=(x2, y2, ax2))
app.mainloop()

Is it possible to control a matplotlib graph using a Tkinter Scrollbar?

I would like to make an equivalent of the function FuncAnimation from matplotlib.animation, in which I could control the current plotted data using the scrollbar.
Say you have a data array which contains data points to be plotted at each time i. When using FuncAnimation, you first need to define a function ( here animate(i) ) which will be called for each time i = 1 to len(data[:,0]) :
def animate(i):
ax.plot(data[i,:])
anim = FuncAnimation(fig, animate, interval=100, frames=len(data[:,0]))
plt.draw()
plt.show()
but you cannot control the time i, like with a play/stop functionality. What I would like to do is to call the function animate(i), with i being the position of the scrollbar.
I found this example ( using the events from matplotlib:
https://matplotlib.org/3.2.1/users/event_handling.html )
but the mpl_connect doesn't have a "scrollbar_event".
import tkinter
from random import randint
import matplotlib as plt
import numpy as np
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
#create figure
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_axes([0,0,1,1])
ax.imshow(np.array([[0,10],[23,40]]))
#create canvas with figure
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def on_key_press(event):
ax.clear()
ax.imshow(np.array([[randint(0,30),randint(0,30)],[randint(0,30),randint(0,30)]]))
canvas.draw_idle()
key_press_handler(event, canvas)
print("you pressed {}".format(event.key))
#connect canvas to event function
canvas.mpl_connect("key_press_event", on_key_press)
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
tkinter.mainloop()
Actually the scroll functionality is given by matplotlib widgets !!
The example below works fine :
import matplotlib
import tkinter as Tk
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from myPytHeader import *
matplotlib.use('TkAgg')
root = Tk.Tk()
root.wm_title("Embedding in TK")
fig = plt.Figure(figsize=(8, 6))
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
nDt = nbLines("grid.dat")
nDx = nbGridPoints("grid.dat")
grid = np.zeros( (nDt,nDx) ) ; loadData("grid.dat", grid)
valu = np.zeros( (nDt,nDx) ) ; loadData("valu.dat", valu)
ax=fig.add_subplot(111)
fig.subplots_adjust(bottom=0.25)
ax_time = fig.add_axes([0.12, 0.1, 0.78, 0.03])
s_time = Slider(ax_time, 'Time', 0, nDt, valinit=0, valstep=1)
def update(val):
frame = int(s_time.val)
ax.clear()
ax.set(xlim=(-0.05, 1.05), ylim=(-0.05, 1.25))
ax.grid()
ax.scatter(grid[frame,:], valu[frame,:], color='b', marker='.')
fig.canvas.draw_idle()
s_time.on_changed(update)
Tk.mainloop()
After all these years I've found solutions to my problems here, I am in debt !!!
Here is the final solution I came with.
I hope it can be useful to someone someday somehow !!
import matplotlib
import numpy as np
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# load data
nDt = 1000
nDx = 400
grd = np.zeros( (nDt,nDx) )
val = np.zeros( (nDt,nDx) )
for t in np.arange(nDt):
for x in np.arange(nDx):
grd[t,x] = x / nDx
val[t,x] = (x / nDx) * (t/nDt) * np.sin(10 * 2*np.pi * (t-x)/nDt)
matplotlib.use('TkAgg')
root = tk.Tk()
root.wm_title("Embedding in TK")
fig = plt.Figure(figsize=(8, 6))
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
ax=fig.add_subplot(111)
fig.subplots_adjust(bottom=0.25)
ax.set(xlim=(-0.05, 1.05), ylim=(-1.05, 1.05))
ax.grid()
scat = ax.scatter(grd[0,:], val[0,:], color='b', marker='.')
ax_time = fig.add_axes([0.12, 0.1, 0.78, 0.03])
s_time = Slider(ax_time, 'Time', 0, nDt, valinit=0, valstep=1)
i_anim = 0
i_relative = 0
i_current = 0
def updateGraph(i):
y_i = val[i,:]
scat.set_offsets(np.c_[grd[i,:], y_i])
def updateFromAnim(i):
global i_anim
global i_current
global i_relative
i_anim = i
i_current = i + i_relative
s_time.set_val(i_current)
updateGraph(i_current)
def updateFromScroll(val):
global i_anim
global i_current
global i_relative
i_relative = int(s_time.val) - i_anim
i_current = int(s_time.val)
updateGraph(i_current)
def onClick():
global anim_running
if anim_running:
anim.event_source.stop()
anim_running = False
else:
anim.event_source.start()
anim_running = True
start_button = tk.Button(root, text="START/STOP", command=onClick)
start_button.pack()
anim_running = True
anim = FuncAnimation(fig, updateFromAnim, interval=100, frames=nDt)
s_time.on_changed(updateFromScroll)
tk.mainloop()

How to show label into barh plot?

I would like to label my bars from the barh-plot. Therefore I have created a text numpy.array=Maintenance_component, which I want to display next to each bar. Unfortunately I did not find a quick solution. The desired result should be as follows.
# ___________________________________________________________________________
# Library
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
import numpy as np
# ___________________________________________________________________________
# Maintenance Array
Maintenance_km = np.array([30,400,400,1700,1850,1600])
Maintenance_cost = np.array([500,500,1000,2000,2040, 1800])
Maintenance_component = np.array(['engine','spoiler','diffusor','radio','window','fueltank'])
# ___________________________________________________________________________
# Main
Vis = tk.Tk()
Vis.title("Main") # titel
# ___________________________________________________________________________
# Plot
fig, ax = plt.subplots(1, 1, figsize=(20,5), facecolor = "white")
Plot_Maintenace_cost2 = plt.barh(range(len(Maintenance_km)), Maintenance_km-Maintenance_cost+500,
left=Maintenance_km,
height=0.9,
color='#C5E0B4')
ax.spines["bottom"].set_position("zero")
ax.spines["top"].set_color("none")
ax.spines["right"].set_color("none")
ax.spines["left"].set_color("none")
ax.tick_params(axis="x", length=20)
_, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
ax.set_xlim(-15, xmax)
ax.set_ylim(ymin, ymax+10) # legend
ax.text(xmax, -5, "km", ha="right", va="top", size=14)
plt.legend(ncol=5, loc="upper left")
plt.tight_layout()
# ___________________________________________________________________________
# Canvas, Toolbar
canvas = FigureCanvasTkAgg(fig, master=Vis)
canvas.draw() # TK-Drawingarea
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)
toolbar = NavigationToolbar2Tk(canvas, Vis)
toolbar.update()
Vis.mainloop()
Maintenance_km = np.array([30,400,400,1700,1850,1600])
Maintenance_cost = np.array([500,500,1000,2000,2040, 1800])
Maintenance_component = np.array(['engine','spoiler','diffusor','radio','window','fueltank'])
fig, ax = plt.subplots()
Plot_Maintenace_cost2 = plt.barh(range(len(Maintenance_km)), Maintenance_km-Maintenance_cost+500,
left=Maintenance_km,
height=0.9,
color='#C5E0B4')
for x,y,t in zip(Maintenance_km+Maintenance_km-Maintenance_cost+500,range(len(Maintenance_km)),Maintenance_component):
ax.annotate(t, xy=(x,y))

How to use Line Collection with pyplot

When you run the code the error should be pretty obvious, just click your mouse in the black space and move it around. I'm not sure how the line segments are being created, I pulled it from the library and its kind of confusing. How can I get the line segments to plot along my scatter plot? When I looks at the segments array being generated I believe it’s creating pairs of x,x and y,y instead of x,y and x,y
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap
import numpy as np
import random
class Mouse_Game:
'''Creates a matplotlib canvas object that plot mouse coordinates when animated.'''
def __init__(self, root, width=400, height=400):
self.frame = tk.Frame(master=root)
self.status = False
self.fig = plt.Figure(dpi=100, facecolor='black')
self.ax = self.fig.add_axes([0,0,1,1], fc='black')
self.width = width
self.height = height
self.ax.axis('off')
#set up the canvas object and bind commands
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame, resize_callback=self.configure) # A tk.DrawingArea.
self.canvas.draw()
self.canvas.get_tk_widget().pack(side='top', fill='both', expand=True)
self.fig.canvas.mpl_connect('button_press_event', self.animate)
self.fig.canvas.mpl_connect('motion_notify_event', self.motion)
def animate(self, event):
#Check if currently running
if not self.status:
self.status = True
self.capture = np.array([(event.xdata, event.ydata)]*40)
else:
self.status = False
#plot a line that follows the mouse around
while self.status:
self.ax.clear()
self.ax.set_xlim(0, self.width)
self.ax.set_ylim(0, self.height)
x = self.capture[:,0]
y = self.capture[:,1]
############################################################
points = self.capture.T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
###########################################################
lc = LineCollection(segments, cmap='magma')
lc.set_array(x)
lc.set_linewidth(2)
self.ax.add_collection(lc)
self.ax.scatter(x, y, marker='o')
self.fig.canvas.draw()
self.fig.canvas.flush_events()
def motion(self, event):
if self.status:
#Append mouse coordinates to array when the mouse moves
self.capture = self.capture[1:40]
self.capture = np.append(self.capture, [(event.xdata, event.ydata)], axis=0)
def configure(self, event):
#Used to adjust coordinate setting when the screen size changes
self.width, self.height = self.canvas.get_width_height()
def _quit():
#destroy window
root.quit()
root.destroy()
root = tk.Tk()
root.wm_title("Mouse Plot")
MG = Mouse_Game(root=root)
MG.frame.pack(expand=True, fill='both')
button = tk.Button(root, text="Quit", command=_quit)
button.pack(side='bottom', pady=10)
tk.mainloop()
I'm not sure why you transpose the array. If you leave the transposition out, it'll work just fine
points = self.capture.reshape(-1, 1, 2)

applying the matplotlib draw() freezes window solution to special case

Being new to python, I've come upon the matplotlib draw() freezes window problem myself and found the solution on this site:
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import random
import numpy as np
import sys
import Tkinter as tk
import time
def function1(fig, ax):
ax.cla()
color_grade_classes = ['#80FF00','#FFFF00','#FF8000', '#FF0000']
varsi = random.randint(1, 100)
for colors, rows in zip(color_grade_classes, [3,2,1,0] ):
indexs = np.arange(5)
heights = [varsi,varsi/2,varsi/3,0,0]
ax.bar(indexs, heights, zs = rows, zdir='y', color=colors, alpha=0.8)
return fig
class App():
def __init__(self):
self.root = tk.Tk()
self.root.wm_title("Embedding in TK")
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, projection='3d')
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
self.fig = function1(self.fig, self.ax)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.label = tk.Label(text="")
self.label.pack()
self.update_clock()
self.root.mainloop()
def update_clock(self):
self.fig = function1(self.fig,self.ax)
self.canvas.show()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
now = time.strftime("%H:%M:%S")
self.label.configure(text=now)
self.root.after(1000, self.update_clock)
app=App()
My problem is incorporating the following plotting code into it. It's not quite the same as the example given. Not sure how to split this up between the function definition and the class declaration. Can anyone help me on this?
t0 = time.time()
while time.time() - t0 <= 10:
data = np.random.random((32, 32))
plt.clf()
im = plt.imshow(data,cmap=cm.gist_gray, interpolation='none')
plt.ion()
cbar = plt.colorbar(im)
cbar.update_normal(im)
cbar.set_clim(0, np.amax(data))
plt.draw()
time.sleep(0.5)
plt.show(block=True)
this seems to work.
Basically the __init__ part initialises the plot and draws the first "frame". Then the function self.update_clockis called every 1000ms, and that function calls function1() which generates new data and redraws the plot.
I moved things around a bit because of the colorbar in your example, but the idea remains the same.
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import random
import numpy as np
import sys
import Tkinter as tk
import time
class App():
def __init__(self):
self.root = tk.Tk()
self.root.wm_title("Embedding in TK")
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111)
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
data = np.random.random((32, 32))
im = self.ax.imshow(data,cmap=cm.gist_gray, interpolation='none')
self.cbar = self.fig.colorbar(im)
self.cbar.update_normal(im)
self.cbar.set_clim(0, np.amax(data))
self.fig = self.function1(self.fig, self.ax)
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.label = tk.Label(text="")
self.label.pack()
self.update_clock()
self.root.mainloop()
def update_clock(self):
self.fig = self.function1(self.fig,self.ax)
self.canvas.show()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
now = time.strftime("%H:%M:%S")
self.label.configure(text=now)
self.root.after(1000, self.update_clock)
def function1(self, fig, ax):
ax.cla()
data = np.random.random((32, 32))
im = ax.imshow(data,cmap=cm.gist_gray, interpolation='none')
self.cbar.update_normal(im)
self.cbar.set_clim(0, np.amax(data))
return fig
app=App()

Categories

Resources