のらりくらり

物理化学分野のポスドクです。プログラミング、読書、自転車などが好きです。

HDF5フォーマットに関するメモ書き

HDF5というファイルフォーマットがあります。
このたび、しばらくC++でHDF5のファイルを出力するというのをやっていたのですが、それで苦労したりしていたので、とりあえず超初歩的なところからいくつかポイントをまとめていきたいと思います。

そもそもHDF5って?
HDF5はHierarchical Data Format 5の略です。科学技術計算などの分野で、たとえば時系列に変化する大量のデータを逐一記録するときなどに使われるそうです。5はメジャーなバージョンの番号からきているのかと思います。
名前のとおり、階層化されたデータの形式、といえばそうなのですが、それだけだとイメージがつかないかもしれないので、まずはこの階層化、の意味するところがどういうものなのかというのをざっくりと説明したいと思います。
階層化されたデータフォーマットの実現のために、HDF5のデータはデータセットとグループという単位からなります。
いきなりこの説明に入りたいのですが、まずはこれに似た構造をCSVファイルとさらにそれを一般的なファイルシステムを用いて管理する事例を考えてみます。
CSVといえば、まずよく下のような名簿みたいなファイルがサンプルとして出てくるのは何度も見られたことがあるのではないかと思います。

名前, 年齢, 性別
山田太郎, 23, M
山田花子, 19, F
田中次郎, 30, M

これをある一つの区域に住む人たちの名簿だとすると、同様に他の区域に住んでいる人の情報をこのような形式で記録することを考えた場合、多量に似たようなファイルが生まれることになります。
ところで、区域に関する情報は、A県B市L町などと言う風に階層化されます。これらを地域(住所)に関する階層をファイルシステムにおけるディレクトリだとするとA県に関するこのような情報は下のようなディレクトリ構造で表されるのは明かです。

A県
  |--B市
  |   |--L町
  |   |   |--1番地に住んでる人.csv
  |   |   |--2番地に住んでる人.csv
  |   | 
  |   |--M町
  |   |--N町
  |
  |--C市
  |--D市

さらに、これを毎年1回新しいものを作り直していくとすると(こういう情報は上書き保存するのはよくない)このA県の一個上の階層は2013とか2014みたいな作った時期に関する階層になるはぜです。
とりあえずこのようなやり方だと、多量のファイルが出来るってのは容易に想像できます。
そこでこれらの階層構造を一つのファイルの中で出来るように実現したものがHDF5です。先ほど、「HDF5のデータはデータセットとグループという単位からなる」と述べました。先の例での階層化のためのディレクトリがグループ、そして実際のデータをまとめて格納したCSVファイル1枚がデータセットという単位と対応します。
以下は、添付されているサンプルコードの出力した階層のマップをビューワで表示させてみたものの一部です。


インストールや環境の構築など
まずはHDF5の公式ページにアクセスしましょう。
準備としてはまずはファイルを出力するためのプログラミング言語向けのライブラリの入手、インストールと、出力されたHDF5ファイルを開いて見るためのビューワの二つが必要になります。
1、ライブラリのビルド・インストール
まずはhdf5のライブラリのインストールを行います。私はMac OS X Mountain Lion上で行いました。個人的にパッケージングシステムはあまり好きではないので自前でビルドしており、おそらくLinuxや他のUNIX系OSでも同じようにして出来るのではないかという風に思います。
ライブラリのソースコードは公式ページのDownloadの中で目的のリンクが見つかるかと思いますが、面倒くさければ現行版のソースコードのリストからダウンロードできると思います。ここからソースコードアーカイブをダウンロードしたら、

$> tar -zxf hdf5-1.8.10.tar.bz2
$> cd hdf5-1.8.10
$> ./configure --prefix=$HOME/local --enable-cxx
$> make
$> make install

お決まりのautotoolsを採用したプロジェクトのビルド作業です。なお、ここではC++からの使用を解説するため、configure時にenable-cxxを渡しています。
Macの場合はmacportやhomebrew,linuxだとyumやapt-getでパッケージングされているようなので、そちらを使用しても全く問題ないと思います。
2、ビューワのインストール
公式ページのここから使用しているプラットフォームに対応したバイナリをダウンロード、インストールすれば良いです。

3、とりあえず動かしてみる
これらのサンプルコードがライブラリのインストール時に一緒にインストールされているはずです。prefixとして指定したディレクトリの中にshare/hdf5_examples というディレクトリが出来ているかと思います。この中に各言語のサンプルコードがあり、僕はこれを参考にまずちらちら書いてみました。これ、makefileをつけてくれればありがたいのですが。。。

今回は、これをどれか一つコンパイルして、とりあえずHdf5のファイルを作り、それを開いてみるところまでやってみます。流れとしては、

$> cd <prefix>/share/hdf5_examples/c++
$> ls
chunks.cpp    compound.cpp  create.cpp    extend_ds.cpp h5group.cpp   readdata.cpp  writedata.cpp
$> c++ h5group.cpp -lhdf5 -lhdf5_cpp
$> ./a.out
dataset "/Data/Compressed_Data" is open
dataset "/Data_new/Compressed_Data" is open

Iterating over elements in the file
Name : Data
Name : Data_new

Unlinking...
"Data" is unlinked

Iterating over elements in the file again
Name : Data_new

一つ重要なのは、(今回我々が使おうとしているのはC++のインターフェースですが)かならず、libhdf5とlibhdf5_cppの二つをリンクする必要があるということです。
今回はh5group.cppをコンパイルしてみましたが、それを実行して上記のようになった後、成功していればGroup.h5というファイルが出力されているはずです。
それをビューワで開いてみて、

という感じの階層構造をもったファイルが出来ていれば、成功です。他のサンプルコードも同様にコンパイルして、Hdf5のファイルを出力することが出来ると思います。

もし次回を書く気になったら、次はデータセットの組み立てについて書きたいと思います。
[2013/08/24追記]その2書きました。