Python讀取資料同化常用的prepbufr格式文件

2022-01-16 小鴻的拾荒之旅

    在做資料同化過程中,經常會使用到常規觀測資料(地面,船舶,浮標,探空,飛機等觀測)、衛星資料(amsua、amsub等)、GPS掩星資料等作為觀測源,通常情況下他們為prepbufr格式。

   在資料同化的分析過程中,我們可能需要直接讀取該資料的要素信息,所以時常會對該類型的資料進行分析和可視化。在大型機中,普遍使用MET這一利器作為讀取prepbufr的工具,但是MET的配置過於複雜,依賴庫過於繁瑣,如何在本地機中以簡單的代價讀取該資料是一個很有意思的問題。

這裡介紹一種基於python的prepbufr讀取方法:

系統:Linux系統,這裡推薦Ubuntu子系統環境依賴:gfortran、初步搭建好的python模塊名稱:ncepbufr源碼地址:https:

1、安裝過程

解壓py-ncepbufr-master.tar.gz

進入解壓後的目錄,注意一定要在當前目錄下

執行python setup.py build,目的是產生src/libbufr.a等文件。默認使用gfortran,如果想使用其他版本的fortran,可以執行:

python setup.py build config_fc --fcompiler=<compiler name>

執行python setup.py install

最終結果:

2、安裝測試

    進入app/py-ncepbufr/test/ 目錄,可以發現該目錄下有很多的python文件。可以用來測試常規觀測、衛星觀測、掩星觀測等能否正常讀取。如果不行可能是環境問題,推薦gfortran。

3、常規觀測和衛星觀測讀取示例

(1)常規觀測

代碼:prepbufr_read_conv.py <input prepbufr> >& info.txt

from __future__ import print_functionimport ncepbufrimport sys
hdstr='SID XOB YOB DHR TYP ELV SAID T29'obstr='POB QOB TOB ZOB UOB VOB PWO MXGS HOVI CAT PRSS TDO PMO'qcstr='PQM QQM TQM ZQM WQM NUL PWQ PMQ'oestr='POE QOE TOE NUL WOE NUL PWE'

if len(sys.argv) < 2: raise SystemExit('prepbufr_read_conv.py <input prepbufr> >& info.txt')
prepbufr_filename = sys.argv[1]bufr = ncepbufr.open(prepbufr_filename)bufr.print_table() bufr.dump_table('prepbufr.table') while bufr.advance() == 0: print(bufr.msg_counter, bufr.msg_type, bufr.msg_date, bufr.receipt_time) while bufr.load_subset() == 0: hdr = bufr.read_subset(hdstr).squeeze() station_id = hdr[0].tostring() obs = bufr.read_subset(obstr) nlevs = obs.shape[-1] oer = bufr.read_subset(oestr) qcf = bufr.read_subset(qcstr) print('station_id, lon, lat, time, station_type, levels =',\ station_id,hdr[1],hdr[2],hdr[3],int(hdr[4]),nlevs) for k in range(nlevs): if nlevs > 1: print('level',k+1) print('obs',obs[:,k]) print('oer',oer[:,k]) print('qcf',qcf[:,k]) if bufr.msg_counter == 2: breakbufr.close()

運行結果:

(2)衛星觀測

代碼:prepbufr_read_radiance.py <input prepbufr> >& info.txt

from __future__ import print_functionimport ncepbufrimport syshdstr1 ='SAID SIID FOVN YEAR MNTH DAYS HOUR MINU SECO CLAT CLON CLATH CLONH HOLS'hdstr2 ='SAZA SOZA BEARAZ SOLAZI'

if len(sys.argv) < 2: raise SystemExit('prepbufr_read_radiance.py <input prepbufr> >& info.txt')
prepbufr_filename = sys.argv[1]bufr = ncepbufr.open(prepbufr_filename)bufr.print_table()while bufr.advance() == 0: print(bufr.msg_counter, bufr.msg_type, bufr.msg_date) while bufr.load_subset() == 0: hdr1 = bufr.read_subset(hdstr1).squeeze() hdr2 = bufr.read_subset(hdstr2).squeeze() yyyymmddhhss ='%04i%02i%02i%02i%02i%02i' % tuple(hdr1[3:9]) print('sat id,sensor id lat, lon, yyyymmddhhmmss =',int(hdr1[0]),\ int(hdr1[1]),hdr1[9],hdr1[10],yyyymmddhhss) obs = bufr.read_subset('TMBR',rep=True).squeeze() nchanl = len(obs) for k in range(nchanl): print('channel, tb =',k+1,obs[k]) if bufr.msg_counter == 4: breakbufr.close()

結果:

具體怎樣將其更好讀取並輸出,讀者請自行改進~

4、常規prepbufr轉nc的代碼:

