From 78f962def0bdb188efe8f72aac7f26838f5c4b62 Mon Sep 17 00:00:00 2001 From: Evelina Ametova Date: Wed, 12 Jun 2019 11:17:40 +0100 Subject: data readers, writer, resizer to composite_data_container branch --- Wrappers/Python/ccpi/io/NEXUSDataReader.py | 144 ++++++++++++++ Wrappers/Python/ccpi/io/NEXUSDataWriter.py | 153 +++++++++++++++ Wrappers/Python/ccpi/io/NikonDataReader.py | 282 ++++++++++++++++++++++++++++ Wrappers/Python/ccpi/io/__init__.py | 6 +- Wrappers/Python/ccpi/processors/Resizer.py | 262 ++++++++++++++++++++++++++ Wrappers/Python/ccpi/processors/__init__.py | 10 + 6 files changed, 856 insertions(+), 1 deletion(-) create mode 100644 Wrappers/Python/ccpi/io/NEXUSDataReader.py create mode 100644 Wrappers/Python/ccpi/io/NEXUSDataWriter.py create mode 100644 Wrappers/Python/ccpi/io/NikonDataReader.py create mode 100755 Wrappers/Python/ccpi/processors/Resizer.py create mode 100755 Wrappers/Python/ccpi/processors/__init__.py (limited to 'Wrappers') diff --git a/Wrappers/Python/ccpi/io/NEXUSDataReader.py b/Wrappers/Python/ccpi/io/NEXUSDataReader.py new file mode 100644 index 0000000..a742dd5 --- /dev/null +++ b/Wrappers/Python/ccpi/io/NEXUSDataReader.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Apr 3 10:30:25 2019 + +@author: evelina +""" + + +import numpy +import os +import matplotlib.pyplot as plt +from ccpi.framework import AcquisitionData, AcquisitionGeometry, ImageData, ImageGeometry + + +h5pyAvailable = True +try: + import h5py +except: + h5pyAvailable = False + + +class NEXUSDataReader(object): + + def __init__(self, + **kwargs): + + ''' + Constructor + + Input: + + nexus_file full path to NEXUS file + ''' + + self.nexus_file = kwargs.get('nexus_file', None) + + if self.nexus_file is not None: + self.set_up(nexus_file = self.nexus_file, + roi = self.roi, + binning = self.binning) + + def set_up(self, + nexus_file = None): + + self.nexus_file = nexus_file + + # check that h5py library is installed + if (h5pyAvailable == False): + raise Exception('h5py is not available, cannot load NEXUS files.') + + if self.nexus_file == None: + raise Exception('Path to nexus file is required.') + + # check if nexus file exists + if not(os.path.isfile(self.nexus_file)): + raise Exception('File\n {}\n does not exist.'.format(self.nexus_file)) + + def load_data(self): + + ''' + Parse NEXUS file and returns either ImageData or Acquisition Data + depending on file content + ''' + + try: + with h5py.File(self.nexus_file,'r') as file: + + if (file.attrs['creator'] != 'NEXUSDataWriter.py'): + raise Exception('We can parse only files created by NEXUSDataWriter.py') + + ds_data = file['entry1/tomo_entry/data/data'] + data = numpy.array(ds_data, dtype = 'float32') + + dimension_labels = [] + + for i in range(data.ndim): + dimension_labels.append(ds_data.attrs['dim{}'.format(i)]) + + if ds_data.attrs['data_type'] == 'ImageData': + self._geometry = ImageGeometry(voxel_num_x = ds_data.attrs['voxel_num_x'], + voxel_num_y = ds_data.attrs['voxel_num_y'], + voxel_num_z = ds_data.attrs['voxel_num_z'], + voxel_size_x = ds_data.attrs['voxel_size_x'], + voxel_size_y = ds_data.attrs['voxel_size_y'], + voxel_size_z = ds_data.attrs['voxel_size_z'], + center_x = ds_data.attrs['center_x'], + center_y = ds_data.attrs['center_y'], + center_z = ds_data.attrs['center_z'], + channels = ds_data.attrs['channels']) + + return ImageData(array = data, + deep_copy = False, + geometry = self._geometry, + dimension_labels = dimension_labels) + + else: # AcquisitionData + self._geometry = AcquisitionGeometry(geom_type = ds_data.attrs['geom_type'], + dimension = ds_data.attrs['dimension'], + dist_source_center = ds_data.attrs['dist_source_center'], + dist_center_detector = ds_data.attrs['dist_center_detector'], + pixel_num_h = ds_data.attrs['pixel_num_h'], + pixel_size_h = ds_data.attrs['pixel_size_h'], + pixel_num_v = ds_data.attrs['pixel_num_v'], + pixel_size_v = ds_data.attrs['pixel_size_v'], + channels = ds_data.attrs['channels'], + angles = numpy.array(file['entry1/tomo_entry/data/rotation_angle'], dtype = 'float32')) + #angle_unit = file['entry1/tomo_entry/data/rotation_angle'].attrs['units']) + + return AcquisitionData(array = data, + deep_copy = False, + geometry = self._geometry, + dimension_labels = dimension_labels) + + except: + print("Error reading nexus file") + raise + + def get_geometry(self): + + ''' + Return either ImageGeometry or AcquisitionGeometry + depepnding on file content + ''' + + return self._geometry + + +''' +# usage example +reader = NEXUSDataReader() +reader.set_up(nexus_file = '/home/evelina/test_nexus.nxs') +acquisition_data = reader.load_data() +print(acquisition_data) +ag = reader.get_geometry() +print(ag) + +reader = NEXUSDataReader() +reader.set_up(nexus_file = '/home/evelina/test_nexus_im.nxs') +image_data = reader.load_data() +print(image_data) +ig = reader.get_geometry() +print(ig) +''' \ No newline at end of file diff --git a/Wrappers/Python/ccpi/io/NEXUSDataWriter.py b/Wrappers/Python/ccpi/io/NEXUSDataWriter.py new file mode 100644 index 0000000..d35e86b --- /dev/null +++ b/Wrappers/Python/ccpi/io/NEXUSDataWriter.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Thu May 2 10:11:20 2019 + +@author: evelina +""" + + +import numpy +import os +import matplotlib.pyplot as plt +from ccpi.framework import AcquisitionData, AcquisitionGeometry, ImageData, ImageGeometry +from NikonDataReader import NikonDataReader +import datetime + + +h5pyAvailable = True +try: + import h5py +except: + h5pyAvailable = False + + +class NEXUSDataWriter(object): + + 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'] = '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 + ds_data.attrs['dist_source_center'] = self.data_container.geometry.dist_source_center + 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() + +writer.set_up(file_name = '/home/evelina/test_nexus_im.nxs', + data_container = im) + +writer.write_file() +''' \ No newline at end of file diff --git a/Wrappers/Python/ccpi/io/NikonDataReader.py b/Wrappers/Python/ccpi/io/NikonDataReader.py new file mode 100644 index 0000000..6f02aa0 --- /dev/null +++ b/Wrappers/Python/ccpi/io/NikonDataReader.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Apr 3 10:30:25 2019 + +@author: evelina +""" + +from ccpi.framework import AcquisitionData, AcquisitionGeometry +import numpy +import matplotlib.pyplot as plt +import os + + +pilAvailable = True +try: + from PIL import Image +except: + pilAvailable = False + + +class NikonDataReader(object): + + def __init__(self, + **kwargs): + ''' + Constructor + + Input: + + xtek_file full path to .xtexct file + + roi region-of-interest to load. If roi = -1 (default), + full projections will be loaded. Otherwise roi is + given by [(row0, row1), (column0, column1)], where + row0, column0 are coordinates of top left corner and + row1, column1 are coordinates of bottom right corner. + + binning number of pixels to bin (combine) along 0 (column) + and 1 (row) dimension. If binning = [1, 1] (default), + projections in original resolution are loaded. Note, + if binning[0] != binning[1], then loaded projections + will have anisotropic pixels, which are currently not + supported by the Framework + + normalize normalize loaded projections by detector + white level (I_0). Default value is False, + i.e. no normalization. + + flip default = False, flip projections in the left-right direction + + ''' + + self.xtek_file = kwargs.get('xtek_file', None) + self.roi = kwargs.get('roi', -1) + self.binning = kwargs.get('binning', [1, 1]) + self.normalize = kwargs.get('normalize', False) + self.flip = kwargs.get('flip', False) + + if self.xtek_file is not None: + self.set_up(xtek_file = self.xtek_file, + roi = self.roi, + binning = self.binning, + normalize = self.normalize, + flip = self.flip) + + def set_up(self, + xtek_file = None, + roi = -1, + binning = [1, 1], + normalize = False, + flip = False): + + self.xtek_file = xtek_file + self.roi = roi + self.binning = binning + self.normalize = normalize + self.flip = flip + + if self.xtek_file == None: + raise Exception('Path to xtek file is required.') + + # check if xtek file exists + if not(os.path.isfile(self.xtek_file)): + raise Exception('File\n {}\n does not exist.'.format(self.xtek_file)) + + # check that PIL library is installed + if (pilAvailable == False): + raise Exception("PIL (pillow) is not available, cannot load TIFF files.") + + # parse xtek file + with open(self.xtek_file, 'r') as f: + content = f.readlines() + + content = [x.strip() for x in content] + + for line in content: + # filename of TIFF files + if line.startswith("Name"): + self._experiment_name = line.split('=')[1] + # number of projections + elif line.startswith("Projections"): + num_projections = int(line.split('=')[1]) + # white level - used for normalization + elif line.startswith("WhiteLevel"): + self._white_level = float(line.split('=')[1]) + # number of pixels along Y axis + elif line.startswith("DetectorPixelsY"): + pixel_num_v_0 = int(line.split('=')[1]) + # number of pixels along X axis + elif line.startswith("DetectorPixelsX"): + pixel_num_h_0 = int(line.split('=')[1]) + # pixel size along X axis + elif line.startswith("DetectorPixelSizeX"): + pixel_size_h_0 = float(line.split('=')[1]) + # pixel size along Y axis + elif line.startswith("DetectorPixelSizeY"): + pixel_size_v_0 = float(line.split('=')[1]) + # source to center of rotation distance + elif line.startswith("SrcToObject"): + source_x = float(line.split('=')[1]) + # source to detector distance + elif line.startswith("SrcToDetector"): + detector_x = float(line.split('=')[1]) + # initial angular position of a rotation stage + elif line.startswith("InitialAngle"): + initial_angle = float(line.split('=')[1]) + # angular increment (in degrees) + elif line.startswith("AngularStep"): + angular_step = float(line.split('=')[1]) + + if self.roi == -1: + self._roi_par = [(0, pixel_num_v_0), \ + (0, pixel_num_h_0)] + else: + self._roi_par = self.roi.copy() + if self._roi_par[0] == -1: + self._roi_par[0] = (0, pixel_num_v_0) + if self._roi_par[1] == -1: + self._roi_par[1] = (0, pixel_num_h_0) + + # calculate number of pixels and pixel size + if (self.binning == [1, 1]): + pixel_num_v = self._roi_par[0][1] - self._roi_par[0][0] + pixel_num_h = self._roi_par[1][1] - self._roi_par[1][0] + pixel_size_v = pixel_size_v_0 + pixel_size_h = pixel_size_h_0 + else: + pixel_num_v = (self._roi_par[0][1] - self._roi_par[0][0]) // self.binning[0] + pixel_num_h = (self._roi_par[1][1] - self._roi_par[1][0]) // self.binning[1] + pixel_size_v = pixel_size_v_0 * self.binning[0] + pixel_size_h = pixel_size_h_0 * self.binning[1] + + ''' + Parse the angles file .ang or _ctdata.txt file and returns the angles + as an numpy array. + ''' + input_path = os.path.dirname(self.xtek_file) + angles_ctdata_file = os.path.join(input_path, '_ctdata.txt') + angles_named_file = os.path.join(input_path, self._experiment_name+'.ang') + angles = numpy.zeros(num_projections, dtype = 'float') + + # look for _ctdata.txt + if os.path.exists(angles_ctdata_file): + # read txt file with angles + with open(angles_ctdata_file) as f: + content = f.readlines() + # skip firt three lines + # read the middle value of 3 values in each line as angles in degrees + index = 0 + for line in content[3:]: + angles[index] = float(line.split(' ')[1]) + index += 1 + angles = angles + initial_angle + + # look for ang file + elif os.path.exists(angles_named_file): + # read the angles file which is text with first line as header + with open(angles_named_file) as f: + content = f.readlines() + # skip first line + index = 0 + for line in content[1:]: + angles[index] = float(line.split(':')[1]) + index += 1 + angles = numpy.flipud(angles + initial_angle) # angles are in the reverse order + + else: # calculate angles based on xtek file + angles = initial_angle + angular_step * range(num_projections) + + # fill in metadata + self._ag = AcquisitionGeometry(geom_type = 'cone', + dimension = '3D', + angles = angles, + pixel_num_h = pixel_num_h, + pixel_size_h = pixel_size_h, + pixel_num_v = pixel_num_v, + pixel_size_v = pixel_size_v, + dist_source_center = source_x, + dist_center_detector = detector_x - source_x, + channels = 1, + angle_unit = 'degree') + + def get_geometry(self): + + ''' + Return AcquisitionGeometry object + ''' + + return self._ag + + def load_projections(self): + + ''' + Load projections and return AcquisitionData container + ''' + + # get path to projections + path_projection = os.path.dirname(self.xtek_file) + + # get number of projections + num_projections = numpy.shape(self._ag.angles)[0] + + # allocate array to store projections + data = numpy.zeros((num_projections, self._ag.pixel_num_v, self._ag.pixel_num_h), dtype = float) + + for i in range(num_projections): + + filename = (path_projection + '/' + self._experiment_name + '_{:04d}.tif').format(i + 1) + + try: + tmp = numpy.asarray(Image.open(filename), dtype = float) + except: + print('Error reading\n {}\n file.'.format(filename)) + raise + + if (self.binning == [1, 1]): + data[i, :, :] = tmp[self._roi_par[0][0]:self._roi_par[0][1], self._roi_par[1][0]:self._roi_par[1][1]] + else: + shape = (self._ag.pixel_num_v, self.binning[0], + self._ag.pixel_num_h, self.binning[1]) + data[i, :, :] = tmp[self._roi_par[0][0]:(self._roi_par[0][0] + (((self._roi_par[0][1] - self._roi_par[0][0]) // self.binning[0]) * self.binning[0])), \ + self._roi_par[1][0]:(self._roi_par[1][0] + (((self._roi_par[1][1] - self._roi_par[1][0]) // self.binning[1]) * self.binning[1]))].reshape(shape).mean(-1).mean(1) + + if (self.normalize): + data /= self._white_level + data[data > 1] = 1 + + if self.flip: + return AcquisitionData(array = data[:, :, ::-1], + deep_copy = False, + geometry = self._ag, + dimension_labels = ['angle', \ + 'vertical', \ + 'horizontal']) + else: + return AcquisitionData(array = data, + deep_copy = False, + geometry = self._ag, + dimension_labels = ['angle', \ + 'vertical', \ + 'horizontal']) + + +''' +# usage example +xtek_file = '/home/evelina/nikon_data/SophiaBeads_256_averaged.xtekct' +reader = NikonDataReader() +reader.set_up(xtek_file = xtek_file, + binning = [1, 1], + roi = -1, + normalize = True, + flip = True) + +data = reader.load_projections() +print(data) +ag = reader.get_geometry() +print(ag) + +plt.imshow(data.as_array()[1, :, :]) +plt.show() +''' diff --git a/Wrappers/Python/ccpi/io/__init__.py b/Wrappers/Python/ccpi/io/__init__.py index 9233d7a..455faba 100644 --- a/Wrappers/Python/ccpi/io/__init__.py +++ b/Wrappers/Python/ccpi/io/__init__.py @@ -15,4 +15,8 @@ # 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. \ No newline at end of file +# limitations under the License. + +from .NEXUSDataReader import NEXUSDataReader +from .NEXUSDataWriter import NEXUSDataWriter +from .NikonDataReader import NikonDataReader diff --git a/Wrappers/Python/ccpi/processors/Resizer.py b/Wrappers/Python/ccpi/processors/Resizer.py new file mode 100755 index 0000000..7509a90 --- /dev/null +++ b/Wrappers/Python/ccpi/processors/Resizer.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +# This work is part of the Core Imaging Library developed by +# Visual Analytics and Imaging System Group of the Science Technology +# Facilities Council, STFC + +# Copyright 2018 Edoardo Pasca + +# 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 ccpi.framework import DataProcessor, AcquisitionData, ImageData +import warnings + + +class Resizer(DataProcessor): + + def __init__(self, + roi = -1, + binning = 1): + + ''' + Constructor + + Input: + + roi region-of-interest to crop. If roi = -1 (default), then no crop. + Otherwise roi is given by a list with ndim elements, + where each element is either -1 if no crop along this + dimension or a tuple with beginning and end coodinates to crop to. + Example: + to crop 4D array along 2nd dimension: + roi = [-1, -1, (100, 900), -1] + + binning number of pixels to bin (combine) along each dimension. + If binning = 1, then projections in original resolution are loaded. + Otherwise, binning is given by a list with ndim integers. + Example: + to rebin 3D array along 1st direction: + binning = [1, 5, 1] + ''' + + kwargs = {'roi': roi, + 'binning': binning} + + super(Resizer, self).__init__(**kwargs) + + def check_input(self, data): + if not ((isinstance(data, ImageData)) or + (isinstance(data, AcquisitionData))): + raise Exception('Processor supports only following data types:\n' + + ' - ImageData\n - AcquisitionData') + elif (data.geometry == None): + raise Exception('Geometry is not defined.') + else: + return True + + def process(self): + + data = self.get_input() + ndim = len(data.dimension_labels) + + geometry_0 = data.geometry + geometry = geometry_0.clone() + + if (self.roi == -1): + roi_par = [-1] * ndim + else: + roi_par = self.roi.copy() + if (len(roi_par) != ndim): + raise Exception('Number of dimensions and number of elements in roi parameter do not match') + + if (self.binning == 1): + binning = [1] * ndim + else: + binning = self.binning.copy() + if (len(binning) != ndim): + raise Exception('Number of dimensions and number of elements in binning parameter do not match') + + if (isinstance(data, ImageData)): + if ((all(x == -1 for x in roi_par)) and (all(x == 1 for x in binning))): + for key in data.dimension_labels: + if data.dimension_labels[key] == 'channel': + geometry.channels = geometry_0.channels + roi_par[key] = (0, geometry.channels) + elif data.dimension_labels[key] == 'horizontal_y': + geometry.voxel_size_y = geometry_0.voxel_size_y + geometry.voxel_num_y = geometry_0.voxel_num_y + roi_par[key] = (0, geometry.voxel_num_y) + elif data.dimension_labels[key] == 'vertical': + geometry.voxel_size_z = geometry_0.voxel_size_z + geometry.voxel_num_z = geometry_0.voxel_num_z + roi_par[key] = (0, geometry.voxel_num_z) + elif data.dimension_labels[key] == 'horizontal_x': + geometry.voxel_size_x = geometry_0.voxel_size_x + geometry.voxel_num_x = geometry_0.voxel_num_x + roi_par[key] = (0, geometry.voxel_num_x) + else: + for key in data.dimension_labels: + if data.dimension_labels[key] == 'channel': + if (roi_par[key] != -1): + geometry.channels = (roi_par[key][1] - roi_par[key][0]) // binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.channels = geometry_0.channels // binning[key] + roi_par[key] = (0, geometry.channels * binning[key]) + elif data.dimension_labels[key] == 'horizontal_y': + if (roi_par[key] != -1): + geometry.voxel_num_y = (roi_par[key][1] - roi_par[key][0]) // binning[key] + geometry.voxel_size_y = geometry_0.voxel_size_y * binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.voxel_num_y = geometry_0.voxel_num_y // binning[key] + geometry.voxel_size_y = geometry_0.voxel_size_y * binning[key] + roi_par[key] = (0, geometry.voxel_num_y * binning[key]) + elif data.dimension_labels[key] == 'vertical': + if (roi_par[key] != -1): + geometry.voxel_num_z = (roi_par[key][1] - roi_par[key][0]) // binning[key] + geometry.voxel_size_z = geometry_0.voxel_size_z * binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.voxel_num_z = geometry_0.voxel_num_z // binning[key] + geometry.voxel_size_z = geometry_0.voxel_size_z * binning[key] + roi_par[key] = (0, geometry.voxel_num_z * binning[key]) + elif data.dimension_labels[key] == 'horizontal_x': + if (roi_par[key] != -1): + geometry.voxel_num_x = (roi_par[key][1] - roi_par[key][0]) // binning[key] + geometry.voxel_size_x = geometry_0.voxel_size_x * binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0]+ ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.voxel_num_x = geometry_0.voxel_num_x // binning[key] + geometry.voxel_size_x = geometry_0.voxel_size_x * binning[key] + roi_par[key] = (0, geometry.voxel_num_x * binning[key]) + + else: # AcquisitionData + if ((all(x == -1 for x in roi_par)) and (all(x == 1 for x in binning))): + for key in data.dimension_labels: + if data.dimension_labels[key] == 'channel': + geometry.channels = geometry_0.channels + roi_par[key] = (0, geometry.channels) + elif data.dimension_labels[key] == 'angle': + geometry.angles = geometry_0.angles + roi_par[key] = (0, len(geometry.angles)) + elif data.dimension_labels[key] == 'vertical': + geometry.pixel_size_v = geometry_0.pixel_size_v + geometry.pixel_num_v = geometry_0.pixel_num_v + roi_par[key] = (0, geometry.pixel_num_v) + elif data.dimension_labels[key] == 'horizontal': + geometry.pixel_size_h = geometry_0.pixel_size_h + geometry.pixel_num_h = geometry_0.pixel_num_h + roi_par[key] = (0, geometry.pixel_num_h) + else: + for key in data.dimension_labels: + if data.dimension_labels[key] == 'channel': + if (roi_par[key] != -1): + geometry.channels = (roi_par[key][1] - roi_par[key][0]) // binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.channels = geometry_0.channels // binning[key] + roi_par[key] = (0, geometry.channels * binning[key]) + elif data.dimension_labels[key] == 'angle': + if (roi_par[key] != -1): + geometry.angles = geometry_0.angles[roi_par[key][0]:roi_par[key][1]] + else: + geometry.angles = geometry_0.angles + roi_par[key] = (0, len(geometry.angles)) + if (binning[key] != 1): + binning[key] = 1 + warnings.warn('Rebinning in angular dimensions is not supported: \n binning[{}] is set to 1.'.format(key)) + elif data.dimension_labels[key] == 'vertical': + if (roi_par[key] != -1): + geometry.pixel_num_v = (roi_par[key][1] - roi_par[key][0]) // binning[key] + geometry.pixel_size_v = geometry_0.pixel_size_v * binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.pixel_num_v = geometry_0.pixel_num_v // binning[key] + geometry.pixel_size_v = geometry_0.pixel_size_v * binning[key] + roi_par[key] = (0, geometry.pixel_num_v * binning[key]) + elif data.dimension_labels[key] == 'horizontal': + if (roi_par[key] != -1): + geometry.pixel_num_h = (roi_par[key][1] - roi_par[key][0]) // binning[key] + geometry.pixel_size_h = geometry_0.pixel_size_h * binning[key] + roi_par[key] = (roi_par[key][0], roi_par[key][0] + ((roi_par[key][1] - roi_par[key][0]) // binning[key]) * binning[key]) + else: + geometry.pixel_num_h = geometry_0.pixel_num_h // binning[key] + geometry.pixel_size_h = geometry_0.pixel_size_h * binning[key] + roi_par[key] = (0, geometry.pixel_num_h * binning[key]) + + if ndim == 2: + n_pix_0 = (roi_par[0][1] - roi_par[0][0]) // binning[0] + n_pix_1 = (roi_par[1][1] - roi_par[1][0]) // binning[1] + shape = (n_pix_0, binning[0], + n_pix_1, binning[1]) + data_resized = data.as_array()[roi_par[0][0]:(roi_par[0][0] + n_pix_0 * binning[0]), + roi_par[1][0]:(roi_par[1][0] + n_pix_1 * binning[1])].reshape(shape).mean(-1).mean(1) + if ndim == 3: + n_pix_0 = (roi_par[0][1] - roi_par[0][0]) // binning[0] + n_pix_1 = (roi_par[1][1] - roi_par[1][0]) // binning[1] + n_pix_2 = (roi_par[2][1] - roi_par[2][0]) // binning[2] + shape = (n_pix_0, binning[0], + n_pix_1, binning[1], + n_pix_2, binning[2]) + data_resized = data.as_array()[roi_par[0][0]:(roi_par[0][0] + n_pix_0 * binning[0]), + roi_par[1][0]:(roi_par[1][0] + n_pix_1 * binning[1]), + roi_par[2][0]:(roi_par[2][0] + n_pix_2 * binning[2])].reshape(shape).mean(-1).mean(1).mean(2) + if ndim == 4: + n_pix_0 = (roi_par[0][1] - roi_par[0][0]) // binning[0] + n_pix_1 = (roi_par[1][1] - roi_par[1][0]) // binning[1] + n_pix_2 = (roi_par[2][1] - roi_par[2][0]) // binning[2] + n_pix_3 = (roi_par[3][1] - roi_par[3][0]) // binning[3] + shape = (n_pix_0, binning[0], + n_pix_1, binning[1], + n_pix_2, binning[2], + n_pix_3, binning[3]) + data_resized = data.as_array()[roi_par[0][0]:(roi_par[0][0] + n_pix_0 * binning[0]), + roi_par[1][0]:(roi_par[1][0] + n_pix_1 * binning[1]), + roi_par[2][0]:(roi_par[2][0] + n_pix_2 * binning[2]), + roi_par[3][0]:(roi_par[3][0] + n_pix_3 * binning[3])].reshape(shape).mean(-1).mean(1).mean(2).mean(3) + + out = type(data)(array = data_resized, + deep_copy = False, + dimension_labels = data.dimension_labels, + geometry = geometry) + + return out + + +''' +#usage exaample +ig = ImageGeometry(voxel_num_x = 200, + voxel_num_y = 200, + voxel_num_z = 200, + voxel_size_x = 1, + voxel_size_y = 1, + voxel_size_z = 1, + center_x = 0, + center_y = 0, + center_z = 0, + channels = 200) + +im = ImageData(array = numpy.zeros((200, 200, 200, 200)), + geometry = ig, + deep_copy = False, + dimension_labels = ['channel',\ + 'vertical',\ + 'horizontal_y',\ + 'horizontal_x']) + + +resizer = Resizer(binning = [1, 1, 7, 1], roi = -1) +resizer.input = im +data_resized = resizer.process() +print(data_resized) +''' diff --git a/Wrappers/Python/ccpi/processors/__init__.py b/Wrappers/Python/ccpi/processors/__init__.py new file mode 100755 index 0000000..cba5897 --- /dev/null +++ b/Wrappers/Python/ccpi/processors/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +Created on Tue Apr 30 13:51:09 2019 + +@author: ofn77899 +""" + +from .CenterOfRotationFinder import CenterOfRotationFinder +from .Normalizer import Normalizer +from .Resizer import Resizer -- cgit v1.2.3 From 0d2062ffad8cf1e0b3c8b5b8aeb800b71a32e69e Mon Sep 17 00:00:00 2001 From: Edoardo Pasca Date: Wed, 12 Jun 2019 13:19:29 +0100 Subject: fix imports in io --- Wrappers/Python/ccpi/io/NEXUSDataReader.py | 3 +-- Wrappers/Python/ccpi/io/NEXUSDataWriter.py | 4 +--- Wrappers/Python/ccpi/io/NikonDataReader.py | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'Wrappers') diff --git a/Wrappers/Python/ccpi/io/NEXUSDataReader.py b/Wrappers/Python/ccpi/io/NEXUSDataReader.py index a742dd5..cf67e27 100644 --- a/Wrappers/Python/ccpi/io/NEXUSDataReader.py +++ b/Wrappers/Python/ccpi/io/NEXUSDataReader.py @@ -9,7 +9,6 @@ Created on Wed Apr 3 10:30:25 2019 import numpy import os -import matplotlib.pyplot as plt from ccpi.framework import AcquisitionData, AcquisitionGeometry, ImageData, ImageGeometry @@ -141,4 +140,4 @@ image_data = reader.load_data() print(image_data) ig = reader.get_geometry() print(ig) -''' \ No newline at end of file +''' diff --git a/Wrappers/Python/ccpi/io/NEXUSDataWriter.py b/Wrappers/Python/ccpi/io/NEXUSDataWriter.py index d35e86b..f780f79 100644 --- a/Wrappers/Python/ccpi/io/NEXUSDataWriter.py +++ b/Wrappers/Python/ccpi/io/NEXUSDataWriter.py @@ -9,9 +9,7 @@ Created on Thu May 2 10:11:20 2019 import numpy import os -import matplotlib.pyplot as plt from ccpi.framework import AcquisitionData, AcquisitionGeometry, ImageData, ImageGeometry -from NikonDataReader import NikonDataReader import datetime @@ -150,4 +148,4 @@ writer.set_up(file_name = '/home/evelina/test_nexus_im.nxs', data_container = im) writer.write_file() -''' \ No newline at end of file +''' diff --git a/Wrappers/Python/ccpi/io/NikonDataReader.py b/Wrappers/Python/ccpi/io/NikonDataReader.py index 6f02aa0..703b65b 100644 --- a/Wrappers/Python/ccpi/io/NikonDataReader.py +++ b/Wrappers/Python/ccpi/io/NikonDataReader.py @@ -8,7 +8,6 @@ Created on Wed Apr 3 10:30:25 2019 from ccpi.framework import AcquisitionData, AcquisitionGeometry import numpy -import matplotlib.pyplot as plt import os -- cgit v1.2.3