Gilfoyle
Gilfoyle

Reputation: 3616

How to update a scatter plot animation

I tried to write a simple script which updates a scatter plot for every timestep t. I wanted to do it as simple as possible. But all it does is to open a window where I can see nothing. The window just freezes. It is maybe just an small error, but I can not find it.

The the data.dat has the format

                x      y
Timestep 1      1      2
                3      1
Timestep 2      6      3
                2      1

(the file contains just the numbers)

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

# Load particle positioins
with open('//home//user//data.dat', 'r') as fp:
    particles = []
    for line in fp:
        line = line.split() 
        if line:
            line = [float(i) for i in line]
            particles.append(line)

T = 100
numbParticles = 2

x, y = np.array([]), np.array([])

plt.ion()
plt.figure()
plt.scatter(x,y)
for t in range(T):
    plt.clf()
    for k in range(numbP):
            x = np.append(x, particles[numbParticles*t+k][0])
            y = np.append(y, particles[numbParticles*t+k][1])
    plt.scatter(x,y)
    plt.draw()
    time.sleep(1)
    x, y = np.array([]), np.array([])

Upvotes: 1

Views: 9673

Answers (2)

unutbu
unutbu

Reputation: 879251

The simplest, cleanest way to make an animation is to use the matplotlib.animation module, as shown in this Matplotlib Animation Tutorial.

Since a scatter plot returns a matplotlib.collections.PathCollection, the way to update it is to call its set_offsets method. You can pass it an array of shape (N, 2) or a list of N 2-tuples -- each 2-tuple being an (x,y) coordinate.

For example,

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

T = 100
numbParticles = 2
particles = np.random.random((T,numbParticles)).tolist()
x, y = np.array([]), np.array([])

def init():
    pathcol.set_offsets([[], []])
    return [pathcol]

def update(i, pathcol, particles):
    pathcol.set_offsets(particles[i])
    return [pathcol]

fig = plt.figure()
xs, ys = zip(*particles)
xmin, xmax = min(xs), max(xs)
ymin, ymax = min(ys), max(ys)
ax = plt.axes(xlim=(xmin, xmax), ylim=(ymin, ymax))
pathcol = plt.scatter([], [], s=100)

anim = FuncAnimation(fig, update, init_func=init, fargs=(pathcol, particles),
                     interval=1000, frames=T, blit=True, repeat=True)
plt.show()

The loop is inside FuncAnimation(), so you don't see it. You can look at the source code if you like (actually there is no loop there, but an iterator), but you can also just accept that seen from the outside FuncAnimation(fig, update, interval=1000, frames=100) will just call the function update every 1000 ms and increment i by 1 up to the number given by frames.

Upvotes: 5

Gilfoyle
Gilfoyle

Reputation: 3616

I finally found a solution. You can do it simply by using this script. I tried to keep it simple:

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

# Helps me to get the data from the file I want to plot
N = 0

# Load particle positioins
with open('//home//user//data.dat', 'r') as fp:
    particles = []
    for line in fp:
        line = line.split() 
        particles.append(line)

# Create new Figure and an Axes which fills it.
fig = plt.figure(figsize=(7, 7))
ax = fig.add_axes([0, 0, 1, 1], frameon=True)
border = 100
ax.set_xlim(-border, border), ax.set_xticks([])
ax.set_ylim(-border, border), ax.set_yticks([])

# particle data
p = 18 # number of particles
myPa = np.zeros(p, dtype=[('position', float, 2)])

# Construct the scatter which we will update during animation
scat = ax.scatter(myPa['position'][:, 0], myPa['position'][:, 1])

def update(frame_number):
    # New positions
    myPa['position'][:] = particles[N*p:N*p+p]

    # Update the scatter collection, with the new colors, sizes and positions.
    scat.set_offsets(myPa['position'])
    increment()

def increment():
    global N
    N = N+1

# Construct the animation, using the update function as the animation director.
animation = FuncAnimation(fig, update, interval=20)

plt.show()

Upvotes: 0

Related Questions