Matplotlib animate data in a dataframe using FuncAnimation command in matplotlib - python

I have data saved in a dataframe format (xarray, similar to Pandas), and I want it to be animated with pcolormesh.
import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
graph_data = mytest.TMP_P0_L1_GLL0[i]
ax1.pcolormesh(graph_data)
FuncAnimation(plt,animate,frames=100)
which doesn't work for some reason (there is no error but when I show fig it is not animating).
the way the data is laid out is that pcolormesh(mytest.TMP_P0_L1_GLL0[0]) will output a quadmesh, pcolormesh(mytest.TMP_P0_L1_GLL0[1]) will output a slightly different quadmesh...etc
Thanks for your help!

The signature of FuncAnimation is FuncAnimation(fig, func, ...). Instead of the pyplot module you need to supply the figure to animate as first argument.
Further, you need to retain a reference to the animation class, ani = FuncAnimation. The following is a minimal example which works fine.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
class test():
TMP_P0_L1_GLL0 = [np.random.rand(5,5) for i in range(100)]
mytest = test()
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
graph_data = mytest.TMP_P0_L1_GLL0[i]
ax1.pcolormesh(graph_data)
ani = FuncAnimation(fig,animate,frames=100)
plt.show()

Related

Why does matplotlib draw `Title` artists over one another in an animation using `FuncAnimation` (but the same doesn't happen with a `plot`)?

Consider the following animation in python written in a file test.py
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
fig, ax = plt.subplots()
title = fig.suptitle("Test _")
p, = ax.plot([0,2], [0,1])
def anim(i):
title.set_text("Test %d" % i)
p.set_data([np.random.rand(),i], [np.random.rand(),i])
ani = FuncAnimation(fig, anim, 10, blit=False)
plt.show()
This works as expected when I run it from the command line python test.py and also from an interactive shell: a line segment with changing start and end point is animated.
Now let's set blit=True
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib as mpl
import numpy as np
import time
fig, ax = plt.subplots()
p, = ax.plot([0,2], [0,1])
def init_func():
return p,
def anim(i):
p.set_data([np.random.rand(),i], [np.random.rand(),i])
return p,
ani = FuncAnimation(fig, anim, 10, blit=True, init_func=init_func)
plt.show()
This also works both on command line and interactive shell.
However, I would like to animate the title of the plot.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib as mpl
import numpy as np
import time
fig, ax = plt.subplots()
title = ax.set_title("Initial Title")
p, = ax.plot([0,2], [0,1])
def init_func():
return p, title
def anim(i):
title.set_text("3D Test %d" % i)
p.set_data([np.random.rand(),i], [np.random.rand(),i])
return p, title
ani = FuncAnimation(fig, anim, 100, blit=True, init_func=init_func)
plt.show()
This almost works but it two things happen:
in interactive shell, the title stays fixed with "Initial Title". It doesn't update
from the command line, the titles do appear and update but they all overlap each other (there is apparently no erasing previous titles when redrawing the new ones).
As you can see, the plot itself doesn't have this issue.
Why does this happen only with the Title artist?
Finally consider the following variant of this code
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib as mpl
import numpy as np
import time
fig, ax = plt.subplots()
title = ax.set_title("50")
p, = ax.plot([0,2], [0,1])
def init_func():
return p,
def anim(i):
title.set_text("3D Test %d" % i)
p.set_data([np.random.rand(),i], [np.random.rand(),i])
return p,
ani = FuncAnimation(fig, anim, 100, blit=True, init_func=init_func)
plt.show()
Here we are calling title.set_text in each update function, but the title artist is not returned so as far as I know FuncAnimation does not consider it as an artist to redraw.
Nonetheless, what happens is that
from the command line the title does get updated but the plot is animated for a few frames and then disappears.
from the interactive shell, the title just stays stuck on the initial title but the plot does work.
What is happening here?

matplotlib animation doesn't animate with imshow

I'm trying to animate a few simple subplots with imshow but there's apparently an issue.
This is a small demo of my problem:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
fig,axs=plt.subplots(2,5,figsize=(10,4))
imgs=[]
for row in axs:
for col in row:
col.set_xlim(4.5,-.5)
col.set_ylim(4.5,-.5)
col.set_xticks([])
col.set_yticks([])
#line A
imgs.append(col.imshow([[]],animated=1))
#freezes the animation([[]] is just a placeholder)
#line B
#imgs.append(col.imshow(np.arange(25).reshape((5,5)),animated=1))
#animation does work if the above line is used instead
def func(frm):
for i in range(10):
imgs[i].set_array(np.arange(25).reshape(5,5)*np.log10(frm+1))
return imgs
anim=animation.FuncAnimation(fig,func,10,interval=100)
plt.show()
If I use line A, the animation freezes as if func is not executed (while actually it is), raising no errors. If line B is used instead, the animation works. Am I missing something about imshow animating?
Animation from multiple imshow can be created by ArtistAnimation object using multiple axes generated by subplots command.
from numpy import random
from matplotlib import animation
import matplotlib.pyplot as plt
img_lst_1 = [random.random((368,1232)) for i in range(10)] # Test data
img_lst_2 = [random.random((368,1232)) for i in range(10)] # Test data
fig, (ax1, ax2) = plt.subplots(2,1)
frames = [] # store generated images
for i in range(len(img_lst_1)):
img1 = ax1.imshow(img_lst_1[i], animated=True)
img2 = ax2.imshow(img_lst_2[i], cmap='gray', animated=True)
frames.append([img1, img2])
ani = animation.ArtistAnimation(fig, frames, interval=500, blit=True,
repeat_delay=1000)
ani.save('movie_example.mp4')
Code output:

Python FuncAnimation not recognizing update

I'm learning how to animate in python for one of my projects and I'm basing my code off of the following example from here.
My adaption of their code goes as follows:
import numpy as np
import h5py, os, glob, sys, time
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def update(i):
for j in np.arange(0,10):
for k in np.arange(0,10):
for channel in ["N","E"]:
x = some_x_value
y = some_y_value
line = plt.loglog(x,y)
ax.set_xlabel(label)
return line, ax
if __name__ == "__main__":
fig, ax = plt.subplots()
anim = FuncAnimation(fig, update, frames=np.arange(0,10), interval=200)
anim.save('Test.gif', dpi=80, writer='imagemagick')
And when I try to run my script I get the following error:
Name Error: name 'update' is not defined.
As I said before, I'm still learning how to animate and don't understand all of what's going on in the code tutorial I found. However, I'm very confused as to why update isn't recognized at all as the way I call update seems to be exactly the same as what's in the tutorial.
import numpy as np
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def update(i, ln):
i = i+1
x = i
y = i ** 2
x_data = ln.get_xdata()
y_data = ln.get_ydata()
ln.set_data(np.concatenate(([x], x_data)),
np.concatenate(([y], y_data)))
return ln
if __name__ == "__main__":
fig, ax = plt.subplots()
ax.set_xlim(1, 10)
ax.set_ylim(1, 100)
line, = ax.loglog([1], [1])
anim = FuncAnimation(fig, update, frames=np.arange(0, 10), interval=200,
fargs=(line, ))
anim.save('Test.gif', dpi=80, writer='imagemagick')
Works as expected. This makes me think that there is some other error in your code which is getting masked.

add_subplot() not working if fig = plt.figure() is in another cell in Ipython Notebook

I ran into a weird problem using matplotlib in Ipython Notebook. Here is the code:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(np.random.randn(10), 'k--')
ax2 = fig.add_subplot(212)
ax2.plot(np.random.randn(10), 'r--')
This works fine and generates an inline figure with two subplots. However, if I put the same code into two cells like this:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax1.plot(np.random.randn(10), 'k--')
ax2 = fig.add_subplot(212)
ax2.plot(np.random.randn(10), 'r--')
Then there is no inline images generated at all.
By default, the inline backend closes a figure after a cell has been fully executed.
You're best approach is to merge those cells.

Improve updated speed in Matplotlib

I'd like to update a matrix text in dynamic by using animation function of matplotlib. But I found that if the data array is too large , the animation will become very very slow. Is there any way to improve it ?
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(figsize=(10,20))
def updatefig(i):
plt.cla()
ax.grid()
data = np.random.rand(50,50)
ax.set_xticks(np.arange(data.shape[1]+1))
ax.set_yticks(np.arange(data.shape[0]+1))
for y in range(data.shape[0]):
for x in range(data.shape[1]):
plt.text(x + 0.5 , y + 0.5, '%.1f' % data[y, x],horizontalalignment='center',verticalalignment='center',color='b',size = 6)
plt.draw()
anim = animation.FuncAnimation(fig, updatefig,interval=50)
plt.show()
Actually, I wants to create a heatmmap plot with data values like below link. But use annotations is the only way i could figure out.
Heamap with values
Find a workaround by import seaborn module.
But how to avoid the graph keep flashing
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
fig, ax = plt.subplots(figsize=(10,20))
sns.set()
def updatefig(i):
plt.clf()
data = np.random.rand(10,10)
sns.heatmap(data, annot=True, linewidths=.5,cbar=False)
anim = animation.FuncAnimation(fig, updatefig,interval=50)
plt.show()

Categories