make a button for animation in matplotlib - python

I just made a simple gui using Qt Designer, the gui has 4 buttons and a widget. The widget will show the animation and the buttons are for pause animation,resume, clean the canvas and start animation. I made this code:
import sys
from PyQt4 import QtGui, uic
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
def start():
def datos(t=0):
while True:
t += 0.1
yield t, np.cos(t)
def init():
ax.set_ylim(-1, 1)
ax.set_xlim(0, 5)
def run(data):
t,y = data
xdata.append(t)
ydata.append(y)
line.set_data(xdata, ydata)
xmin,xmax =ax.get_xlim()
if t > xmax:
ax.set_xlim(xmin, 1.5*xmax)
ax.figure.canvas.draw()
ani = animation.FuncAnimation(fig, run, datos, blit=False, interval=50,
repeat=False, init_func=init)
def stop():
ani.event_source.stop()
def borr():
plt.clf()
canvas.draw()
def anim():
ani.event_source.start()
window.resume.clicked.connect(anim)
window.pause.clicked.connect(stop)
window.clean.clicked.connect(borr)
return ani
layout=QtGui.QVBoxLayout()
fig=plt.figure()
canvas=FigureCanvas(fig)
layout.addWidget(canvas)
ax = fig.add_subplot(111)
line,=ax.plot([],[],lw=2)
ax.grid()
xdata, ydata = [], []
app = QtGui.QApplication(sys.argv)
window = uic.loadUi("animacion.ui")
window.start.clicked.connect(start)
window.widget.setLayout(layout)
window.show()
sys.exit(app.exec_())
this shows the grid, but when I press the start button it doesnt show the animation
I also made this code:
import sys
from PyQt4 import QtCore, QtGui, uic
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
def datos(t=0):
while True:
t += 0.1
yield t, np.cos(t)
def init():
ax.set_ylim(-1, 1)
ax.set_xlim(0, 5)
def run(data):
t,y = data
xdata.append(t)
ydata.append(y)
line.set_data(xdata, ydata)
xmin,xmax =ax.get_xlim()
if t > xmax:
ax.set_xlim(xmin, 1.5*xmax)
ax.figure.canvas.draw()
def start():
window.widget.setLayout(layout)
def stop():
ani.event_source.stop()
def borr():
plt.clf()
canvas.draw()
def anim():
ani.event_source.start()
layout=QtGui.QVBoxLayout()
fig=plt.figure('test')
canvas=FigureCanvas(fig)
layout.addWidget(canvas)
ax = fig.add_subplot(111)
line,=ax.plot([],[],lw=2)
ax.grid()
xdata, ydata = [], []
app = QtGui.QApplication(sys.argv)
window = uic.loadUi("animacion.ui")
window.resume.clicked.connect(anim)
window.pause.clicked.connect(stop)
window.clean.clicked.connect(borr)
window.start.clicked.connect(start)
ani = animation.FuncAnimation(fig, run, datos, blit=False, interval=50,
repeat=False, init_func=init)
window.show()
sys.exit(app.exec_())
In this case, when I press start the animation begins, I can pause and resume. But when a clean the canvas an press start again it doesnt show the function.
How can I make it works?
thanks!

Try to provide minimal working examples. Without animacion.ui we cannot run you code.
Refering to the second code: The problem here seems to be that inside borr() you clear the figure (plt.clf()). If the figure is cleared, where should the animation be drawn to?

I solved the problem making a function with the animation
import sys
from PyQt4 import QtGui, uic
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
def start():
def datos(t=0):
while True:
t += 0.1
yield t, np.cos(t)
def init():
ax.set_ylim(-1, 1)
ax.set_xlim(0, 5)
def run(data):
t,y = data
xdata.append(t)
ydata.append(y)
line.set_data(xdata, ydata)
xmin,xmax =ax.get_xlim()
if t > xmax:
ax.set_xlim(xmin, 1.5*xmax)
ax.figure.canvas.draw()
def stop():
ani.event_source.stop()
def borr():
plt.clf()
canvas.draw()
def anim():
ani.event_source.start()
window.resume.clicked.connect(anim)
window.pause.clicked.connect(stop)
window.clean.clicked.connect(borr)
ax = fig.add_subplot(111)
line,=ax.plot([],[],lw=2)
ax.grid()
xdata, ydata = [], []
ani = animation.FuncAnimation(fig, run, datos, blit=False, interval=50,
repeat=False, init_func=init)
canvas.draw()
layout=QtGui.QVBoxLayout()
fig=plt.figure()
canvas=FigureCanvas(fig)
layout.addWidget(canvas)
app = QtGui.QApplication(sys.argv)
window = uic.loadUi("animacion.ui")
window.start.clicked.connect(start)
window.widget.setLayout(layout)
window.show()
sys.exit(app.exec_())

