J_yang
J_yang

Reputation: 2822

matplotlib circle, animation, how to remove old circle in animation

I am trying to simulate an animation of a circular shock wave from a selected data point using Matplotlib's circle and animation. But I couldn't figure out a way to remove the older circles in every new frame. As a result, as the radius increases, I got more and more circles drawing on the canvas - like this:

enter image description here

Any advice on animating a circular shockwave on a matplotlib plot?

The code I have so far is :

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

testData = np.random.rand(100,2)-[0.5, 0.5]

fig, ax = plt.subplots()
def init():
    fig.clf()
    sctPlot, = ax.plot(testData[:,0], testData[:,1], ".")

# i is the radius
def animate(i):
    init()
    q = 20 #initial index for the starting position
    pos = testData[q,:]
    circle1=plt.Circle(pos,i,color='r',fill=False, clip_on = False)
    fig.gca().add_artist(circle1)

def init():
    sctPlot, = ax.plot(testData[:,0], testData[:,1], ".")
    return sctPlot,

ani = animation.FuncAnimation(fig, animate, np.arange(0.4, 2, 0.1), init_func=init,
    interval=25, blit=False)
plt.show()

Upvotes: 5

Views: 5387

Answers (2)

CT Zhu
CT Zhu

Reputation: 54380

I think you can just use set_radius to change the circle size every time:

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


testData = np.random.rand(100,2)-[0.5, 0.5]

fig, ax = plt.subplots()
circle1=plt.Circle(testData[20,:],0,color='r',fill=False, clip_on = False)
ax.add_artist(circle1)
# i is the radius
def animate(i):
    #init()
    #you don't want to redraw the same dots over and over again, do you?
    circle1.set_radius(i)


def init():
    sctPlot, = ax.plot(testData[:,0], testData[:,1], ".")
    return sctPlot,

ani = animation.FuncAnimation(fig, animate, np.arange(0.4, 2, 0.1), init_func=init,
    interval=25, blit=False)
plt.show()

So you are not removing and redrawing patches every round, which I think may be more efficient.

Upvotes: 6

Amy Teegarden
Amy Teegarden

Reputation: 3972

Add this code to your animate function:

for obj in ax.findobj(match = type(plt.Circle(1, 1))):
  obj.remove()

ax.findobj(match = type(plt.Circle(1, 1))) looks for all the circle patches on the axes, which you can then remove before plotting a new circle. I used plt.Circle() to make a circle object to match -- the arguments you pass it don't really matter.

Upvotes: 3

Related Questions