I am making a matplotlib animation in which a quiver arrow moves across the page. This cannot be achieved in the usual way (creating one Quiver object and updating it with each frame of the animation) because although there is a set_UVC method for updating the u, v components, there is no equivalent method for changing the x, y position of the arrows. Therefore, I am creating a new Quiver object for each frame.
This works fine when I do a plt.show() and the animation is drawn on the screen. The arrow moves from left to right across the page, and when one arrow appears the previous one disappears, which is what I want. However, when I save as a gif or mp4 the previous arrows are not cleared, so I end up with a whole line of arrows appearing. How can I fix this?
My code is as follows:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
n = 21
x = np.linspace(-1.0, 1.0, num=n)
def animate(i):
q = plt.quiver(x[i:i+1], [0], [1], [0])
return q,
plt.gca().set_xlim([-1, 1])
anim = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=n,
repeat=True, blit=True)
plt.show()
#anim.save('anim.gif', dpi=80, writer='imagemagick')
#anim.save('anim.mp4', dpi=80, writer='ffmpeg')
The solution is found here, as suggested by Jean-Sébastien above. My code now reads:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
n = 21
x = np.linspace(-1.0, 1.0, num=n)
q = plt.quiver(x[:1], [0], [1], [0])
def animate(i):
q.set_offsets([[x[i], 0]])
return q,
plt.gca().set_xlim([-1, 1])
anim = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=n,
repeat=True, blit=True)
plt.show()
#anim.save('anim.gif', dpi=80, writer='imagemagick')
#anim.save('anim.mp4', dpi=80, writer='ffmpeg')
Try to clear the frame every time in your animate function. The code below worked well to me.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
n = 21
x = np.linspace(-1.0, 1.0, num=n)
fig = plt.figure()
def animate(i):
fig.clear() # clear fig
q = plt.quiver(x[i:i+1], [0], [1], [0])
plt.gca().set_xlim([-1, 1])
return q,
anim = matplotlib.animation.FuncAnimation(plt.gcf(), animate, frames=n,
repeat=True, blit=True)
# plt.show()
# anim.save('anim.gif', dpi=80, writer='imagemagick')
anim.save('anim.mp4', dpi=80, writer='ffmpeg')
Related
I'm new to python's matplotlib, and i want to animate a 1x1 square that moves diagonally across a grid space. I have written this bit of code that almost does what i want it to do, but the previous positions of the rectangle are still visible.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from matplotlib.patches import Rectangle
moving_block = [[0,0],[1,1],[2,2],[3,3],[4,4],[5,5]]
fig, ax = plt.subplots()
#set gridlines and lines every one unit
ax.grid(which='both')
ax.axis([0,5,0,5])
rectangle = Rectangle(moving_block[0], 1,1)
ax.add_patch(rectangle)
def animate(i):
ax.add_patch(Rectangle(moving_block[i], 1,1))
ani = matplotlib.animation.FuncAnimation(fig, animate,
frames=len(moving_block), interval=300, repeat=True)
plt.show()
How can i make only the current rectangle visible? Should i be using something other than this ax.add_patch(Rectangle) function?
Added cleaning "ax", at each iteration in the function "animate".
If you are satisfied with the answer, do not forget to vote for it :-)
import matplotlib.pyplot as plt
import matplotlib.animation
from matplotlib.patches import Rectangle
moving_block = [[0,0],[1,1],[2,2],[3,3],[4,4],[5,5]]
fig, ax = plt.subplots()
#set gridlines and lines every one unit
ax.grid(which='both')
ax.axis([0, 5, 0, 5])
rectangle = Rectangle(moving_block[0], 1,1)
ax.add_patch(rectangle)
def animate(i):
ax.clear()
ax.axis([0, 5, 0, 5])
ax.grid(which='both')
ax.add_patch(Rectangle(moving_block[i], 1,1))
ani = matplotlib.animation.FuncAnimation(fig, animate,
frames=len(moving_block), interval=300, repeat=True)
plt.show()
I have used .set_data() method/function to update co-ordinate of the line after every frame. x1,y1 values are being updated but they are not being update in the line plot. What am I doing wrong here?
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(6,6)
ax=plt.axes(xlim=(-10,10), ylim=(-10,10))
l1, = ax.plot([0.0, 1.0],[0.0,5.0], color = 'b', linewidth = 1)
def animate(i):
x1=np.sin(np.radians((i)+90))
y1=np.cos(np.radians((i)+90))
l1.set_data=([0,x1],[0,y1])
#print (x1,y1)
return l1,
anim = animation.FuncAnimation(fig, animate, frames=360, interval=20, blit=True)
plt.show()
You wrote l1.set_data=([0,x1],[0,y1]). Is that a typo? This should be (notice the removal of the = sign):
l1.set_data([0,x1],[0,y1])
so I am following a tutorial of plotting values that change in the regular intervals(live data)... I am using matplotlib and using FuncAnimation... I have imported all the necessary modules but no answer... here is what i have done and the output
x = []
y = []
c = count()
def anim(i):
x.append(next(c))
y.append(random.randint(0,10))
plt.cla()
plt.plot(x,y,'or',markersize=10)
ani = FuncAnimation(plt.gcf(),anim,interval=5000)
the output:
<Figure size 432x288 with 0 Axes>
This section explains the basic structure of the animation.
Configure the objects that will draw the graph. (Line 5)
Set the Y value you want to animate with the animation function (def anim()).
Then update the value of the graph object set in #1
Set the number of times to draw, the interval between draws, the inability to repeat, etc. with Funcanimation().
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
fig, ax = plt.subplots()
im, = ax.plot([], [], 'or', markersize=10)
x = np.arange(10)
ax.set_xlim(0, 9)
ax.set_ylim(0, 1)
def anim(i):
y = np.random.rand(10)
im.set_data(x, y)
anim = FuncAnimation(fig, anim, frames=50, interval=200, repeat=False, blit=False)
fig.show()
Good day !
Problem explanation:
I want to animate a Polygon which values I receive from an array (in my simple example it is a moving sqaure). I want to keep the Polygon's x-and y-values mutable. Dont worry about what movement the Polygon does. It is just an example. Working with "set_xy()" like in the solution from 'animation to translate polygon using matplotlib' is wanted.
Goal -> in every animation frame I want to load the Polygon values from the arrays (P1x,P1y,P2x,P2y,...) and update the figure.
Question:
In my code I still have problems to work with the patches. I'm trying to update the Polygon values with the index i. How do I have to define the patch? Does this have to be done bevor the animation call?
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
P1x=[0.0,0.5,1.0,1.5,2.0,2.5,3.0]
P1y=[0.0,0.0,0.0,0.0,0.0,0.0,0.0]
P2x=[1.0,1.5,2.0,2.5,3.0,3.5,4.0]
P2y=[0.0,0.0,0.0,0.0,0.0,0.0,0.0]
P3x=[1.0,1.5,2.0,2.5,3.0,3.5,4.0]
P3y=[1.0,1.0,1.0,1.0,1.0,1.0,1.0]
P4x=[0.0,0.5,1.0,1.5,2.0,2.5,3.0]
P4y=[1.0,1.0,1.0,1.0,1.0,1.0,1.0]
def init():
return patch,
def animate(i):
v = np.array([
[P1x[i], P1y[i]],
[P2x[i], P2y[i]],
[P3x[i], P3y[i]],
[P4x[i], P4y[i]]
])
patch=patches.Polygon(v,closed=True, fc='r', ec='r')
return patch,
ani = animation.FuncAnimation(fig, animate, np.arange(1, 5), init_func=init,
interval=1000, blit=True)
plt.show()
Thanks a lot for your help!
Yes, you will need to create the Polygon first and add it to the axes. Inside the animating function you may use the patch's patch.set_xy() method to update the vertices of the polygon.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
P1x=[0.0,0.5,1.0,1.5,2.0,2.5,3.0]
P1y=[0.0,0.0,0.0,0.0,0.0,0.0,0.0]
P2x=[1.0,1.5,2.0,2.5,3.0,3.5,4.0]
P2y=[0.0,0.0,0.0,0.0,0.0,0.0,0.0]
P3x=[1.0,1.5,2.0,2.5,3.0,3.5,4.0]
P3y=[1.0,1.0,1.0,1.0,1.0,1.0,1.0]
P4x=[0.0,0.5,1.0,1.5,2.0,2.5,3.0]
P4y=[1.0,1.0,1.0,1.0,1.0,1.0,1.0]
P = np.concatenate((np.array([P1x, P2x, P3x, P4x]).reshape(4,1,len(P1x)),
np.array([P1y, P2y, P3y, P4y]).reshape(4,1,len(P1x))), axis=1)
patch = patches.Polygon(P[:,:,0],closed=True, fc='r', ec='r')
ax.add_patch(patch)
def init():
return patch,
def animate(i):
patch.set_xy(P[:,:,i])
return patch,
ani = animation.FuncAnimation(fig, animate, np.arange(P.shape[2]), init_func=init,
interval=1000, blit=True)
plt.show()
I would like to create a animation where my data points would gradually appear on my graph and freeze when all the data points have appeared. I've seen in done with correlations i'm just not too sure how to do it with just individual points themselves
This isn't something that will show anything particularly useful but i though it would look cool since i am trying to visualize some location data on a map
I know this isn't very clear so please as for clarifications, I'm not too sure how to phrase my problem very well.
Thanks
matplotlib.animation.FuncAnimation is the right tool for you. First create an empty graph, and then gradually add data points to it in the function. The following piece of code will illustrate it:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x = np.arange(10)
y = np.random.random(10)
fig = plt.figure()
plt.xlim(0, 10)
plt.ylim(0, 1)
graph, = plt.plot([], [], 'o')
def animate(i):
graph.set_data(x[:i+1], y[:i+1])
return graph
ani = FuncAnimation(fig, animate, frames=10, interval=200)
plt.show()
The result (saved as gif file) is shown below:
EDIT: To make the animation look stopped when finished in matplotlib window, you need to make it infinite (omit frames parameter in FuncAnimation), and set the frame counter to the last number in your frame series:
def animate(i):
if i > 9:
i = 9
graph.set_data(x[:i+1], y[:i+1])
return graph
ani = FuncAnimation(fig, animate, interval=200)
Or, which is better, you can set repeat parameter in FuncAnimation to False, as per answer to this question.
EDIT 2: To animate a scatter plot, you need a whole bunch of other methods. A piece of code is worth a thousand words:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x = np.arange(10)
y = np.random.random(10)
size = np.random.randint(150, size=10)
colors = np.random.choice(["r", "g", "b"], size=10)
fig = plt.figure()
plt.xlim(0, 10)
plt.ylim(0, 1)
graph = plt.scatter([], [])
def animate(i):
graph.set_offsets(np.vstack((x[:i+1], y[:i+1])).T)
graph.set_sizes(size[:i+1])
graph.set_facecolors(colors[:i+1])
return graph
ani = FuncAnimation(fig, animate, repeat=False, interval=200)
plt.show()