Related

How can i add an ellipse in an animated tkinter gui figure?

I have a tkinter GUI where I'm plotting live data from a sensor using the matplotlib animation. When enough data are collected, a fitting ellipse is calculated. And this ellipse should then be plotted in the same figure as the recorded sensor data.
The original code is a bit lengthy, so here is a piece of working code that shows the problem. Currently the ellipse is drawn in a new window when the animation is stopped by button. Can someone explain me how to add this ellipse to the live plot figure in tkinter GUI?
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import pyplot as plt, animation
from matplotlib.patches import Ellipse
import numpy as np
plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
fig = plt.Figure(dpi=100)
ax = fig.add_subplot(xlim=(0, 2), ylim=(-1, 1))
line, = ax.plot([], [], lw=2)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
def StopAnimation():
anim.pause()
plotEllipse()
def StartAnimation():
anim.resume()
buttonStop = tkinter.Button(master=root, text="Stop Animation", command=StopAnimation)
buttonStop.pack(side=tkinter.BOTTOM)
buttonStart = tkinter.Button(master=root, text="Start Animation", command=StartAnimation)
buttonStart.pack(side=tkinter.BOTTOM)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def plotEllipse():
ell= Ellipse((1,0), 1, 0.75, angle=45, edgecolor = 'red', facecolor='none', lw = 2)
fig1, ax1 = plt.subplots(1, 1, figsize=(10, 6))
ax1.add_artist(ell)
ax1.set_xlim(0, 2)
ax1.set_ylim(-1, 1)
plt.show()
def init():
line.set_data([], [])
return line,
def animate(i):
x = np.linspace(0, 2, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,frames=200, interval=20, blit=True)
tkinter.mainloop()
i would have expected to plot into the tkinter gui figure with ax.add_artist(ell)

Matplotlib FuncAnimation Created twice - duplicate when embbeded in tkinter

