1. 程式人生 > 其它 >【IDL程式碼庫】大資料分塊寫入HDF5檔案示例程式碼

【IDL程式碼庫】大資料分塊寫入HDF5檔案示例程式碼

IDL提供了專門針對HDF5科學資料格式的讀寫函式庫。可以參考IDL幫助的Routines (alphabetical) > Routines: H > HDF5 Routines 這個章節檢視函式列表。

如果只是簡單的讀寫HDF5檔案,可以利用下面三個函式即可:

  • H5_GETDATA        讀取資料
  • H5_LIST                檢視資料列表
  • H5_PUTDATA        寫入資料

注:上面3個函式用法非常簡單,這裡不再舉例。要求IDL最低版本為8.3。

下面介紹如何將一個大資料分塊寫入HDF5檔案。在test_write_h5d.pro原始碼中,分成了如下幾個步驟

(1)首先隨機建立一個大資料,利用了hanning函式(生成漢寧窗,主要用於快速傅立葉變換),再計算兩個維度的步長、步數。

(2)然後將第一個分塊資料寫入資料集,並進行第一個分塊資料的視覺化展示。

(3)最後是一個巢狀迴圈,將剩餘分塊資料動態寫入,併疊加展示每一個分塊資料。

下圖為視覺化結果,左側圖形為分塊效果,右側圖形為整體資料效果。 

圖:視覺化效果


最後附上原始碼:

PRO test_write_h5d
  COMPILE_OPT idl2

  ; 建立新的 HDF5檔案,可修改
  file = 'D:\temp\mytest_h5_file.h5'
  fid = H5F_CREATE(file)

  ; 隨機建立初始維度
  random_number1 = SORT(RANDOMU(seed, 1000))
  random_number2 = SORT(RANDOMU(seed, 2000))
  dim1 = random_number1[0]>500
  dim2 = random_number2[0]>1000

  ; 每一個維度的分塊步長
  step1 = 100
  step2 = 200

  ; 每一個維度的分塊數目
  nstep1 = dim1/step1
  nstep2 = dim2/step2

  ; 重新定義大資料維度,可以完美分塊
  dim1 = nstep1*step1
  dim2 = nstep2*step2

  ; 建立一個大資料
  data = hanning(dim1,dim2)

  ; 取出第一個分塊資料
  data_segment = data[0:(step1-1),0:(step2-1)]

  ; 展示第一個分塊資料
  s = surface(data_segment, title='分塊效果展示', $
    xrange=[0,dim1-1], yrange=[0,dim2-1], layout=[2,1,1],$
    dimensions=[900,500], margin=[.2,.2,.2,.2])

  ; 根據資料建立一個datatype
  datatype_id = H5T_IDL_CREATE(data)

  ; 建立一個dataspace,並且可以進行擴充套件
  dataspace_id = H5S_CREATE_SIMPLE([step1,step2],$
    max_dimensions=[-1,-1])

  ; 建立一個dataset
  dataset_id = H5D_CREATE(fid,'Hanning', datatype_id,$
    dataspace_id, chunk_dimensions=[step1,step2])

  ; 擴充套件dataset的維度,以適應第一個分塊資料
  H5D_EXTEND,dataset_id,SIZE(data_segment,/dimensions)

  ; 將第一個分塊資料寫入dataset
  H5D_WRITE,dataset_id,data_segment

  ; 同上面操作相似,將剩下的資料分塊寫入到HDF5檔案中
  FOR ind1 = 0L, nstep1-1 DO BEGIN
    FOR ind2 = 0L, nstep2-1 DO BEGIN

      ; 如果檔案dataspace已存在,則關閉
      IF (ISA(iter_data_space_id)) THEN BEGIN
        H5S_CLOSE, iter_data_space_id
      ENDIF

      ; 如果memory dataspace已存在,則關閉
      IF (ISA(iter_data_space_id2)) THEN BEGIN
        H5S_CLOSE, iter_data_space_id2
      ENDIF

      ; 計算當前分塊的起始行列號
      start1 = ind1 * step1
      start2 = ind2 * step2

      ; 獲取當前分塊資料
      data_segment = data[start1:(start1+step1-1),start2:(start2+step2-1)]
      
      ; 展示當前分塊資料
      s = surface(data_segment, layout=[2,1,1], $
        LINDGEN(step1)+start1, LINDGEN(step2)+start2, /overplot)

      ; 擴充套件dataset維度,輸入維度應該是擴充套件後維度,而不是新增的維度
      H5D_EXTEND, dataset_id, [start1+step1, start2+step2]

      ; 建立新的dataspace
      iter_data_space_id = H5D_GET_SPACE(dataset_id)

      ; 選中包含當前分塊資料的 slab
      H5S_SELECT_HYPERSLAB, iter_data_space_id, [start1,start2], $
        [step1,step2], /RESET

      ; 建立memory data space
      iter_data_space_id2 = H5S_CREATE_SIMPLE([step1,step2])

      ; 使用檔案dataspace和 Memory dataspace,將當前分塊資料寫入Dataset
      H5D_WRITE, dataset_id, data_segment, $
        FILE_SPACE_ID=iter_data_space_id,$
        MEMORY_SPACE_ID=iter_data_space_id2
    ENDFOR
  ENDFOR

  ; 關閉前邊開啟的識別符號
  H5S_CLOSE, iter_data_space_id
  H5S_CLOSE, iter_data_space_id2
  H5S_CLOSE,dataspace_id
  H5D_CLOSE,dataset_id
  H5T_CLOSE,datatype_id
  H5F_CLOSE,fid

  HELP, data

  ; 讀取新建的HDF5資料列表
  h5_list, file
  ; 獲取資料並進行視覺化
  in_dat = H5_GETDATA(file, '/Hanning')
  s=surface(in_dat, layout=[2,1,2], /current, $
    margin=[.2,.2,.2,.2], title='完整資料展示')

END