Show elapsed time(frame number) in matplotlib - python

I want to show the elapsed time in my animation in matplotlib. I created a text instance, but when I am trying to update it(based on the frame number) nothing changes. Here is part of the code:
fig = plt.figure()
ax = plt.axes(xlim =(-4E8,4E8), ylim= (-4E8,4E8))
time_text = ax.text(0.05, 0.95,'',horizontalalignment='left',verticalalignment='top', transform=ax.transAxes)
def init():
for line, pt in zip(lines, pts):
line.set_data([], [])
pt.set_data([], [])
time_text.set_text('hello')
return lines + pts
return time_text
def animate(i):
i = (10 * i) % data.shape[1]
#update lines and points here
for line, pt, dt in zip(lines,pts, data):
x, y, z = dt[:i].T
line.set_data(x, y)
pt.set_data(x[-1:], y[-1:])
time_text.set_text('time = %.1d' % i) #<<<<<Here. This doesn't work
return lines + pts
return time_text
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=700, interval=1, blit=True)
plt.show()
The time depend on the frame number so I tried this:
time_text.set_text('time = %.1d' % i)
but it doesn't get updated(stays "hello").
Any ideas? What am I doing wrong?

Change this:
return lines + pts
return time_text
to this:
return lines + pts + [time_txt,]
The second return is never getting hit, so it doesn't know to update that artist.

Related

How to allow python code to continue after a matplotlib graph is executed so that a loop can feed realtime data into the matplotlib graph

Hello i'm making an application that allows you to effectively create a youtube poll by counting certain responses and then displaying the results realtime in a graph. My current problem is that my code won't start to loop through youtube chat until i've closed the graph, and if i have the graph appear after the loop then there is no information for the graph to update in real-time as the loop will have stopped. how do i get the graph to appear and then for the loop to go through youtube chat, or is there a more elegant way of achieving the same objective?
def animate(i):
x.append(next(index))
y1.append(numprompt1)
y2.append(numprompt2)
plt.cla()
plt.plot(x, numprompt1, label ='prompt 1')
plt.plot(x, numprompt2, label ='prompt 2')
plt.legend(loc='upper left')
FuncAnimation(plt.gcf(), animate, interval=1000)
#livechat code
while livechat.is_alive():
try:
chatdata = livechat.get()
for c in chatdata.items:
print(f"{c.datetime} [{c.author.name}]- {c.message}")
message = str({c.message})
if prompt1 in message:
numprompt1 += 1
print (prompt1, "has been said", numprompt1, "times")
elif prompt2 in message:
numprompt2 += 1
print (prompt2, "has been said", numprompt2, "times")
chatdata.tick()
except KeyboardInterrupt:
livechat.terminate()
break
You can try this example:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
y1 = []
y2 = []
numprompt1 = 0
numprompt2 = 0
fig=plt.figure()
ax = fig.add_subplot(1,1,1)
def animate(i):
global y1
global y2
global numprompt1
global numprompt2
a = ax.clear()
numprompt1 += 1.1
numprompt2 += 1.2
y1.append(numprompt1)
y2.append(numprompt2)
x = np.arange(len(y1))
a = ax.plot(x, y1, color = 'green', label = 'prompt 1')
a = ax.plot(x, y2, color = 'red', label = 'prompt 2')
a = ax.legend()
ani = animation.FuncAnimation(fig, animate, interval=1000)
a = plt.show()

frames overlap in python3 matplotlib animation

