Reputation: 862
I have a class that imports matplotlib when needed and functions as a callback that receives a NumPy array, which should be shown in the next rendered frame. I need to dump this in a window as an animation on the screen. The current code is:
import matplotlib.pyplot as plt
import numpy as np
class Renderer(object):
def __init__(self):
self._image = None
def __call__(self, buffer):
if not self._image:
self._image = plt.imshow(buffer, animated=True)
else:
self._image.set_data(buffer)
plt.draw()
renderer = Renderer()
for _ in range(100):
renderer(
np.random.randint(low=0, high=255, size=(240, 320, 3), dtype=np.uint8))
There's some pretty heavy computation doing simulations that are generating each frame, so I don't worry that the frame rate will be too high.
Currently, the code does absolutely nothing, i.e. nothing appears on screen. Does anyone have an idea how to do an animation with the library?
UPDATE: Regarding context, so in my use case an instance of Renderer gets passed down to a layer of code that generates pixels and draws them on the screen by calling the Renderer object. In other words, when something should be drawn is out of my control, I also can't control the frame rate and don't know the time interval between the frames. For this reason what I really need from an API point-of-view is just a way to dump a bunch of pixels on the screen right now.
The FuncAnimation approach has the problem that getting the frames to it would require changing the Renderer callback to put frames on a queue from where the generator generating frames would pull them. FuncAnimation also seems to require me to know the time interval between frames a priori, which I don't know and isn't necessarily constant.
Upvotes: 0
Views: 504
Reputation: 339340
Just as usual for animations, use interactive mode (plt.ion()
) or a FuncAnimation
.
plt.ion()
)import matplotlib.pyplot as plt
import numpy as np
class Renderer(object):
def __init__(self):
self._image = None
def __call__(self, buffer):
if not self._image:
self._image = plt.imshow(buffer, animated=True)
else:
self._image.set_data(buffer)
plt.pause(0.01)
plt.draw()
renderer = Renderer()
plt.ion()
for _ in range(100):
renderer(
np.random.randint(low=0, high=255, size=(240, 320, 3), dtype=np.uint8))
plt.ioff()
plt.show()
FuncAnimaton
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
class Renderer(object):
def __init__(self):
self._image = None
def __call__(self, buffer):
if not self._image:
self._image = plt.imshow(buffer, animated=True)
else:
self._image.set_data(buffer)
renderer = Renderer()
fig, ax = plt.subplots()
def update(i):
renderer(
np.random.randint(low=0, high=255, size=(240, 320, 3), dtype=np.uint8))
ani = FuncAnimation(fig, update, frames=100, interval=10)
plt.show()
Upvotes: 1