BaseI18MultiModalLoader.set_motors()   F
last analyzed

Complexity

Conditions 17

Size

Total Lines 85
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 68
nop 3
dl 0
loc 85
rs 1.8
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like savu.plugins.unregistered.i18_loaders.base_i18_multi_modal_loader.BaseI18MultiModalLoader.set_motors() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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)
0 ignored issues
show
introduced by
The variable units does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable label does not seem to be defined for all execution paths.
Loading history...
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])
0 ignored issues
show
introduced by
The variable proj_dir does not seem to be defined in case data_obj.data_mapping._is_map on line 164 is False. Are you sure this can never be the case?
Loading history...
introduced by
The variable rotation does not seem to be defined for all execution paths.
Loading history...
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