Source code for dxfile.dxtomo

#!/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()