【问题标题】:Is it possible to set X-axis time range when plotting binary data with gnuplot?使用gnuplot绘制二进制数据时是否可以设置X轴时间范围?
【发布时间】:2019-11-16 17:31:01
【问题描述】:

我有一个二进制数据文件,其中包含一个标题,后跟一堆五字节的数据记录。每个字节都是对不同数量的度量,所有这些都是同时获取的1。我想显示一个有五行的图表,显示每个数量如何随时间变化。数据文件的开始时间是在文件开头的一些字节中编码的,我知道每条记录都是在前一条记录之后2秒拍摄的,但是记录没有单独的时间戳。

我可以通过完全忽略实际时间来或多或少地像我想要的那样绘制它;如果你 set xdata time,那么 gnuplot 会做正确的事。但是,它无法显示正确的时间。另一方面,如果您set xrange ["*time1*":"*time2*"],那么您根本不会得到任何图表,因为 gnuplot 不知道未加时间戳的记录对应于这些时间。

有没有办法告诉 gnuplot 文件中的二进制记录以特定时间戳开始,以便它们匹配到正确的 xrange?

我的二进制数据(50 字节标头 = 0003 签名,uint16 年,uint8 月,uint8 日,uint8 小时,uint8 分钟,uint8 秒,其他随机内容,然后是 5 字节记录):