"""convert prepbufr file to netCDF"""from __future__ import print_functionimport ncepbufrimport numpy as npfrom netCDF4 import Datasetfrom ncepbufr import prepbufr_mnemonics_dict as mnemonics_dictimport sys
nobs_chunk = 200
time_min = -3.0; time_max = 3.0
if len(sys.argv) < 3: raise SystemExit('prepbufr2nc <input prepbufr> <output netcdf>')
prepbufr_filename = sys.argv[1]netcdf_filename = sys.argv[2]if prepbufr_filename == netcdf_filename: raise IOError('cannot overwrite input prepbufr file')
hdstr='SID XOB YOB DHR TYP ELV SAID T29'obstr='POB QOB TOB ZOB UOB VOB PWO CAT PRSS TDO PMO XDR YDR HRDR'qcstr='PQM QQM TQM ZQM WQM PWQ PMQ'oestr='POE QOE TOE ZOE WOE PWE'
skiptypes = ['SATWND']
bufr = ncepbufr.open(prepbufr_filename)nmessages = 0while bufr.advance() == 0: if bufr.msg_type in skiptypes: continue nmessages += 1bufr.rewind()
nc = Dataset(netcdf_filename,'w',format='NETCDF4')
hd = nc.createDimension('hdrinfo',len(hdstr.split()))nhdd = len(hd)ob = nc.createDimension('obinfo',len(obstr.split()))nobd = len(ob)oe = nc.createDimension('oeinfo',len(oestr.split()))noed = len(oe)qc = nc.createDimension('qcinfo',len(qcstr.split()))nqcd = len(qc)nobsd = nc.createDimension('nobs',None)nmsgs = nc.createDimension('nmsgs',nmessages)
hdrdata =\nc.createVariable('header',np.float64,('nobs','hdrinfo'),\fill_value=bufr.missing_value,zlib=True,chunksizes=(nobs_chunk,nhdd))hdrdata.desc = 'observation header data'for key in hdstr.split(): hdrdata.setncattr(key,mnemonics_dict[key])hdrdata.hdrinfo = hdstrobid = nc.createVariable('obid',str,('nobs',),zlib=True)obid.desc = 'observation id (station id/type code/lon/lat/time/elevation/pressure)'obdata =\nc.createVariable('obdata',np.float32,('nobs','obinfo'),\fill_value=bufr.missing_value,zlib=True,chunksizes=(nobs_chunk,nobd))oedata =\nc.createVariable('oberr',np.float32,('nobs','oeinfo'),\fill_value=bufr.missing_value,zlib=True,chunksizes=(nobs_chunk,noed))qc_fillval = 255qcdata =\nc.createVariable('qcdata',np.uint8,('nobs','qcinfo'),\fill_value=qc_fillval,zlib=True,chunksizes=(nobs_chunk,nqcd))msgnum = nc.createVariable('msgnum',np.uint32,('nobs'),\zlib=True,chunksizes=(nobs_chunk,))msgnum.desc = 'bufr message number'subsetnum = nc.createVariable('subsetnum',np.uint16,('nobs'),\zlib=True,chunksizes=(nobs_chunk,))subsetnum.desc='subset number within bufr message'msgtype = nc.createVariable('msgtype',str,('nmsgs'),zlib=True)msgtype.desc='bufr message type'msgdate = nc.createVariable('msgdate',np.uint32,('nmsgs'),zlib=True)msgdate.desc='bufr message date'for key in obstr.split(): obdata.setncattr(key,mnemonics_dict[key])obdata.obinfo = obstrobdata.desc = 'observation data'for key in oestr.split(): oedata.setncattr(key,mnemonics_dict[key])oedata.oeinfo = oestroedata.desc = 'observation error data'for key in qcstr.split(): qcdata.setncattr(key,mnemonics_dict[key])qcdata.qcinfo = qcstrqcdata.desc = 'observation QC data'
nob = 0obid_set = set()nmsg = 0while bufr.advance() == 0: if bufr.msg_type in skiptypes: continue
hdrarr = []; obsarr = []; qcarr = []; errarr = []; obidarr = [] msgnumarr = []; subsetnumarr = [] nobs_message = 0 nsubset = 0 nc['msgtype'][nmsg] = bufr.msg_type nc['msgdate'][nmsg] = bufr.msg_date nmsg += 1
while bufr.load_subset() == 0: nsubset += 1 hdr = bufr.read_subset(hdstr).squeeze() obs = bufr.read_subset(obstr) qc = bufr.read_subset(qcstr) err = bufr.read_subset(oestr) nlevs_use = 0 for nlev in range(obs.shape[-1]): lon = hdr[1]; lat = hdr[2]; time = hdr[3] press = obs[0,nlev]; z = hdr[5] if hdr[4] in [120,220,221]: lon = obs[11,nlev]; lat = obs[12,nlev] if obs[13,nlev] >= time_min and obs[13,nlev] < time_max: time = obs[13,nlev] elif hdr[4] >= 223 and hdr[4] <= 228: z = obs[3,nlev] try: obidstr = "%s %3i %6.2f %6.2f %9.5f %5i %6.1f" % \ (hdr[0].tostring(), int(hdr[4]), lon, lat, time, z, press) except: obidstr = "unknown" if obidstr not in obid_set: obid_set.add(obidstr) else: print('skipping duplicate ob %s' % obidstr) continue hdrarr.append(hdr.squeeze()) obidarr.append(obidstr) obsarr.append(obs[:,nlev]) errarr.append(err[:,nlev]) qcarr.append(qc[:,nlev]) msgnumarr.append(nmsg) subsetnumarr.append(nsubset) nob += 1; nlevs_use += 1 nobs_message += nlevs_use hdrarr = np.array(hdrarr); obsarr = np.array(obsarr) errarr = np.array(errarr); qcarr = np.array(qcarr) obidarr = np.array(obidarr); msgnumarr = np.array(msgnumarr) subsetnumarr = np.array(subsetnumarr) qcarr = np.where(qcarr == bufr.missing_value,qc_fillval,qcarr).astype(np.uint8) nob1 = nob-nobs_message print('writing message %s out of %s, type %s with %s obs' %\ (nmsg,nmessages,bufr.msg_type,nobs_message)) nc['header'][nob1:nob] = hdrarr nc['obdata'][nob1:nob] = obsarr nc['oberr'][nob1:nob] = errarr nc['qcdata'][nob1:nob] = qcarr nc['obid'][nob1:nob] = obidarr nc['msgnum'][nob1:nob] = msgnumarr nc['subsetnum'][nob1:nob] = subsetnumarr nc.sync()
bufr.close(); nc.close()