I have a troubleing bug that i just could not understands it's origin. Several days of attempts and still no luck.
I'm trying to create a line cursor that correspond to played audio with FuncAnimation and for some reason, the animation is created twice ONLY when the callback (line_select_callback) that activates the function is triggered from RectangleSelector widget after drawing wiith the mouse. when I use a standard TK button to activate the SAME function (line_select_callback), it operates well.
some debugging code with reevant prints is present.
I've created minimal working example.
My guess is it has something to do with the figure that is not attached to the tk window, and is silently activated in addition to the embedded figure, I'm not really sure.
Any help will be very much appreciated, Thanks! :)
import os
import threading
import tkinter as tk
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg)
from matplotlib.widgets import RectangleSelector
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import animation
class LineAnimation:
def __init__(self, fig, ax):
print(' enter LineAnimation ctor')
# Parameters
self.ax = ax
self.fig = fig
self.xdata, self.ydata = [], []
self.ln, = plt.plot([], [], 'ro')
# Print figures list
figures = [manager.canvas.figure
for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
print('figures BEFORE animation: ', figures)
self.animation = animation.FuncAnimation(fig=self.fig,
func=self.update,
init_func=self.init,
frames=np.linspace(0, 2 * np.pi, 128),
interval=25,
blit=True, repeat=False,
cache_frame_data=False)
self.fig.canvas.draw()
# Print figures list
figures = [manager.canvas.figure
for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
print('figures AFTER animation: ', figures, '\n')
def init(self):
# Prints for debugging
print('\nenter init animate')
print('Thread id: ', threading.get_ident())
print('Process id: ', os.getpid(), '\n')
# Init
self.ax.set_xlim(0, 2*np.pi)
self.ax.set_ylim(-1, 1)
return self.ln,
def update(self, frame):
self.xdata.append(frame)
self.ydata.append(np.sin(frame))
self.ln.set_data(self.xdata, self.ydata)
return self.ln,
class Example:
def __init__(self):
# init window
self.root = tk.Tk(className=' Species segmentation')
self.fig, self.ax = plt.subplots()
# init sine audio file
self.fs = 44100
self.dur = 2
self.freq = 440
self.x = np.sin(2*np.pi*np.arange(self.fs*self.dur)*self.freq/self.fs)
# plt.ion()
# Embedd in tk
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root) # A tk.DrawingArea.
self.canvas.draw()
self.canvas.get_tk_widget().grid()
# Plot something
self.N = 100000
self.xp = np.linspace(0, 10, self.N)
self.ax.plot(self.xp, np.sin(2*np.pi*self.xp))
self.ax.set_title(
"Plot for demonstration purpuse")
# init Rectangle Selector
self.RS = RectangleSelector(self.ax, self.line_select_callback,
drawtype='box', useblit=True,
button=[1, 3], # avoid using middle button
minspanx=5, minspany=5,
spancoords='pixels', interactive=True,
rectprops={'facecolor': 'yellow', 'edgecolor': 'black', 'alpha': 0.15, 'fill': True})
self.canvas.draw()
# plt.show()
tk.mainloop()
def line_select_callback(self, eclick, erelease):
print('enter line_select_callback')
self.anim = LineAnimation(
self.fig,
self.ax)
self.fig.canvas.draw()
# plt.show()
Example()
I managed to isolate the cause for this issue: The presence of the
rectangle selector (which uses blitting) and the use of animation (which also uses blitting) on the same axes.
I've managed to create the animation properly, but only when I disabled the rectangle selector
self.RS.set_active(False)
self.RS.update()
self.canvas.flush_events()
and removed his artists (i needed to do that manually in my code) using:
for a in self.RS.artists:
a.set_visible(False)
after that, The animation worked properly.

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()

Python: Animating a vector using mplot3d and animation

I'm trying to make a 3d plot with Matplotlib and the animation package from matplotlib. In addition, the animation should be a part of a Gui generated using PyQt and Qt-Designer. Currently I'm stuck on using the "animation.Funcnimation()" correctly, at least i think so...
So here is my code:
import sys
from PyQt4.uic import loadUiType
from PyQt4 import QtGui
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import animation
import numpy as np
import Quaternion as qt
Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui')
class Kinematic(Ui_MainWindow, QMainWindow):
def __init__(self):
super(Kinematic, self).__init__()
self.setupUi(self)
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111,projection = '3d')
self.fig.tight_layout()
self.ani = animation.FuncAnimation(self.fig, self.update,
init_func=self.setup_plot, blit=True)
self.canvas = FigureCanvas(self.fig)
self.mplvl.addWidget(self.canvas)
self.canvas.draw()
def setup_plot(self):
self.ax.view_init(40, 45)
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
self.ax.set_zlabel('Z')
self.ax.set_xlim3d(-1,1)
self.ax.set_ylim3d(-1,1)
self.ax.set_zlim3d(-1,1)
g_x = np.matrix([[1.0],[0.0],[0.0]])
g_y = np.matrix([[0.0],[1.0],[0.0]])
g_z = np.matrix([[0.0],[0.0],[1.0]])
self.ax.plot([0,g_x[0]], [0,g_x[1]], [0,g_x[2]], label='$X_0$')
self.ax.plot([0,g_y[0]], [0,g_y[1]], [0,g_y[2]], label='$Y_0$')
self.ax.plot([0,g_z[0]], [0,g_z[1]], [0,g_z[2]], label='$Z_0$')
self.vek, = self.ax.plot([0,-1], [0,0], [0,0], label='$g \cdot R$', animated=True)
self.ax.legend(loc='best')
self.ax.scatter(0,0,0, color='k')
return self.vek,
def update(self, i):
b = self.bslider.value() / 100
g = np.matrix([[1.0],[0.0],[0.0]])
q = np.array([0,b,0.5,0])
R = qt.QtoR(q)
x, y, z = R*g
self.vek, = self.ax.plot([0,x], [0,y], [0,z], label='$g \cdot R$', animated=True) #the rotated vector
return self.vek,
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Kinematic()
main.show()
sys.exit(app.exec_())
You won't be able to run it by just copy-paste because you don't have the file "Newsphere.ui" (Line 13) and the Quaternion.py (Line 11). So when I run it, I get the following (actually like I wish!):
Coordinate system
My goal is now to draw a vector (Line 50) and animate it (Line 66) using data which I get from the Gui-slider (Line 58). Can anyone help me with this? I'm stuck with this for days!
Since your problem is with the animation part, below you can see a snippet that animate an arrow that is rotating.
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def data_gen(num):
"""Data generation"""
angle = num * np.pi/36
vx, vy, vz = np.cos(angle), np.sin(angle), 1
ax.cla()
ax.quiver(0, 0, 0, vx, vy, vz, pivot="tail", color="black")
ax.quiver(0, 0, 0, vx, vy, 0, pivot="tail", color="black",
linestyle="dashed")
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-1, 1)
ax.view_init(elev=30, azim=60)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
data_gen(0)
ani = animation.FuncAnimation(fig, data_gen, range(72), blit=False)
plt.show()
The documentation on animations might not be the best. But there are several examples out there, for example, this one animates the Lorenz attractor.
So if someone is interested in a solution of the mentioned problem, here we go: (again it is not a code for copy-paste because of the missing 'Newsphere.ui', but I try to explain the important snippets)
import sys
from PyQt4.uic import loadUiType
from PyQt4 import QtGui
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import animation
import numpy as np
Ui_MainWindow, QMainWindow = loadUiType('Newsphere.ui')
class Kinematic(Ui_MainWindow, QMainWindow):
def __init__(self):
super(Kinematic, self).__init__()
self.setupUi(self)
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111,projection = '3d')
self.fig.tight_layout()
self.ax.view_init(40, -45)
# dashed coordinate system
self.ax.plot([0,1], [0,0], [0,0], label='$X_0$', linestyle="dashed")
self.ax.plot([0,0], [0,-1], [0,0], label='$Y_0$', linestyle="dashed")
self.ax.plot([0,0], [0,0], [0,1], label='$Z_0$', linestyle="dashed")
self.ax.set_xlim3d(-1,1)
self.ax.set_ylim3d(-1,1)
self.ax.set_zlim3d(-1,1)
self.ax.set_xlabel('X')
self.ax.set_ylabel('Y')
self.ax.set_zlabel('Z')
self.ax.scatter(0,0,0, color='k') # black origin dot
self.canvas = FigureCanvas(self.fig)
self.mplvl.addWidget(self.canvas)
self.ani = animation.FuncAnimation(self.fig, self.data_gen, init_func=self.setup_plot, blit=True)
def setup_plot(self):
self.ax.legend(loc='best')
self.vek = self.ax.quiver(0, 0, 0, 0, 0, 0, label='$g \cdot R$', pivot="tail", color="black")
return self.vek,
def data_gen(self, i):
b = self.bslider.value() / 100
vx, vy, vz = np.cos(b), np.sin(b), 0
self.vek = self.ax.quiver(0, 0, 0, vx, vy, vz, label='$g \cdot R$', pivot="tail", color="black")
self.canvas.draw()
return self.vek,
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Kinematic()
main.show()
sys.exit(app.exec_())
By running the code I get
(These are two pictures combined in one showing the same process)
I generated a GUI file named Newsphere.ui following this tutorial. Basically it contains just a Widget, a QSlider and a QSpinBox. The Widget has the layout-name "mplvl", which occures in line 41. This adds the generated figure to the widget (I think so...). The QSlider is connected with the QSpinBox (done in QtDesigner) and has the name "bslider", line 55. So in this line the slider-value gets divided by 100 because I didn't found a slider that generates me a float-value. The key-line for me was line 61, where the canvas is drawn. Now the animation.FuncAnimation (line 43) draws a new vector when I change the slider value, compare the pics. Also it is important to draw the changing vector as a ax.quiver and not as a ax.plot like in my previous attempt.
If there are questions or suggestions for improvement please ask/post.