00000000  03 00 e3 07 0b 0f 16 22  13 63 97 00 00 fc 78 00  |.......".c....x.|
00000010  00 60 5c 04 00 00 00 00  00 63 00 00 00 00 00 00  |.`\......c......|
00000020  00 00 00 00 00 00 00 00  ff ff ff 00 00 ff ff ff  |................|
00000030  00 00 61 3a 00 00 00 61  3a 00 00 00 61 3b 00 00  |..a:...a:...a;..|
00000040  00 61 3b 00 00 00 60 3c  00 00 00 60 3c 00 00 00  |.a;...`<...`<...|
00000050  60 3c 00 00 00 60 3c 00  00 00 60 3d 00 00 00 60  |`<...`<...`=...`|
00000060  3d 00 00 00 60 3c 00 00  00 60 3c 00 00 00 61 3e  |=...`<...`<...a>|
00000070  00 00 00 61 3e 00 00 00  61 3f 00 00 00 61 3f 00  |...a>...a?...a?.|
00000080  00 00 61 3f 00 02 00 61  3f 00 02 00 61 3f 00 01  |..a?...a?...a?..|
00000090  00 61 3f 00 01 00 61 3f  00 00 00 61 3f 00 00 00  |.a?...a?...a?...|
000000a0  61 3f 00 00 00 61 3f 00  00 00 61 41 00 01 00 61  |a?...a?...aA...a|
000000b0  41 00 01 00 60 42 00 00  00 60 42 00 00 00 60 40  |A...`B...`B...`@|
000000c0  00 00 00 60 40 00 00 00  60 3d 00 00 00 60 3d 00  |...`@...`=...`=.|
000000d0  00 00 60 3c 00 00 00 60  3c 00 00 00 60 3c 00 00  |..`<...`<...`<..|
000000e0  00 60 3c 00 00 00 60 3c  00 00 00 60 3c 00 00 00  |.`<...`<...`<...|
000000f0  60 3d 00 00 00 60 3d 00  00 00 60 3e 00 00 00 60  |`=...`=...`>...`|
00000100  3e 00 00 00 60 3e 00 00  00 60 3e 00 00 00 60 3f  |>...`>...`>...`?|
00000110  00 00 00 60 3f 00 00 00  60 40 00 00 00 60 40 00  |...`?...`@...`@.|
00000120  00 00 60 40 00 05 00 60  40 00 05 00 60 40 00 04  |..`@...`@...`@..|
00000130  00 60 40 00 04 00 60 3f  00 00 00 60 3f 00 00 00  |.`@...`?...`?...|
00000140  60 40 00 00 00 60 40 00  00 00 60 3f 00 00 00 60  |`@...`@...`?...`|
00000150  3f 00 00 00 60 3e 00 00  00 60 3e 00 00 00 60 3e  |?...`>...`>...`>|
00000160  00 0f 00 60 3e 00 0f 00  60 3c 00 00 00 60 3c 00  |...`>...`<...`<.|
00000170  00 00 60 3d 00 00 00 60  3d 00 00 00 60 3e 00 01  |..`=...`=...`>..|
00000180  00 60 3e 00 01 00 60 3e  00 18 00 60 3e 00 18 00  |.`>...`>...`>...|
00000190  60 3e 00 02 00 60 3e 00  02 00 60 3e 00 03 00 60  |`>...`>...`>...`|

我的 gnuplot 脚本:

#!/usr/bin/gnuplot

fn="20191115223419"

set title "Heart Rate, O2, Motion"
set xlabel "Time"

set xdata time
set timefmt "%Y%m%d%H%M%S"
set xrange ["20191115223419":"20191116071015"]
set format x "%H:%M"

set yrange [40:120]     # Heart rate
set y2range [50:100]    # O2 saturation

plot \
     fn binary skip=0x32 format="%5uint8" using 0:2 with lines lt rgb "red" title "HR", \
     fn binary skip=0x32 format="%5uint8" using 0:(($4)/4+40) with lines lt rgb "orange" title "Motion", \
     fn binary skip=0x32 format="%5uint8" using 0:1 with lines lt rgb "gray60" title "O2" axes x1y2

pause -1 "Hit <ENTER> to continue..."

如果我注释掉 xrange 行,它会根据需要绘制。

我知道我可以很容易地编写一个脚本来将数据转换成更好的形式,也许这就是要做的事情:Python 把它变成一个更好的字符串,然后 gnuplot 那个。但如果我能单独告诉 gnuplot 做我想做的事,我会很高兴。


1这 5 个字节实际上是 O2 饱和度、脉率、虚拟(始终为零)、运动传感器和另一个虚拟字节。我的 gnuplot 脚本只绘制了 3 个非虚拟值。

【问题讨论】:

    标签: plot graph gnuplot


    【解决方案1】:

    没有实际测试,因为我没有你的数据文件...

    您不需要set xdata time。 我将提取开始时间作为一个单独的问题,并假设您在运行脚本时以某种可用的形式拥有它。每条记录的增量时间为 2 秒,因此每个点的完整时间为start + 2 * $0

    start = strptime("%Y%m%d%H%M%S", "20191115223419") # start time in seconds
    set xtics time format "%H%M%S"
    set xrange [start : start + whatever]
    plot \
     fn binary skip=0x32 format="%5uint8" using (start+2*$0):2 with lines lt rgb "red" title "HR", \
     fn binary skip=0x32 format="%5uint8" using (start+2*$0):(($4)/4+40) with lines lt rgb "orange" title "Motion", \
     fn binary skip=0x32 format="%5uint8" using (start+2*$0):1 with lines lt rgb "gray60" title "O2" axes x1y2
    

    【讨论】:

    • 太棒了,谢谢!我不知道我是否可以从二进制文件中提取时间(所以我最终可能不得不做脚本的事情)但至少我收到的数据文件名正是开始时间,所以我可以使用@987654324 @ 得到它。 (whatever 更难:我必须计算记录才能弄清楚它应该是什么。但现在 gnuplot 的自动量程工作正常。)
    【解决方案2】:

    这是一个完整的 gnuplot 脚本,用于从二进制文件中提取 Y/M/D H:M:S 数据并绘制其余数据以及示例图像。

    #!/usr/bin/gnuplot
    #
    # This script plots data from a Viatom pulse oximeter (www.viatomtech.com).  The
    # Android app extracts recorded data and stores it in an Sqlite3 database, and also
    # creates files under /sdcard/PlusebitO2CN with names based on the recording start
    # date & time.  These are binary files with a two-byte "signature" of 0x0003; 7 bytes
    # of start date/time as uint16:year, uint8 month, day, hour, minute, second; 41 bytes
    # of something else ??? and then 5-byte records of Oxygenation, Heart Rate, dummy-1,
    # motion-sensor, dummy-2.
    #
    
    # Put file name here...everything else is automagic.
    #
    fn="20191115223419"
    #
    ####################################################
    
    set title "Heart Rate, O2, Motion"
    set xlabel "Time"
    
    #
    # Get start time from binary file by fake-plotting.  This will
    # print a warning message; I don't know how to get rid of it.
    #
    set term unknown
    plot fn binary skip=2 format="%uint16%5uint8" every 1:1:0:0:0:0 \
         using (year=$1):(month=$2):(day=$3):(hour=$4):(minute=$5):(second=$6):1 with candlesticks
    # Now put the values we extracted into a single 'YYYYmmddHHMMSS' string
    sd=sprintf("%04d%d%d%d%d%d", year, month, day, hour, minute, second )
    set term qt
    
    set xdata time
    start=strptime("%Y%m%d%H%M%S", sd ) # sd contains YYYYmmddHHMMSS extracted from file
    set xtics time format "%H%M%S"
    #set timefmt "%Y%m%d%H%M%S"
    #set xrange ["20191115223419":"20191116071015"]
    set format x "%H:%M"
    
    set yrange [40:120]     # Heart rate
    set y2range [50:100]    # O2 saturation
    
    plot \
         fn binary skip=0x32 format="%5uint8" using (start+2*$0):2 with lines lt rgb "red" title "HR", \
         fn binary skip=0x32 format="%5uint8" using (start+2*$0):(($4)/4+40) with lines lt rgb "orange" title "Motion", \
         fn binary skip=0x32 format="%5uint8" using (start+2*$0):1 with lines lt rgb "gray60" title "O2" axes x1y2
    
    pause -1 "Hit <ENTER> to continue..."
    

    结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      • 2011-06-15
      相关资源
      最近更新 更多