AN_
AN_

Reputation: 143

How to make dots in an matplotlib animation disappear?

I am making an animation in matplotlib, where dots are moving in a certain direction. I would like them to disappear, when they reach a given value. In the following code, the dots are moving in a U shape and stop at the end.
I would like the dots to disappear, when they stop, at x= 7-9, y=7:

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

n_particles = 40
b_particles=5
box_width = 10
n_steps = 5000
dt = 0.001

fig, ax = plt.subplots()
ax.set_xlim(0, 20)
ax.set_ylim(0, 20)
# -------
def get_initial_coordinates():

    x=[random.uniform(2,3) for i in range(n_particles)]
    y=[random.uniform(2,7) for i in range(n_particles)]
    return x,y
def get_initial_velocities():
    directions=[np.array([0,1]),np.array([1,0]),np.array([-1,0]),np.array([0,-1])]
    direction=random.choice(directions)
    d1 = []
    for i in range(n_particles):
        d1.append(random.choice(directions))
    d1 = np.array(d1)

    xv=[ 0  for i in range(n_particles)]
    yv=[ -20  for i in range(n_particles)]

    return xv, yv
throughwall = []
for i in range(n_particles):
    throughwall.append(random.random() * 100)
def take_step(x,y,xv,yv):
    for i in range(n_particles):
     x[i] +=xv[i]*dt
     y[i] +=yv[i]*dt
     if y[i] <= random.uniform(-1,3):
        xv[i] = 20
        yv[i]=0
     if x[i] >=random.uniform(7,10):
         xv[i]=0
         yv[i]= 20
     if y[i] >=7 and 7<x[i]<9:
         xv[i]=0
         yv[i]=0
    return x,y,xv,yv
x,y = get_initial_coordinates()
xv,yv= get_initial_velocities()
for i in range(n_steps):
    x,y,xv,yv= take_step(x,y,xv,yv)
#---------------------
fig = plt.figure()
ax = plt.axes(xlim=(0, 10), ylim=(0, 10))
ax.set_aspect('equal')
e, = ax.plot([x[i] for i in range(n_particles)],
             [y[i] for i in range(n_particles)], 'ro')
x,y= get_initial_coordinates()
xv,yv= get_initial_velocities()

import matplotlib.patches as patches

ax.add_patch(
     patches.Rectangle(
        (3, 3),4,4,edgecolor = 'blue', fill=False) )
ax.add_patch(
     patches.Rectangle(
        (2, 2),6,5,edgecolor = 'blue',fill=False) )
def animate(i):
    take_step(x,y,xv,yv)
    e.set_data([x[i]for i in range(n_particles)],
               [y[i] for i in range(n_particles)])
    return e,
anim = animation.FuncAnimation(fig, animate, frames=200, interval=20)
plt.show()

Upvotes: 1

Views: 492

Answers (1)

JohanC
JohanC

Reputation: 80459

At the moment the particle reaches the end, one could set its position far outside the view. The code below sets the y at 1000. As the view limits (xlim and ylim) aren't changed, the dot will be invisible.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib import animation
import numpy as np
import random

n_particles = 40
b_particles = 5
box_width = 10
dt = 0.001

fig, ax = plt.subplots()
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.set_aspect('equal')

def get_initial_coordinates():
    x = np.random.uniform(2, 3, n_particles)
    y = np.random.uniform(2, 7, n_particles)
    return x, y

def get_initial_velocities():
    xv = np.zeros(n_particles)
    yv = np.zeros(n_particles) - 20
    return xv, yv

def take_step(x, y, xv, yv):
    for i in range(n_particles):
        x[i] += xv[i] * dt
        y[i] += yv[i] * dt
        if y[i] <= random.uniform(-1, 3):
            xv[i] = 20
            yv[i] = 0
        if x[i] >= random.uniform(7, 10):
            xv[i] = 0
            yv[i] = 20
        if y[i] >= 7 and 7 < x[i] < 9:
            xv[i] = 0
            yv[i] = 0
        if y[i] >= 7 and x[i] >= 7:
            y[i] = 10000
    return x, y, xv, yv

x, y = get_initial_coordinates()
xv, yv = get_initial_velocities()
e, = ax.plot(x, y, 'ro')

ax.add_patch(
    patches.Rectangle(
        (3, 3), 4, 4, edgecolor='blue', fill=False))
ax.add_patch(
    patches.Rectangle(
        (2, 2), 6, 5, edgecolor='blue', fill=False))

def animate(i):
    take_step(x, y, xv, yv)
    e.set_data(x, y)
    return e,

anim = animation.FuncAnimation(fig, animate, frames=200, interval=20)
plt.show()

An alternative could be to draw a reservoir where the particles will stop. Making the reservoir white, and setting its zorder higher than the dots (default the dots get zorder 2) will make the dots hidden. For the reservoir not to hide the border of the U shape, the rectangles of the U shape can get a still higher zorder.

The code below lets the particles stop near y == 7.5 to make sure they arrive at the center of the reservoir.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib import animation
import numpy as np
import random

n_particles = 40
b_particles = 5
box_width = 10
dt = 0.001

fig, ax = plt.subplots()
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.set_aspect('equal')

def get_initial_coordinates():
    x = np.random.uniform(2, 3, n_particles)
    y = np.random.uniform(2, 7, n_particles)
    return x, y

def get_initial_velocities():
    xv = np.zeros(n_particles)
    yv = np.zeros(n_particles) - 20
    return xv, yv

def take_step(x, y, xv, yv):
    for i in range(n_particles):
        x[i] += xv[i] * dt
        y[i] += yv[i] * dt
        if y[i] <= random.uniform(-1, 3):
            xv[i] = 20
            yv[i] = 0
        if x[i] >= random.uniform(7, 10):
            xv[i] = 0
            yv[i] = 20
        if y[i] >= 7.5 and 7 < x[i] < 9:
            xv[i] = 0
            yv[i] = 0
    return x, y, xv, yv

x, y = get_initial_coordinates()
xv, yv = get_initial_velocities()
e, = ax.plot(x, y, 'ro')

ax.add_patch(
    patches.Rectangle(
        (3, 3), 4, 4, edgecolor='blue', fill=False, zorder=4))
ax.add_patch(
    patches.Rectangle(
        (2, 2), 6, 5, edgecolor='blue', fill=False, zorder=4))
# draw the reservoir, white makes it invisible, change its color
#   to `facecolor='gold', alpha=0.5` to see what's happening
ax.add_patch(
    patches.Rectangle(
        (6, 7), 3, 1, edgecolor='none', facecolor='white', zorder=3))

def animate(i):
    take_step(x, y, xv, yv)
    e.set_data(x, y)
    return e,

anim = animation.FuncAnimation(fig, animate, frames=200, interval=20)
plt.show()

Upvotes: 1

Related Questions