張恩紅,尹海燕
(1.廣東省氣象探測(cè)數(shù)據(jù)中心,廣東廣州 510080;2.廣東省氣象計(jì)算機(jī)應(yīng)用開發(fā)研究所,廣東廣州 510080)
由于科學(xué)技術(shù)的進(jìn)步和探測(cè)技術(shù)水平的提高,采集的觀測(cè)數(shù)據(jù)和加工的產(chǎn)品數(shù)據(jù)量越來越大,傳統(tǒng)的數(shù)據(jù)傳輸格式已無法滿足全球數(shù)據(jù)交換業(yè)務(wù)的需求。為了便于全球數(shù)據(jù)的交換使用,盡量減少數(shù)據(jù)傳輸壓力,提高數(shù)據(jù)交換效率,世界氣象組織(WMO)一直在推行氣象數(shù)據(jù)格式的標(biāo)準(zhǔn)化,即推行二進(jìn)制的表格驅(qū)動(dòng)碼,包括BUFR、GRIB和CREX碼?,F(xiàn)在全球很多國(guó)家都已經(jīng)采用這個(gè)規(guī)范進(jìn)行數(shù)據(jù)編碼和共享傳輸。我國(guó)也完成了數(shù)據(jù)格式的轉(zhuǎn)換工作。這個(gè)業(yè)務(wù)的推廣,給數(shù)據(jù)使用的用戶帶來一個(gè)新的問題,那就是數(shù)據(jù)解碼技術(shù)的更換與升級(jí)。
為了能夠及時(shí)用上新格式的數(shù)據(jù),WMO提供了編碼規(guī)范,專家學(xué)者們開始研究BUFR格式數(shù)據(jù)的解碼及應(yīng)用軟件的開發(fā)。王穎等[1]詳細(xì)闡述了我國(guó)氣象行業(yè)推進(jìn)表格驅(qū)動(dòng)碼工作的進(jìn)展與取得的成果。隨著氣象衛(wèi)星的發(fā)展,觀測(cè)手段頗為豐富,在氣象預(yù)報(bào)與分析中廣泛應(yīng)用[2-5]。王素娟等[6]詳細(xì)分析氣象衛(wèi)星風(fēng)速的BUFR碼格式,并且編寫了相關(guān)的數(shù)據(jù)寫入軟件,實(shí)現(xiàn)了數(shù)據(jù)的業(yè)務(wù)化;張曉等[7]、袁雨暉[8]、陳增鏡等[9]、王恩文等[10]、高雅潔[11]分別從不同的應(yīng)用方向做了相關(guān)的應(yīng)用研究。本研究著重討論如何利用python語言對(duì)壓縮格式的BUFR碼進(jìn)行解碼,并提出在解碼中可能存在的問題,供同行參考。
BUFR的基本格式已經(jīng)在很多文章有介紹,最全面的是世界氣象組織(WMO)《氣象編碼手冊(cè)》[12],中國(guó)氣象局也組織專家翻譯并編寫了《表格驅(qū)動(dòng)碼編碼手冊(cè)》[13]。本研究摘取部分重點(diǎn)內(nèi)容,進(jìn)行分解說明。
BUFR文件的編碼主要包括6部分:指示符段、標(biāo)識(shí)段、(選編段)、數(shù)據(jù)描述段、數(shù)據(jù)段、結(jié)束段,每段功能的詳細(xì)說明請(qǐng)參考WMO相關(guān)文檔。在BUFR的壓縮格式解碼中,前3段無重要信息,按文件說明常規(guī)解碼即可,重點(diǎn)是數(shù)據(jù)描述段的解碼。指示符段的長(zhǎng)度為8個(gè)八位組。前4個(gè)八位組是國(guó)際電報(bào)字符5號(hào)碼表示的BUFR;八位組5—7(24比特)是以二進(jìn)制形式表示的整個(gè)BUFR信息的長(zhǎng)度(包括指示符段);八位組8是以二進(jìn)制表示的BUFR碼的版本號(hào)。標(biāo)識(shí)段的前3個(gè)八位組是以二進(jìn)制形式表示的段長(zhǎng),并以八位組為單位。數(shù)據(jù)描述段的重點(diǎn)包括1—3八位組記錄本段的長(zhǎng)度,取決于后面的數(shù)據(jù)解讀;5—6八位組描述本數(shù)據(jù)集的子集個(gè)數(shù),決定了后面數(shù)據(jù)解壓縮時(shí)讀取數(shù)據(jù)的個(gè)數(shù);在第7個(gè)八位組中,第1 bit位描述數(shù)據(jù)的性質(zhì),1表示觀測(cè)數(shù)據(jù)、0表示其他數(shù)據(jù),第2 bit位描述數(shù)據(jù)的格式,1表示壓縮格式、0表示非壓縮格式。第8—9個(gè)八位組記錄該數(shù)據(jù)集的要素描述表的代碼。
第8—9組(字節(jié))的內(nèi)容說明:
從八位組8開始的描述符集合,稱作“數(shù)據(jù)描述”。每個(gè)描述符占兩個(gè)八位組,分為F(2位)、X(6位)和Y(8位)共3個(gè)部分。
(1)如果F=0,描述符為要素描述符。X和Y的值將直接地對(duì)應(yīng)表2中的一個(gè)入口,X表示類,Y表示類中的入口。
(2)如果F=1,描述符為重復(fù)描述符,該描述符按照相關(guān)規(guī)則對(duì)重復(fù)數(shù)據(jù)描述運(yùn)算符作出定義。X值和Y值分別定義運(yùn)算符的作用范圍和重復(fù)次數(shù)。如果Y=0,則為延遲重復(fù),并由下一個(gè)要素描述符定義一個(gè)數(shù)據(jù)項(xiàng)作為重復(fù)數(shù);該描述符也可以通過其Y值指示后面的數(shù)據(jù)和后面的描述符一起重復(fù)。
(3)如果F=2,描述符為運(yùn)算符描述符。X值指示《表格驅(qū)動(dòng)碼編碼手冊(cè)》的表C中的一種運(yùn)算,Y值的含義取決于具體的運(yùn)算。
(4)如果F=3,描述符為序列描述符。此時(shí),X值和Y值直接地對(duì)應(yīng)《表格驅(qū)動(dòng)碼編碼手冊(cè)》表D中的一個(gè)入口。表D的每一個(gè)入口包含一系列要素描述符、數(shù)據(jù)描述運(yùn)算符和序列描述符。一個(gè)序列描述符等同于它在表D入口所對(duì)應(yīng)的一組描述符。
以W_XX-EUMETSAT-Darmstadt,SURFACE+SATELLITE,JASON2+OGDR_C_EUMS_20160730103615_d_297_135_20160730100932.bin文件為例,從文件的解報(bào)內(nèi)容來看,第3段的第7個(gè)八位組的二進(jìn)制值是11000000,第1 bit值為“1”,說明是觀測(cè)數(shù)據(jù);第2 bit值為“1”,說明該數(shù)據(jù)格式是壓縮格式,這個(gè)信息非常重要,取決于后面的數(shù)據(jù)格式問題,若出錯(cuò),后面的工作將無法繼續(xù)。第8個(gè)八位組的二進(jìn)制值為11101000和第9 個(gè)八位組的二進(jìn)制值為00001010,從表1的說明可知,F(xiàn)=3,X=40,Y=10,則可知應(yīng)該是對(duì)表參照碼1的 3 40 010的要素描述符,該文件的要素描述如表1所示。再根據(jù)表1中的表參照碼2到《表格驅(qū)動(dòng)碼編碼手冊(cè)》[13]中查找對(duì)應(yīng)的要素說明信息,包括該要素的單位、比例因子n、基準(zhǔn)值VB、數(shù)據(jù)寬度(占bit數(shù),測(cè)量值V)。實(shí)際值(VR)的計(jì)算公式為VR=V·10n+VB。
表1 要素描述符
由于BUFR數(shù)據(jù)的壓縮格式可以節(jié)約很多的空間,在大數(shù)據(jù)量的觀測(cè)中,為了減少數(shù)據(jù)傳輸?shù)膲毫?,?jīng)常采用BUFR碼的壓縮格式。壓縮形式的二進(jìn)制數(shù)據(jù)的格式可描述如下:
鑒于非壓縮格式的數(shù)據(jù)特點(diǎn),數(shù)據(jù)處理的流程圖如圖1所示。
圖1 數(shù)據(jù)解碼流程示意圖
首先需要從指示段獲取子集個(gè)數(shù)S,即后面的要素增量的個(gè)數(shù),然后讀取配置文件,獲取需要讀取數(shù)據(jù)的要素個(gè)數(shù),然后根據(jù)配置文件中定義的要素占位長(zhǎng)度獲取數(shù)據(jù),直到完全讀取完所有要素的數(shù)據(jù)。要想正確解碼需要以下幾個(gè)步驟:第一步需要獲取每個(gè)要素的基準(zhǔn)值占位寬度,這個(gè)值可以通過表1的“表參照碼1”“表參照碼2”組合獲得;第二步,根據(jù)要素基準(zhǔn)值的占位符長(zhǎng)度,通過程序讀取指定寬度的bit值,然后還得按每個(gè)字節(jié)8 bit的結(jié)構(gòu),重新組織所獲取的二進(jìn)制數(shù)據(jù),這是二進(jìn)制數(shù)據(jù)的難點(diǎn)之處,數(shù)據(jù)處理的方法可以分為幾種情況(表2);第三步,也是非壓縮格式解碼最關(guān)鍵一步,即獲取NBINC1的值,該值是判定是否有增量值及確定增量值所有占有bit位數(shù)的量。數(shù)據(jù)獲取方法很簡(jiǎn)單,根據(jù)定義,這個(gè)數(shù)值的寬度是固定,在基礎(chǔ)值之后的6 bit數(shù)據(jù),當(dāng)然,這6 bit的數(shù)據(jù)可能是在同一個(gè)字節(jié)里,也可能是在連續(xù)的兩個(gè)字節(jié)里。編碼如:NBINC1=((ord(data2)&0x7e)>>1),在一個(gè)字節(jié)中的連續(xù)6 bit或者n_NBINC1=((ord(data5)&0x0f)<<2)+((ord(data1)&0xc0)>>6)在兩個(gè)字節(jié)中,前一字節(jié)4 bit加上后一字節(jié)2 bit。當(dāng)NBINC1=0時(shí),該要素的值是不變的,即每個(gè)記錄的值都一樣,當(dāng)NBINC1>0時(shí),該值為要素增量數(shù)據(jù)的占位寬度的bit數(shù)量。最后根據(jù)NBINCs的值獲取相應(yīng)增量數(shù)據(jù),這里需要連續(xù)獲取數(shù)據(jù)子集個(gè)數(shù)增量值。
表2 字節(jié)重組方案
由于氣象衛(wèi)星的觀測(cè)范圍廣、數(shù)據(jù)采集的量大,因此,數(shù)據(jù)傳輸?shù)碾y度也很大,對(duì)數(shù)據(jù)傳輸技術(shù)要求很高。壓縮格式的BUFR碼,很適合氣象衛(wèi)星數(shù)據(jù)的存儲(chǔ)與傳輸,在實(shí)際業(yè)務(wù)中,已經(jīng)大量使用?;谝陨系腂UFR碼解碼分析,以歐洲衛(wèi)星中心(EUMETSAT)的Jason2衛(wèi)星為例,分析基于python語言的解碼過程重點(diǎn)和難點(diǎn)內(nèi)容,其中主程序的程序結(jié)構(gòu)和部分重要代碼如下:
從程序結(jié)構(gòu)來看,第1行是引用了自建的函數(shù)(其中,readbufr_pole_tide_height:獲取潮汐高度;readbufr_inverted_corr:反向的氣壓表訂正;readbufr_sea_surf_anomaly:海平面高度距平,是自己創(chuàng)建的函數(shù)。),可以看出,這是一個(gè)主體程序,還有附帶很多其他程序(函數(shù)或者函數(shù)庫(kù))。一個(gè)復(fù)雜的數(shù)據(jù)處理文件,很難在一個(gè)程序中完全實(shí)現(xiàn),那樣既不容易調(diào)試也不容解讀程序;第4—7行是獲取該數(shù)據(jù)有多少個(gè)記錄數(shù),在壓縮格式BUFR解碼中是至關(guān)重要的信息,后面每一個(gè)要素?cái)?shù)據(jù)的獲取都需要用到,如果該數(shù)值錯(cuò)誤,將導(dǎo)致所有解碼結(jié)果都錯(cuò)誤;第35—36行,是定義數(shù)據(jù)輸出文件,并打開一個(gè)可以支持寫入的文件,后續(xù)所有解碼數(shù)據(jù)均需要寫入該文件,確保數(shù)據(jù)統(tǒng)一輸出;第35行,是調(diào)用了1個(gè)自建函數(shù),輸入的3個(gè)參數(shù),分別是該要素的數(shù)據(jù)起始字節(jié)位置、輸入文件、輸出文件,有了這3個(gè)參數(shù)在函數(shù)體了就可以根據(jù)《表格驅(qū)動(dòng)碼編碼手冊(cè)》[13]中定義的比例因子、基準(zhǔn)值、數(shù)據(jù)寬度等信息獲取相應(yīng)的數(shù)據(jù),并且輸出到指定的輸出文件,其中數(shù)據(jù)起始字節(jié)位置數(shù)值的計(jì)算非常復(fù)雜(該值是從上一個(gè)要素解碼后計(jì)算出來的),首先要知道起始位置(L1),再加上該要素基礎(chǔ)值的占位寬度(n),再加上NBINC1的占位6 bit,最后加上增量值的占位寬度(s)乘以要素格式(N),起始位L=L1+(n+6+s×N)/8[+1],其中[+1]是需要根據(jù)該要素占位bit數(shù)決定,bit總數(shù)除以8,余數(shù)少于起始字節(jié)起始bit,則不用[+1],反之,則要[+1];第36、37兩行也是必須的,正常關(guān)閉程序前面打開的文件,否則形成垃圾信息占用系統(tǒng)內(nèi)存。
在壓縮格式BUFR的解碼中,由于編碼結(jié)構(gòu)的復(fù)雜性和不確定性,常常容易出現(xiàn)解碼錯(cuò)誤的現(xiàn)象,并且難以判定是否錯(cuò)誤。本研究針對(duì)容易出錯(cuò)的情形進(jìn)行分析。
錯(cuò)誤1:取值順序與輸出值的順序。Bufr格式是二進(jìn)制格式的文件,實(shí)際存儲(chǔ)數(shù)據(jù)是二進(jìn)制的0、1形式保存,從第1位到最后一位。數(shù)據(jù)的抽取也是從第1位往后逐bit位抽取的,但是,在取完值之后,需要重新按計(jì)算機(jī)的8 bit為一個(gè)字節(jié)的結(jié)構(gòu)從后往前組織數(shù)據(jù)。
錯(cuò)誤2:多字節(jié)值的生成;在取值過程中,有些要素的寬度是占用很多bit的,例如,“C波段海洋范圍”占位寬度31 bit,此時(shí),獲取的31 bit,需要分為4字節(jié),而且是從后往前排,即最后3個(gè)字節(jié)各8 bit,最前一個(gè)字節(jié)7 bit,從前往后分別記為:a、b、c、d字節(jié),計(jì)算值為a×256×256×256+b×256×256+c×256+d。在實(shí)際計(jì)算時(shí),容易從前往后取bit組成新的字節(jié),并且容易計(jì)算成a+b+c+d的值。
錯(cuò)誤3:NBINC s的取值;NBINC s的固定長(zhǎng)度是6 bit,該值的大小取決于后面增量的bit數(shù),因此,該值的準(zhǔn)確獲取非常重要。在計(jì)算的結(jié)果判斷上有個(gè)重要的方法,即該值的小于或者等于初始值的占位寬度,如果是大于初值占位數(shù),一般都錯(cuò)誤,需要重新檢查數(shù)值的獲取及重組方法。常見錯(cuò)誤是:由于NBINCs取值結(jié)構(gòu)簡(jiǎn)單,忽略了錯(cuò)誤的存在,導(dǎo)致取值大于初值占位寬度,從而導(dǎo)致后續(xù)的取值大相徑庭。
本研究通過實(shí)際壓縮格式BUFR文件的解碼實(shí)例,詳細(xì)分析了分析解碼過程,列出了解碼的重要步驟。詳細(xì)闡述了實(shí)際解碼過程中遇到問題的解決方法,為后來者提供參考,減少錯(cuò)誤重犯,大大提高了解碼編程的效率和準(zhǔn)確性。