2

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')
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
  • is it possible your settings are for transparent figure patches? You can check via `matplotlib.rcParams['savefig.frameon']`, which should be `True` to make each new patch have a solid background (http://matplotlib.org/api/pyplot_api.html) or set the argument using `anim.save('anim.mp4', [..etc..], extra_args={'frameon':True})` (http://matplotlib.org/api/animation_api.html) – slushy Nov 12 '16 at 13:22
  • Check this to change the position of the arrows: http://stackoverflow.com/questions/17758942/is-it-possible-to-update-matplotlib-quiver-position-coordinates-in-an-animation – Jean-Sébastien Nov 12 '16 at 14:51
  • 1
    Using q.set_offsets as suggested by @Jean works perfectly. Thank you! – Simon Peatman Nov 12 '16 at 23:22

2 Answers2

2

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')
Community
  • 1
  • 1
0

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')
mgcy
  • 153
  • 1
  • 1
  • 8