Matplotlib FuncAnimation only draws one frame - python

I am trying to do an animation using the FuncAnimation module, but my code only produces one frame and then stops. It seems like it doesn't realize what it needs to update. Can you help me what went wrong?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(0,2*np.pi,100)
def animate(i):
PLOT.set_data(x[i], np.sin(x[i]))
print("test")
return PLOT,
fig = plt.figure()
sub = fig.add_subplot(111, xlim=(x[0], x[-1]), ylim=(-1, 1))
PLOT, = sub.plot([],[])
animation.FuncAnimation(fig, animate, frames=len(x), interval=10, blit=True)
plt.show()

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(0,2*np.pi,100)
fig = plt.figure()
sub = fig.add_subplot(111, xlim=(x[0], x[-1]), ylim=(-1, 1))
PLOT, = sub.plot([],[])
def animate(i):
PLOT.set_data(x[:i], np.sin(x[:i]))
# print("test")
return PLOT,
ani = animation.FuncAnimation(fig, animate, frames=len(x), interval=10, blit=True)
plt.show()
You need to keep a reference to the animation object around, otherwise it gets garbage collected and it's timer goes away.
There is an open issue to attach a hard-ref to the animation to the underlying Figure object.
As written, your code well only plot a single point which won't be visible, I changed it a bit to draw up to current index

Related

Plotting a live graph using matplotlib

I am trying a code to plot a live graph but i always land up with an empty plot. Here is my code :
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
import random
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
y = random.randint(0,100) # generate random data
x = i # set x as iteration number
ax1.clear()
ax1.plot(x, y, 'ro')
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
I get warning but i am using plt.show() to show animation. Not sure what i am doing wrong :
UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. `anim`, that exists until you have outputted the Animation using `plt.show()` or `anim.save()`.
warnings.warn(

How to make jupyter HTML-matplotlib animation with seaborn heatmap?

I trying to make HTML(anim.to_html5_video) animation work in jupyter with seaborn heatmap.
First, I get working working samples from documentation, and make "pure matplotlib" image map animated example, it worked, with small problem ("parasite output" in animation cell)
Then, I tried to make it work with seaborn.heatmap… but failed. Animation looks like "infinite mirror" — obviously something wrong with matplotlib axes/plot composition, but I can't get it.
Common initialization cell:
import pandas as pd
import seaborn as sns
import numpy as np
%matplotlib inline
#%matplotlib notebook # Tried both, not needed for animation.
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML
Animation worked, but "unwanted static output image exists":
fig, ax = plt.subplots()
nx = 50
ny = 50
line2d, = ax.plot([], [], lw=2)
def init():
line2d.set_data([], [])
ax.imshow(np.zeros((nx, ny)))
return (line2d,)
def animate(i):
data = np.random.rand(nx, ny)
ax.set_title('i: ' + str(i))
ax.imshow(data)
return (line2d,)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=10, interval=1000, blit=False)
HTML(anim.to_html5_video())
So, looks that all OK with my jupyter setup (packages, ffmpeg, etc).
But, I cannot get how to make it with seaborn.heatmap:
fig, ax = plt.subplots()
nx = 50
ny = 50
line2d, = ax.plot([], [], lw=2)
ax_global = ax
def init_heatmap():
line2d.set_data([], [])
sns.heatmap(np.zeros((nx, ny)), ax=ax_global)
return (line2d,)
def animate_heatmap(i):
data = np.random.rand(nx, ny)
sns.heatmap(data, ax=ax_global)
ax.set_title('Frame: ' + str(i))
return (line2d,)
anim = animation.FuncAnimation(fig, animate_heatmap, init_func=init_heatmap,
frames=10, interval=1000, blit=True)
HTML(anim.to_html5_video())
Both samples ready to test on github
Of course, I want to see animation with random map and "stable heat-axes"
but get this
https://vimeo.com/298786185/
You can toggle the "colorbar". From the Seaborn.heatmap documentation, you need to change sns.heatmap(data, ax=ax_global) to sns.heatmap(data, ax=ax_global, cbar=False) and also do the same inside the init_heatmap().

Not able to plot real time graph using matplotlib

I have written the following code with the help of online search. My intention here is to get a real time graph with time on x axis and some randomly generated value on y axis
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
xar = []
yar = []
x,y = time.time(), np.random.rand()
xar.append(x)
yar.append(y)
ax1.clear()
ax1.plot(xar,yar)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
With the above code I just see the range of y axis changing continuously and the graph will not appear in the figure.
The problem is that you never update xvar and yvar. You can do that by moving the definitions of the lists outside the definition of animate.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
xar = []
yar = []
def animate(i):
x,y = time.time(), np.random.rand()
xar.append(x)
yar.append(y)
ax1.clear()
ax1.plot(xar,yar)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()

How to make a Matplotlib animated violinplot?

I am trying to animate a violinplot, so I have started off with something I think should be very basic, but it is not working. I think the problem is that violinplot doesn't accept set_data, but I don't otherwise know how to pass the changing data to violinplot. For this example I would like a plot where the mean slowly shifts to higher values. If I am barking up the wrong tree, please advise on a code which does work to animate violinplot.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
data = np.random.rand(100)
def animate(i):
v.set_data(data+i) # update the data
return v
v = ax.violinplot([])
ax.set_ylim(0,200)
v_ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),
interval=50, blit=True)
Indeed, there is no set_data method for the violinplot. The reason is probably, that there is a lot of calculations going on in the background when creating such a plot and it consists of a lot of different elements, which are hard to update.
The easiest option would be to simply redraw the violin plot and not use blitting.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
data = np.random.normal(loc=25, scale=20, size=100)
def animate(i, data):
ax.clear()
ax.set_xlim(0,2)
ax.set_ylim(0,200)
data[:20] = np.random.normal(loc=25+i, scale=20, size=20)
np.random.shuffle(data)
ax.violinplot(data)
animate(0)
v_ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),
fargs=(data,), interval=50, blit=False)
plt.show()

How to update tick labels in animated matplotlib graph

How can I get the tick labels to update once changed in an animated graph?
Here is just a simple example of what I need. I realize I can set blit=False and have it work, however the project I am working on requires blit=True for performance reasons.
import matplotlib
matplotlib.use('Qt4Agg')
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
import time
fig, ax = plt.subplots()
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))
def animate(i):
line.set_ydata(np.sin(x + i/10.0))
if i > 30:
ax.tick_params(axis='y', colors='red') ### How do I get my graph to reflect this change?
return line,
def init():
line.set_ydata(np.ma.array(x, mask=True))
return line,
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init,
interval=100, blit=True)
plt.show()
I got it working with the monkey patch suggested in this post.
Hope this works for wandering souls (like me) that spent A LOT of time trying to solve this problem.

Categories