I'm getting confused with the FuncAnimation method. I was trying to show real-time sensor data on my raspberry pi using GPIOs. I set the x range to 100. When my data frames are over 100, I will only pick the recent 100 frames to show. At the beginning when the number of frames is less than 100, the pic shows correctly. The problem is that when frames are over 100, the later pic will overlap with the former pic and the graph just mess up. Here's the beginning graph and the overlap graph.
enter image description here
enter image description here
I checked the matplotlib API and I changed the param "blit" from True to False.
The overlap disappears but the frame rate is becoming too low.
Since I also used FuncAnimation with blit set True in another code and the overlap didn't appear, I guess there something else wrong.
The overlap code is below:
max_limit = 20
fig, ax = plt.subplots(light_num, 1)
data = []
lines = []
for i in range(light_num):
data.append([])
ln_one_light, = ax[i].plot([], [], 'r-')
lines.append(ln_one_light)
def init():
for i in range(light_num):
ax[i].set_xlim(0, max_limit)
ax[i].set_ylim(lower_bound, upper_bound)
return lines
def update(frame):
# print(frame)
global data
for i in range(light_num):
data[i].append(frame[i])
if len(data[i]) > max_limit:
data[i] = data[i][1:]
time_axis = np.arange(len(data[i]))
for i in range(light_num):
# print(time_axis, data[i])
lines[i].set_data(time_axis, data[i])
return lines
def gen_function():
res_array = []
output_string = ''
for i in range(light_num):
val = GPIO.input(light_io_array[i])
res_array.append(val)
output_string = output_string + str(val) + ' '
# print(res_array)
lights_data_writer.update_data(output_string)
yield res_array
ani = FuncAnimation(fig, update, frames=gen_function, interval = 500, repeat = True,
init_func=init, blit=True)
plt.show()
The code that I used with blit set as True, but no overlap happens:
fig, ax = plt.subplots(3, 1)
data_x, data_y, data_z = [], [], []
ln_x, = ax[0].plot([], [], 'r-')
ln_y, = ax[1].plot([], [], 'r-')
ln_z, = ax[2].plot([], [], 'r-')
def init():
for i in range(3):
ax[i].set_xlim(0, 100)
ax[i].set_ylim(-5, 5)
return (ln_x, ln_y, ln_z)
def update(frame):
(x, y, z) = frame
global data_x, data_y, data_z
data_x.append(x)
data_y.append(y)
data_z.append(z)
if len(data_x) > 100:
data_x = data_x[1:]
data_y = data_y[1:]
data_z = data_z[1:]
time_xyz = np.arange(len(data_x))
# print(time_xyz, data_x)
ln_x.set_data(time_xyz, data_x)
ln_y.set_data(time_xyz, data_y)
ln_z.set_data(time_xyz, data_z)
return (ln_x, ln_y, ln_z)
def gen_function():
while True:
(x, y, z) = adxl345.getAxes()
output_string = 'acc '+str(x)+' '+str(y)+' '+str(z)
imu_data_writer.update_data(output_string)
yield (x, y, z)
ani = FuncAnimation(fig, update, frames=gen_function, interval = 100,
init_func=init, blit=True)
plt.show()
Thank you for anyone who can have a look and check out what I have done wrong.

List index out of range when trying to generate gif from plot

