加快通过 shell 命令管道传输的输入的 gnuplot 列迭代



我有一个脚本可以转换原始数据以便与 gnuplot 交互使用。scipt采用的参数让我对数据进行一些过滤。原则上,可以通过以下脚本来模拟它:

import time, sys
print('Generating data...', file=sys.stderr)
time.sleep(1)
print('x', '100*x', 'x**3', '2**x')
for x in range(*map(int, sys.argv[1:3])):
  print(x, 100*x, x**3, 2**x)

我通过将 shell 命令管道到 gnuplot 并迭代列来在列中绘制一系列数据:

gnuplot> plot for [i=2:4] '< python3 pipe_data.py 1 11' u 1:i w l t columnhead(i)
Generating data...
Generating data...
Generating data...
gnuplot>

目前,当我注意到脚本需要很长时间才能多次运行它时,我会在 gnuplot 之外执行它并将输出保存到文件中。但是,每当我想将参数更改为脚本时,都必须这样做很麻烦。

我希望 gnuplot 只执行一次'< python3 pipe_data.py',这样屏幕上只打印一个Generating data...。这可能吗?

理想情况下,gnuplot 会缓存以 < 开头的特殊文件名的内容。这样就可以在不重新生成数据的情况下调整图的外观,例如:

gnuplot> plot for [i=2:4] '< python3 pipe_data.py 1 11' u 1:i w l t columnhead(i)
Generating data...
gnuplot> plot for [i=2:4] '< python3 pipe_data.py 1 11' u 1:i w lp t columnhead(i)
gnuplot> plot for [i=2:4] '< python3 pipe_data.py 5 12' u 1:i w lp t columnhead(i)
Generating data...
gnuplot> plot for [i=2:4] '< python3 pipe_data.py 1 11' u 1:i w p t columnhead(i)
gnuplot>

当原始数据发生变化时,这可能会成为问题,gnuplot 无法知道这一点。但我仍然希望有一些方法可以达到这种效果。如果不是只使用 gnuplot,那么也许使用一些外部工具?

作为记录,我使用 gnuplot v4.6。

以下命令应该执行您想要的操作。我正在生成一个 ona 数据点文件,该文件采用两个参数,ij .该文件在调用 plot data(i,j) 时自动生成,然后每次重复使用。通过您的命令更改我的sleep 5; echo %i %i。如果您不使用整数,则还需要更改格式。

data(i,j) = system(sprintf('name="temp_%i_%i"; if [ ! -s $name ]; then sleep 5; echo %i %i > $name; fi; echo $name', i, j, i, j))

用法示例:

# You'll notice a 5-second pause here while the command is running:
plot data(1,1)
# Now it will run at once because the file already exists:
plot data(1,1)

我想出了一个bash脚本,为我解决了所有问题:

  • 循环访问列时,用于处理数据的脚本仅运行一次
  • 调整剧情显示时,无需再等待脚本运行
  • 我可以将其他参数传递给脚本并缓存结果
  • 我可以回到以前的论点,而不必等待
  • 适用于任何脚本,无论它可能需要什么参数和多少参数
  • 如果任何文件(脚本或数据)发生更改,它将被拾取并重新运行
  • 它是完全透明的,无需额外的设置或调整
  • 不必担心清理,因为系统会为我完成清理

我将其命名为$(用于现金/缓存),chmod u+x将其命名,并将其放在PATH中:

#!/bin/bash
# hash all arguments
KEY="$@"
# hash last modified dates of any files
for arg in "$@"
do
  if [ -f $arg ]
  then
    KEY+=`date -r "$arg" + %s`
  fi
done
# use the hash as a name for temporary file
FILE="/tmp/command_cache.`echo -n "$KEY" | md5sum | cut -c -10`"
# use cached file or execute the command and cache it
if [ -f $FILE ]
then
  cat $FILE
else
  $@ | tee $FILE
fi

现在我可以使用<$而不是<来利用它:

> plot for [i=2:4] '<$ python3 pipe_data.py 1 11' u 1:i w l t columnhead(i)
Generating data...
> plot for [i=2:4] '<$ python3 pipe_data.py 1 11' u 1:i w lp t columnhead(i)
> plot for [i=2:4] '<$ python3 pipe_data.py 5 12' u 1:i w lp t columnhead(i)
Generating data...
> plot for [i=2:4] '<$ python3 pipe_data.py 1 11' u 1:i w p t columnhead(i)
>

最新更新