|
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:: base_i18_multi_modal_loader |
|
17
|
|
|
:platform: Unix |
|
18
|
|
|
:synopsis: Contains a base class from which all multi-modal loaders are \ |
|
19
|
|
|
derived. |
|
20
|
|
|
|
|
21
|
|
|
.. moduleauthor:: Nicola Wadeson <[email protected]> |
|
22
|
|
|
|
|
23
|
|
|
""" |
|
24
|
|
|
|
|
25
|
|
|
import h5py |
|
26
|
|
|
import logging |
|
27
|
|
|
from savu.data.data_structures.data_add_ons import DataMapping |
|
28
|
|
|
|
|
29
|
|
|
from savu.plugins.loaders.mapping_loaders.base_multi_modal_loader \ |
|
30
|
|
|
import BaseMultiModalLoader |
|
31
|
|
|
|
|
32
|
|
|
|
|
33
|
|
|
class BaseI18MultiModalLoader(BaseMultiModalLoader): |
|
34
|
|
|
def __init__(self, name='BaseI18MultiModalLoader'): |
|
35
|
|
|
super(BaseI18MultiModalLoader, self).__init__(name) |
|
36
|
|
|
|
|
37
|
|
|
def multi_modal_setup(self, ltype, name): |
|
38
|
|
|
# set up the file handles |
|
39
|
|
|
exp = self.exp |
|
40
|
|
|
data_obj = exp.create_data_object("in_data", name) |
|
41
|
|
|
data_obj.backing_file = \ |
|
42
|
|
|
h5py.File(exp.meta_data.get("data_file"), 'r') |
|
43
|
|
|
f = data_obj.backing_file |
|
44
|
|
|
logging.debug("Creating file '%s' '%s'_entry", |
|
45
|
|
|
data_obj.backing_file.filename, ltype) |
|
46
|
|
|
|
|
47
|
|
|
data_obj.meta_data.set( |
|
48
|
|
|
"mono_energy", f[self.parameters['monochromator']][()]/1e3) |
|
49
|
|
|
x = f[self.parameters['x']][()] |
|
50
|
|
|
|
|
51
|
|
|
if self.parameters['x'] is not None: |
|
52
|
|
|
if x.ndim > 1: |
|
53
|
|
|
data_obj.meta_data.set("x", x[0, :]) |
|
54
|
|
|
else: |
|
55
|
|
|
data_obj.meta_data.set("x", x) |
|
56
|
|
|
|
|
57
|
|
|
if self.parameters['y'] is not None: |
|
58
|
|
|
y = f[self.parameters['y']][()] |
|
59
|
|
|
data_obj.meta_data.set("y", y) |
|
60
|
|
|
if self.parameters['rotation'] is not None: |
|
61
|
|
|
rotation_angle = f[self.parameters['rotation']][()] |
|
62
|
|
|
if rotation_angle.ndim > 1: |
|
63
|
|
|
rotation_angle = rotation_angle[:, 0] |
|
64
|
|
|
|
|
65
|
|
|
data_obj.meta_data.set("rotation_angle", rotation_angle) |
|
66
|
|
|
return data_obj |
|
67
|
|
|
|
|
68
|
|
|
def set_motors(self, data_obj, ltype): |
|
69
|
|
|
# now lets extract the map, if there is one! |
|
70
|
|
|
# to begin with |
|
71
|
|
|
data_obj.data_mapping = DataMapping() |
|
72
|
|
|
logging.debug("========="+ltype+"=========") |
|
73
|
|
|
motors = self.parameters['scan_pattern'] |
|
74
|
|
|
data_obj.data_mapping.set_axes(self.parameters['scan_pattern']) |
|
75
|
|
|
nAxes = len(data_obj.get_shape()) |
|
76
|
|
|
#logging.debug nAxes |
|
77
|
|
|
cts = 0 |
|
78
|
|
|
chk = 0 |
|
79
|
|
|
chk1 = 0 |
|
80
|
|
|
motor_type = [] |
|
81
|
|
|
labels = [] |
|
82
|
|
|
fast_axis = self.parameters["fast_axis"] |
|
83
|
|
|
logging.debug("axes input are:"+str(motors)) |
|
84
|
|
|
unknown_count = 0 |
|
85
|
|
|
for ii in range(nAxes): |
|
86
|
|
|
# find the rotation axis |
|
87
|
|
|
try: |
|
88
|
|
|
data_axis = self.parameters[motors[ii]]# get that out the file |
|
89
|
|
|
logging.debug("the data axis is %s" % str(data_axis)) |
|
90
|
|
|
if motors[ii]=="rotation": |
|
91
|
|
|
data_obj.data_mapping._is_tomo = True |
|
92
|
|
|
motor_type.append('rotation') |
|
93
|
|
|
label = 'rotation_angle' |
|
94
|
|
|
units = 'degrees' |
|
95
|
|
|
logging.debug(ltype + " reader: %s", "is a tomo scan") |
|
96
|
|
|
elif motors[ii] in ["x","y"]: |
|
97
|
|
|
cts += 1 # increase the order of the map |
|
98
|
|
|
motor_type.append('translation') |
|
99
|
|
|
if (motors[ii]==fast_axis): |
|
100
|
|
|
label='x' |
|
101
|
|
|
else: |
|
102
|
|
|
label='y' |
|
103
|
|
|
units = 'mm' |
|
104
|
|
|
except KeyError as e: |
|
105
|
|
|
#print("exception was ",str(e)) |
|
106
|
|
|
#print("found no motor") |
|
107
|
|
|
motor_type.append('None') |
|
108
|
|
|
#now the detector axes |
|
109
|
|
|
if ltype =='fluo': |
|
110
|
|
|
label = 'energy' |
|
111
|
|
|
units = 'counts' |
|
112
|
|
|
elif ltype =='xrd': |
|
113
|
|
|
if chk==0: |
|
114
|
|
|
label = 'detector_x' |
|
115
|
|
|
elif chk==1: |
|
116
|
|
|
label = 'detector_y' |
|
117
|
|
|
units = 'index' |
|
118
|
|
|
chk=chk+1 |
|
119
|
|
|
|
|
120
|
|
|
except IndexError: |
|
121
|
|
|
''' |
|
122
|
|
|
some additional singleton dimensions have been added in the latest mapping project stuff on I18 |
|
123
|
|
|
This fixes that. |
|
124
|
|
|
''' |
|
125
|
|
|
if ltype =='xrd': |
|
126
|
|
|
if chk1 == 0: |
|
127
|
|
|
label = 'detector_x' |
|
128
|
|
|
elif chk1 == 1: |
|
129
|
|
|
label = 'detector_y' |
|
130
|
|
|
units = 'pixels' |
|
131
|
|
|
chk1=chk1+1 |
|
132
|
|
|
else: |
|
133
|
|
|
label = 'unknown_%s' % unknown_count |
|
134
|
|
|
units = 'unknown' |
|
135
|
|
|
unknown_count += 1 |
|
136
|
|
|
except: |
|
137
|
|
|
raise |
|
138
|
|
|
|
|
139
|
|
|
labels.append(label+'.'+units) |
|
|
|
|
|
|
140
|
|
|
if not motors: |
|
141
|
|
|
logging.debug("%s reader: No maps found!", ltype) |
|
142
|
|
|
#logging.debug labels |
|
143
|
|
|
data_obj.set_axis_labels(*tuple(labels)) |
|
144
|
|
|
data_obj.data_mapping.set_motors(motors) |
|
145
|
|
|
data_obj.data_mapping.set_motor_type(motor_type) |
|
146
|
|
|
if (cts): |
|
147
|
|
|
data_obj.data_mapping._is_map = cts |
|
148
|
|
|
else: |
|
149
|
|
|
logging.debug("'%s' reader: No translations found!", ltype) |
|
150
|
|
|
pass |
|
151
|
|
|
logging.debug("axis labels:"+str(labels)) |
|
152
|
|
|
logging.debug("motor_type:"+str(motor_type)) |
|
153
|
|
|
|
|
154
|
|
|
def add_patterns_based_on_acquisition(self, data_obj, ltype): |
|
155
|
|
|
motor_type = data_obj.data_mapping.get_motor_type() |
|
156
|
|
|
projection = [] |
|
157
|
|
|
for item, key in enumerate(motor_type): |
|
158
|
|
|
if key == 'translation': |
|
159
|
|
|
projection.append(item) |
|
160
|
|
|
# logging.debug projection |
|
161
|
|
|
elif key == 'rotation': |
|
162
|
|
|
rotation = item |
|
163
|
|
|
dims = list(range(len(data_obj.get_shape()))) |
|
164
|
|
|
if data_obj.data_mapping._is_map: |
|
165
|
|
|
proj_dir = tuple(projection) |
|
166
|
|
|
data_obj.add_pattern("PROJECTION", core_dims=proj_dir, |
|
167
|
|
|
slice_dims=tuple(set(dims) - set(proj_dir))) |
|
168
|
|
|
|
|
169
|
|
|
if data_obj.data_mapping._is_tomo: |
|
170
|
|
|
#rotation and fast axis |
|
171
|
|
|
sino_dir = (rotation, proj_dir[-1]) |
|
|
|
|
|
|
172
|
|
|
slice_dims = tuple(set(dims) - set(sino_dir)) |
|
173
|
|
|
if slice_dims: |
|
174
|
|
|
data_obj.add_pattern("SINOGRAM", core_dims=sino_dir, |
|
175
|
|
|
slice_dims=slice_dims) |
|
176
|
|
|
|
|
177
|
|
|
if ltype == 'fluo': |
|
178
|
|
|
spec_core = (-1,) # it will always be this |
|
179
|
|
|
spec_slice = tuple(dims[:-1]) |
|
180
|
|
|
data_obj.add_pattern("SPECTRUM", core_dims=spec_core, |
|
181
|
|
|
slice_dims=spec_slice) |
|
182
|
|
|
|
|
183
|
|
|
|
|
184
|
|
|
if ltype == 'xrd': |
|
185
|
|
|
diff_core = (-2,-1) # it will always be this |
|
186
|
|
|
diff_slice = tuple(dims[:-2]) |
|
187
|
|
|
data_obj.add_pattern("DIFFRACTION", core_dims=diff_core, |
|
188
|
|
|
slice_dims=diff_slice) |
|
189
|
|
|
|
|
190
|
|
|
if ltype == 'monitor': |
|
191
|
|
|
# this is needed for I0 corrections of single sinogram ND data |
|
192
|
|
|
channel_core = (dims[-1],) |
|
193
|
|
|
channel_slice = tuple(dims[:-1]) |
|
194
|
|
|
data_obj.add_pattern("CHANNEL", core_dims=channel_core, |
|
195
|
|
|
slice_dims=channel_slice) |
|
196
|
|
|
|
|
197
|
|
|
|