将大数据集绘制为动画时 gnuplot 变慢

gnuplot slow when plotting large data set as animation

我正在尝试使用如下脚本从大文本文件中绘制"animated"大量数据(1000 个粒子的位置):

set terminal wxt size 1000,600
k=999999
N = 999
do for [i=0:k]{
plot for [j=0:N-1] "pos.txt" using 2*j+1:2*j+2  every ::2*i+1::2*i+1 ls 1 pt 7 ps 2 notitle

在文件中,每一行都有我要绘制的点在特定时间的坐标X和Y。我正在使用 every 绘制每行中的所有数据一次,然后转到下一行。

输出是这样的(1000 个粒子移动)

但是绘图太慢了,我不知道我能做些什么来让它绘图更快。它每 5 秒或更长时间绘制一行。该文件加权一些 MB。我应该改变终端吗?或者我存储数据的方式?我认为 gnuplot 加载大文件时可能会出现问题。
一些粒子在模拟中消失了,所以当索引 j(井 2j+1)超过粒子数时我也得到错误 line 14: warning: Skipping data file with no valid points 但我试着让它读取粒子数每次都更慢。非常感谢。

我怀疑每次绘图时 gnuplot 都会读取整个文件,而不是读取有问题的行,然后是下一行,然后是下一行,等等。一种可能的策略是将粒子轨迹分离到不同的文件中,但特别是它可以通过简单地 plot 加上块 selection 和 every 来帮助删除 plot for,而不是 selecting 列您在同一块中的同一时间步的粒子位置。

现在您的数据看起来像这样:

x1 y1 x2 y2 x3 y3 # Time step 1
x1 y1 x2 y2 x3 y3 # Time step 2

并且 gnuplot 需要为每个时间步 粒子读取一次文件。如果您按如下方式构建文件(请注意块之间的一个空行):

# Time step 1
x1 y1
x2 y2
x3 y3

# Time step 2
x1 y1
x2 y2
x3 y3

那你就不需要plot for了,只需要在every:

中插入一个额外的分号就可以select包含所有粒子的相应方块
set terminal wxt size 1000,600
k=999999
#N = 999 you don't need this anymore!
do for [i=0:k] {
plot "pos.txt" every :::i::i
}

上面的代码为每个时间步而不是每个时间步 粒子读取文件,并一次绘制所有粒子。

如果性能非常关键,您可以考虑使用完全不同的数据格式。尽管更改 ASCII 文件的格式带来了巨大的改进,但它的扩展性很差,因为 gnuplot 必须始终从数据文件的开头扫描以确定开始的位置。我做了一些测试,绘制前 1000 帧花了我 60 秒,而绘制 9000 到 10000 点花了 600 秒。

您需要一种数据格式,允许您在恒定时间内搜索任何数据集。在我的论文中,我用 hdf5, and then you can use the external utility h5totxt 保存了我所有的实验数据(巨大的数据集)以提取所需的数据集。这里不需要扫描整个文件就可以计算出请求数据集的位置,并且访问时间与帧数无关。

为了测试,我使用了以下 python 脚本来生成测试数据文件 points.h5:

from numpy import random
import h5py
P = random.normal(size=(10000,1000,2))
f = h5py.File('points.h5', 'w')
f.create_dataset('points', data=P)

用于绘图的 gnuplot 脚本是

set terminal wxt size 1000,600
k=9999
do for [i=0:9999]{
  plot sprintf("< h5totxt -s ' ' -x %d points.h5", i) using 1:2 ls 1 pt 7 ps 2 title sprintf("%d", i)
}

现在,无论拍摄哪一帧(0-1000 或 9000-10000),绘制 1000 帧都需要 40 秒。