I am trying to generate a GIF for an image I created. However, I am encountering this error message
MovieWriter imagemagick unavailable; trying to use <class 'matplotlib.animation.PillowWriter'> instead.
~\Anaconda3\lib\site-packages\matplotlib\animation.py in finish(self)
573
574 def finish(self):
--> 575 self._frames[0].save(
576 self._outfile, save_all=True, append_images=self._frames[1:],
577 duration=int(1000 / self.fps), loop=0)
IndexError: list index out of range
Here is my code
from matplotlib import animation, rc
#Set the plot up,
fig = plt.figure()
ax = plt.axes()
plt.title('Sale Price vs Living Area')
plt.xlabel('Living Area in square feet (normalised)')
plt.ylabel('Sale Price ($)')
plt.scatter(x[:,1], y, color='red')
line, = ax.plot([], [], lw=2)
annotation = ax.text(-1, 700000, '')
annotation.set_animated(True)
plt.close()
#Generate the animation data,
def init():
line.set_data([], [])
annotation.set_text('')
return line, annotation
def animate(i):
x = np.linspace(-5, 20, 1000)
y = past_thetas[i][1]*x + past_thetas[i][0]
line.set_data(x, y)
annotation.set_text('Cost = %.2f e10' % (past_costs[i]/10000000000))
return line, annotation
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=300, interval=0, blit=True)
anim.save('animation.gif', writer='imagemagick', fps = 30)
This is a sample of what I have in past_thetas
[array([0.61279458, 0.07571964]),
array([5402.42825457, 2578.99911609]),
array([10750.22555995, 5132.1344718 ]),
array([16044.54489229, 7659.73965526]),
array([21285.9210313 , 10162.06995636]),
array([26474.88340892, 12639.37811224]),
array([31611.95616276, 15091.91433277]),
array([36697.65818907, 17519.92632585]),
array([41732.50319511, 19923.65932241]),
array([46716.99975109, 22303.35610116]),
array([51651.65134151, 24659.25701318]),
array([56536.95641603, 26991.60000612]),
array([61373.4084398 , 29300.62064827]),
array([66161.49594334, 31586.55215234]),
array([70901.70257184, 33849.62539904]),
array([75594.50713405, 36090.06896035]),
array([80240.38365065, 38308.10912268]),
array([84839.80140207, 40503.96990963]),
array([89393.22497599, 42677.87310471]),
array([93901.11431416, 44830.03827366]),
array([98363.92475895, 46960.6827867 ]),
array([102782.10709929, 49070.02184043]),
array([107156.10761624, 51158.26847958]),
array([111486.36812801, 53225.63361853]),
array([115773.32603466, 55272.32606263]),
array([120017.41436225, 57298.55252927]),
array([124219.06180656, 59304.51766874]),
array([128378.69277642, 61290.42408495]),
array([132496.72743659, 63256.47235584]),
array([136573.58175016, 65202.86105368]),
array([140609.66752059, 67129.78676511]),
array([144605.39243332, 69037.44411098]),
array([148561.16009692, 70926.02576604]),
array([152477.37008388, 72795.72247837]),
array([156354.41797098, 74646.72308865]),
array([160192.6953792 , 76479.21454926]),
array([163992.59001334, 78293.38194312]),
array([167754.48570114, 80089.40850244]),
array([171478.76243206, 81867.47562715]),
array([175165.79639568, 83627.76290331]),
array([178815.96001965, 85370.44812116]),
array([182429.62200739, 87095.70729314])]

My Matplotlib subplot title removes itself

