My program plots the positions of particles in my file for every time step. Unfortunately it gets slower and slower although I used matplotlib.animation
. Where is the bottleneck?
My data file for two particles looks like the following:
# x y z
# t1 1 2 4
# 4 1 3
# t2 4 0 4
# 3 2 9
# t3 ...
My script:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
# Number of particles
numP = 2
# Dimensions
DIM = 3
timesteps = 2000
with open('//home//data.dat', 'r') as fp:
particleData = []
for line in fp:
line = line.split()
particleData.append(line)
x = [float(item[0]) for item in particleData]
y = [float(item[1]) for item in particleData]
z = [float(item[2]) for item in particleData]
# Attaching 3D axis to the figure
fig = plt.figure()
ax = p3.Axes3D(fig)
# Setting the axes properties
border = 1
ax.set_xlim3d([-border, border])
ax.set_ylim3d([-border, border])
ax.set_zlim3d([-border, border])
def animate(i):
global x, y, z, numP
#ax.clear()
ax.set_xlim3d([-border, border])
ax.set_ylim3d([-border, border])
ax.set_zlim3d([-border, border])
idx0 = i*numP
idx1 = numP*(i+1)
ax.scatter(x[idx0:idx1],y[idx0:idx1],z[idx0:idx1])
ani = animation.FuncAnimation(fig, animate, frames=timesteps, interval=1, blit=False, repeat=False)
plt.show()
I would suggest to use pyqtgraph in this case. Citation from the docs:
You can check out some examples after the installation:
This small code snippet generates 1000 random points and displays them in a 3D scatter plot by constantly updating the opacity, similar to the 3D scatter plot example in
pyqtgraph.examples
:Small gif to give you an idea of the performance:
EDIT:
Displaying multiple points at every single time step is a little bit tricky since the
gl.GLScatterPlotItem
takes only(N,3)-arrays
as point locations, see here. You could try to make a dictionary ofScatterPlotItems
where each of them includes all time steps for a specific point. Then one would need to adapt the update function accordingly. You can find an example below wherepos
is an(100,10,3)-array
representing 100 time steps for each point. I reduced the update time to1000 ms
for a slower animation.Keep in mind that in this examples, all points are shown in the scatter plot, however, the color opacity (4th dimension in the color array) is updated in every time step to get an animation. You could also try to update the points instead of the color to get better performance...
I would guess your bottleneck is calling
ax.scatter
andax.set_xlim3d
and similar in every frame in the animation.Ideally, you should make a call to
scatter
once, then use the object returned by scatter and itsset_...
properties in theanimate
function (more details here).I can't figure out how to do it with
scatter
, but if you useax.plot(x, y, z, 'o')
instead, you can then follow the demo method here.Using some random data for
x, y, z
. It would work like this