plot - 使用gnuplot绘制二进制数据时是否可以设置X轴时间范围?
问题描述
我有一个二进制数据文件,其中包含一个标头,后跟一堆五字节的数据记录。每个字节是对不同数量的测量,所有这些都是同时获取的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 个字节实际上是 O 2饱和度、脉搏率、虚拟(始终为零)、运动传感器和另一个虚拟字节。我的 gnuplot 脚本只绘制了 3 个非虚拟值。
解决方案
这是一个完整的 gnuplot 脚本,用于从二进制文件中提取 Y/M/DH: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..."
推荐阅读
- php - 在 css 中使用 php,substr_count() 搜索文件位置
- laravel - 满足条件时,Laravel 允许用户访问特定路线
- android - 可点击视图是异步的?
- java - Spring JPA - 在代码中实现唯一约束 - Tx 隔离级别
- java - 如何在代码覆盖中覆盖equals方法
- javascript - 如何让 Quokka.js 识别本地模块
- amazon-web-services - 如何在 AWS 任务定义中指定磁盘空间?
- javascript - TypeError:无法读取未定义错误的属性“来自”
- python - Python 前缀后缀中缀,无括号
- react-native - react-native run-android VS ./gradlew assembleDebug