Embedding a live updating matplotlib graph in wxpython

I am a newbie into wx python. The following is the code to plot live graph from a text file which can be updated live. Can anybody please help me to embed this code into a wx frame. I desperately need it for my project.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
fig= plt.figure()
ax1=fig.add_subplot(1,1,1)
def animate(i):
pullData= open('C:/test/e.txt','r').read()
dataArray= pullData.split('\n')
xar=[]
yar=[]
for eachLine in dataArray:
if len(eachLine)>1:
x,y= eachLine.split(',')
xar.append(int(x))
yar.append(int(y))
ax1.clear()
ax1.plot(xar,yar)
ani= animation.FuncAnimation(fig,animate, interval=1000)
plt.show()
Here I'll give you an example but you need to change the plotting part for your needs:
import wx
import numpy as np
import matplotlib.figure as mfigure
import matplotlib.animation as manim
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
class MyFrame(wx.Frame):
def __init__(self):
super(MyFrame,self).__init__(None, wx.ID_ANY, size=(800, 600))
self.fig = mfigure.Figure()
self.ax = self.fig.add_subplot(111)
self.canv = FigureCanvasWxAgg(self, wx.ID_ANY, self.fig)
self.values = []
self.animator = manim.FuncAnimation(self.fig,self.anim, interval=1000)
def anim(self,i):
if i%10 == 0:
self.values = []
else:
self.values.append(np.random.rand())
self.ax.clear()
self.ax.set_xlim([0,10])
self.ax.set_ylim([0,1])
return self.ax.plot(np.arange(1,i%10+1),self.values,'d-')
wxa = wx.PySimpleApp()
w = MyFrame()
w.Show(True)
wxa.MainLoop()

Categories

Resources