Matplotlib animation; animate in push mode, not with a call back function
Question:
I want to create a matplotlib animation, but instead of having matplotlib call me I want to call matplotlib. For example I want to do this:
from random import random
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def update(frame):
plt.scatter(random(),random())
fig, ax = plt.subplots()
ani = FuncAnimation(fig, update, interval=340, repeat=True)
ani.save("my.mov", "avconv")
Like this:
def update():
plt.scatter(random(),random())
fig, ax = plt.subplots()
ani = MadeUpSubClassPassiveAnimation(fig)
while True:
update()
ani.update()
# do other stuff ...
ani.save("my.mov", "avconv")
I realize I could drive a live plot like this:
def update():
plt.scatter(x, y)
plt.pause(0.01)
fig, ax = plt.subplots()
plt.ion()
while True:
update()
time.sleep(1)
But AFAIK I need to use Animation
for the save()
functionality. So, is it possible to drive Animation
rather than have it drive me? If so how?
Answers:
An Animation
is run when being saved. This means that the animation needs to reproducibly give the same result when being run twice (once for saving, once for showing). In other words, the animation needs to be defined in terms of successive frames. With this requirement, any animation can be constructed using a callback on either a function (FuncAnimation
) or on a list of frames (ArtistAnimation
).
The example from the question could be done with an ArtistAnimation
(in order not to have different random numbers for the saved and the shown animation, respectively):
from random import random
import matplotlib.animation
import matplotlib.pyplot as plt
def update(frame: int) -> list[matplotlib.artist.Artist]:
sc = ax.scatter(random(), random())
return [sc]
fig, ax = plt.subplots()
artists = []
for i in range(10):
sc = update(i)
artists.append(sc)
# If you want previous plots to be present in all frames, add:
# artists = [[j[0] for j in artists[:i+1]] for i in range(len(artists))]
ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=100)
ani.save(__file__ + ".gif", writer="imagemagick")
plt.show()
I want to create a matplotlib animation, but instead of having matplotlib call me I want to call matplotlib. For example I want to do this:
from random import random
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def update(frame):
plt.scatter(random(),random())
fig, ax = plt.subplots()
ani = FuncAnimation(fig, update, interval=340, repeat=True)
ani.save("my.mov", "avconv")
Like this:
def update():
plt.scatter(random(),random())
fig, ax = plt.subplots()
ani = MadeUpSubClassPassiveAnimation(fig)
while True:
update()
ani.update()
# do other stuff ...
ani.save("my.mov", "avconv")
I realize I could drive a live plot like this:
def update():
plt.scatter(x, y)
plt.pause(0.01)
fig, ax = plt.subplots()
plt.ion()
while True:
update()
time.sleep(1)
But AFAIK I need to use Animation
for the save()
functionality. So, is it possible to drive Animation
rather than have it drive me? If so how?
An Animation
is run when being saved. This means that the animation needs to reproducibly give the same result when being run twice (once for saving, once for showing). In other words, the animation needs to be defined in terms of successive frames. With this requirement, any animation can be constructed using a callback on either a function (FuncAnimation
) or on a list of frames (ArtistAnimation
).
The example from the question could be done with an ArtistAnimation
(in order not to have different random numbers for the saved and the shown animation, respectively):
from random import random
import matplotlib.animation
import matplotlib.pyplot as plt
def update(frame: int) -> list[matplotlib.artist.Artist]:
sc = ax.scatter(random(), random())
return [sc]
fig, ax = plt.subplots()
artists = []
for i in range(10):
sc = update(i)
artists.append(sc)
# If you want previous plots to be present in all frames, add:
# artists = [[j[0] for j in artists[:i+1]] for i in range(len(artists))]
ani = matplotlib.animation.ArtistAnimation(fig, artists, interval=100)
ani.save(__file__ + ".gif", writer="imagemagick")
plt.show()