結果:

5、結語

    

    Python只是一種工具而已,重要的是看他能否解決實際的問題。如果你認為MET更好,這完全是正常的想法,由個人實際需求決定。關於本文讀入資料以後的工作,這完全可以很自由的解決,謝謝您閱讀到最後,感謝您支持!!

相關焦點

  • 【盤點】常用海洋數據資料
    數據資料涵蓋全球海底地形數據、海洋遙感數據、船測數據、浮標資料、模式同化資料等諸多方面。本文盤點目前國際常用的海洋數據資料:①地形數據,②衛星遙感資料,③再分析資料,④海洋調查資料,⑤其他。NCEP/NCAR 再分析資料採用網上通用數據格式(Network Common Data Format)。它的文件名一般分為 3 部分:變量名、特徵名、後綴。例如 air.mon.mean.nc (文件中 air 表示變量是空氣溫度,mon.mean 表示特徵是月平均值,nc 是 Netcdf 的後綴)。
  • 【Python教程】常用第三方模塊:requests
    此外,在安裝第三方模塊一節中,我們強烈推薦安裝Anaconda,安裝後,數十個常用的第三方模塊就已經就緒,不用pip手動安裝。我們已經講解了Python內置的urllib模塊,用於訪問網絡資源。但是,它用起來比較麻煩,而且,缺少很多實用的高級功能。更好的方案是使用requests。它是一個Python第三方庫,處理URL資源特別方便。
  • CSV文件操作起來還挺方便的【python爬蟲入門進階】(10)
    用正則表達式爬取古詩文網站,邊玩邊學【python爬蟲入門進階】(09)本文主要介紹csv文件的讀寫操作,文件簡單易懂。CSV文件是什麼?CSV即Comma Separate Values,這種文件格式經常用來作為不同程序之間的數據交互的格式。
  • python pip常用指令(install,list,freeze)
    在公眾號「python風控模型」裡回復關鍵字:學習資料 QQ學習群:1026993837 領學習資料
  • 基於python的OpenCV庫應用,將圖片轉化為視頻文件,程序打包發布
    如果你使用過python的畫圖庫matplotlib就知道,它其實只能生成靜態的圖片,如果我們想將實驗結果保存以備後續的觀察、分析和使用,該軟體那將顯得力不從心,也比如自己有一組靜態的美景照片,那麼如果想轉化為視頻那應該怎麼辦呢,python來解決。
  • csv文件讀寫操作 | pyhton內置csv模塊
    CSV文件,是一種常用的文本格式,因為其格式簡單、兼容性好,被廣泛使用,特別是用於程序之間轉換數據。
  • 如何使用Python進行人臉識別?
    輸入cmd,打開命令提示符。3.然後分別輸入:pip install opencv-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.compip install opencv-contrib-python -i http://pypi.douban.com
  • CSS-T | Mysql Client 任意文件讀取攻擊鏈拓展
    http://russiansecurity.expert/2016/04/20/mysql-connect-file-read/在後來的研究中,和@Dawu的討論中頓時覺得這應該是一個很有趣的trick,在逐漸追溯這個漏洞的過去的過程中,我漸漸發現這個問題作為mysql的一份feature存在了很多年,從13年就有人分享這個問題。D
  • python 代碼如何打包成.exe文件(Pyinstaller)
    本篇講如何用PyInstaller庫一步步打包python代碼。和系統版本https://www.lfd.uci.edu/~gohlke/pythonlibs/#pip打包.exe文件我寫了一段簡單的 requests 代碼yoyoblog.py"""使用requests庫獲取我的博客首頁文章地址上海-悠悠 blog:https://www.cnblogs.com/yoyoketang/"""import
  • 實用,5個案例讓 Python 輸出漂亮的表格!
    回復1024獲取Python資料原文連結:https://linuxops.org/blog/python/prettytable.html1.C、從csv文件添加數據PrettyTable不僅提供了手動按行按列添加數據,也支持直接從csv文件中讀取數據。#!
  • python 基礎 — 常用模塊
    python 的 tempstamp 是一個浮點數。>>> (datetime.now()-timedelta(days=1, hours=1, minutes=1, seconds=1)).strftime('%Y-%m-%d %H:%M:%S')'2018-03-02 21:15:24'7、datetime.now().timetuple()返回當前時間 struct_time 格式
  • python的輸入與輸出
    open()用於打開或創建文件對象,語法格式如下:f = open(file, mode='r', buffering = -1, encoding = None)在使用open函數時可以指定打開文件的模式為r(只讀),w(寫入,寫入前刪除久內容),x(創建新文件,如果文件已存在就報錯
  • 數據讀取與數據擴增方法
    它是由python語言編寫的,由scipy 社區開發和維護。skimage包由許多的子模塊組成,各個子模塊提供不同的功能。使用io.imread()讀取圖片將其儲存為一個RGB像素值矩陣。,包括動畫圖像,視頻,體積數據和科學格式。
  • 雷達資料同化之雲分析篇
    如何利用雷達資料,提高短時短臨預報能力,是諸多科學家面臨的問題。其中,資料同化是提高模式初始場,進而提高預報準確率的主要手段。雷達反射率因子,則因其與模式變量的關係高度非線性化,在同化過程中往往需要一定的反演或特殊的同化技術,使得對它的同化極具挑戰性。雲分析作為一種傳統的雷達反射率的同化方法,以高效,快速而著稱,至今仍被各大預報中心快速更新同化系統所採用。
  • 滲透技巧——Windows系統文件執行記錄的獲取與清除
    /AppCompatCacheParser/用法示例:讀取當前系統的註冊表並將結果輸出的到指定路徑: AppCompatCacheParser.exe --csv c:\test輸出結果按照上次修改的時間排序: AppCompatCacheParser.exe --csv c:\test -t讀取指定System
  • TensorFlow 篇 | TensorFlow 數據輸入格式之 TFRecord
    「導語」 TFRecord 是 TensorFlow 生態中的一個重要組件,它是一種二進位序列的存儲格式,使用該格式可以使輸入數據的讀取和處理更為高效,從而提升整體訓練流程的速度,另外,它還具有極高的靈活性,可以為複雜特徵數據的構建與解析提供便利。本文將對 TFRecord 數據文件的生成與讀取流程進行詳細地介紹,並提供相應的示例代碼作為參考。
  • Python輸出簡潔美觀的文本化表格
    PrettyTable不僅提供了手動按行按列添加數據,也支持直接從csv文件中讀取數據。#!()fp = open("res.csv", "r")table = from_csv(fp)print(table)fp.close()如果要讀取cvs文件數據,必須要先導入from_csv,否則無法運行。
  • Python 操作 Excel 匯總合集(代碼demo)
    作者:王翔丨來源:碼農升級python操作excel的模塊簡直不要太多,今天就為大家比較下各模塊之間的優缺點。其次,這兩個模塊主要用於處理xls文件,而對xlsx的文件處理很挫,甚至xlwt不支持…但為何到現在依然在使用這些模塊,因為他對xls文檔處理的優勢….模塊官網win32comhttp://pythonexcels.com/python-excel-mini-cookbook/DataNitrohttps://datanitro.com/這兩個模塊又是怎麼一回事兒?
  • Python+requests接口自動化測試框架實例詳解教程
    依然只說常用的返回值的操作。,就是常用的方法啦,大家可自行取之。(重要的事情說三遍),安裝的方法很簡單,由於小編是使用pip來管理python包安裝的,所以只要進入python安裝路徑下的pip文件夾下,執行以下命令即可哈哈哈,這樣我們就可以利用python連結資料庫啦~(鼓個掌,慶祝下)小夥伴們發現沒,在整個文件中,我們並沒有出現具體的變量值哦,為什麼呢?