-1

I can't seem to get a TimedAnimation animation of an image to display anything if all entries in the initial frame contain the same value. For example, the following doesn't display anything if the indicated line remains commented out. Changing the first frame to contain np.ones(self.shape) also doesn't have any effect.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anim

class MyAnimation(anim.TimedAnimation):
    def __init__(self):
        fig = plt.figure()
        self.shape = (10, 10)
        data = np.zeros(self.shape)
        # data.flat[0] = 1 # uncomment this to get the animation to display         
        self.ax = plt.imshow(data)
        super(self.__class__, self).__init__(fig, interval=50, blit=True)

    def _draw_frame(self, framedata):
        data = np.random.rand(*self.shape)
        self.ax.set_data(data)

    def new_frame_seq(self):
        return iter(range(100))

ani = MyAnimation()

Turning off blitting doesn't seem to have any effect. Changing the backend doesn't seem to make any difference either; I tried Qt4Agg and nbagg (the latter via Jupyter notebook 4.1.0) with the same results. I'm using numpy 1.10.4 and matplotlib 1.5.1 with Python 2.7.11.

Is the above behavior expected? If not, is there something I should be doing to get the animation to display when the first frame is a blank or solid image?

lebedov
  • 1,371
  • 2
  • 12
  • 27

1 Answers1

1

Setting the data does not recompute the color limits. In the case of all of the input values being the same the min/max are auto-scaled to the same value, hence you never see the data be update. You can either explicitly set the limits on init

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as anim

class MyAnimation(anim.TimedAnimation):
    def __init__(self, ax=None):
        if ax is None:
            fig, ax = plt.subplots()

        self.shape = (10, 10)
        data = np.zeros(self.shape)
        self.im = ax.imshow(data, vmin=0, vmax=1)
        super(self.__class__, self).__init__(ax.figure, interval=50, blit=True)

    def _draw_frame(self, framedata):
        data = np.random.rand(*self.shape)
        self.im.set_data(data)

    def new_frame_seq(self):
        return iter(range(100))

ani = MyAnimation()

or use self.im.set_clim in the _draw_frame method.

I am also not sure that sub-classing TimedAnimation is the easiest way to do what ever you are trying to do (FuncAnimation is pretty flexible).

tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • Thanks - setting vmin/vmax did the trick. ``TimedAnimation`` is admittedly not necessary in this toy example, but I asked about it because I find it more convenient to use in a more involved scenario where I explicitly save/access certain variables in the class instance. – lebedov Apr 03 '16 at 00:50