Animation can only display the firstframe [duplicate] - python

This question already has answers here:
Animation in iPython notebook
(4 answers)
Closed 4 years ago.
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
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))
return line,
def init():
line.set_ydata(np.sin(x))
return line,
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)
plt.show()
I coded in jupyter Notebook,matplotlib's version is 2.2.0 and python's is 2.7.
I tried to display a animation,but the output is only the first frame,a static picture.
I cannot find the error.
This is the static picture:

Jupyter notebooks output pngs which cannot be animated. You can use Javascript to animate a plot in a notebook.
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
from IPython.display import HTML
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))
return line,
def init():
line.set_ydata(np.sin(x))
return line,
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)
HTML(ani.to_jshtml())

Related

Scatter Animation python

I have my data file containing x,y coordinates of a fractal. I want to get a animation of this coordinates.
I have tried this code.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
data1=np.loadtxt('data.txt')
fig = plt.figure()
ax = plt.axes()
scat = ax.scatter([], [])
def init():
scat.set_offsets([])
return scat
def animate(i):
scat.set_offsets(data1)
return scat
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=700, interval=1, blit=True)
plt.show()
Error is 'PathCollection' object is not iterable.
I don't know much, any help will be thankful.

Why simple animation code for my wave function does not work?

I am trying to animate the wave function of electrons in an atom. I wrote the simplest python code following whats given in Matplotlob documentation on animation, but it does not do anything. Can anyone help?
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
import math
angles = (np.linspace(0, 2 * np.pi, 360, endpoint=False))
fig= plt.figure()
ax = fig.add_subplot(111, polar=True)
line1, =ax.plot([],[], 'g-', linewidth=1)
def update(theta):
line1.set_data(angles,energy_band(3, theta, 3))
return line1,
def init():
line1.set_data([],[])
return line1,
def energy_band(wave_number, phase_offset, energy_level):
return [math.sin(2*np.pi/360*i*wave_number+phase_offset*np.pi/360)+energy_level for i in range(360)]
ani = animation.FuncAnimation(fig, update, frames=[i for i in range(0,3600,5)], blit=True, interval=200, init_func=init)
plt.show()
The problem is with your data. Firstly, you must call set_data with single numeric. Secondly, if you divide energy function with 100 you have got data in a good scale to show. Moreover I set limits of axis. Check how I modify your code:
line1, =ax.plot([],[], 'ro')# 'g-', linewidth=1)
def update(theta):
line1.set_data(angles[int(theta)], energy_band(3, theta, 3)[int(theta)]/100)
#line1.set_data(angles,energy_band(3, theta, 3)/100)
return line1,
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
#line1.set_data([],[])
return line1,
Another thing is an interactive mode. It's usually a problem when matplotlib do nothing, especially working with jupyter notebook.
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
matplotlib.interactive(True)
plt.ion()
matplotlib.is_interactive()
The problem is that the data you want to animate lies between 2 and 4, but the polar plot shows only the range between -0.04 and 0.04. This is due to the use of an empty plot for the start. It would require you to set the limits manually. For example,
ax.set_rlim(0,5)
This is the only addition needed for your code to work.
However, one might optimize a bit more, e.g. use numpy throughout and reuse existing variables,
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
angles = (np.linspace(0, 2 * np.pi, 360, endpoint=False))
fig= plt.figure()
ax = fig.add_subplot(111, polar=True)
line1, =ax.plot([],[], 'g-', linewidth=1)
def update(theta):
line1.set_data(angles,energy_band(3, theta, 3))
return line1,
def init():
line1.set_data([],[])
ax.set_rlim(0,5)
return line1,
def energy_band(wave_number, phase_offset, energy_level):
return np.sin(angles*wave_number+phase_offset*np.pi/360)+energy_level
ani = animation.FuncAnimation(fig, update, frames=np.arange(0,3600,5),
blit=True, interval=200, init_func=init)
plt.show()

Why does the output of animation.FuncAnimation have to be bound to a name? [duplicate]

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

How to embed matplotlib funcAnimation object within PyQT GUI [duplicate]

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

How to animate a seaborn's heatmap or correlation matrix?

I am relatively new to python (coming from Matlab). As one project, I am trying to create an animated plot of a correlation matrix over time. To make the plots nice, I am trying seaborn. I struggled to get the animation done at all (having issues with Matplotlib backend on a mac), but a very basic animation now works using this code from the web:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
nx = 50
ny = 50
fig = plt.figure()
data = np.random.rand(nx, ny)
im = plt.imshow(data)
def init():
im.set_data(np.zeros((nx, ny)))
def animate(i):
#xi = i // ny
#yi = i % ny
data = np.random.rand(nx, ny)
im.set_data(data)
return im
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=50, repeat = False)
Now, I was trying to adapt this to seaborn, but did not succeed. It seems that seaborn works on subplots and to animate these was far harder. The best thing I got once was a kind of recursive plot, where seaborn.heatmaps were plotted on top of each other. Also, the im.set_data method was not available.
Any suggestions are highly appreciated.
I replaced plt.imshow (casting data via set_data didn't work) with seaborn.heatmap.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import animation
fig = plt.figure()
data = np.random.rand(10, 10)
sns.heatmap(data, vmax=.8, square=True)
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, square=True, cbar=False)
def animate(i):
data = np.random.rand(10, 10)
sns.heatmap(data, vmax=.8, square=True, cbar=False)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=20, repeat = False)
This creates the recursive plot I struggled with.
In addition to your answer above, I wanted to do this from a list of dataframes and save as a gif. So, using your code and Serenity's answer to Matplotlib animation iterating over list of pandas dataframes
fig = plt.figure()
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, square=True, cbar=False)
def animate(i):
data = data_list[i]
sns.heatmap(data, vmax=.8, square=True, cbar=False)
data_list = []
for j in range(20):
data = np.random.rand(10, 10)
data_list.append(data)
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=20, repeat = False)
savefile = r"test3.gif"
pillowwriter = animation.PillowWriter(fps=20)
anim.save(savefile, writer=pillowwriter)
plt.show()
Thanks!!!
Here's a complete example (tested with Matplotlib 3.0.3).
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
def animate_heat_map():
fig = plt.figure()
nx = ny = 20
data = np.random.rand(nx, ny)
ax = sns.heatmap(data, vmin=0, vmax=1)
def init():
plt.clf()
ax = sns.heatmap(data, vmin=0, vmax=1)
def animate(i):
plt.clf()
data = np.random.rand(nx, ny)
ax = sns.heatmap(data, vmin=0, vmax=1)
anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1000)
plt.show()
if __name__ == "__main__":
animate_heat_map()
Based on the answer of r schmaelzle I created animated seaborn heatmap with annotaion.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import animation
class Heatmap:
def __init__(self):
self.fig, self.ax = plt.subplots()
self.anim = None
def animate(self):
def init():
sns.heatmap(np.zeros((10, 10)), vmax=.8, ax=self.ax)
def animate(i):
self.ax.texts = []
sns.heatmap(np.random.rand(10, 10), annot=True, vmax=.8, cbar=False, ax=self.ax)
self.anim = animation.FuncAnimation(self.fig, animate, init_func=init, frames=20, repeat=False)
if __name__ == '__main__':
hm = Heatmap()
hm.animate()
The trick to update annotations is to make empty ax.texts = [].
I hope it will help others! :)

Categories

Resources