Commit 7853c0732d9ebe9aad87f26bc096b0791fd04359
1 parent
81b99bfa
Exists in
master
and in
68 other branches
ENC: Aesthetic commit, related to methods naming and organization inside Slice class
Showing
2 changed files
with
226 additions
and
179 deletions
Show diff stats
invesalius/constants.py
1 | 1 | from project import Project |
2 | 2 | |
3 | +# Slice orientation | |
3 | 4 | AXIAL = 0 |
4 | 5 | CORONAL = 1 |
5 | 6 | SAGITAL = 2 |
6 | 7 | |
8 | +# Colour representing each orientation | |
9 | +ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red | |
10 | + 'CORONAL': (0,1,0), # Green | |
11 | + 'SAGITAL': (0,0,1)} # Blue | |
7 | 12 | |
8 | -proj = Project() | |
13 | +# Camera according to slice's orientation | |
14 | +CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)} | |
15 | +CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} | |
9 | 16 | |
17 | +# Mask threshold options | |
18 | +proj = Project() | |
10 | 19 | THRESHOLD_RANGE = proj.threshold_modes["Bone"] |
11 | - | |
12 | 20 | THRESHOLD_PRESETS_INDEX = 0 #Bone |
13 | - | |
14 | 21 | THRESHOLD_HUE_RANGE = (0, 0.6667) |
15 | 22 | THRESHOLD_INVALUE = 5000 |
16 | 23 | THRESHOLD_OUTVALUE = 0 |
17 | 24 | |
25 | +# Mask properties | |
18 | 26 | MASK_NAME_PATTERN = "Mask %d" |
19 | - | |
27 | +MASK_OPACITY = 0.3 | |
20 | 28 | MASK_COLOUR = [(0.33, 1, 0.33), |
21 | 29 | (1, 1, 0.33), |
22 | 30 | (0.33, 0.91, 1), |
... | ... | @@ -34,33 +42,32 @@ MASK_COLOUR = [(0.33, 1, 0.33), |
34 | 42 | #(0.792156862745098, 1.0, 0.66666666666666663), # too "light" |
35 | 43 | #(0.66666666666666663, 0.792156862745098, 1.0)] |
36 | 44 | |
37 | -MASK_OPACITY = 0.3 | |
45 | +# Related to slice editor brush | |
46 | +BRUSH_FORMAT = 0 # 0: circle, 1: square | |
47 | +BRUSH_SIZE = 30 | |
48 | +BRUSH_OP = 0 # 0: erase, 1: add, 2: threshold | |
49 | +BRUSH_COLOUR = (0,0,1.0) | |
38 | 50 | |
39 | -OP_ADD = 0 | |
40 | -OP_DEL = 1 | |
41 | -OP_THRESH =2 | |
42 | 51 | |
43 | -# Surface creation default values. List contains: | |
52 | +# Surface creation values. Each element's list contains: | |
44 | 53 | # 0: imagedata reformat ratio |
45 | 54 | # 1: smooth_iterations |
46 | 55 | # 2: smooth_relaxation_factor |
47 | 56 | # 3: decimate_reduction |
48 | - | |
49 | 57 | SURFACE_QUALITY = { |
50 | 58 | "Low": (3, 2, 0.3000, 0.4), |
51 | 59 | "Medium": (2, 2, 0.3000, 0.4), |
52 | 60 | "High": (0, 1, 0.3000, 0.1), |
53 | 61 | "Optimal": (0, 2, 0.3000, 0.4), |
54 | - "Custom": (None, None, None, None) | |
55 | -} | |
56 | - | |
62 | + "Custom": (None, None, None, None)} | |
57 | 63 | DEFAULT_SURFACE_QUALITY = "Optimal" |
58 | 64 | |
59 | - | |
65 | +# Surface properties | |
60 | 66 | SURFACE_TRANSPARENCY = 0.0 |
61 | 67 | SURFACE_NAME_PATTERN = "Surface %d" |
62 | 68 | |
63 | -WINDOW_LEVEL = ({"Abdomen":(350,50), | |
69 | +# Imagedata - window and level presets | |
70 | +WINDOW_LEVEL = {"Abdomen":(350,50), | |
64 | 71 | "Bone":(2000, 300), |
65 | 72 | "Brain Posterior Fossa":(120,40), |
66 | 73 | "Brain":(80,40), |
... | ... | @@ -76,12 +83,6 @@ WINDOW_LEVEL = ({"Abdomen":(350,50), |
76 | 83 | "Pelvis": (450,50), |
77 | 84 | "Sinus":(4000, 400), |
78 | 85 | "Vasculature - Hard":(240,80), |
79 | - "Vasculature - Soft":(650,160) | |
80 | - }) | |
86 | + "Vasculature - Soft":(650,160)} | |
81 | 87 | |
82 | -ORIENTATION_COLOUR = {'AXIAL': (1,0,0), # Red | |
83 | - 'CORONAL': (0,1,0), # Green | |
84 | - 'SAGITAL': (0,0,1)} # Blue | |
85 | -CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)} | |
86 | -CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} | |
87 | 88 | ... | ... |
invesalius/data/slice_.py
... | ... | @@ -11,109 +11,220 @@ from utils import Singleton |
11 | 11 | |
12 | 12 | class Slice(object): |
13 | 13 | __metaclass__= Singleton |
14 | - # Only one project will be initialized per time. Therefore, we use | |
15 | - # Singleton design pattern for implementing it | |
14 | + # Only one slice will be initialized per time (despite several viewers | |
15 | + # show it from distinct perspectives). | |
16 | + # Therefore, we use Singleton design pattern for implementing it. | |
16 | 17 | |
17 | 18 | def __init__(self): |
18 | 19 | self.imagedata = None |
19 | - self.__bind_events() | |
20 | 20 | self.current_mask = None |
21 | - | |
21 | + self.__bind_events() | |
22 | + | |
22 | 23 | def __bind_events(self): |
23 | - ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values') | |
24 | - ps.Publisher().subscribe(self.SetEditionThresholdRange, | |
25 | - 'Set edition threshold values') | |
26 | - ps.Publisher().subscribe(self.OnChangeCurrentMaskColour, | |
27 | - 'Change mask colour') | |
28 | - ps.Publisher().subscribe(self.AddMask, 'Create new mask') | |
29 | - ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected') | |
30 | - ps.Publisher().subscribe(self.CreateSurfaceFromIndex, | |
31 | - 'Create surface from index') | |
24 | + # Slice properties | |
32 | 25 | ps.Publisher().subscribe(self.UpdateCursorPosition, |
33 | 26 | 'Update cursor position in slice') |
34 | - ps.Publisher().subscribe(self.ShowMask, 'Show mask') | |
35 | - ps.Publisher().subscribe(self.ChangeMaskName, 'Change mask name') | |
36 | - ps.Publisher().subscribe(self.EraseMaskPixel, 'Erase mask pixel') | |
37 | - ps.Publisher().subscribe(self.EditMaskPixel, 'Edit mask pixel') | |
38 | - ps.Publisher().subscribe(self.AddMaskPixel, 'Add mask pixel') | |
27 | + # General slice control | |
28 | + ps.Publisher().subscribe(self.CreateSurfaceFromIndex, | |
29 | + 'Create surface from index') | |
30 | + # Mask control | |
31 | + ps.Publisher().subscribe(self.__add_mask, 'Create new mask') | |
32 | + ps.Publisher().subscribe(self.__select_current_mask, | |
33 | + 'Change mask selected') | |
34 | + # Mask properties | |
35 | + ps.Publisher().subscribe(self.__set_current_mask_edition_threshold, | |
36 | + 'Set edition threshold values') | |
37 | + ps.Publisher().subscribe(self.__set_current_mask_threshold, | |
38 | + 'Set threshold values') | |
39 | + ps.Publisher().subscribe(self.__set_current_mask_colour, | |
40 | + 'Change mask colour') | |
41 | + ps.Publisher().subscribe(self.__set_mask_name, 'Change mask name') | |
42 | + ps.Publisher().subscribe(self.__show_mask, 'Show mask') | |
43 | + | |
44 | + # Operations related to slice editor | |
45 | + ps.Publisher().subscribe(self.__erase_mask_pixel, 'Erase mask pixel') | |
46 | + ps.Publisher().subscribe(self.__edit_mask_pixel, 'Edit mask pixel') | |
47 | + ps.Publisher().subscribe(self.__add_mask_pixel, 'Add mask pixel') | |
48 | + | |
49 | + #--------------------------------------------------------------------------- | |
50 | + # BEGIN PUBSUB_EVT METHODS | |
51 | + #--------------------------------------------------------------------------- | |
52 | + def __get_mask_data_for_surface_creation(self, pubsub_evt): | |
53 | + mask_index = pubsub_evt.data | |
54 | + CreateSurfaceFromIndex | |
39 | 55 | |
40 | - def EraseMaskPixel(self, pubsub_evt): | |
56 | + | |
57 | + | |
58 | + | |
59 | + def __add_mask(self, pubsub_evt): | |
60 | + mask_name = pubsub_evt.data | |
61 | + self.CreateMask(name=mask_name) | |
62 | + self.ChangeCurrentMaskColour(self.current_mask.colour) | |
63 | + | |
64 | + def __select_current_mask(self, pubsub_evt): | |
65 | + mask_index = pubsub_evt.data | |
66 | + self.SelectCurrentMask(mask_index) | |
67 | + #--------------------------------------------------------------------------- | |
68 | + def __set_current_mask_edition_threshold(self, evt_pubsub): | |
69 | + if self.current_mask: | |
70 | + threshold_range = evt_pubsub.data | |
71 | + index = self.current_mask.index | |
72 | + self.SetMaskEditionThreshold(index, threshold_range) | |
73 | + | |
74 | + def __set_current_mask_threshold(self, evt_pubsub): | |
75 | + threshold_range = evt_pubsub.data | |
76 | + index = self.current_mask.index | |
77 | + self.SetMaskThreshold(index, threshold_range) | |
78 | + | |
79 | + def __set_current_mask_colour(self, pubsub_evt): | |
80 | + # "if" is necessary because wx events are calling this before any mask | |
81 | + # has been created | |
82 | + if self.current_mask: | |
83 | + colour_wx = pubsub_evt.data | |
84 | + colour_vtk = [c/255.0 for c in colour_wx] | |
85 | + self.SetMaskColour(self.current_mask.index, colour_vtk) | |
86 | + | |
87 | + def __set_mask_name(self, pubsub_evt): | |
88 | + index, name = pubsub_evt.data | |
89 | + self.SetMaskName(index, name) | |
90 | + | |
91 | + def __show_mask(self, pubsub_evt): | |
92 | + # "if" is necessary because wx events are calling this before any mask | |
93 | + # has been created | |
94 | + if self.current_mask: | |
95 | + index, value = pubsub_evt.data | |
96 | + self.ShowMask(index, value) | |
97 | + #--------------------------------------------------------------------------- | |
98 | + def __erase_mask_pixel(self, pubsub_evt): | |
41 | 99 | position = pubsub_evt.data |
42 | 100 | self.ErasePixel(position) |
43 | 101 | |
44 | - def EditMaskPixel(self, pubsub_evt): | |
102 | + def __edit_mask_pixel(self, pubsub_evt): | |
45 | 103 | position = pubsub_evt.data |
46 | 104 | self.EditPixelBasedOnThreshold(position) |
47 | 105 | |
48 | - def AddMaskPixel(self, pubsub_evt): | |
106 | + def __add_mask_pixel(self, pubsub_evt): | |
49 | 107 | position = pubsub_evt.data |
50 | 108 | self.DrawPixel(position) |
51 | - | |
52 | - def ChangeMaskName(self, pubsub_evt): | |
53 | - index, name = pubsub_evt.data | |
54 | - | |
109 | + #--------------------------------------------------------------------------- | |
110 | + # END PUBSUB_EVT METHODS | |
111 | + #--------------------------------------------------------------------------- | |
112 | + | |
113 | + | |
114 | + def SetMaskColour(self, index, colour, update=True): | |
115 | + "Set a mask colour given its index and colour (RGB 0-1 values)" | |
116 | + proj = Project() | |
117 | + proj.mask_dict[index].colour = colour | |
118 | + | |
119 | + (r,g,b) = colour | |
120 | + scalar_range = int(self.imagedata.GetScalarRange()[1]) | |
121 | + self.lut_mask.SetTableValue(1, r, g, b, 1.0) | |
122 | + self.lut_mask.SetTableValue(scalar_range - 1, r, g, b, 1.0) | |
123 | + | |
124 | + colour_wx = [r*255, g*255, b*255] | |
125 | + ps.Publisher().sendMessage('Change mask colour in notebook', | |
126 | + (self.current_mask.index, (r,g,b))) | |
127 | + ps.Publisher().sendMessage('Set GUI items colour', colour_wx) | |
128 | + if update: | |
129 | + ps.Publisher().sendMessage('Update slice viewer') | |
130 | + | |
131 | + def SetMaskName(self, index, name): | |
132 | + "Rename a mask given its index and the new name" | |
55 | 133 | proj = Project() |
56 | 134 | proj.mask_dict[index].name = name |
57 | 135 | |
136 | + def SetMaskEditionThreshold(self, index, threshold_range): | |
137 | + "Set threshold bounds to be used while editing slice" | |
138 | + proj = Project() | |
139 | + proj.mask_dict[index].edition_threshold_range = threshold_range | |
58 | 140 | |
59 | - def ShowMask(self, pubsub_evt): | |
60 | - | |
61 | - # This is necessary because wx events are calling this before it was created | |
62 | - if self.current_mask: | |
63 | - mask_index, value = pubsub_evt.data | |
141 | + def SetMaskThreshold(self, index, threshold_range): | |
142 | + """ | |
143 | + Set a mask threshold range given its index and tuple of min and max | |
144 | + threshold values. | |
145 | + """ | |
146 | + thresh_min, thresh_max = threshold_range | |
147 | + | |
148 | + if self.current_mask.index == index: | |
149 | + # Update pipeline (this must be here, so pipeline is not broken) | |
150 | + self.img_thresh_mask.SetInput(self.imagedata) | |
151 | + self.img_thresh_mask.ThresholdBetween(float(thresh_min), | |
152 | + float(thresh_max)) | |
153 | + self.img_thresh_mask.Update() | |
64 | 154 | |
65 | - proj = Project() | |
66 | - proj.mask_dict[mask_index].is_shown = value | |
155 | + # Create imagedata copy so the pipeline is not broken | |
156 | + imagedata = self.img_thresh_mask.GetOutput() | |
157 | + self.current_mask.imagedata.DeepCopy(imagedata) | |
158 | + self.current_mask.threshold_range = threshold_range | |
67 | 159 | |
68 | - | |
69 | - if (mask_index == self.current_mask.index): | |
70 | - if value: | |
71 | - self.blend_filter.SetOpacity(1, self.current_mask.opacity) | |
72 | - else: | |
73 | - | |
74 | - self.blend_filter.SetOpacity(1, 0) | |
75 | - self.blend_filter.Update() | |
76 | - ps.Publisher().sendMessage('Update slice viewer') | |
77 | - | |
160 | + # Update pipeline (this must be here, so pipeline is not broken) | |
161 | + self.img_colours_mask.SetInput(self.current_mask.imagedata) | |
78 | 162 | |
79 | - | |
80 | - def CreateSurfaceFromIndex(self, pubsub_evt): | |
81 | - mask_index = pubsub_evt.data | |
163 | + # Update viewer | |
164 | + ps.Publisher().sendMessage('Update slice viewer') | |
165 | + | |
166 | + # Update data notebook (GUI) | |
167 | + ps.Publisher().sendMessage('Set mask threshold in notebook', | |
168 | + (self.current_mask.index, | |
169 | + self.current_mask.threshold_range)) | |
170 | + else: | |
171 | + proj = Project() | |
172 | + proj.mask_dict[index].threshold_range = threshold_range | |
82 | 173 | |
83 | - | |
174 | + def ShowMask(self, index, value): | |
175 | + "Show a mask given its index and 'show' value (0: hide, other: show)" | |
84 | 176 | proj = Project() |
85 | - mask = proj.mask_dict[mask_index] | |
86 | - | |
87 | - # This is very important. Do not use masks' imagedata. It would mess up | |
88 | - # surface quality event when using contour | |
89 | - imagedata = self.imagedata | |
90 | - | |
91 | - colour = mask.colour | |
92 | - threshold = mask.threshold_range | |
93 | - | |
94 | - ps.Publisher().sendMessage('Create surface', | |
95 | - (imagedata,colour,threshold)) | |
177 | + proj.mask_dict[index].is_shown = value | |
178 | + if (mask_index == self.current_mask.index): | |
179 | + if value: | |
180 | + self.blend_filter.SetOpacity(1, self.current_mask.opacity) | |
181 | + else: | |
182 | + self.blend_filter.SetOpacity(1, 0) | |
183 | + self.blend_filter.Update() | |
184 | + ps.Publisher().sendMessage('Update slice viewer') | |
185 | + #--------------------------------------------------------------------------- | |
186 | + def ErasePixel(self, position): | |
187 | + "Delete pixel, based on x, y and z position coordinates." | |
188 | + x, y, z = position | |
189 | + colour = self.imagedata.GetScalarRange()[0]# - 1 # Important to effect erase | |
190 | + imagedata = self.current_mask.imagedata | |
191 | + imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) | |
192 | + imagedata.Update() | |
96 | 193 | |
97 | - def OnChangeCurrentMaskColour(self, pubsub_evt): | |
98 | - colour_wx = pubsub_evt.data | |
99 | - colour_vtk = [c/255.0 for c in colour_wx] | |
100 | - self.ChangeCurrentMaskColour(colour_vtk) | |
194 | + def DrawPixel(self, position, colour=None): | |
195 | + "Draw pixel, based on x, y and z position coordinates." | |
196 | + x, y, z = position | |
197 | + if not colour: | |
198 | + colour = self.imagedata.GetScalarRange()[1] | |
199 | + imagedata = self.current_mask.imagedata | |
200 | + imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) | |
201 | + imagedata.Update() | |
101 | 202 | |
102 | - def OnChangeCurrentMask(self, pubsub_evt): | |
203 | + def EditPixelBasedOnThreshold(self, position): | |
204 | + "Erase or draw pixel based on edition threshold range." | |
205 | + x, y, z = position | |
206 | + colour = self.imagedata.GetScalarComponentAsDouble(x, y, z, 0) | |
207 | + thresh_min, thresh_max = self.current_mask.edition_threshold_range | |
103 | 208 | |
104 | - mask_index = pubsub_evt.data | |
209 | + if (colour >= thresh_min) and (colour <= thresh_max): | |
210 | + self.DrawPixel(position, colour) | |
211 | + else: | |
212 | + self.ErasePixel(position) | |
213 | + #--------------------------------------------------------------------------- | |
214 | + def SelectCurrentMask(self, index): | |
215 | + "Insert mask data, based on given index, into pipeline." | |
105 | 216 | |
106 | 217 | # This condition is not necessary in Linux, only under mac and windows |
107 | - # in these platforms, because the combobox event is binded when the | |
108 | - # same item is selected again. | |
109 | - if mask_index != self.current_mask.index: | |
218 | + # because combobox event is binded when the same item is selected again. | |
219 | + if index != self.current_mask.index: | |
110 | 220 | proj = Project() |
111 | - future_mask = proj.GetMask(mask_index) | |
221 | + future_mask = proj.GetMask(index) | |
112 | 222 | |
113 | 223 | self.current_mask = future_mask |
114 | 224 | |
115 | 225 | colour = future_mask.colour |
116 | - self.ChangeCurrentMaskColour(colour, update=False) | |
226 | + index = future_mask.index | |
227 | + self.SetMaskColour(index, colour, update=False) | |
117 | 228 | |
118 | 229 | imagedata = future_mask.imagedata |
119 | 230 | self.img_colours_mask.SetInput(imagedata) |
... | ... | @@ -132,25 +243,35 @@ class Slice(object): |
132 | 243 | self.current_mask.threshold_range) |
133 | 244 | ps.Publisher().sendMessage('Select mask name in combo', mask_index) |
134 | 245 | ps.Publisher().sendMessage('Update slice viewer') |
246 | + #--------------------------------------------------------------------------- | |
135 | 247 | |
136 | 248 | |
137 | 249 | |
138 | - def ChangeCurrentMaskColour(self, colour, update=True): | |
139 | - # This is necessary because wx events are calling this before it was created | |
140 | - if self.current_mask: | |
141 | - (r,g,b) = colour | |
142 | - scalar_range = int(self.imagedata.GetScalarRange()[1]) | |
143 | - self.current_mask.colour = colour | |
144 | 250 | |
145 | - self.lut_mask.SetTableValue(1, r, g, b, 1.0) | |
146 | - self.lut_mask.SetTableValue(scalar_range - 1, r, g, b, 1.0) | |
147 | 251 | |
148 | - colour_wx = [r*255, g*255, b*255] | |
149 | - ps.Publisher().sendMessage('Change mask colour in notebook', | |
150 | - (self.current_mask.index, (r,g,b))) | |
151 | - ps.Publisher().sendMessage('Set GUI items colour', colour_wx) | |
152 | - if update: | |
153 | - ps.Publisher().sendMessage('Update slice viewer') | |
252 | + | |
253 | + def CreateSurfaceFromIndex(self, pubsub_evt): | |
254 | + mask_index = pubsub_evt.data | |
255 | + | |
256 | + | |
257 | + proj = Project() | |
258 | + mask = proj.mask_dict[mask_index] | |
259 | + | |
260 | + # This is very important. Do not use masks' imagedata. It would mess up | |
261 | + # surface quality event when using contour | |
262 | + imagedata = self.imagedata | |
263 | + | |
264 | + colour = mask.colour | |
265 | + threshold = mask.threshold_range | |
266 | + | |
267 | + ps.Publisher().sendMessage('Create surface', | |
268 | + (imagedata,colour,threshold)) | |
269 | + | |
270 | + | |
271 | + | |
272 | + | |
273 | + | |
274 | + | |
154 | 275 | |
155 | 276 | |
156 | 277 | def GetOutput(self): |
... | ... | @@ -235,11 +356,6 @@ class Slice(object): |
235 | 356 | |
236 | 357 | return img_colours_bg.GetOutput() |
237 | 358 | |
238 | - def AddMask(self, pubsub_evt): | |
239 | - mask_name = pubsub_evt.data | |
240 | - self.CreateMask(name=mask_name) | |
241 | - self.ChangeCurrentMaskColour(self.current_mask.colour) | |
242 | - | |
243 | 359 | def CreateMask(self, imagedata=None, name=None): |
244 | 360 | |
245 | 361 | future_mask = Mask() |
... | ... | @@ -311,15 +427,6 @@ class Slice(object): |
311 | 427 | mask_thresh_imagedata = self.__create_mask_threshold(imagedata) |
312 | 428 | current_mask.imagedata.DeepCopy(mask_thresh_imagedata) |
313 | 429 | |
314 | - #import time | |
315 | - #viewer = vtk.vtkImageViewer() | |
316 | - #viewer.SetInput(mask_thresh_imagedata) | |
317 | - #viewer.SetColorWindow(400) | |
318 | - #viewer.SetColorLevel(200) | |
319 | - #viewer.Render() | |
320 | - #time.sleep(5) | |
321 | - | |
322 | - | |
323 | 430 | # map the input image through a lookup table |
324 | 431 | img_colours_mask = vtk.vtkImageMapToColors() |
325 | 432 | img_colours_mask.SetOutputFormatToRGBA() |
... | ... | @@ -348,64 +455,3 @@ class Slice(object): |
348 | 455 | imagedata_mask.Update() |
349 | 456 | |
350 | 457 | return imagedata_mask |
351 | - | |
352 | - def SetThresholdRange(self, evt_pubsub): | |
353 | - thresh_min, thresh_max = evt_pubsub.data | |
354 | - | |
355 | - self.img_thresh_mask.SetInput(self.imagedata) | |
356 | - self.img_thresh_mask.ThresholdBetween(float(thresh_min), | |
357 | - float(thresh_max)) | |
358 | - self.img_thresh_mask.Update() | |
359 | - | |
360 | - imagedata = self.img_thresh_mask.GetOutput() | |
361 | - | |
362 | - self.current_mask.imagedata.DeepCopy(imagedata) | |
363 | - | |
364 | - self.img_colours_mask.SetInput(self.current_mask.imagedata) | |
365 | - | |
366 | - # save new data inside current mask | |
367 | - self.current_mask.threshold_range = (thresh_min, thresh_max) | |
368 | - | |
369 | - ps.Publisher().sendMessage('Set mask threshold in notebook', | |
370 | - (self.current_mask.index, | |
371 | - self.current_mask.threshold_range)) | |
372 | - ps.Publisher().sendMessage('Update slice viewer') | |
373 | - | |
374 | - def SetEditionThresholdRange(self, evt_pubsub): | |
375 | - if self.current_mask: | |
376 | - thresh_min, thresh_max = evt_pubsub.data | |
377 | - self.current_mask.edition_threshold_range = thresh_min, thresh_max | |
378 | - | |
379 | - def ErasePixel(self, position): | |
380 | - """ | |
381 | - Delete pixel, based on x, y and z position coordinates. | |
382 | - """ | |
383 | - x, y, z = position | |
384 | - colour = self.imagedata.GetScalarRange()[0]# - 1 # Important to effect erase | |
385 | - imagedata = self.current_mask.imagedata | |
386 | - imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) | |
387 | - imagedata.Update() | |
388 | - | |
389 | - def DrawPixel(self, position, colour=None): | |
390 | - """ | |
391 | - Draw pixel, based on x, y and z position coordinates. | |
392 | - """ | |
393 | - x, y, z = position | |
394 | - if not colour: | |
395 | - colour = self.imagedata.GetScalarRange()[1] | |
396 | - imagedata = self.current_mask.imagedata | |
397 | - imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) | |
398 | - imagedata.Update() | |
399 | - | |
400 | - def EditPixelBasedOnThreshold(self, position): | |
401 | - """ | |
402 | - Erase or draw pixel based on edition threshold range. | |
403 | - """ | |
404 | - x, y, z = position | |
405 | - colour = self.imagedata.GetScalarComponentAsDouble(x, y, z, 0) | |
406 | - thresh_min, thresh_max = self.current_mask.edition_threshold_range | |
407 | - | |
408 | - if (colour >= thresh_min) and (colour <= thresh_max): | |
409 | - self.DrawPixel(position, colour) | |
410 | - else: | |
411 | - self.ErasePixel(position) | ... | ... |