Upgrade to Pro — share decks privately, control downloads, hide ads and more …

知ろう!使おう!HDF5ファイル!/pycon-jp-2019-talk

thinkAmi
September 17, 2019

 知ろう!使おう!HDF5ファイル!/pycon-jp-2019-talk

PyCon JP 2019の発表資料です

thinkAmi

September 17, 2019
Tweet

More Decks by thinkAmi

Other Decks in Programming

Transcript

  1. お前誰よ / Who are you ? @thinkAmi Python/Django/Web アプリケーションエンジニア Blog

    :メモ的な思考的な (http://thinkami.hatenablog.com/) ( 株) 日本システム技研 PyCon JP 2019 Gold Sponsor (2016-18 Silver Sponsor) ギークラボ長野 Python Boot Camp in 長野 みんなのPython 勉強会 in 長野
  2. HDF 5 HDF Hierarchical Data Format 階層構造を持ったデータフォーマット The HDF Group

    がサポート https://www.hdfgroup.org/ HDF5 ファイルの開発を進めるNPO 団体 米国立スーパーコンピュータ応用研究所 (NCSA: National Center for Supercomputing Applications) 発
  3. HDF5 ファイルと言語バインディング 公式 C, Fortran, C++, Java, P/Invoke サードパーティ Python,

    R, Julia, 他 参考:HDF5 Language Bindings https://portal.hdfgroup.org/display/HDF5/HDF5+Language+Bind ings
  4. HDFView とは The HDF Group が提供しているビューワー & エディタ Open JDK

    11 で動作 HDF5 の他、HDF4 もサポート 公式ページ https://portal.hdfgroup.org/display/HDFVIEW/HDFView
  5. ライブラリの比較 名前 Layer 特徴 h5py 低 HDF5 API を忠実に再現 PyTables

    高 HDF5 ファイルを拡張、テーブル概念の追加やパフ ォーマンス改善等を実装。よりデータベースに近い 詳細については、各ライブラリのFAQ を参照 http://docs.h5py.org/en/stable/faq.html#what-s-the-difference- between-h5py-and-pytables http://www.pytables.org/FAQ.html#how-does-pytables-compare- with-the-h5py-project
  6. h5py とPyTables のデータ互換性 例:PyTables で作った文字列データを、h5py で読む # PyTables でファイルを作る with

    tables.open_file(filepath, 'w') as f: dataset = f.create_vlarray('/', 'str_data', atom=VLUnicodeAtom()) dataset.append(' シナノゴールド') # PyTables で開く with tables.open_file(filepath, 'r') as f: node = f.get_node(where='/', name='str_data') for row in node.iterrows(): print(row) # => シナノゴールド # h5py で開く with h5py.File(filepath, mode='r') as f: dataset = f['str_data'] print(dataset[0]) # => [12471 12490 12494 12468 12540 12523 12489]
  7. HDF5 ファイルを開く 書込・読込は、 mode で切り替え import h5py output = OUTPUT_DIR.joinpath('use_h5py.h5')

    # with を抜けると、書き込まれる with h5py.File(output, mode='w') as file: # 処理
  8. Dataset ( 文字列) 作成 ds_str = group.create_dataset( # h5py 2.9

    までは、 dtype=h5py.special_dtype(vlen=str) name='name', shape=(1,), dtype=h5py.string_dtype()) ds_str[0] = ' シナノゴールド'
  9. Dataset ( 画像) 作成 # 画像を読み込み image_path = INPUT_DIR.joinpath('shinanogold.png') with

    image_path.open(mode='rb') as img: image_binary = img.read() # NumPy 配列化 image_data = np.frombuffer(image_binary, dtype='uint8') # バイナリの型定義 TYPE_OF_BINARY = h5py.special_dtype(vlen=np.dtype('uint8')) # 画像を設定 ds_img = group.create_dataset( 'image', image_data.shape, dtype=TYPE_OF_BINARY) ds_img[0] = image_data
  10. Dataset (Excel) 作成 画像と変わらない excel_path = INPUT_DIR.joinpath('mybook.xlsx') with excel_path.open(mode='rb') as

    excel: excel_binary = excel.read() # np.frombuffer() を使うところだけが違う excel_data = np.frombuffer(excel_binary, dtype='uint8') ds_excel = group.create_dataset( 'spec', excel_data.shape, dtype=TYPE_OF_BINARY) ds_excel[0] = excel_data
  11. Attribute 作成 Group, Dataset のどちらにも作成可能 # Group のAttribute group.attrs['title'] =

    ' りんご情報' # Dataset のAttribute ds_str.attrs['color'] = ' 黄色系'
  12. Dataset ( 画像) の読込 画像も、Dataset の取得方法は同じ # HDF5 ファイルから、image の入ったDataset

    を取得 rds_img = file['apple/image'] # Pillow で開く Image.open(io.BytesIO(rds_img[0])).show()
  13. Dataset (Excel) の読込 # HDF5 ファイルから、Excel の入ったDataset を取得 dataset =

    f['apple/spec'] # 一度ファイルとして保存 with excel_path.open('wb') as w: w.write(dataset[0]) # 拡張子"xlsx" に関連付けされたアプリで開く os.system(f'open {excel_path}') # Mac の場合
  14. 検索 (h5py) visititems() で各オブジェクト(Group/Dataset) にアクセス可能 コールバック関数内で絞り込むことも可能 def print_callback(name, obj): #

    コールバック関数 print(f'name: {name}, type: {type(obj)}') # データの検索 file.visititems(print_callback) # 結果 ( 見栄えを調整) # name: apple, type: <class 'h5py._hl.group.Group'> # name: apple/excel, type: <class 'h5py._hl.dataset.Dataset'> # name: apple/image, type: <class 'h5py._hl.dataset.Dataset'> # name: apple/name, type: <class 'h5py._hl.dataset.Dataset'>
  15. gzip 圧縮 10MB のバイナリをDataset に入れると、無圧縮では約170MB create_dataset() の引数 compression に圧縮形式 (gzip

    など) を入れる with h5py.File(compression_file_path, mode='w') as file: compression = file.create_dataset( 'big_size_data', big_size_data.shape, dtype=TYPE_OF_BINARY, # 圧縮形式を指定 compression='gzip') compression[0] = big_size_data # HDF5 ファイルのサイズを表示 print(f'{str(os.path.getsize(compression_file_path)).rjust(10)} [compress]') # => 10003716 [compress] ( 約10MB)
  16. ところで import pathlib import h5py BASE_DIR = pathlib.Path(__file__).resolve().parents[0] OUTPUT_DIR =

    BASE_DIR.joinpath('output', 'h5py') output = OUTPUT_DIR.joinpath('use_h5py.h5') with h5py.File(output, mode='w') as file: ...
  17. HTTP + HDF5 ファイル h5serv HDF REST API に準拠し、HTTP でHDF5

    ファイルを操作 Tornado ベース The HDF Group のリポジトリにて提供 https://github.com/HDFGroup/h5serv
  18. h5serv でDataset 作成 Dataset の型定義をPOST URL_BASE = 'http://test.example.com:5000/' str_type =

    {'charSet': 'H5T_CSET_UTF8', 'class': 'H5T_STRING', 'strPad': 'H5T_STR_NULLTERM', 'length': 'H5T_VARIABLE'} payload = {'type': str_type, 'shape': 1} res1 = requests.post( URL_BASE + 'datasets', json=payload ).json()
  19. h5serv でDataset 作成 Dataset の中身をPUT url = URL_BASE + 'datasets/'

    + res1.get('id') + '/value' res2 = requests.put( url, json={ 'value': ' ワールド' } )
  20. h5serv で作成されたもの 2 つのHDF5 ファイル 全体の構造を管理するHDF5 ファイル (mytoc.h5) データが格納される実際のHDF5 ファイル

    (test.h5) $ python h5serv --port=5000 --toc_name=mytoc.h5 --domain=example.com URL_BASE = 'http://test.example.com:5000/'
  21. h5pyd HDF REST API のクライアントライブラリ The HDF Group のリポジトリにて提供 https://github.com/HDFGroup/h5pyd-

    h5py とほぼ互換のAPI を持つ 少し書き換えるだけで、既存コードのHTTP 化が可能
  22. h5serv とh5pyd を使う サーバーで、h5serv を起動 クライアントで、h5pyd を使ったスクリプトを実行 with h5pyd.File('test.example.com', mode='w',

    endpoint='http://localhost:5000') as file: ds_str = file.create_dataset(name='hello', data='world', dtype='S6') # byte 型になるので、デコードしておく print(file['hello'].value.decode('utf-8')) # => hello
  23. HSDS HSDS = Highly Scalable Data Service The HDF5 Grouop

    のリポジトリにて提供 https://github.com/HDFGroup/hsds クラウドネイティブな構成 データの保管先はAWS S3
  24. HDF5 のバージョン HDF5 x.y.z 現在は、2 系統 HDF5 1.8.x 系 HDF5

    1.10.x 系 ライブラリによっては、1.8.x しかサポートしてない場合も
  25. ライフサイクル マイグレーションページに記載あり https://portal.hdfgroup.org/display/HDF5/Migrating+from+HDF5 +1.8+to+HDF5+1.10 1.8 系:2020 年5 月でパッチリリース終了 HDF HDF5

    における境界外読み取りに関する脆弱性 https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019- 002044.html 1.12 系:2019 年夏にリリース予定( だった)
  26. h5py で使われるバージョン HDF5 のライブラリ libhdf5 を自動的で検知・利用 自分で指定することも可能 $ brew install

    hdf5 /usr/local/Cellar/hdf5/1.10.5_1 $ export HDF5_DIR=/usr/local/Cellar/hdf5/1.10.5_1 $ pip install --no-binary=h5py h5py >>> h5py.version.info h5py 2.10.0 HDF5 1.10.5 # 指定したバージョン
  27. まとめ 科学技術分野以外でも、HDF5 ファイルは手軽に使える Python ライブラリが充実している h5py, PyTables, h5serv, h5pyd, HSDS

    ローカルだけでなく、サーバー・クラウドでも利用可能 今後もHDF5 ファイルには機能が追加されていく予定
  28. 次のステップ 書籍「Python and HDF5 」(Andrew Collette 著、米オライリー) Python ライブラリの扱い方 意外と奥が深い、HDF

    の世界(Python ・h5py 入門) - Qiita https://qiita.com/simonritchie/items/23db8b4cb5c590924d95 Getting started with HDF5 and PyTables - PyCon Slovakia(SK) 2018 https://pyvideo.org/pycon-sk-2018/getting-started-with-hdf5- and-pytables.html
  29. 公式情報 The HDF Group のtwitter https://twitter.com/hdf5 HDF Forum https://forum.hdfgroup.org/latest SlideShare

    The HDF-EOS Tools and Information Center https://www.slideshare.net/HDFEOS Youtube https://www.youtube.com/channel/UCRhtsIZquL3r-zH-R-r9-tQ
  30. h5serv を使うための準備 自分の端末で使う場合、hosts ファイルに設定 < ファイル名>.< 適当なドメイン> h5serv が動作している example.com

    にアクセスすると、 test.h5 フ ァイルを操作できるよう設定 127.0.0.1 test.example.com domain オプションで、ドメインを指定して起動 $ python h5serv --port=5000 --toc_name=mytoc.h5 --domain=example.com
  31. h5serv を使うための準備 操作対象のファイルを作成 中身は空で問題ない p = Path(__file__).resolve().parents[0].joinpath('h5serv', 'data', 'test.h5') with

    h5py.File(p, mode='w') as f: pass この時点での data ディレクトリ構成 $ tree . ├── public/ ├── readme.txt └── test.h5
  32. h5serv での動作確認 型定義を作成 str_type = {'charSet': 'H5T_CSET_UTF8', 'class': 'H5T_STRING', 'strPad':

    'H5T_STR_NULLTERM', 'length': 'H5T_VARIABLE'} payload = {'type': str_type, 'shape': 1} res1 = requests.post( URL_BASE + 'datasets', json=payload ).json()
  33. バージョン (HDF5 x.y.z) x: major version number ライブラリやファイルフォーマットの大きな変更あり y: minor

    version number 新しい機能によるファイルフォーマットの変更 偶数はstable 、奇数はdevelop z: release number バグ修正等ライブラリの改善、フォーマットの変更なし https://portal.hdfgroup.org/display/HDF5/HDF5+Library+Release+ Version+Numbers