Test Failed
Pull Request — master (#648)
by Daniil
03:44
created

savu.plugins.corrections.auto_crop_estimate   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 120
Duplicated Lines 15 %

Importance

Changes 0
Metric Value
eloc 61
dl 18
loc 120
rs 10
c 0
b 0
f 0
wmc 9

6 Methods

Rating   Name   Duplication   Size   Complexity  
A AutoCropEstimate.get_max_frames() 0 2 1
A AutoCropEstimate.nOutput_datasets() 0 2 1
A AutoCropEstimate.post_process() 0 24 4
A AutoCropEstimate.__init__() 0 2 1
A AutoCropEstimate.process_frames() 0 17 1
A AutoCropEstimate.setup() 18 18 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
# Copyright 2019 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
.. module:: auto_crop_estimate
16
   :platform: Unix
17
   :synopsis: A plugin to estimate cropping values in order to crop projections automatically
18
.. moduleauthor:: Daniil Kazantsev <[email protected]>
19
"""
20
from savu.plugins.driver.cpu_plugin import CpuPlugin
21
from savu.plugins.utils import register_plugin
22
from savu.plugins.plugin import Plugin
23
24
# add larix autocropping module
25
from larix.methods.misc import AUTOCROP
26
27
#import logging
28
import numpy as np
29
30
@register_plugin
31
class AutoCropEstimate(Plugin, CpuPlugin):
32
    """
33
    A plugin to estimate cropping values (indices) in order to crop projection data automatically \
34
    (works well when the object of interest lies fully within the field of view). This plugin will return a \
35
    metadata dataset indices2crop with estimated cropping indices to be accessed later wih plugin auto_crop_projections.
36
    
37
    :param threshold: A threshold to control the cropping strength . Default: 0.1.
38
    :param margin_skip: Skip number of pixels around the image border . Default: 10.    
39
    :param statbox_size: The size of the box to collect background statistics (mean) . Default: 30.
40
    :param increase_crop: Increase crop values to ensure more accurate cropping . Default: 40.
41
    :param method: A method how final indices across multiple frames are estimated,\
42
    choose minmax, mean or median . Default: 'median'.
43
    :param out_datasets: 4xN(frames) array with indices to crop . Default: ['indices2crop'].
44
    """
45
46
    def __init__(self):
47
        super(AutoCropEstimate, self).__init__("AutoCropEstimate")
48
49 View Code Duplication
    def setup(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
50
        # set up the output dataset that is created by the plugin
51
        in_dataset, out_dataset = self.get_datasets()
52
        # set information relating to the plugin data
53
        in_pData, out_pData = self.get_plugin_datasets()
54
        in_pData[0].plugin_data_setup('PROJECTION', self.get_max_frames())
55
        self.orig_full_shape = in_dataset[0].get_shape() # includes flats/darks/projections
56
57
        fullData = in_dataset[0]
58
        slice_dirs = list(in_dataset[0].get_slice_dimensions())
59
        self.new_shape = (np.prod(np.array(fullData.get_shape())[slice_dirs]), 4)
60
61
        out_dataset[0].create_dataset(shape=self.new_shape ,
62
                                      axis_labels=['x.pixels', 'y.pixels'],
63
                                      remove=True,
64
                                      transport='hdf5')
65
        out_dataset[0].add_pattern("METADATA", core_dims=(1,), slice_dims=(0,))
66
        out_pData[0].plugin_data_setup('METADATA', self.get_max_frames())
67
68
    def process_frames(self, data):        
69
        proj2D = data[0] # get 2D projection image [DetectorHoriz, DetectorVert]        
70
        proj2D[proj2D > 0.0] = -np.log(proj2D[proj2D > 0.0])
71
        proj2D[proj2D < 0.0] = 0.0
72
        
73
        pars = {'input_data' : proj2D, 			   # input grayscale image
74
        	'threshold' : self.parameters['threshold'], # threshold to control cropping strength
75
	        'margin_skip' : self.parameters['margin_skip'], # skip number of pixels around the image border
76
        	'statbox_size' : self.parameters['statbox_size'],# the size of the box to collect background statistics (mean)
77
	        'increase_crop' : self.parameters['increase_crop']} # increase crop values to ensure better cropping
78
79
        indices2crop = AUTOCROP(pars['input_data'], pars['threshold'],
80
                           pars['margin_skip'], pars['statbox_size'],
81
                           pars['increase_crop'])
82
83
        #print(indices2crop)
84
        return [np.array([indices2crop])]
85
86
    def post_process(self):
87
        in_datasets, out_datasets = self.get_datasets()
88
        cropped_indices = out_datasets[0].data[...]
89
        
90
        if (str(self.parameters['method']) == 'minmax'):
91
            crop_left_horiz = np.min(cropped_indices[:,0])
92
            crop_right_horiz = np.max(cropped_indices[:,1])
93
            crop_up_vert = np.min(cropped_indices[:,2])
94
            crop_down_vert = np.max(cropped_indices[:,3])                 
95
        elif (str(self.parameters['method']) == 'mean'):
96
            crop_left_horiz = np.mean(cropped_indices[:,0])
97
            crop_right_horiz = np.mean(cropped_indices[:,1])
98
            crop_up_vert = np.mean(cropped_indices[:,2])
99
            crop_down_vert = np.mean(cropped_indices[:,3])
100
        elif (str(self.parameters['method']) == 'median'):
101
            crop_left_horiz = np.median(cropped_indices[:,0])
102
            crop_right_horiz = np.median(cropped_indices[:,1])
103
            crop_up_vert = np.median(cropped_indices[:,2])
104
            crop_down_vert = np.median(cropped_indices[:,3])     
105
        else:
106
            print("Please select a method how final indices across multiple frames are estimated, choose minmax, mean or median")           
107
            
108
        #print("Suggested values for cropping: detectorHoriz from {} to {}, detectorVertical from {} to {}".format(crop_left_horiz,crop_right_horiz,crop_up_vert,crop_down_vert))
109
        in_datasets[0].meta_data.set('indices2crop', [crop_left_horiz, crop_right_horiz, crop_up_vert, crop_down_vert])
0 ignored issues
show
introduced by
The variable crop_right_horiz does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable crop_left_horiz does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable crop_up_vert does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable crop_down_vert does not seem to be defined for all execution paths.
Loading history...
110
        #print(in_datasets[0].get_name())       
111
        # a possible option to incorporate values into 
112
        #preview = [:, mid, :]
113
        #self.preview_flag = self.set_preview(in_datasets[0], preview)
114
115
    def nOutput_datasets(self):
116
        return 1
117
118
    def get_max_frames(self):
119
        return 'single'
120