When I run my code I create a figure, then I create a subplot in that figure. Then when I try to add a title to it using ax.set_title("title") it sometimes shows up for a split second then goes away. I have tried using plot.title aswell with no luck.
I tried recreating the error in a small example but for some reason it worked just fine there, so here is the entire source code of the code.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.style as style
import plotgen
from matplotlib.widgets import Button
class plotWindow():
def __init__(self):
style.use("bmh")
self.dp = 30
self.fig = plt.figure()
self.ax = self.fig.add_subplot(1, 1, 1, label="ax1")
self.cax = 1
self.maxax = 2
self.minax = 1
plotgen.clear("plot1.txt")
plotgen.clear("plot2.txt")
axnext = plt.axes([0.80, 0.01, 0.06, 0.06])
axprev = plt.axes([0.73, 0.01, 0.06, 0.06])
bnext = Button(axnext, 'Next >')
bnext.on_clicked(self.changePlotNext)
bprev = Button(axprev, "< Previous")
bprev.on_clicked(self.changePlotPrev)
ani = animation.FuncAnimation(self.fig, self.animate, interval=500)
plt.show()
def changePlotNext(self, i):
if self.cax < self.maxax:
self.cax += 1
self.ax.set_title("Pump " + str(self.cax))
def changePlotPrev(self, i):
if self.cax > self.minax:
self.cax -= 1
self.ax.set_title("Pump " + str(self.cax))
def animate(self, i):
if self.cax == 1:
plotgen.generate("plot1.txt")
graph_data = open('plot1.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x, y = line.split(',')
xs.append(x)
ys.append(float(y))
self.ax.clear()
lx = len(xs)
ly = len(ys)
if len(xs) < self.dp:
pxs = xs
pys = ys
else:
pxs = xs[(lx - (self.dp - 1)):(lx - 1)]
pys = ys[(ly - (self.dp - 1)):(ly - 1)]
self.ax.plot(pxs, pys, "r")
elif self.cax == 2:
plotgen.generate("plot2.txt")
graph_data = open('plot2.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x, y = line.split(',')
xs.append(x)
ys.append(float(y))
self.ax.clear()
lx = len(xs)
ly = len(ys)
if len(xs) <= self.dp:
pxs = xs
pys = ys
else:
pxs = xs[(lx - (self.dp - 1)):(lx - 1)]
pys = ys[(ly - (self.dp - 1)):(ly - 1)]
self.ax.plot(pxs, pys)
plotWindow()
As you can see in my changePlotNext and changePlotPrev functions I'm trying to change the title. Sometimes they display for a split second when I change, but then it goes away. And I am very aware that I have not set a title to display before I change the plot.
In animate, you have self.ax.clear(), which is removing all artists, texts, etc. on the Axes, including the title.
A simple option, then, is to reset the title after you clear the axes. So if you add:
self.ax.set_title("Pump " + str(self.cax))
in both places, immediately after you call self.ax.clear(), your titles will still be shown.
Another option would be to stop clearing the axes, but just remove the items you need to remove. I think this is just the lines you have plotted? So, for example, you could remove the call to self.ax.clear(), and add:
for line in self.ax.lines:
line.remove()
in its place. That will remove just the plotted line, but retain the title.

Getting matplotlib animation to work

Hi I'm having trouble in getting matplotlib animation to work
The idea is to animate throughout a few lists and images.
a[0] is basically time points/images to plot/imshow
"timepoints[a[0].astype(np.int)][:i]/60" is simply the indexed "real time" to be in the x axis
May anyone give me some hints?
Appreciated
def draw_plot(resolution,timepoints,a,ts_g,ts_r,contrast):
def animate(i):
#~ ax.cla()
#~ ax2.cla()
#~ ax3.cla()
#~ ax4.cla()
print "ax"
ax.errorbar(timepoints[a[0].astype(np.int)][:i]/60,list(a[1][0])[:i], yerr=list(a[4][0])[:i], fmt='-o',color='green')
ax.errorbar(timepoints[a[0].astype(np.int)][:i]/60,list(a[1][1])[:i], yerr=list(a[4][1])[:i], fmt='-o',color='red')
ax.axis([0,timepoints[a[0].astype(np.int)][-1]/60,np.min(np.concatenate((a[1][0],a[1][1])))*0.75,np.max(np.concatenate((a[1][0],a[1][1])))*1.3])
ax.set_autoscale_on(False)
print "ax2"
ax2.plot(timepoints[a[0].astype(np.int)][:i]/60,list(a[2][0])[:i],color='green')
ax2.plot(timepoints[a[0].astype(np.int)][:i]/60,list(a[2][1])[:i],color='red')
ax2.axis([0,timepoints[a[0].astype(np.int)][-1]/60,np.min(np.concatenate((a[2][0],a[2][1])))*0.75,np.max(np.concatenate((a[2][0],a[2][1])))*1.3])
ax2.set_autoscale_on(False)
j = int(a[0][i]-1)
r = ts_r[j]#.T
g = ts_g[j]#.T
max_ = contrast[3]
min_ = contrast[2] #~
r[r>max_]=max_
r[r<min_]=min_
r -= min_
r *= _16bit/(max_-min_)#r.max()
max_ = contrast[1]
min_ = contrast[0]
g[g>max_]=max_
g[g<min_]=min_
g -= min_
g *= _16bit/(max_-min_)#r.max()
#~
g_16 = g
r = (r*ratio).astype(np.uint8)
g = (g*ratio).astype(np.uint8)
b = np.zeros(r.shape).astype(np.uint8)
centered = np.dstack((r,g,b)).astype(np.uint8)
#~ aa = np.dstack((np.zeros(ts[0].shape).T,ts[j].T,np.zeros(ts[0].shape)))
print "ax3"
ax3.imshow(centered)
ax3.plot(list(a[5][0]/resolution)[:i],list(512-a[5][1]/resolution)[:i],color='blue')
ax3.axis([0,512,512,0])
print "ax4"
ax4.imshow(centered)
x = int (list(a[5][0]/resolution)[i])
y = int (list(512-a[5][1]/resolution)[i])
#~ ax4.axis([512,0,512,0])
ax4.axis([x-10,x+10,y-10,y+10])
ax4.get_xaxis().set_visible(False)
ax4.get_yaxis().set_visible(False)
print "ax5"
ax5.imshow(g_16,cmap='gray')
#~ x = int (list(a[5][0]/resolution)[i])
#~ y = int (list(512-a[5][1]/resolution)[i])
#~ ax4.axis([512,0,512,0])
ax5.axis([x-10,x+10,y-10,y+10])
ax5.get_xaxis().set_visible(False)
ax5.get_yaxis().set_visible(False)
plt.draw()
fig = plt.figure()
ax = plt.subplot2grid((2,5), (0,0),colspan=2)
ax2 = plt.subplot2grid((2,5), (1,0),colspan=2)
ax3 = plt.subplot2grid((2,5), (0, 2), colspan=2,rowspan=2)
ax4 = plt.subplot2grid((2,5), (0,4))
ax5 = plt.subplot2grid((2,5), (1, 4))
line, = ax.plot([], [], lw=2)
line2, = ax2.plot([], [], lw=2)
ani = animation.FuncAnimation(fig, animate, frames= len(a[0]), interval=20000,repeat=False,blit=True)
plt.show()
Alright, like this it works.
However:
1- I can't return the list with several axes/lines (lines = [] ) I have to return each one individually (errorline_g, etc, etc).It works with normal ax.plots, so I don't know why errorbars can't do the same.
same with Vertical bars. I had to use errorline_g, ( bottomsg,topsg), (vertsg, )= ax.errorbar([],[],yerr=1,fmt='-o',color='green')
If I don't unpack the tuple at declaration if I would try to return vertsg or vertsg[0] it doesn't work.
def draw_plot(resolution,timepoints,a,ts_g,ts_r,contrast,csvfile):
fig = plt.figure()
ax = plt.subplot2grid((2,5), (0,0),colspan=2)
ax2 = plt.subplot2grid((2,5), (1,0),colspan=2)
ax3 = plt.subplot2grid((2,5), (0, 2), colspan=2,rowspan=2)
ax4 = plt.subplot2grid((2,5), (0,4))
ax5 = plt.subplot2grid((2,5), (1, 4))
ax.axis([0,(timepoints[a[0].astype(np.int)-1][-1]/60)+5,np.min(np.concatenate((a[1][0],a[1][1])))*0.75,np.max(np.concatenate((a[1][0],a[1][1])))*1.3])
ax.set_autoscale_on(False)
ax2.axis([0,(timepoints[a[0].astype(np.int)-1][-1]/60)+5,np.min(np.concatenate((a[2][0],a[2][1])))*0.75,np.max(np.concatenate((a[2][0],a[2][1])))*1.3])
ax2.set_autoscale_on(False)
#~ ax3.axis([0,512,512,0])
ax3.get_yaxis().set_visible(False)
ax4.get_xaxis().set_visible(False)
ax4.get_yaxis().set_visible(False)
ax5.get_xaxis().set_visible(False)
ax5.get_yaxis().set_visible(False)
errorline_g, ( bottomsg,topsg), (vertsg, )= ax.errorbar([],[],yerr=1,fmt='-o',color='green')
errorline_r, ( bottomsr,topsr), (vertsr, ) = ax.errorbar([],[],yerr=1,fmt='-o',color='red')
lines = []
lines += ax2.plot([],[], color='green', lw=2)
lines += ax2.plot([],[], color='red', lw=2)
lines += ax3.plot([],[],color='blue')
def animate(i=0):
#~ ax.cla()
#~ ax2.cla()
#~ ax3.cla()
#~ ax4.cla()
x = timepoints[a[0].astype(np.int)][:i+1]/60
y = list(a[1][0])[:i+1]
g_berr = np.array(a[1][0])[:i+1]+np.array(a[4][0])[:i+1]
g_terr = np.array(a[1][0])[:i+1]-np.array(a[4][0])[:i+1]
r_berr =np.array(a[1][1])[:i+1]+np.array(a[4][1])[:i+1]
r_terr =np.array(a[1][1])[:i+1]-np.array(a[4][1])[:i+1]
errorline_g.set_data(x,y)
bottomsg.set_data(x,g_berr)
topsg.set_data(x,g_terr)
vertsg.set_segments(zip(zip(x,g_terr),zip(x,g_berr)))
#~ ax.errorbar(timepoints[a[0].astype(np.int)][:i]/60,list(a[1][1])[:i], yerr=list(a[4][1])[:i], fmt='-o',color='red')
ax.fill_between(x, g_berr, g_terr,
alpha=0.05, edgecolor='green', facecolor='green')
#~ print errorline_g
y = list(a[1][1])[:i+1]
errorline_r.set_data(x,y)
bottomsr.set_data(x,r_berr)
topsr.set_data(x,r_terr)
ax.fill_between(x, r_berr, r_terr,
alpha=0.08, edgecolor='red', facecolor='red')
vertsr.set_segments(zip(zip(x,r_terr),zip(x,r_berr)))
lines[0].set_data(timepoints[a[0].astype(np.int)][:i+1]/60,list(a[2][0])[:i+1])
lines[1].set_data(timepoints[a[0].astype(np.int)][:i+1]/60,list(a[2][1])[:i+1])
j = int(a[0][i]-1)
r = ts_r[j]#.T
g = ts_g[j]#.T
max_ = contrast[3]
min_ = contrast[2] #~
r[r>max_]=max_
r[r<min_]=min_
r -= min_
r *= _16bit/(max_-min_)#r.max()
max_ = contrast[1]
min_ = contrast[0]
g[g>max_]=max_
g[g<min_]=min_
g -= min_
g *= _16bit/(max_-min_)#r.max()
g_16 = g
r = (r*ratio).astype(np.uint8)
g = (g*ratio).astype(np.uint8)
b = np.zeros(r.shape).astype(np.uint8)
centered = np.dstack((r,g,b)).astype(np.uint8)
ax3.imshow(centered)
lines[2].set_data(list(a[5][0]/resolution)[:i],list(512-a[5][1]/resolution)[:i])
#~ ax3.axis([0,512,512,0])
ax4.imshow(centered)
x = int (list(a[5][0]/resolution)[i])
y = int (list(512-a[5][1]/resolution)[i])
#~#
ax4.axis([x-10,x+10,y-10,y+10])
ax5.imshow(g_16,cmap='gray')
ax5.axis([x-10,x+10,y-10,y+10])
#~ plt.draw()
return errorline_g, errorline_r, lines[0], lines[1],lines[2],bottomsg,topsg,bottomsr,topsr,ax,ax2,ax3,ax4,ax5,vertsg
def init():
errorline_g.set_data([],[])
errorline_r.set_data([],[])
for line in lines:
line.set_data([],[])
#~ lines[0].set_data([],[])
#~ lines[1].set_data([],[])
ax3.imshow(np.zeros(ts_r[0].shape))
ax4.imshow(np.zeros(ts_r[0].shape))
ax5.imshow(np.zeros(ts_r[0].shape))
return errorline_g, errorline_r, lines[0], lines[1], lines[2],ax,ax2,ax3,ax4,ax5
ani = animation.FuncAnimation(fig, animate, init_func=init, frames= len(a[0]), interval=500,repeat=False,blit=True)
plt.show()
#~ ani.save('./mp4/'+csvfile.strip('.csv').strip('./')+".mp4")
plt.close()

Categories