Python:动画 3D 散点图变慢

Sam*_*uel 2 python animation matplotlib scatter3d

我的程序绘制了文件中每个时间步的粒子位置。不幸的是,尽管我使用了,但它变得越来越慢matplotlib.animation。瓶颈在哪里?

我的两个粒子的数据文件如下所示:

#     x   y   z
# t1  1   2   4
#     4   1   3
# t2  4   0   4
#     3   2   9
# t3  ...
Run Code Online (Sandbox Code Playgroud)

我的脚本:

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()
Run Code Online (Sandbox Code Playgroud)

a.s*_*iet 5

我建议在这种情况下使用pyqtgraph。文档中的引用:

其主要目标是 1) 提供快速的交互式图形来显示数据(绘图、视频等),2) 提供帮助快速应用程序开发的工具(例如,Qt Designer 中使用的属性树)。

安装后您可以查看一些示例:

import pyqtgraph.examples
pyqtgraph.examples.run()
Run Code Online (Sandbox Code Playgroud)

这个小代码片段生成 1000 个随机点,并通过不断更新不透明度将它们显示在 3D 散点图中,类似于以下中的 3D 散点图示例pyqtgraph.examples

from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import numpy as np

app = QtGui.QApplication([])
w = gl.GLViewWidget()
w.show()
g = gl.GLGridItem()
w.addItem(g)

#generate random points from -10 to 10, z-axis positive
pos = np.random.randint(-10,10,size=(1000,3))
pos[:,2] = np.abs(pos[:,2])

sp2 = gl.GLScatterPlotItem(pos=pos)
w.addItem(sp2)

#generate a color opacity gradient
color = np.zeros((pos.shape[0],4), dtype=np.float32)
color[:,0] = 1
color[:,1] = 0
color[:,2] = 0.5
color[0:100,3] = np.arange(0,100)/100.

def update():
    ## update volume colors
    global color
    color = np.roll(color,1, axis=0)
    sp2.setData(color=color)

t = QtCore.QTimer()
t.timeout.connect(update)
t.start(50)


## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()
Run Code Online (Sandbox Code Playgroud)

小 gif 让您了解表演:

在此输入图像描述

编辑:

在每个时间步显示多个点有点棘手,因为gl.GLScatterPlotItem(N,3)-arrays作为点位置,请参见此处。您可以尝试制作一个字典,ScatterPlotItems其中每个字典都包含特定点的所有时间步长。那么就需要相应地调整更新函数。您可以在下面找到一个示例,其中pos代表(100,10,3)-array每个点 100 个时间步长。我将更新时间缩短为1000 ms较慢的动画。

from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import numpy as np

app = QtGui.QApplication([])
w = gl.GLViewWidget()
w.show()
g = gl.GLGridItem()
w.addItem(g)

pos = np.random.randint(-10,10,size=(100,10,3))
pos[:,:,2] = np.abs(pos[:,:,2])

ScatterPlotItems = {}
for point in np.arange(10):
    ScatterPlotItems[point] = gl.GLScatterPlotItem(pos=pos[:,point,:])
    w.addItem(ScatterPlotItems[point])

color = np.zeros((pos.shape[0],10,4), dtype=np.float32)
color[:,:,0] = 1
color[:,:,1] = 0
color[:,:,2] = 0.5
color[0:5,:,3] = np.tile(np.arange(1,6)/5., (10,1)).T

def update():
    ## update volume colors
    global color
    for point in np.arange(10):
        ScatterPlotItems[point].setData(color=color[:,point,:])
    color = np.roll(color,1, axis=0)

t = QtCore.QTimer()
t.timeout.connect(update)
t.start(1000)


## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
    QtGui.QApplication.instance().exec_()
Run Code Online (Sandbox Code Playgroud)

请记住,在此示例中,所有点都显示在散点图中,但是,颜色不透明度(颜色数组中的第四维)会在每个时间步中更新以获得动画。您还可以尝试更新点而不是颜色以获得更好的性能......