Source code for hdf5

"""
This module will collect tools for reading, writing and testing structured
HDF5_ files.

HDF5 Format Specification
-------------------------

Here is a sample of the HDF5 file format.

::

    /
    attributes: {'date': '2014-07-22',
                 'time': '13:00:00',
                 'hdf5_version': 'v0.1',  # Version of the format specification
                 'source': 'PSB-B19-AFM',
                 'help': 'What is this data?'
                 'extra_dimensions': 'x2'
                 'comment': 'This is an example HDF5 file with multiple dimensions, and several averages for each data point.'}
        x
        attributes: {'name': 'Frequency',
                     'unit': 'Hz',
                     'label': 'f [Hz]'
                     'label_latex': r'$f \\: [\\mathrm{Hz}]$',
                     'initial': 0.0,
                     'step': 0.5,
                     'help': 'Frequency array for PSD.'}
            [0, 0.5, 1.0, 1.5]

        x2
        attributes: {'name': 'Laser Power',
                     'unit': 'mW',
                     'label': 'P [mW]',
                     'label_latex': r'$P \\: [\\mathrm{mW}]$',
                     'help': 'Interferometer Output Laser Power'
                    }
            [2.0]

        y/
        attributes: {'name': 'Power Spectral Density of position fluctuations',
                     'unit': 'nm^2/Hz',
                     'label': 'PSD [nm^2 / Hz]',
                     'label_latex': r'$P_{\\delta x} \: [\\mathrm{nm}^2 / \\mathrm{Hz}]',
                     'n_avg': 4,  # If n_avg is not equal to one, there should be a dataset y_std containing standard deviations
                     'help': 'Power spectral density of position fluctuations.'}
            [1, 2.1, 2.9, 4]

        y_std/
            [0.2, 0.3, 0.4, 0.5]


        workup/
            FFT
             [1, 2, 3]
            FTTunit
             'nm'



Note: If ``x`` is an empty array, we can determine the array from
the initial and step attributes.

Note: If ``y['n_avg'] == 1``, then ``y`` is a dataset rather than a group,
with ``y`` data stored directly, as shown below.

::

        y
        attributes: {'name': 'PSD_{\delta x}'
                     'n_avg': 1,
                     'unit': 'nm^2/Hz',
                     'help': 'Power spectral density of position fluctuations.'}
            [1, 2.1, 2.9, 4]

After the data has been processed, you can output any fitting or workup
parameters to a group called ``workup``.

.. _HDF5: http://www.hdfgroup.org/HDF5/
        
"""

from __future__ import division, print_function, absolute_import

[docs]def update_attrs(h5_attrs, attrs): """Update the attributes in ``h5_attrs``, an ``h5py`` group or dataset, by adding attributes in the dictionary attrs. This will overwrite existing attributes. """ for key, val in attrs.items(): h5_attrs[key] = val
[docs]def attr_dict_options(setting): """Shorthand for describing possible combinations of required attributes for an hdf5 dataset. Possible values for setting: very_permissive Only require name, unit; other attributes can be inferred / ignored.""" attr_dict_settings = { 'permissive' : {u'name', u'unit'}, 'label' : {u'name', u'unit', u'label'}, 'latex' : {u'name', u'unit', u'label', u'label_latex'}, 'freqdemod_y' : {u'name', u'unit', u'label', u'label_latex', u'abscissa'}, 'pedantic_y' : {u'name', u'unit', u'label', u'label_latex', u'abscissa', u'help', u'n_avg'}, 'permissive_x' : {u'name', u'unit', u'step'}, 'label_x' : {u'name', u'unit', u'step', u'label'}, 'latex_x' : {u'name', u'unit', u'step', u'label', u'label_latex'}, 'freqdemod_x' : {u'name', u'unit', u'step', u'label', u'label_latex', u'initial'}, 'pedantic_x' : {u'name', u'unit', u'step', u'label', u'label_latex', u'initial', u'help'},} return attr_dict_settings[setting]
[docs]def check_minimum_attrs(attrs, setting='permissive'): required_attrs = attr_dict_options(setting) attrs_set = set(attrs) if attrs_set < required_attrs: raise ValueError("""\ dataset missing required attributes: {}""".format(", ".join(required_attrs - attrs_set)))
[docs]def infer_labels(attrs): name = attrs['name'] unit = attrs['unit'] attr_dict = dict(attrs.items()) label_dict = {'label': '{} [{}]'.format(name, unit), 'label_latex': '${0} \: [\mathrm{{{1}}}]$'.format(name, unit)} label_dict.update(attr_dict) update_attrs(attrs, label_dict)
[docs]def add_attrs_if_missing(h5_attrs, **kwargs): h5_attrs_dict = dict(h5_attrs.items()) kwargs.update(h5_attrs_dict) update_attrs(h5_attrs, kwargs)
[docs]def infer_missing_attrs(attrs, dataset_type=None, abscissa=None, n_avg=1): infer_labels(attrs) if dataset_type == 'x': add_attrs_if_missing(attrs, initial=0) elif dataset_type == 'y': if abscissa is not None: add_attrs_if_missing(attrs, abscissa=abscissa, n_avg=n_avg) else: raise ValueError('absicca must be specified')