Source code for ccpi.io.NEXUSDataWriter

# -*- coding: utf-8 -*-
#  CCP in Tomographic Imaging (CCPi) Core Imaging Library (CIL).

#   Copyright 2017 UKRI-STFC
#   Copyright 2017 University of Manchester

#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at

#   http://www.apache.org/licenses/LICENSE-2.0

#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import os
from ccpi.framework import AcquisitionData, AcquisitionGeometry, ImageData, ImageGeometry
import datetime


h5pyAvailable = True
try:
    import h5py 
except:
    h5pyAvailable = False


[docs]class NEXUSDataWriter(object):
[docs] def __init__(self, **kwargs): self.data_container = kwargs.get('data_container', None) self.file_name = kwargs.get('file_name', None) if ((self.data_container is not None) and (self.file_name is not None)): self.set_up(data_container = self.data_container, file_name = self.file_name)
def set_up(self, data_container = None, file_name = None): self.data_container = data_container self.file_name = file_name if not ((isinstance(self.data_container, ImageData)) or (isinstance(self.data_container, AcquisitionData))): raise Exception('Writer supports only following data types:\n' + ' - ImageData\n - AcquisitionData') # check that h5py library is installed if (h5pyAvailable == False): raise Exception('h5py is not available, cannot load NEXUS files.') def write_file(self): # if the folder does not exist, create the folder if not os.path.isdir(os.path.dirname(self.file_name)): os.mkdir(os.path.dirname(self.file_name)) # create the file with h5py.File(self.file_name, 'w') as f: # give the file some important attributes f.attrs['file_name'] = self.file_name f.attrs['file_time'] = str(datetime.datetime.utcnow()) f.attrs['creator'] = np.string_('NEXUSDataWriter.py') f.attrs['NeXus_version'] = '4.3.0' f.attrs['HDF5_Version'] = h5py.version.hdf5_version f.attrs['h5py_version'] = h5py.version.version # create the NXentry group nxentry = f.create_group('entry1/tomo_entry') nxentry.attrs['NX_class'] = 'NXentry' # create dataset to store data ds_data = f.create_dataset('entry1/tomo_entry/data/data', (self.data_container.as_array().shape), dtype = 'float32', data = self.data_container.as_array()) # set up dataset attributes if (isinstance(self.data_container, ImageData)): ds_data.attrs['data_type'] = 'ImageData' else: ds_data.attrs['data_type'] = 'AcquisitionData' for i in range(self.data_container.as_array().ndim): ds_data.attrs['dim{}'.format(i)] = self.data_container.dimension_labels[i] if (isinstance(self.data_container, AcquisitionData)): ds_data.attrs['geom_type'] = self.data_container.geometry.geom_type ds_data.attrs['dimension'] = self.data_container.geometry.dimension if self.data_container.geometry.dist_source_center is not None: ds_data.attrs['dist_source_center'] = self.data_container.geometry.dist_source_center if self.data_container.geometry.dist_center_detector is not None: ds_data.attrs['dist_center_detector'] = self.data_container.geometry.dist_center_detector ds_data.attrs['pixel_num_h'] = self.data_container.geometry.pixel_num_h ds_data.attrs['pixel_size_h'] = self.data_container.geometry.pixel_size_h ds_data.attrs['pixel_num_v'] = self.data_container.geometry.pixel_num_v ds_data.attrs['pixel_size_v'] = self.data_container.geometry.pixel_size_v ds_data.attrs['channels'] = self.data_container.geometry.channels ds_data.attrs['n_angles'] = self.data_container.geometry.angles.shape[0] # create the dataset to store rotation angles ds_angles = f.create_dataset('entry1/tomo_entry/data/rotation_angle', (self.data_container.geometry.angles.shape), dtype = 'float32', data = self.data_container.geometry.angles) #ds_angles.attrs['units'] = self.data_container.geometry.angle_unit else: # ImageData ds_data.attrs['voxel_num_x'] = self.data_container.geometry.voxel_num_x ds_data.attrs['voxel_num_y'] = self.data_container.geometry.voxel_num_y ds_data.attrs['voxel_num_z'] = self.data_container.geometry.voxel_num_z ds_data.attrs['voxel_size_x'] = self.data_container.geometry.voxel_size_x ds_data.attrs['voxel_size_y'] = self.data_container.geometry.voxel_size_y ds_data.attrs['voxel_size_z'] = self.data_container.geometry.voxel_size_z ds_data.attrs['center_x'] = self.data_container.geometry.center_x ds_data.attrs['center_y'] = self.data_container.geometry.center_y ds_data.attrs['center_z'] = self.data_container.geometry.center_z ds_data.attrs['channels'] = self.data_container.geometry.channels
''' # usage example xtek_file = '/home/evelina/nikon_data/SophiaBeads_256_averaged.xtekct' reader = NikonDataReader() reader.set_up(xtek_file = xtek_file, binning = [3, 1], roi = [200, 500, 1500, 2000], normalize = True) data = reader.load_projections() ag = reader.get_geometry() writer = NEXUSDataWriter() writer.set_up(file_name = '/home/evelina/test_nexus.nxs', data_container = data) writer.write_file() ig = ImageGeometry(voxel_num_x = 100, voxel_num_y = 100) im = ImageData(array = numpy.zeros((100, 100), dtype = 'float'), geometry = ig) im_writer = NEXUSDataWriter() im_writer.set_up(file_name = '/home/evelina/test_nexus_im.nxs', data_container = im) im_writer.write_file() ag = AcquisitionGeometry(geom_type = 'parallel', dimension = '2D', angles = numpy.array([0, 1]), pixel_num_h = 200, pixel_size_h = 1, pixel_num_v = 100, pixel_size_v = 1) ad = ag.allocate() ag_writer = NEXUSDataWriter() ag_writer.set_up(file_name = '/home/evelina/test_nexus_ag.nxs', data_container = ad) ag_writer.write_file() '''