Skip to content

[Doc]: Surprising behavior of FuncAnimation example in the first frames #29856

Open

Description

@bluthej

Documentation Link

https://matplotlib.org/devdocs/users/explain/animations/animations.html#funcanimation

Problem

When looking carefully at the first few frames of the animation from the FuncAnimation example by setting interval=2_000 for instance, there are some surprises:

  • First, a single point is plotted, corresponding to the initial scatter plot
  • Then this point disappears, corresponding to the first frame which is empty because frame=0 and we take slices (x = t[:frame], y = z[:frame])
  • Then the point reappears, and in the following frames the trajectory is plotted as expected

I think the expected behavior is that the first point appears, and then the trajectory starts, which can be obtained by replacing frames=40 with frames=range(2, 40).

Side point

That does raise another related point which I encountered and which is what led me to look at that example, which is that saving the animation to a file and showing it in an interactive window behave differently with respect to the first frame. The initial state of the plot is shown in interactive mode but does not show up in the saved GIF. In the FuncAnimation example, when saving the animation to a GIF, the first frame doesn't have any point, then the point appears and the trajectory then proceeds normally (so it's like I described above but without the first frame).

My understanding is this comes from the fact that the animation does not have access to the initial figure setup, but I might be wrong. This "inconsistency" is a little sad for me because in order to have the first frame show up in the GIF I have to accept the fact that it's shown twice in interactive mode.

Shall I open another issue about this?

Suggested improvement

No response

Activity

  1. timhoffm commented on Apr 3, 2025

    @timhoffm
    Member

    the current behavior becomes more clear when adding a title

    title = ax.set_title("initial")
    ...
    def update(frame):
        ...
        title.set_text(f"frame {frame}")
    

    The initial plot is drawn and stays it for one full interval. Only then frame 0 is drawn. Note also that the initial state does not come back in following cycles of the animation.

    The initial plot is not part of the animation as you have realized when saving the file, the same happens when you do this in a jupyter notebook.

    from IPython.display import HTML
    ...
    ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=1000)
    HTML(ani.to_jshtml())
    

    So we currently have:

    • if the animation is saved, it contains only the frames
    • if the animation is displayed, the animation is started by the draw_event
      self._first_draw_id = fig.canvas.mpl_connect('draw_event', self._start)

      It then starts the timer but the first frame is only drawn when the timer expires
      def _start(self, *args):
      """
      Starts interactive animation. Adds the draw frame command to the GUI
      handler, calls show to start the event loop.
      """
      # Do not start the event source if saving() it.
      if self._fig.canvas.is_saving():
      return
      # First disconnect our draw event handler
      self._fig.canvas.mpl_disconnect(self._first_draw_id)
      # Now do any initial draw
      self._init_draw()
      # Actually start the event_source.
      self.event_source.start()

      This leaves the initial state standing at the beginning

    I therefore think the startup behavior for an animation that is shown is incorrect. Maybe we should try to render the first frame as part of _start(). Not sure how well this works because of the warning in DrawEvent. Probably the cleaner but also more complicated apporach is to not trigger the Animation through a draw event, but built in explicit logic in show() to directly transfer the drawing control to the animation when a figure with an animation is shown. But that requires more rearchitecting since figures currently do not know that they have an animation (see #16221 (comment)).

  2. bluthej commented on Apr 4, 2025

    @bluthej
    Author

    I therefore think the startup behavior for an animation that is shown is incorrect.

    I do agree!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions