动态Gnuplot图

时间:2012-12-06 17:53:50

标签: file dynamic graph gnuplot

我有一个不断更新的数据文件。我想使用Gnuplot动态绘制更新数据文件,可能使用最后100个数据点的窗口。

有可能吗?如果是这样,我们会赞赏一些指示。

4 个答案:

答案 0 :(得分:5)

不幸的是,Gnuplot没有内置的方法,IIRC GNU plotutils。

无论如何,这是使用Gnuplot和一些bash脚本完成它的一种方法:

# An updating data file
while :; do echo $((RANDOM%100)); sleep .1; done > datafile

使用plot命令初始化Gnuplot,让其他更新来自replot:

(
  echo "plot [0:100] [0:100] '< tail -n100 datafile' with lines";
  while :; do sleep .4; echo replot; done
) | gnuplot -persist

这使得Gnuplot每0.4秒评估tail -n100 datafile并将结果用作数据集。 tail命令返回datafile的最后100行。

答案 1 :(得分:1)

使用 的动态绘图:

只有 100 个最后的值

通过gnuplot脚本(快速演示)

简单地试试这两个命令:

.1 在后台填充动态数据文件

ping -i.2 google.com |
    sed -ue 's/.*seq=\([0-9]\+\) .*time=\([0-9.]\+\) .*/\1 \2/p;d' > file.dat &

.2 使用内联脚本运行 gnuplot(随意将 MAX=40 替换为 MAX=100 ;-)

MAX=40
gnuplot -e "while(1){pause 0.1;stats 'file.dat' u 0 nooutput;
    lPnts=STATS_records<$MAX?0: STATS_records-$MAX;
    plot 'file.dat' using 1:2 skip lPnts title 'google' w st  }"

您必须按 Ctrl+C 退出 gnuplot,然后 kill %% 停止运行 ping

通过脚本

有一个小 脚本维护数据文件,只保留最后 100 个值。这只是使用计数器,然后在计数器达到限制后删除数据文件中的第一个值:

#!/bin/bash

declare TMPDIR=/tmp DEST=${1:-google.com} DELAY=${2:-.25} MAXDATA=100
[ -d /dev/shm ] && [ -w /dev/shm ] && TMPDIR=/dev/shm
read -r TMPDAT < <(mktemp -p "$TMPDIR" --suffix .dat plot-XXXXXXXXXX)

exec {PFD}> >(exec gnuplot)
closExit() { exec {PFD}>&- ; [ -f "$TMPDAT" ] && rm "$TMPDAT" ; exit ;}
trap closExit 0 1 2 3 6 15

getDatas() {
    read -r data < <(
        ping -c 1 -n "$DEST" 2>&1 |
            sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d'
    )
    now=$EPOCHREALTIME
    printf '%.6f %s\n' >>"$TMPDAT" "$now" "$data"
    (( cnt++ > MAXDATA )) && sed -e 1d -i "$TMPDAT"
    printf ' %8d %(%a %b %d %T)T.%s %s\n' \
            "$cnt" "${now%.*}" "${now#*.}" "$data"
}
getDatas

echo >&$PFD "set term wxt noraise persist title 'Ping $DEST';"
echo >&$PFD "set xdata time;"
echo >&$PFD "set timefmt '%s';"

while ! read -rsn 1 -t "$DELAY" ;do
    getDatas
    echo >&$PFD "plot '$TMPDAT' using 1:2 with line title 'ping $DEST';"
done

示例运行(加速约 x15 动画 gif):

Ping graph sample

多进程演示脚本

我编写了一个 multiping bash script,它可以动态运行 gnuplot(并将尽可能多的后台任务 ping 到一起)。

在这个脚本中,没有对最后 N 个值的限制,但是这个脚本展示了如何从许多不同的流中读取数据,保持 STDIO 的交互性和寻址另一个用于订购 plot upgradegnuplot 子流程的流。

你可以运行:

multiping.sh -pci .3 www.google.com www.stackexchange.com

那里的目标是创建交互式 脚本来管理不同的子流程,用于输入和/或输出。

命令

在跑步时,您可以与:

  • q 退出(关闭所有 FD,终止所有子进程)
  • p 使用新的 gnuplot 子进程开始绘图
  • s 停止绘图
  • r 重置控制台终端
  • h 在控制台终端打印标题行

使用

命令行 -h 开关将显示然后帮助:

Usage: multiping.sh [-[cdhp]] [-i N] <host or ip> [host or ip] [host or ip]...
  Options:
    -c      colors (red for no answer, green for higher "seq" number)
    -d      Debug this (by opening 2 xterm windows... look at script)
    -h      help (print this)
    -iN     Interval for ping command (min 0.2 in user mode)
    -p      Plot dynamically (require gnuplot)
    All following argument will be "target" for "ping" command.

答案 2 :(得分:1)

这是一个 gnuplot-only 版本,不需要外部脚本。 它也适用于 gnuplot 4.6.0(OP 提出问题时的版本)。 由于我缺少不断更新的数据源,因此我在 gnuplot 本身中创建了数据文件。如果您的文件由另一个程序从外部更新,请跳过标有 # *skip 的行。

绘图在 while 循环中运行(选中 help while)并且可以通过按 x、选中 help bind 来停止。通过设置适当的数字来调整图之间的时间延迟(选中 help pause)。

代码:

### dynamic plotting of last 20 points
reset

FILE = 'Test.dat'

bind x 'stop = 1'   # stop loop via pressing x
stop = 0

N = 20
set yrange [0:3]

set print FILE          # *skip these lines if your file is updated by another program
set print FILE append   # *skip
idx = 0                 # *skip

while (!stop) {

    print sprintf("%g %g",idx=idx+1,sin(idx/3.)+rand(0)*0.5+1)   # *skip
    
    pause 0.05       # pause in seconds
    stats [*:*][*:*] FILE u 0 nooutput
    LastN = STATS_records<N ? 0 : STATS_records-N
    
    plot FILE u 1:2 every ::LastN w lp pt 7
}
set print               # *skip
### end of code 

结果:(使用 ScreenToGif 从 gnuplot 4.6.0 上的 wxt 终端截屏)

enter image description here

答案 3 :(得分:0)

脚本驱动进行动态绘图

这是一个使用google的简单ping示例:

#!/bin/bash

export DEST=${1:-google.com} DELAY=${2:-3} GPFD
openGnuPlot() {
    local fd=1
    while [ -e /dev/fd/$fd ];do ((fd++)) ;done
    eval "exec $fd> >(gnuplot)"
    GPFD=$fd
}
openGnuPlot

TMPDIR=/tmp
[ -d /dev/shm ] && [ -w /dev/shm ] && TMPDIR=/dev/shm
read TMPDATA < <(mktemp -p $TMPDIR --suffix .dat plot-XXXXXXXXXX)
trap "exec $GPFD>&-;[ -f $TMPDATA ]&&rm $TMPDATA;exit" 0 1 2 3 6 9 15
getDatas() {
    read data < <(
        ping -c 1 -n $DEST 2>&1 |
            sed -u 's/^64.*time=\([0-9.]\+\) .*$/\1/p;d'
    )
    printf "%(%s)T %s\n" >>$TMPDATA -1 "$data"
    printf "%(%a %b %d %T)T %s\n" -1 "$data"
}
getDatas

echo >/dev/fd/$GPFD "set term wxt noraise persist title 'Ping $DEST';"
echo >/dev/fd/$GPFD "set xdata time;"
echo >/dev/fd/$GPFD "set timefmt '%s';"

while :;do
    sleep $DELAY
    getDatas
    echo >/dev/fd/$GPFD \
         "plot '$TMPDATA' using 1:2 with line title 'ping $DEST';"
done

演示:

Sample Bash Dyn GnuPlot Graph with ping google.com

具有多个主机的第二个样本

此脚本执行许多同时ping并动态绘制图形

#!/bin/bash

export DEST=${1:-google.com} DELAY=${2:-3} GPFD
openGnuPlot() {
    local fd=1
    while [ -e /dev/fd/$fd ];do ((fd++)) ;done
    eval "exec $fd> >(gnuplot)"
    GPFD=$fd
}
openGnuPlot

TMPDIR=/tmp
[ -d /dev/shm ] && [ -w /dev/shm ] && TMPDIR=/dev/shm
read TMPDATA < <(mktemp -p $TMPDIR --suffix .dat plot-XXXXXXXXXX)
trap "exec $GPFD>&-;[ -f $TMPDATA ]&&rm $TMPDATA;exit" 0 1 2 3 6 9 15

getDatas() {
    local -A var tim
    local host out
    while IFS=$' \t:,()\n\r' read a b c d e f g h; do
        case $a in 
            PING )        printf -v var[$c] $b ;;
            64 )        printf -v tim[${var[$d]}] ${g#*=} ;;
        esac
    done < <(for host; do ping -nc1 $host & sleep .01;done )
    for host; do
          out+=" "${tim[$host]:--1}
    done
    printf "%(%s)T %s\n" >>$TMPDATA -1 "$out"
    printf "%(%a %b %d %T)T %s\n" -1 "$out"
}

echo >/dev/fd/$GPFD "set term wxt noraise persist title 'Ping $DEST';"
echo >/dev/fd/$GPFD "set xdata time;"
echo >/dev/fd/$GPFD "set timefmt '%s';"

plotlines=() fld=2
for host in $DEST;do
    plotlines+=("'$TMPDATA' using 1:$((fld++)) with line title 'ping $host'")
done
IFS=, eval 'plotcmd="plot ${plotlines[*]};"'

getDatas $DEST
while :;do
    sleep $DELAY
    getDatas $DEST
    echo >/dev/fd/$GPFD "$plotcmd"
done

使用以下语法运行示例:script.sh "stackoverflow.com google.com" 4用于同时从 stackoverflow google 执行ping图,延迟时间为4秒。

警告: gif动画延迟完全是假的!

enter image description here