Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating "growing" line plot in Python/Matplotlib

I want to produce a set of frames that can be used to animate a plot of a growing line. In the past, I have always used plt.draw() and set_ydata() to redraw the y-data as it changed over time. This time, I wish to draw a "growing" line, moving across the graph with time. Because of this, set_ydata doesn't work (xdata is changing length). For example,

import numpy as np import matplotlib.pyplot as plt  x = np.linspace(0, 10, 100) y = np.sin(x)  plt.figure() for n in range(len(x)):     plt.plot(x[:n], y[:n], color='k')     plt.axis([0, 10, 0, 1])     plt.savefig('Frame%03d.png' %n) 

While this works, it becomes very slow as it scales. Is there a faster way to do this?

like image 796
Blink Avatar asked Jan 21 '15 18:01

Blink


1 Answers

A couple of notes:

First off, the reason that things become progressively slower is that you're drawing more and more and more overlapping lines in the same position.

A quick fix is to clear the plot each time:

import numpy as np import matplotlib.pyplot as plt  x = np.linspace(0, 10, 100) y = np.sin(x)  plt.figure() for n in range(len(x)):     plt.cla()     plt.plot(x[:n], y[:n], color='k')     plt.axis([0, 10, 0, 1])     plt.savefig('Frame%03d.png' %n) 

Better yet, however, update both the x and y data at the same time:

import numpy as np import matplotlib.pyplot as plt  x = np.linspace(0, 10, 100) y = np.sin(x)  fig, ax = plt.subplots() line, = ax.plot(x, y, color='k')  for n in range(len(x)):     line.set_data(x[:n], y[:n])     ax.axis([0, 10, 0, 1])     fig.canvas.draw()     fig.savefig('Frame%03d.png' %n) 

And if you'd like to use the animation module (side note: blit=True may not work properly on some backends (e.g. OSX), so try blit=False if you have issues):

import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation  x = np.linspace(0, 10, 100) y = np.sin(x)  fig, ax = plt.subplots() line, = ax.plot(x, y, color='k')  def update(num, x, y, line):     line.set_data(x[:num], y[:num])     line.axes.axis([0, 10, 0, 1])     return line,  ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y, line],                               interval=25, blit=True) ani.save('test.gif') plt.show() 

enter image description here

like image 104
Joe Kington Avatar answered Sep 24 '22 09:09

Joe Kington