diff --git a/gwinc/util.py b/gwinc/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..b0a7618261a2dfddee7d1bf977f77db7ef4c7ac7
--- /dev/null
+++ b/gwinc/util.py
@@ -0,0 +1,34 @@
+import datetime
+import h5py
+
+from . import struct
+
+
+def load_hdf5(path):
+    """Load IFO and noises from HDF5 file.
+
+    Returns (name, ifo, noises) tuple load from file.
+
+    """
+    with h5py.File(path, 'r') as f:
+        name = f.attrs['name']
+        ifo = struct.Struct.from_yaml(f.attrs['IFO'])
+        noises = {}
+        for name, data in f['/traces'].items():
+            noises[name] = data.value
+        return name, ifo, noises
+
+
+def save_hdf5(name, ifo, noises, path):
+    """Save IFO and noises to HDF5 file.
+
+    """
+    with h5py.File(path, 'w') as f:
+        f.attrs['schema'] = 'GWINC noise budget'
+        # FIXME: add GWINC version
+        f.attrs['date'] = datetime.datetime.now().isoformat()
+        f.attrs['name'] = name
+        f.attrs['IFO'] = ifo.to_yaml()
+        tgrp = f.create_group('traces')
+        for noise, data in noises.items():
+            tgrp.create_dataset(noise, data=data)
diff --git a/setup.py b/setup.py
index 8113c907058f258ea9e226172891d13836958778..ecb7f502ca92ba0417873f50383089485e415926 100755
--- a/setup.py
+++ b/setup.py
@@ -30,6 +30,7 @@ setup_args = dict(
     install_requires = [
         'numpy',
         'scipy',
+        'h5py',
         'matplotlib',
     ],