|
1
|
|
|
# Copyright 2014 Diamond Light Source Ltd. |
|
2
|
|
|
# |
|
3
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
|
4
|
|
|
# you may not use this file except in compliance with the License. |
|
5
|
|
|
# You may obtain a copy of the License at |
|
6
|
|
|
# |
|
7
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0 |
|
8
|
|
|
# |
|
9
|
|
|
# Unless required by applicable law or agreed to in writing, software |
|
10
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, |
|
11
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12
|
|
|
# See the License for the specific language governing permissions and |
|
13
|
|
|
# limitations under the License. |
|
14
|
|
|
|
|
15
|
|
|
""" |
|
16
|
|
|
.. module:: temp_loader |
|
17
|
|
|
:platform: Unix |
|
18
|
|
|
:synopsis: A class for loading standard tomography data in a variety of |
|
19
|
|
|
formats. |
|
20
|
|
|
|
|
21
|
|
|
.. moduleauthor:: Nicola Wadeson <[email protected]> |
|
22
|
|
|
|
|
23
|
|
|
""" |
|
24
|
|
|
|
|
25
|
|
|
import os |
|
26
|
|
|
import tempfile |
|
27
|
|
|
import warnings |
|
28
|
|
|
|
|
29
|
|
|
import h5py |
|
30
|
|
|
import numpy as np |
|
31
|
|
|
|
|
32
|
|
|
from savu.data.data_structures.data_types.data_plus_darks_and_flats \ |
|
33
|
|
|
import NoImageKey |
|
34
|
|
|
from savu.data.data_structures.data_types.image_data import ImageData |
|
35
|
|
|
from savu.plugins.loaders.base_loader import BaseLoader |
|
36
|
|
|
from savu.plugins.utils import register_plugin |
|
37
|
|
|
|
|
38
|
|
|
|
|
39
|
|
|
@register_plugin |
|
40
|
|
|
class ImageLoader(BaseLoader): |
|
41
|
|
|
""" |
|
42
|
|
|
Load any FabIO compatible formats (e.g. tiffs) |
|
43
|
|
|
|
|
44
|
|
|
:param dataset_name: The name assigned to the dataset. Default: 'tomo'. |
|
45
|
|
|
:param angles: A python statement to be evaluated \ |
|
46
|
|
|
(e.g np.linspace(0, 180, nAngles)) or a file. Default: None. |
|
47
|
|
|
:param frame_dim: Which dimension requires stitching? Default: 0. |
|
48
|
|
|
:param data_prefix: A file prefix for the data file. Default: None. |
|
49
|
|
|
:param dark_prefix: A file prefix for the dark field files, including the\ |
|
50
|
|
|
folder path if different from the data. Default: None. |
|
51
|
|
|
:param flat_prefix: A file prefix for the flat field files, including the\ |
|
52
|
|
|
folder path if different from the data. Default: None. |
|
53
|
|
|
""" |
|
54
|
|
|
|
|
55
|
|
|
def __init__(self, name='ImageLoader'): |
|
56
|
|
|
super(ImageLoader, self).__init__(name) |
|
57
|
|
|
|
|
58
|
|
|
def setup(self): |
|
59
|
|
|
exp = self.exp |
|
60
|
|
|
data_obj = exp.create_data_object('in_data', |
|
61
|
|
|
self.parameters['dataset_name']) |
|
62
|
|
|
|
|
63
|
|
|
rot = 0 |
|
64
|
|
|
detY = 1 |
|
65
|
|
|
detX = 2 |
|
66
|
|
|
data_obj.set_axis_labels('rotation_angle.degrees', |
|
67
|
|
|
'detector_y.pixel', |
|
68
|
|
|
'detector_x.pixel') |
|
69
|
|
|
|
|
70
|
|
|
data_obj.add_pattern('PROJECTION', core_dims=(detX, detY), |
|
71
|
|
|
slice_dims=(rot,)) |
|
72
|
|
|
data_obj.add_pattern('SINOGRAM', core_dims=(detX, rot), |
|
73
|
|
|
slice_dims=(detY,)) |
|
74
|
|
|
|
|
75
|
|
|
path = os.path.abspath(exp.meta_data.get("data_file")) |
|
76
|
|
|
data_obj.data = self._get_data_type(data_obj, path) |
|
77
|
|
|
|
|
78
|
|
|
self.set_rotation_angles(data_obj) |
|
79
|
|
|
|
|
80
|
|
|
# dummy file |
|
81
|
|
|
filename = path.split(os.sep)[-1] + '.h5' |
|
82
|
|
|
data_obj.backing_file = \ |
|
83
|
|
|
h5py.File(os.path.join(tempfile.mkdtemp(), filename), 'a') |
|
84
|
|
|
|
|
85
|
|
|
data_obj.set_shape(data_obj.data.get_shape()) |
|
86
|
|
|
self.set_data_reduction_params(data_obj) |
|
87
|
|
|
self._set_darks_and_flats(data_obj, path) |
|
88
|
|
|
|
|
89
|
|
|
def _set_darks_and_flats(self, dObj, path): |
|
90
|
|
|
if not self.parameters['flat_prefix']: |
|
91
|
|
|
return |
|
92
|
|
|
|
|
93
|
|
|
dObj.data = NoImageKey(dObj, None, 0) |
|
94
|
|
|
fdim = self.parameters['frame_dim'] |
|
95
|
|
|
|
|
96
|
|
|
# read dark and flat images |
|
97
|
|
|
fpath, ffix = self._get_path(self.parameters['flat_prefix'], path) |
|
98
|
|
|
flat = ImageData(fpath, dObj, [fdim], None, ffix) |
|
99
|
|
|
|
|
100
|
|
|
if self.parameters['dark_prefix']: |
|
101
|
|
|
dpath, dfix = self._get_path(self.parameters['dark_prefix'], path) |
|
102
|
|
|
dark = ImageData(dpath, dObj, [fdim], None, dfix) |
|
103
|
|
|
else: |
|
104
|
|
|
shape = dObj.get_shape() |
|
105
|
|
|
dark = np.zeros([1] + [shape[i] for i in [1, 2]], dtype=flat.dtype) |
|
106
|
|
|
|
|
107
|
|
|
dObj.data._set_dark_path(dark) |
|
108
|
|
|
dObj.data._set_flat_path(flat) |
|
109
|
|
|
dObj.data._set_dark_and_flat() |
|
110
|
|
|
|
|
111
|
|
|
def _get_path(self, param, data): |
|
112
|
|
|
ppath, pfix = os.path.split(param) |
|
113
|
|
|
ppath = \ |
|
114
|
|
|
os.path.join(data, ppath) if not os.path.isabs(ppath) else ppath |
|
115
|
|
|
return ppath, pfix |
|
116
|
|
|
|
|
117
|
|
|
def _get_data_type(self, obj, path): |
|
118
|
|
|
prefix = self.parameters['data_prefix'] |
|
119
|
|
|
return ImageData(path, obj, [self.parameters['frame_dim']], None, prefix) |
|
120
|
|
|
|
|
121
|
|
|
def set_rotation_angles(self, data_obj): |
|
122
|
|
|
angles = self.parameters['angles'] |
|
123
|
|
|
|
|
124
|
|
|
if angles is None: |
|
125
|
|
|
angles = np.linspace(0, 180, data_obj.data.get_shape()[0]) |
|
126
|
|
|
else: |
|
127
|
|
|
try: |
|
128
|
|
|
ldict = {} |
|
129
|
|
|
exec("angles = " + angles,globals(),ldict) |
|
130
|
|
|
angles = ldict['angles'] |
|
131
|
|
|
except Exception as e: |
|
132
|
|
|
warnings.warn("Could not execute statement: {}".format(e)) |
|
133
|
|
|
try: |
|
134
|
|
|
angles = np.loadtxt(angles) |
|
135
|
|
|
except Exception as e: |
|
136
|
|
|
raise Exception('Cannot set angles in loader. Error: {}'.format(e)) |
|
137
|
|
|
|
|
138
|
|
|
n_angles = len(angles) |
|
139
|
|
|
data_angles = data_obj.data.get_shape()[self.parameters['frame_dim']] |
|
140
|
|
|
if data_angles != n_angles: |
|
141
|
|
|
raise Exception("The number of angles %s does not match the data " |
|
142
|
|
|
"dimension length %s", n_angles, data_angles) |
|
143
|
|
|
data_obj.meta_data.set("rotation_angle", angles) |
|
144
|
|
|
|