Skip to content
Advertisement

The saved animated plot keeps looping although Matplotlib FuncAnimation(…,repeat=False)

I’d like to make an animation using matplotlib for a powerpoint presentation. The animation should only play once.

In my code, the argument repeat of FuncAnimation() was set to false. Because I need to import the figure into powerpoint, I saved it using ani.save('test.gif'). The problem is when I open the saved figure which is test.gif, the lineplot keeps looping.

All the searches on Stackoverflow suggest repeat=False, or using PillowWriter. Both solutions are not working for me, so I have two questions:

  1. why does the saved figure ignores repeat=False?
  2. how can I solve this issue?

Thank you in advance for helping me out. Please, find my code below:

import pandas as pd

import matplotlib.pyplot as plt

# import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation, PillowWriter

df = pd.DataFrame(
    {
        "x": {
            0: 0,
            1: 1,
            2: 2,
            3: 3,
            4: 4,
            5: 5,
            6: 6,
            7: 7,
            8: 8,
            9: 9,
            10: 10,
            11: 11,
            12: 12,
            13: 13,
            14: 14,
            15: 15,
            16: 16,
            17: 17,
            18: 18,
            19: 19,
            20: 20,
            21: 21,
            22: 22,
            23: 23,
            24: 24,
            25: 25,
            26: 26,
            27: 27,
            28: 28,
            29: 29,
            30: 30,
            31: 31,
            32: 32,
            33: 33,
            34: 34,
            35: 35,
            36: 36,
            37: 37,
            38: 38,
            39: 39,
            40: 40,
            41: 41,
            42: 42,
            43: 43,
            44: 44,
            45: 45,
            46: 46,
            47: 47,
            48: 48,
            49: 49,
            50: 50,
        },
        "y": {
            0: 0.7695,
            1: 0.7983,
            2: 0.7958,
            3: 0.7975,
            4: 0.7983,
            5: 0.7966,
            6: 0.7971,
            7: 0.7962,
            8: 0.7962,
            9: 0.7975,
            10: 0.7983,
            11: 0.7987,
            12: 0.7996,
            13: 0.7992,
            14: 0.7967,
            15: 0.7983,
            16: 0.7971,
            17: 0.7987,
            18: 0.7979,
            19: 0.7983,
            20: 0.7983,
            21: 0.7921,
            22: 0.7975,
            23: 0.7962,
            24: 0.7975,
            25: 0.7979,
            26: 0.7983,
            27: 0.7992,
            28: 0.7983,
            29: 0.7983,
            30: 0.7987,
            31: 0.7983,
            32: 0.7983,
            33: 0.7983,
            34: 0.7992,
            35: 0.7975,
            36: 0.7996,
            37: 0.7992,
            38: 0.7979,
            39: 0.7987,
            40: 0.7983,
            41: 0.7983,
            42: 0.7987,
            43: 0.7987,
            44: 0.7992,
            45: 0.7992,
            46: 0.7979,
            47: 0.7996,
            48: 0.7992,
            49: 0.7987,
            50: 0.7992,
        },
    }
)


x = df["x"]
y = df["y"]
fig, ax = plt.subplots()
line, = ax.plot(x, y, color="b")

def update(num, x, y, line):
    line.set_data(x[:num], y[:num])
    return (line,)

ani = FuncAnimation(
    fig, update, len(x), fargs=[x, y, line], interval=15, blit=True, repeat=False
)

# ani.save('test.gif')
ani.save("test2.gif", dpi=80, writer=PillowWriter(fps=5))

plt.show()

Advertisement

Answer

Use ImageMagickWriter:

ani.save("test2.gif", dpi=80, writer=ImageMagickWriter(fps=5, extra_args=['-loop', '1']))

I spent a lot of time looking into this. Its a little bit of a hack as ‘-loop 0’ is passed to the movie writer (convert) and the extra_args are appended but override. Here is a GIF I created using extra_args=[‘-loop’, ‘1’]:

Loop once GIF NB: Open image in a new tab to see it play.

I never got PillowWriter to work even when overriding the hard coded loop=0 in the finish() method:

class PillowWriterNG(PillowWriter):
    def finish(self):
            self._frames[0].save(
                self.outfile, save_all=True, append_images=self._frames[1:],
                duration=int(1000 / self.fps), loop=1)

Changing the loop parameter from 0 to 1 stops the infinite looping but it still runs twice!

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement