0

I'm trying to create an animated figure for showing multiple tens of thousands of data points, appearing over time, in a single figure. Using blit=True to avoid redrawing everything every frame doesn't work without telling it to redraw everything every frame - I want to just draw the new data points.

Neither python matplotlib update scatter plot from a function or How to animate a scatter plot? answer the question because I want to add new artists, not just update existing ones with set_offsets, which forces every point to be redrawn. The documentation says that it does support new artists:

func must return an iterable of all artists that were modified or created

I'm running matplotlib 3.1.1 on macOS 10.13 and RHEL7 - the MacOSX backend doesn't work at all for me with blitting, so manually selecting TkAgg on that system:

import matplotlib
matplotlib.use("TkAgg") # On macOS

import matplotlib.animation as animation
import matplotlib.pyplot as plt


def animate(n):
    scatter = ax1.scatter([n], [n])
    return [scatter]


fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_xlim(0, 20)
ax1.set_ylim(0, 20)

ani = animation.FuncAnimation(fig, animate, interval=100, blit=True)
plt.show()

But when running this, only the last plotted data point remains on the figure: Animation only showing single artist

How can I use blitting to write new data points without drawing everything every frame?

misnomer
  • 2,136
  • 2
  • 13
  • 14
  • Have a look here (https://stackoverflow.com/a/42738014/10640534) and here (https://stackoverflow.com/a/43680172/10640534). – Patol75 Oct 08 '19 at 23:07
  • Yes, I viewed both of those, and both are answering different questions. Neither of them handle a) blitting or b) adding new artists. If I update an existing artist, all X0,000 points are redrawn every frame, which quickly becomes very slow. – misnomer Oct 09 '19 at 08:01
  • I've updated the question to hopefully make it clearer that neither of those questions actually answer it, just answer a different question about the same topic – misnomer Oct 09 '19 at 08:23
  • Would the following work for you then? `import matplotlib.animation as animation import matplotlib.pyplot as plt def animate(n): scatter = ax.scatter(n, n) if n == 0: return ax.get_children()[0], else: return ax.get_children()[:n] fig, ax = plt.subplots() ax.set_xlim(0, 20) ax.set_ylim(0, 20) ani = animation.FuncAnimation(fig, animate, interval=100, blit=True) plt.show()` – Patol75 Oct 09 '19 at 12:00
  • After further research, I think this isn't actually possible like I want - I dove into the animation code and it deliberately clears the axis back to the original every frame. Looks like the standard animation classes are just for drawing on top of a complicated base. I have an example of it working which is why I thought it was possible, but I think that is accidentally causing a refresh anyway. I'll self-answer when I'm a bit more certain. – misnomer Oct 09 '19 at 12:08
  • What about the piece of code here (https://matplotlib.org/api/animation_api.html#funcanimation), the one that plots a sine function? Does not it do what you want? – Patol75 Oct 09 '19 at 12:21

0 Answers0