#!/usr/bin/env python
# -*- coding: utf-8 -*-
# #########################################################################
# Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. #
# #
# Copyright 2015. UChicago Argonne, LLC. This software was produced #
# under U.S. Government contract DE-AC02-06CH11357 for Argonne National #
# Laboratory (ANL), which is operated by UChicago Argonne, LLC for the #
# U.S. Department of Energy. The U.S. Government has rights to use, #
# reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR #
# UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR #
# ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is #
# modified to produce derivative works, such modified software should #
# be clearly marked, so as not to confuse it with the version available #
# from ANL. #
# #
# Additionally, redistribution and use in source and binary forms, with #
# or without modification, are permitted provided that the following #
# conditions are met: #
# #
# * Redistributions of source code must retain the above copyright #
# notice, this list of conditions and the following disclaimer. #
# #
# * Redistributions in binary form must reproduce the above copyright #
# notice, this list of conditions and the following disclaimer in #
# the documentation and/or other materials provided with the #
# distribution. #
# #
# * Neither the name of UChicago Argonne, LLC, Argonne National #
# Laboratory, ANL, the U.S. Government, nor the names of its #
# contributors may be used to endorse or promote products derived #
# from this software without specific prior written permission. #
# #
# THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS #
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT #
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS #
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago #
# Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, #
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, #
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER #
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT #
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN #
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE #
# POSSIBILITY OF SUCH DAMAGE. #
# #########################################################################
"""
Subclasses the h5py module for interacting with Data Exchange files.
"""
from __future__ import print_function
import logging
import h5py
import os
import sys
__author__ = 'David Vine'
__copyright__ = 'Copyright (c) 2015, UChicago Argonne, LLC.'
__docformat__ = 'restructuredtext en'
__platform__ = 'Unix'
__version__ = '1.6'
__all__ = ['File',
'Entry']
py3 = sys.version_info[0] == 3
logger = logging.getLogger(__name__)
[docs]class File(h5py.File):
"""
Interact with Data Exchange files.
Methods
-------
create_top_level_group(self, group_name):
Helper function for creating a top level group which will
update the ``implements`` group automagically.
add_entry(self, dexen_ob, overwrite=False):
This method is used to parse DataExchangeEntry objects and
add them to the DataExchangeFile.
"""
def __init__(self, *args, **kwargs):
super(File, self).__init__(*args, **kwargs)
if kwargs['mode'] in ['w', 'a']: # New File
if not 'exchange' in self.keys():
self.create_top_level_group('exchange')
else:
# Verify this file conforms to Data Exchange guidelines
try:
assert 'implements' in self.keys()
assert 'exchange' in self.keys()
except AssertionError:
print(
'WARNING: File does not have either/both "implements" or "exchange" group')
def __repr__(self):
if not self.id:
r = u'<Closed DataExchange file>'
else:
# Filename has to be forced to Unicode if it comes back bytes
# Mode is always a "native" string
filename = self.filename
if isinstance(filename, bytes): # Can't decode fname
filename = filename.decode('utf8', 'replace')
r = u'<DataExchange file "%s" (mode %s)>' % (os.path.basename(filename),
self.mode)
if py3:
return r
return r.encode('utf8')
[docs] def create_top_level_group(self, group_name):
"""
Create a group in the file root and updates the ``implements``
group accordingly. This method should ALWAYS be used to create
groups in the file root.
"""
self.create_group(group_name)
try:
implements = self['/implements'].value
if group_name not in implements.split(':'):
del self['implements']
self.create_dataset(
'implements', data=':'.join([implements, group_name]))
except KeyError:
self.create_dataset('implements', data=group_name)
[docs] def add_entry(self, dexen_ob, overwrite=False):
"""
This method is used to parse DataExchangeEntry objects and add
them to the DataExchangeFile.
"""
if type(dexen_ob) != list:
dexen_ob = [dexen_ob]
for dexen in dexen_ob:
# Does HDF5 path exist?
path = dexen.root.split('/')
try:
path.remove('')
except ValueError:
pass
if not path[0] in self.keys():
self.create_top_level_group(path[0])
root = dexen.root
self.require_group('/'.join([root, getattr(dexen, 'entry_name')]))
dsets = [ds for ds in dir(dexen) if not ds.startswith('__')]
[dsets.remove(item)
for item in ['entry_name', 'root', 'docstring']]
for ds_name in dsets:
if getattr(dexen, ds_name)['value'] is not None:
if 'dataset_opts' in getattr(dexen, ds_name).keys():
opts = getattr(dexen, ds_name)['dataset_opts']
else:
opts = {}
try:
ds = self['/'.join([root, getattr(dexen, 'entry_name')])].create_dataset(
ds_name, data=getattr(dexen, ds_name)['value'], **opts)
for key in getattr(dexen, ds_name).keys():
if key in ['value', 'docstring', 'dataset_opts']:
pass
else:
ds.attrs[key] = getattr(dexen, ds_name)[key]
except RuntimeError:
# Likely cause of runtime error is dataset already
# existing in file
dataset_exists = ds_name in self[
'/'.join([root, getattr(dexen, 'entry_name')])].keys()
if dataset_exists:
if not overwrite:
print(
'WARNING: Dataset {:s} already exists. This entry has been skipped.'.format(ds_name))
else:
# The overwite flag is set so delete the
# existing dataset and write the new one in its
# place
del self[
'/'.join([root, getattr(dexen, 'entry_name'), ds_name])]
ds = self['/'.join([root, getattr(dexen, 'entry_name')])].create_dataset(
ds_name, data=getattr(dexen, ds_name)['value'], **opts)
for key in getattr(dexen, ds_name).keys():
if key in ['value', 'docstring', 'dataset_opts']:
pass
else:
ds.attrs[key] = getattr(
dexen, ds_name)[key]
else:
raise
[docs]class Entry(object):
"""
Interact with Data Exchange files.
Methods
-------
_entry_definitions(self)
Contains the archetypes for Data Exchange file entries.
_generate_classes(self)
This method is used to turn the Entry._entry_definitions into generate_classes
which can be instantitated for hold data.
"""
def __init__(self, **kwargs):
self._entry_definitions()
self._generate_classes()
[docs] def _entry_definitions(self):
"""
This method contains the archetypes for Data Exchange file entries.
The syntax for an entry is:
*'root': The HDF5 path where this entry will be created (e.g. '/measurement_3/sample' or '/exchange/').
*'entry_name': The name of entry (e.g. 'monochromator' or 'sample_7'). It is a HDF5 Group.
*'docstring': Describes this type of entry. E.g for sample: "The sample measured."
*This is used only for autogegnerating documentation for DataExchangeEntry.
*It does not get written to the DataExchangeFile.
*'ENTRY': An entry is a dataset with attributes under the 'name' group.
Each 'ENTRY' must have:
* value: The dataset
Each 'ENTRY' should have:
* units: Units for value - an attribute of the dataset
* docstring: Used for autogenerating documentation
Each 'ENTRY' can have (i.e optional):
*'dataset_opts': Options passed to the create_dataset function. E.g.:
*'dataset_opts': {'compression':'gzip', 'compression_opts':4}
Where a value is ``None`` this entry will not be added to the DataExchangeFile.
'ENTRY' can have any other parameter and these will be treated as HDF5 dataset attributes
"""
self._exchange = {
'root': 'exchange',
'entry_name': '',
'docstring': 'Used for grouping the results of the measurement',
'name': {
'value': None,
'units': 'text',
'docstring': 'Description of the data contained inside'
}
}
self._data = {
'root': '/exchange',
'entry_name': '',
'docstring': 'The result of the measurement.',
'data': {
'value': None,
'units': 'counts',
'docstring': 'The result of the measurement.'
},
}
self._sample = {
'root': '/measurement',
'entry_name': 'sample',
'docstring': 'The sample measured.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Descriptive name of the sample.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the sample.'
},
'preparation_date': {
'value': None,
'units': 'text',
'docstring': 'Date and time the sample was prepared.'
},
'chemical_formula': {
'value': None,
'units': 'text',
'docstring': 'Sample chemical formula using the CIF format.'
},
'mass': {
'value': None,
'units': 'kg',
'docstring': 'Mass of the sample.'
},
'concentration': {
'value': None,
'units': 'kgm^-3',
'docstring': 'Mass/volume.'
},
'environment': {
'value': None,
'units': 'text',
'docstring': 'Sample environment.'
},
'temperature': {
'value': None,
'units': 'kelvin',
'docstring': 'Sample temperature.'
},
'temperature_set': {
'value': None,
'units': 'kelvin',
'docstring': 'Sample temperature set point.'
},
'pressure': {
'value': None,
'units': 'kPa',
'docstring': 'Sample pressure.'
},
'fatigue_cycle': {
'value': None,
'units': None,
'docstring': 'Sample fatigue cycles.'
},
'thickness': {
'value': None,
'units': 'm',
'docstring': 'Sample thickness.'
},
'tray': {
'value': None,
'units': 'text',
'docstring': 'Sample position in the sample changer/robot.'
},
'comment': {
'value': None,
'units': 'text',
'docstring': 'comment'
}
}
self._experiment = {
'root': '/measurement/sample',
'entry_name': 'experiment',
'docstring': 'This provides references to facility ids for the proposal, scheduled activity, and safety form.',
'proposal': {
'value': None,
'units': 'text',
'docstring': 'Proposal reference number. For the APS this is the General User Proposal number.'
},
'activity': {
'value': None,
'units': 'text',
'docstring': 'Proposal scheduler id. For the APS this is the beamline scheduler activity id.'
},
'safety': {
'value': None,
'units': 'text',
'docstring': 'Safety reference document. For the APS this is the Experiment Safety Approval Form number.'
},
'title': {
'value': None,
'units': 'text',
'docstring': 'Experiment title. For the APS this is the proposal title assigned by the user.'
},
}
self._experimenter = {
'root': '/measurement/sample',
'entry_name': 'experimenter',
'docstring': 'Description of a single experimenter.',
'name': {
'value': None,
'units': 'text',
'docstring': 'User name.'
},
'role': {
'value': None,
'units': 'text',
'docstring': 'User role.'
},
'affiliation': {
'value': None,
'units': 'text',
'docstring': 'User affiliation.'
},
'address': {
'value': None,
'units': 'text',
'docstring': 'User address.'
},
'phone': {
'value': None,
'units': 'text',
'docstring': 'User phone number.'
},
'email': {
'value': None,
'units': 'text',
'docstring': 'User email address.'
},
'facility_user_id': {
'value': None,
'units': 'text',
'docstring': 'User badge number.'
},
}
self._instrument = {
'root': '/measurement',
'entry_name': 'instrument',
'docstring': 'All relevant beamline components status at the beginning of a measurement',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the instrument.'
},
'comment': {
'value': None,
'units': 'text',
'docstring': 'comment'
},
}
self._source = {
'root': '/measurement/instrument',
'entry_name': 'source',
'docstring': 'The light source being used',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the facility.'
},
'datetime': {
'value': None,
'units': 'text',
'docstring': 'Date and time source was measured.'
},
'beamline': {
'value': None,
'units': 'text',
'docstring': 'Name of the beamline.'
},
'current': {
'value': None,
'units': 'A',
'docstring': 'Electron beam current (A).'
},
'energy': {
'value': None,
'units': 'J',
'docstring': 'Characteristic photon energy of the source (J). For an APS bending magnet this is 30 keV or 4.807e-15 J.'
},
'pulse_energy': {
'value': None,
'units': 'J',
'docstring': 'Sum of the energy of all the photons in the pulse (J).'
},
'pulse_width': {
'value': None,
'units': 's',
'docstring': 'Duration of the pulse (s).'
},
'mode': {
'value': None,
'units': 'text',
'docstring': 'top-up'
},
'beam_intensity_incident': {
'value': None,
'units': 'phs^-1',
'docstring': 'Incident beam intensity in (photons per s).'
},
'beam_intensity_transmitted': {
'value': None,
'units': 'phs^-1',
'docstring': 'Transmitted beam intensity (photons per s).'
},
}
self._attenuator = {
'root': '/measurement/instrument',
'entry_name': 'attenuator',
'docstring': 'X-ray beam attenuator.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the attenuator.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description or composition of attenuator.'
},
'thickness': {
'value': None,
'units': 'm',
'docstring': 'Thickness of attenuator along beam direction.'
},
'transmission': {
'value': None,
'units': 'None',
'docstring': 'The nominal amount of the beam that gets through (transmitted intensity)/(incident intensity)'
}
}
self._monochromator = {
'root': '/measurement/instrument',
'entry_name': 'monochromator',
'docstring': 'X-ray beam monochromator.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the monochromator.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the monochromator'
},
'energy': {
'value': None,
'units': 'J',
'docstring': 'Peak of the spectrum that the monochromator selects. When units is not defined this field is in J'
},
'energy_error': {
'value': None,
'units': 'J',
'docstring': 'Standard deviation of the spectrum that the monochromator selects. When units is not defined this field is in J.'
},
'mono_stripe': {
'value': None,
'units': 'text',
'docstring': 'Type of multilayer coating or crystal.'
}
}
self._mirror = {
'root': '/measurement/instrument',
'entry_name': 'mirror',
'docstring': 'X-ray beam mirror.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the mirror.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the mirror'
},
'angle': {
'value': None,
'units': 'rad',
'docstring': 'Mirror incident angle'
}
}
self._detector = {
'root': '/measurement/instrument',
'entry_name': 'detector',
'docstring': 'X-ray detector.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the detector.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the detector'
},
'manufacturer': {
'value': None,
'units': 'text',
'docstring': 'The detector manufacturer.'
},
'model': {
'value': None,
'units': 'text',
'docstring': 'The detector model'
},
'serial_number': {
'value': None,
'units': 'text',
'docstring': 'The detector serial number.'
},
'firmware_version': {
'value': None,
'units': 'text',
'docstring': 'The detector firmware version.'
},
'software_version': {
'value': None,
'units': 'text',
'docstring': 'The detector software version.'
},
'bit_depth': {
'value': None,
'units': 'dimensionless',
'docstring': 'The detector ADC bit depth.'
},
'pixel_size_x': {
'value': None,
'units': 'm',
'docstring': 'Physical detector pixel size (m).'
},
'pixel_size_y': {
'value': None,
'units': 'm',
'docstring': 'Physical detector pixel size (m).'
},
'actual_pixel_size_x': {
'value': None,
'units': 'm',
'docstring': 'Pixel size on the sample plane (m).'
},
'actual_pixel_size_y': {
'value': None,
'units': 'm',
'docstring': 'Pixel size on the sample plane (m).'
},
'dimension_x': {
'value': None,
'units': 'pixels',
'docstring': 'The detector horiz. dimension.'
},
'dimension_y': {
'value': None,
'units': 'text',
'docstring': 'The detector vertical dimension.'
},
'binning_x': {
'value': None,
'units': 'pixels',
'docstring': 'If the data are collected binning the detector x binning and y binning store the binning factor.'
},
'binning_y': {
'value': None,
'units': 'dimensionless',
'docstring': 'If the data are collected binning the detector x binning and y binning store the binning factor.'
},
'operating_temperature': {
'value': None,
'units': 'dimensionless',
'docstring': 'The detector operating temperature (K).'
},
'exposure_time': {
'value': None,
'units': 's',
'docstring': 'The set detector exposure time (s).'
},
'delay_time': {
'value': None,
'units': 's',
'docstring': 'Detector delay time (s). This is used in combination with a mechanical shutter.'
},
'stabilization_time': {
'value': None,
'units': 's',
'docstring': 'Detector delay time (s). This is used during stop and go data collection to allow the sample to stabilize.'
},
'frame_rate': {
'value': None,
'units': 'fps',
'docstring': 'The detector frame rate (fps).'
},
'shutter_mode': {
'value': None,
'units': 'text',
'docstring': 'The detector shutter mode: global, rolling etc.'
},
'output_data': {
'value': None,
'units': 'text',
'docstring': 'String HDF5 path to the exchange group where the detector output data is located.'
},
'counts_per_joule': {
'value': None,
'units': 'counts',
'docstring': 'Number of counts recorded per each joule of energy received by the detector'
},
'basis_vectors': {
'value': None,
'units': 'fps',
'docstring': 'A matrix with the basis vectors of the detector data.'
},
'corner_position': {
'value': None,
'units': 'fps',
'docstring': 'The x, y and z coordinates of the corner of the first data element.'
},
}
self._roi = {
'root': '/measurement/instrument/detector',
'entry_name': 'roi',
'docstring': 'region of interest (ROI) of the image actually collected, if smaller than the full CCD.',
'name': {
'value': None,
'units': 'text',
'docstring': 'ROI name'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'ROI description'
},
'min_x': {
'value': None,
'units': 'pixels',
'docstring': 'Top left x pixel position'
},
'min_y': {
'value': None,
'units': 'pixels',
'docstring': 'Top left y pixel position'
},
'size_x': {
'value': None,
'units': 'pixels',
'docstring': 'Horizontal image size'
},
'size_y': {
'value': None,
'units': 'pixels',
'docstring': 'Vertical image size'
}
}
self._objective = {
'root': '/measurement/instrument/detection_system',
'entry_name': 'objective',
'docstring': 'microscope objective lenses used.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Lens name'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Lens description'
},
'manufacturer': {
'value': None,
'units': 'text',
'docstring': 'Lens manufacturer'
},
'model': {
'value': None,
'units': 'text',
'docstring': 'Lens model.'
},
'magnification': {
'value': None,
'units': 'dimensionless',
'docstring': 'Lens specified magnification'
},
'numerical_aperture': {
'value': None,
'units': 'dimensionless',
'docstring': 'The numerical aperture (N.A.) is a measure of the light-gathering characteristics of the lens.'
}
}
self._scintillator = {
'root': '/measurement/instrument/detection_system',
'entry_name': 'scintillator',
'docstring': 'scintillator used.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Scintillator name'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Scintillator description'
},
'manufacturer': {
'value': None,
'units': 'text',
'docstring': 'Scintillator Manufacturer.'
},
'serial_number': {
'value': None,
'units': 'text',
'docstring': 'Scintillator serial number.'
},
'scintillating_thickness': {
'value': None,
'units': 'm',
'docstring': 'Scintillator thickness.'
},
'substrate_thickness': {
'value': None,
'units': 'm',
'docstring': 'Scintillator substrate thickness.'
}
}
self._sample_stack = {
'root': '/measurement/instrument',
'entry_name': 'sample',
'docstring': 'Sample stack name',
'name': {
'value': None,
'units': 'text',
'docstring': 'Descriptive name of the sample stack.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the sample stack.'
},
}
self._sample_stack_setup = {
'root': '/measurement/instrument/sample',
'entry_name': 'setup',
'docstring': 'Tomography specific tag to store motor positions that are static during data collection.',
'sample_x': {
'value': None,
'units': 'mm',
'docstring': 'Initial position of the X stage under the rotary motor.'
},
'sample_y': {
'value': None,
'units': 'mm',
'docstring': 'Initial position of the Y stage under the rotary motor.'
},
'sample_z': {
'value': None,
'units': 'mm',
'docstring': 'Initial position of the Z stage under the rotary motor.'
},
'sample_xx': {
'value': None,
'units': 'mm',
'docstring': 'Initial position of the X stage on top of the rotary motor.'
},
'sample_zz': {
'value': None,
'units': 'mm',
'docstring': 'Initial position of the Z stage on top of the rotary motor.'
},
'detector_distance': {
'value': None,
'units': 'mm',
'docstring': 'Sample to detector distance.'
}
}
self._interferometer = {
'root': '/measurement/instrument/',
'entry_name': 'interferometer',
'docstring': 'interferometer name',
'name': {
'value': None,
'units': 'text',
'docstring': 'Descriptive name of the interferometer.'
},
'description': {
'value': None,
'units': 'text',
'docstring': 'Description of the interferometer.'
},
}
self._interferometer_setup = {
'root': '/measurement/instrument/interferometer/',
'entry_name': 'setup',
'docstring': 'Tomography specific tag to store interferometer parameters.',
'grid_start': {
'value': None,
'units': 'mm',
'docstring': 'Interferometer grid start.'
},
'grid_end': {
'value': None,
'units': 'mm',
'docstring': 'Interferometer grid end.'
},
'number_of_grid_periods': {
'value': None,
'units': None,
'docstring': 'Interferometer number of grid periods.'
},
'number_of_grid_steps': {
'value': None,
'units': None,
'docstring': 'Interferometer number of grid steps.'
}
}
self._process = {
'root': '/process',
'entry_name': '',
'docstring': 'Describes parameters used to generate raw and processed data.',
'name': {
'value': None,
'units': 'text',
'docstring': 'Name of the simulation'
},
}
self._acquisition = {
'root': '/process',
'entry_name': 'acquisition',
'docstring': 'Tomography specific tag to store dynamic (per image) parameters.',
'start_date': {
'value': None,
'units': 'text',
'docstring': 'Date and time measurement starts.'
},
'end_date': {
'value': None,
'units': 'text',
'docstring': 'Date and time measurement ends.'
},
'sample_position_x': {
'value': None,
'units': 'mm',
'docstring': 'Vector containing the position of the sample axis x at each projection image collection.'
},
'sample_position_y': {
'value': None,
'units': 'mm',
'docstring': 'Vector containing the position of the sample axis y at each projection image collection.'
},
'sample_position_z': {
'value': None,
'units': 'mm',
'docstring': 'Vector containing the position of the sample axis z at each projection image collection.'
},
'sample_image_shift_x': {
'value': None,
'units': 'pixels',
'docstring': 'Vector containing the shift of the sample axis x at each projection on the detector plane.'
},
'sample_image_shift_y': {
'value': None,
'units': 'pixels',
'docstring': 'Vector containing the shift of the sample axis y at each projection on the detector plane.'
},
'image_theta': {
'value': None,
'units': 'degree',
'docstring': 'Vector containing the rotary stage angular position read from the encoder at each image.'
},
'scan_index': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the identifier assigned by beamline controls to each individual series of images or scan.'
},
'scan_date': {
'value': None,
'units': None,
'docstring': 'Vector containing for each image the wall date/time at start of scan in iso 8601.'
},
'image_date': {
'value': None,
'units': 'time',
'docstring': 'Vector containing the date/time each image was acquired in iso 8601.'
},
'time_stamp': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the relative time since scan_date in 1e-7 seconds.'
},
'image_number': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the the image serial number as assigned by the camera. Unique for each individual scan. Always starts at 0.'
},
'image_exposure_time': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the the measured exposure time in 1e-7 seconds (0.1us)'
},
'image_is_complete': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the boolen status of: is any pixel data missing?'
},
'shutter': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image the beamline shutter status: 0 for closed, 1 for open'
},
'image_type': {
'value': None,
'units': None,
'docstring': 'Vector containin for each image contained in /exchange/data 0 for white, 1 for projection and 2 for dark'
},
}
self._acquisition_setup = {
'root': '/process/acquisition',
'entry_name': 'setup',
'docstring': 'Tomography specific tag to store static scan parameters.',
'number_of_projections': {
'value': None,
'units': None,
'docstring': 'Number of projections.'
},
'number_of_darks': {
'value': None,
'units': None,
'docstring': 'Number of dark images.'
},
'number_of_whites': {
'value': None,
'units': None,
'docstring': 'Number of white images.'
},
'number_of_inter_whites': {
'value': None,
'units': None,
'docstring': 'Number of inter whites.'
},
'white_frequency': {
'value': None,
'units': None,
'docstring': 'White frequency.'
},
'sample_in': {
'value': None,
'units': 'mm',
'docstring': 'Position of the sample axis (x or y) used for taking the sample out of the beam during data collection.'
},
'sample_out': {
'value': None,
'units': 'mm',
'docstring': 'Position of the sample axis (x or y) used for taking the sample out of the beam during the white field data collection.'
},
'rotation_start_angle': {
'value': None,
'units': 'degree',
'docstring': 'Position of rotation axis at the end of data collection.'
},
'rotation_end_angle': {
'value': None,
'units': 'degree',
'docstring': 'Position of rotation axis at the start of the data collection.'
},
'rotation_speed': {
'value': None,
'units': 'degree per second',
'docstring': 'Rotation axis speed.'
},
'angular_step': {
'value': None,
'units': 'degree',
'docstring': 'Rotation axis angular step used during data collection.'
},
'mode': {
'value': None,
'units': 'text',
'docstring': 'Scan mode: continuos or stop-go.'
},
'comment': {
'value': None,
'units': 'text',
'docstring': 'comment'
},
}
[docs] def _generate_classes(self):
"""
This method is used to turn the Entry._entry_definitions into generate_classes
which can be instantitated for hold data.
"""
def __init__(self, **kwargs):
for kw in kwargs:
setattr(self, kw, kwargs[kw])
# Generate a class for each entry definition
for entry_name in self.__dict__:
try:
if entry_name.startswith('_'):
entry_type = getattr(self, entry_name)
entry_name = entry_name[1:]
if entry_name not in Entry.__dict__.keys():
entry_type['__base__'] = Entry
entry_type['__name__'] = entry_type['entry_name']
entry_type['__init__'] = __init__
setattr(
Entry, entry_name, type(entry_type['entry_name'], (object,), entry_type))
except:
print("Unable to create Entry for {:s}".format(entry_name))
raise
Entry()