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()
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])
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')
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
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