基于压缩格式BUFR码的气象卫星数据解码解析
2021-11-10张恩红尹海燕
张恩红,尹海燕
(1.广东省气象探测数据中心,广东广州 510080;2.广东省气象计算机应用开发研究所,广东广州 510080)
由于科学技术的进步和探测技术水平的提高,采集的观测数据和加工的产品数据量越来越大,传统的数据传输格式已无法满足全球数据交换业务的需求。为了便于全球数据的交换使用,尽量减少数据传输压力,提高数据交换效率,世界气象组织(WMO)一直在推行气象数据格式的标准化,即推行二进制的表格驱动码,包括BUFR、GRIB和CREX码。现在全球很多国家都已经采用这个规范进行数据编码和共享传输。我国也完成了数据格式的转换工作。这个业务的推广,给数据使用的用户带来一个新的问题,那就是数据解码技术的更换与升级。
为了能够及时用上新格式的数据,WMO提供了编码规范,专家学者们开始研究BUFR格式数据的解码及应用软件的开发。王颖等[1]详细阐述了我国气象行业推进表格驱动码工作的进展与取得的成果。随着气象卫星的发展,观测手段颇为丰富,在气象预报与分析中广泛应用[2-5]。王素娟等[6]详细分析气象卫星风速的BUFR码格式,并且编写了相关的数据写入软件,实现了数据的业务化;张晓等[7]、袁雨晖[8]、陈增镜等[9]、王恩文等[10]、高雅洁[11]分别从不同的应用方向做了相关的应用研究。本研究着重讨论如何利用python语言对压缩格式的BUFR码进行解码,并提出在解码中可能存在的问题,供同行参考。
1 压缩格式BUFR的格式重点内容
BUFR的基本格式已经在很多文章有介绍,最全面的是世界气象组织(WMO)《气象编码手册》[12],中国气象局也组织专家翻译并编写了《表格驱动码编码手册》[13]。本研究摘取部分重点内容,进行分解说明。
1.1 关键段的解码定义
BUFR文件的编码主要包括6部分:指示符段、标识段、(选编段)、数据描述段、数据段、结束段,每段功能的详细说明请参考WMO相关文档。在BUFR的压缩格式解码中,前3段无重要信息,按文件说明常规解码即可,重点是数据描述段的解码。指示符段的长度为8个八位组。前4个八位组是国际电报字符5号码表示的BUFR;八位组5—7(24比特)是以二进制形式表示的整个BUFR信息的长度(包括指示符段);八位组8是以二进制表示的BUFR码的版本号。标识段的前3个八位组是以二进制形式表示的段长,并以八位组为单位。数据描述段的重点包括1—3八位组记录本段的长度,取决于后面的数据解读;5—6八位组描述本数据集的子集个数,决定了后面数据解压缩时读取数据的个数;在第7个八位组中,第1 bit位描述数据的性质,1表示观测数据、0表示其他数据,第2 bit位描述数据的格式,1表示压缩格式、0表示非压缩格式。第8—9个八位组记录该数据集的要素描述表的代码。
第8—9组(字节)的内容说明:
从八位组8开始的描述符集合,称作“数据描述”。每个描述符占两个八位组,分为F(2位)、X(6位)和Y(8位)共3个部分。
(1)如果F=0,描述符为要素描述符。X和Y的值将直接地对应表2中的一个入口,X表示类,Y表示类中的入口。
(2)如果F=1,描述符为重复描述符,该描述符按照相关规则对重复数据描述运算符作出定义。X值和Y值分别定义运算符的作用范围和重复次数。如果Y=0,则为延迟重复,并由下一个要素描述符定义一个数据项作为重复数;该描述符也可以通过其Y值指示后面的数据和后面的描述符一起重复。
(3)如果F=2,描述符为运算符描述符。X值指示《表格驱动码编码手册》的表C中的一种运算,Y值的含义取决于具体的运算。
(4)如果F=3,描述符为序列描述符。此时,X值和Y值直接地对应《表格驱动码编码手册》表D中的一个入口。表D的每一个入口包含一系列要素描述符、数据描述运算符和序列描述符。一个序列描述符等同于它在表D入口所对应的一组描述符。
1.2 关键段的解码应用
以W_XX-EUMETSAT-Darmstadt,SURFACE+SATELLITE,JASON2+OGDR_C_EUMS_20160730103615_d_297_135_20160730100932.bin文件为例,从文件的解报内容来看,第3段的第7个八位组的二进制值是11000000,第1 bit值为“1”,说明是观测数据;第2 bit值为“1”,说明该数据格式是压缩格式,这个信息非常重要,取决于后面的数据格式问题,若出错,后面的工作将无法继续。第8个八位组的二进制值为11101000和第9 个八位组的二进制值为00001010,从表1的说明可知,F=3,X=40,Y=10,则可知应该是对表参照码1的 3 40 010的要素描述符,该文件的要素描述如表1所示。再根据表1中的表参照码2到《表格驱动码编码手册》[13]中查找对应的要素说明信息,包括该要素的单位、比例因子n、基准值VB、数据宽度(占bit数,测量值V)。实际值(VR)的计算公式为VR=V·10n+VB。
表1 要素描述符
2 解码编程实现
2.1 解码实现过程
由于BUFR数据的压缩格式可以节约很多的空间,在大数据量的观测中,为了减少数据传输的压力,经常采用BUFR码的压缩格式。压缩形式的二进制数据的格式可描述如下:
鉴于非压缩格式的数据特点,数据处理的流程图如图1所示。
图1 数据解码流程示意图
首先需要从指示段获取子集个数S,即后面的要素增量的个数,然后读取配置文件,获取需要读取数据的要素个数,然后根据配置文件中定义的要素占位长度获取数据,直到完全读取完所有要素的数据。要想正确解码需要以下几个步骤:第一步需要获取每个要素的基准值占位宽度,这个值可以通过表1的“表参照码1”“表参照码2”组合获得;第二步,根据要素基准值的占位符长度,通过程序读取指定宽度的bit值,然后还得按每个字节8 bit的结构,重新组织所获取的二进制数据,这是二进制数据的难点之处,数据处理的方法可以分为几种情况(表2);第三步,也是非压缩格式解码最关键一步,即获取NBINC1的值,该值是判定是否有增量值及确定增量值所有占有bit位数的量。数据获取方法很简单,根据定义,这个数值的宽度是固定,在基础值之后的6 bit数据,当然,这6 bit的数据可能是在同一个字节里,也可能是在连续的两个字节里。编码如:NBINC1=((ord(data2)&0x7e)>>1),在一个字节中的连续6 bit或者n_NBINC1=((ord(data5)&0x0f)<<2)+((ord(data1)&0xc0)>>6)在两个字节中,前一字节4 bit加上后一字节2 bit。当NBINC1=0时,该要素的值是不变的,即每个记录的值都一样,当NBINC1>0时,该值为要素增量数据的占位宽度的bit数量。最后根据NBINCs的值获取相应增量数据,这里需要连续获取数据子集个数增量值。
表2 字节重组方案
2.2 解码应用
由于气象卫星的观测范围广、数据采集的量大,因此,数据传输的难度也很大,对数据传输技术要求很高。压缩格式的BUFR码,很适合气象卫星数据的存储与传输,在实际业务中,已经大量使用。基于以上的BUFR码解码分析,以欧洲卫星中心(EUMETSAT)的Jason2卫星为例,分析基于python语言的解码过程重点和难点内容,其中主程序的程序结构和部分重要代码如下:
从程序结构来看,第1行是引用了自建的函数(其中,readbufr_pole_tide_height:获取潮汐高度;readbufr_inverted_corr:反向的气压表订正;readbufr_sea_surf_anomaly:海平面高度距平,是自己创建的函数。),可以看出,这是一个主体程序,还有附带很多其他程序(函数或者函数库)。一个复杂的数据处理文件,很难在一个程序中完全实现,那样既不容易调试也不容解读程序;第4—7行是获取该数据有多少个记录数,在压缩格式BUFR解码中是至关重要的信息,后面每一个要素数据的获取都需要用到,如果该数值错误,将导致所有解码结果都错误;第35—36行,是定义数据输出文件,并打开一个可以支持写入的文件,后续所有解码数据均需要写入该文件,确保数据统一输出;第35行,是调用了1个自建函数,输入的3个参数,分别是该要素的数据起始字节位置、输入文件、输出文件,有了这3个参数在函数体了就可以根据《表格驱动码编码手册》[13]中定义的比例因子、基准值、数据宽度等信息获取相应的数据,并且输出到指定的输出文件,其中数据起始字节位置数值的计算非常复杂(该值是从上一个要素解码后计算出来的),首先要知道起始位置(L1),再加上该要素基础值的占位宽度(n),再加上NBINC1的占位6 bit,最后加上增量值的占位宽度(s)乘以要素格式(N),起始位L=L1+(n+6+s×N)/8[+1],其中[+1]是需要根据该要素占位bit数决定,bit总数除以8,余数少于起始字节起始bit,则不用[+1],反之,则要[+1];第36、37两行也是必须的,正常关闭程序前面打开的文件,否则形成垃圾信息占用系统内存。
3 解码常见错误分析
在压缩格式BUFR的解码中,由于编码结构的复杂性和不确定性,常常容易出现解码错误的现象,并且难以判定是否错误。本研究针对容易出错的情形进行分析。
错误1:取值顺序与输出值的顺序。Bufr格式是二进制格式的文件,实际存储数据是二进制的0、1形式保存,从第1位到最后一位。数据的抽取也是从第1位往后逐bit位抽取的,但是,在取完值之后,需要重新按计算机的8 bit为一个字节的结构从后往前组织数据。
错误2:多字节值的生成;在取值过程中,有些要素的宽度是占用很多bit的,例如,“C波段海洋范围”占位宽度31 bit,此时,获取的31 bit,需要分为4字节,而且是从后往前排,即最后3个字节各8 bit,最前一个字节7 bit,从前往后分别记为:a、b、c、d字节,计算值为a×256×256×256+b×256×256+c×256+d。在实际计算时,容易从前往后取bit组成新的字节,并且容易计算成a+b+c+d的值。
错误3:NBINC s的取值;NBINC s的固定长度是6 bit,该值的大小取决于后面增量的bit数,因此,该值的准确获取非常重要。在计算的结果判断上有个重要的方法,即该值的小于或者等于初始值的占位宽度,如果是大于初值占位数,一般都错误,需要重新检查数值的获取及重组方法。常见错误是:由于NBINCs取值结构简单,忽略了错误的存在,导致取值大于初值占位宽度,从而导致后续的取值大相径庭。
本研究通过实际压缩格式BUFR文件的解码实例,详细分析了分析解码过程,列出了解码的重要步骤。详细阐述了实际解码过程中遇到问题的解决方法,为后来者提供参考,减少错误重犯,大大提高了解码编程的效率和准确性。