Commit 3043ba903884aea3fe13f9e3fcd885fa5fd76690

Authored by tatiana
1 parent 7aabaaed

ENC: Masks relation with GUI (both data_notebook and tab)

invesalius/data/mask.py
@@ -12,4 +12,5 @@ class Mask(): @@ -12,4 +12,5 @@ class Mask():
12 self.threshold_range = const.THRESHOLD_RANGE 12 self.threshold_range = const.THRESHOLD_RANGE
13 self.name = const.MASK_NAME_PATTERN %(Mask.general_index+1) 13 self.name = const.MASK_NAME_PATTERN %(Mask.general_index+1)
14 self.edition_threshold_range = const.THRESHOLD_RANGE 14 self.edition_threshold_range = const.THRESHOLD_RANGE
  15 + self.is_shown = 1
15 16
16 \ No newline at end of file 17 \ No newline at end of file
invesalius/data/slice_.py
@@ -17,6 +17,7 @@ class Slice(object): @@ -17,6 +17,7 @@ class Slice(object):
17 def __init__(self): 17 def __init__(self):
18 self.imagedata = None 18 self.imagedata = None
19 self.__bind_events() 19 self.__bind_events()
  20 + self.current_mask = None
20 21
21 def __bind_events(self): 22 def __bind_events(self):
22 ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values') 23 ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values')
@@ -30,9 +31,33 @@ class Slice(object): @@ -30,9 +31,33 @@ class Slice(object):
30 'Create surface from index') 31 'Create surface from index')
31 ps.Publisher().subscribe(self.UpdateCursorPosition, 32 ps.Publisher().subscribe(self.UpdateCursorPosition,
32 'Update cursor position in slice') 33 'Update cursor position in slice')
  34 + ps.Publisher().subscribe(self.ShowMask, 'Show mask')
  35 +
  36 +
  37 + def ShowMask(self, pubsub_evt):
  38 +
  39 + # This is necessary because wx events are calling this before it was created
  40 + if self.current_mask:
  41 + mask_index, value = pubsub_evt.data
  42 +
  43 + proj = Project()
  44 + proj.mask_dict[mask_index].is_shown = value
  45 +
  46 +
  47 + if (mask_index == self.current_mask.index):
  48 + if value:
  49 + self.blend_filter.SetOpacity(1, self.current_mask.opacity)
  50 + else:
  51 +
  52 + self.blend_filter.SetOpacity(1, 0)
  53 + self.blend_filter.Update()
  54 + ps.Publisher().sendMessage('Update slice viewer')
  55 +
  56 +
33 57
34 def CreateSurfaceFromIndex(self, pubsub_evt): 58 def CreateSurfaceFromIndex(self, pubsub_evt):
35 mask_index = pubsub_evt.data 59 mask_index = pubsub_evt.data
  60 +
36 61
37 proj = Project() 62 proj = Project()
38 mask = proj.mask_dict[mask_index] 63 mask = proj.mask_dict[mask_index]
@@ -65,24 +90,29 @@ class Slice(object): @@ -65,24 +90,29 @@ class Slice(object):
65 self.current_mask = future_mask 90 self.current_mask = future_mask
66 91
67 colour = future_mask.colour 92 colour = future_mask.colour
68 - self.ChangeCurrentMaskColour(colour) 93 + self.ChangeCurrentMaskColour(colour, update=False)
69 94
70 imagedata = future_mask.imagedata 95 imagedata = future_mask.imagedata
71 self.img_colours_mask.SetInput(imagedata) 96 self.img_colours_mask.SetInput(imagedata)
72 97
  98 + if self.current_mask.is_shown:
  99 + self.blend_filter.SetOpacity(1, self.current_mask.opacity)
  100 + else:
  101 +
  102 + self.blend_filter.SetOpacity(1, 0)
  103 + self.blend_filter.Update()
  104 +
73 ps.Publisher().sendMessage('Set mask threshold in notebook', 105 ps.Publisher().sendMessage('Set mask threshold in notebook',
74 (self.current_mask.index, 106 (self.current_mask.index,
75 self.current_mask.threshold_range)) 107 self.current_mask.threshold_range))
76 ps.Publisher().sendMessage('Set threshold values in gradient', 108 ps.Publisher().sendMessage('Set threshold values in gradient',
77 self.current_mask.threshold_range) 109 self.current_mask.threshold_range)
  110 + ps.Publisher().sendMessage('Select mask name in combo', mask_index)
78 ps.Publisher().sendMessage('Update slice viewer') 111 ps.Publisher().sendMessage('Update slice viewer')
79 112
80 - def ChangeCurrentMaskColour(self, colour):  
81 - try:  
82 - self.current_mask  
83 - except AttributeError:  
84 - pass  
85 - else: 113 + def ChangeCurrentMaskColour(self, colour, update=True):
  114 + # This is necessary because wx events are calling this before it was created
  115 + if self.current_mask:
86 (r,g,b) = colour 116 (r,g,b) = colour
87 scalar_range = int(self.imagedata.GetScalarRange()[1]) 117 scalar_range = int(self.imagedata.GetScalarRange()[1])
88 self.current_mask.colour = colour 118 self.current_mask.colour = colour
@@ -94,11 +124,12 @@ class Slice(object): @@ -94,11 +124,12 @@ class Slice(object):
94 ps.Publisher().sendMessage('Change mask colour in notebook', 124 ps.Publisher().sendMessage('Change mask colour in notebook',
95 (self.current_mask.index, (r,g,b))) 125 (self.current_mask.index, (r,g,b)))
96 ps.Publisher().sendMessage('Set GUI items colour', colour_wx) 126 ps.Publisher().sendMessage('Set GUI items colour', colour_wx)
97 - ps.Publisher().sendMessage('Update slice viewer') 127 + if update:
  128 + ps.Publisher().sendMessage('Update slice viewer')
98 129
99 130
100 def GetOutput(self): 131 def GetOutput(self):
101 - return self.blend_imagedata.GetOutput() 132 + return self.cast_filter.GetOutput()
102 133
103 def SetInput(self, imagedata): 134 def SetInput(self, imagedata):
104 self.imagedata = imagedata 135 self.imagedata = imagedata
@@ -110,18 +141,18 @@ class Slice(object): @@ -110,18 +141,18 @@ class Slice(object):
110 mask_opacity = self.current_mask.opacity 141 mask_opacity = self.current_mask.opacity
111 142
112 # blend both imagedatas, so it can be inserted into viewer 143 # blend both imagedatas, so it can be inserted into viewer
113 - blend_imagedata = vtk.vtkImageBlend()  
114 - blend_imagedata.SetBlendModeToNormal()  
115 - blend_imagedata.SetOpacity(0, 1)  
116 - blend_imagedata.SetOpacity(1, mask_opacity)  
117 - blend_imagedata.SetInput(0, imagedata_bg)  
118 - blend_imagedata.SetInput(1, imagedata_mask)  
119 - blend_imagedata.SetBlendModeToNormal()  
120 - blend_imagedata.GetOutput().ReleaseDataFlagOn()  
121 - #self.blend_imagedata = blend_imagedata  
122 -  
123 - #blend_imagedata.Update()  
124 - #extent = blend_imagedata.GetOutput().GetWholeExtent() 144 + blend_filter = vtk.vtkImageBlend()
  145 + blend_filter.SetBlendModeToNormal()
  146 + blend_filter.SetOpacity(0, 1)
  147 + if self.current_mask.is_shown:
  148 + blend_filter.SetOpacity(1, mask_opacity)
  149 + else:
  150 + blend_filter.SetOpacity(1, 0)
  151 + blend_filter.SetInput(0, imagedata_bg)
  152 + blend_filter.SetInput(1, imagedata_mask)
  153 + blend_filter.SetBlendModeToNormal()
  154 + blend_filter.GetOutput().ReleaseDataFlagOn()
  155 + self.blend_filter = blend_filter
125 156
126 # global values 157 # global values
127 CURSOR_X = -1 # SAGITAL 158 CURSOR_X = -1 # SAGITAL
@@ -133,7 +164,7 @@ class Slice(object): @@ -133,7 +164,7 @@ class Slice(object):
133 164
134 cross = vtk.vtkImageCursor3D() 165 cross = vtk.vtkImageCursor3D()
135 cross.GetOutput().ReleaseDataFlagOn() 166 cross.GetOutput().ReleaseDataFlagOn()
136 - cross.SetInput(blend_imagedata.GetOutput()) 167 + cross.SetInput(blend_filter.GetOutput())
137 cross.SetCursorPosition(CURSOR_X, CURSOR_Y, CURSOR_Z) 168 cross.SetCursorPosition(CURSOR_X, CURSOR_Y, CURSOR_Z)
138 cross.SetCursorValue(CURSOR_VALUE) 169 cross.SetCursorValue(CURSOR_VALUE)
139 cross.SetCursorRadius(CURSOR_RADIUS) 170 cross.SetCursorRadius(CURSOR_RADIUS)
@@ -146,7 +177,7 @@ class Slice(object): @@ -146,7 +177,7 @@ class Slice(object):
146 cast.SetOutputScalarTypeToUnsignedChar() 177 cast.SetOutputScalarTypeToUnsignedChar()
147 cast.Update() 178 cast.Update()
148 179
149 - self.blend_imagedata = cast 180 + self.cast_filter = cast
150 181
151 182
152 def UpdateCursorPosition(self, pubsub_evt): 183 def UpdateCursorPosition(self, pubsub_evt):
@@ -154,11 +185,9 @@ class Slice(object): @@ -154,11 +185,9 @@ class Slice(object):
154 new_pos = pubsub_evt.data 185 new_pos = pubsub_evt.data
155 self.cross.SetCursorPosition(new_pos) 186 self.cross.SetCursorPosition(new_pos)
156 self.cross.Modified() 187 self.cross.Modified()
157 - self.blend_imagedata.Update()  
158 - ps.Publisher().sendMessage('Update slice viewer', None)  
159 - 188 + self.cast_filter.Update()
  189 + ps.Publisher().sendMessage('Update slice viewer')
160 190
161 -  
162 def __create_background(self, imagedata): 191 def __create_background(self, imagedata):
163 192
164 thresh_min, thresh_max = imagedata.GetScalarRange() 193 thresh_min, thresh_max = imagedata.GetScalarRange()
@@ -208,15 +237,19 @@ class Slice(object): @@ -208,15 +237,19 @@ class Slice(object):
208 237
209 # when this is not the first instance, user will have defined a name 238 # when this is not the first instance, user will have defined a name
210 if name is not None: 239 if name is not None:
  240 + print "new mask, we will check if it will be shown"
211 future_mask.name = name 241 future_mask.name = name
  242 + if future_mask.is_shown:
  243 + self.blend_filter.SetOpacity(1, future_mask.opacity)
  244 + else:
  245 + self.blend_filter.SetOpacity(1, 0)
  246 + self.blend_filter.Update()
212 247
213 # insert new mask into project and retrieve its index 248 # insert new mask into project and retrieve its index
214 proj = Project() 249 proj = Project()
215 proj.AddMask(future_mask.index, future_mask) 250 proj.AddMask(future_mask.index, future_mask)
216 251
217 252
218 - imagedata1 = proj.mask_dict[0].imagedata  
219 -  
220 # update gui related to mask 253 # update gui related to mask
221 ps.Publisher().sendMessage('Add mask', 254 ps.Publisher().sendMessage('Add mask',
222 (future_mask.index, 255 (future_mask.index,
@@ -227,7 +260,6 @@ class Slice(object): @@ -227,7 +260,6 @@ class Slice(object):
227 self.current_mask = future_mask 260 self.current_mask = future_mask
228 261
229 262
230 -  
231 def __create_mask(self, imagedata): 263 def __create_mask(self, imagedata):
232 # create new mask instance and insert it into project 264 # create new mask instance and insert it into project
233 self.CreateMask(imagedata=imagedata) 265 self.CreateMask(imagedata=imagedata)
invesalius/data/surface.py
@@ -35,7 +35,6 @@ class SurfaceManager(): @@ -35,7 +35,6 @@ class SurfaceManager():
35 35
36 """ 36 """
37 def __init__(self): 37 def __init__(self):
38 - print "surface manager was created"  
39 self.actors_dict = {} 38 self.actors_dict = {}
40 self.__bind_events() 39 self.__bind_events()
41 40
invesalius/data/viewer_slice.py
@@ -173,8 +173,7 @@ class Viewer(wx.Panel): @@ -173,8 +173,7 @@ class Viewer(wx.Panel):
173 coord[index] = extent_max[index] 173 coord[index] = extent_max[index]
174 elif coord[index] < extent_min[index]: 174 elif coord[index] < extent_min[index]:
175 coord[index] = extent_min[index] 175 coord[index] = extent_min[index]
176 -  
177 - print "New coordinate: ", coord 176 + #print "New coordinate: ", coord
178 177
179 return coord 178 return coord
180 179
invesalius/gui/data_notebook.py
@@ -93,17 +93,17 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -93,17 +93,17 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
93 def __init_image_list(self): 93 def __init_image_list(self):
94 self.imagelist = wx.ImageList(16, 16) 94 self.imagelist = wx.ImageList(16, 16)
95 95
96 - image = wx.Image("../icons/object_visible.jpg") 96 + image = wx.Image("../icons/object_invisible.jpg")
97 bitmap = wx.BitmapFromImage(image.Scale(16, 16)) 97 bitmap = wx.BitmapFromImage(image.Scale(16, 16))
98 bitmap.SetWidth(16) 98 bitmap.SetWidth(16)
99 bitmap.SetHeight(16) 99 bitmap.SetHeight(16)
100 - img_check = self.imagelist.Add(bitmap)  
101 -  
102 - image = wx.Image("../icons/object_invisible.jpg") 100 + img_null = self.imagelist.Add(bitmap)
  101 +
  102 + image = wx.Image("../icons/object_visible.jpg")
103 bitmap = wx.BitmapFromImage(image.Scale(16, 16)) 103 bitmap = wx.BitmapFromImage(image.Scale(16, 16))
104 bitmap.SetWidth(16) 104 bitmap.SetWidth(16)
105 bitmap.SetHeight(16) 105 bitmap.SetHeight(16)
106 - img_null = self.imagelist.Add(bitmap) 106 + img_check = self.imagelist.Add(bitmap)
107 107
108 self.SetImageList(self.imagelist, wx.IMAGE_LIST_SMALL) 108 self.SetImageList(self.imagelist, wx.IMAGE_LIST_SMALL)
109 109
@@ -113,35 +113,37 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -113,35 +113,37 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
113 print "Editing label", evt.GetLabel() 113 print "Editing label", evt.GetLabel()
114 #print evt.GetImage() 114 #print evt.GetImage()
115 #print evt.GetId() 115 #print evt.GetId()
116 - #print evt.GetIndex()  
117 - print "--------"  
118 - print evt.m_oldItemIndex  
119 - print evt.m_itemIndex  
120 - index = evt.GetIndex() 116 + print evt.GetIndex()
  117 + #print "--------"
  118 + #print evt.m_oldItemIndex
  119 + #print evt.m_itemIndex
  120 + #index = evt.GetIndex()
121 #print dir(evt) 121 #print dir(evt)
122 122
123 - print "Get item data:", self.GetItemData(index)  
124 - print "Get item position:", self.GetItemPosition(index)  
125 - print "Get next item:", self.GetNextItem(index) 123 + #print "Get item data:", self.GetItemData(index)
  124 + #print "Get item position:", self.GetItemPosition(index)
  125 + #print "Get next item:", self.GetNextItem(index)
126 evt.Skip() 126 evt.Skip()
127 127
128 def OnItemActivated(self, evt): 128 def OnItemActivated(self, evt):
129 print "OnItemActivated" 129 print "OnItemActivated"
130 self.ToggleItem(evt.m_itemIndex) 130 self.ToggleItem(evt.m_itemIndex)
131 131
  132 +
132 def OnCheckItem(self, index, flag): 133 def OnCheckItem(self, index, flag):
133 - # TODO: use pubsub to communicate to models 134 +
134 if flag: 135 if flag:
135 - print "checked, ", index  
136 - else:  
137 - print "unchecked, ", index 136 + for key in self.mask_list_index.keys():
  137 + if key != index:
  138 + self.SetItemImage(key, 0)
  139 + ps.Publisher().sendMessage('Change mask selected',index)
  140 + ps.Publisher().sendMessage('Show mask', (index, flag))
138 141
139 def CreateColourBitmap(self, colour): 142 def CreateColourBitmap(self, colour):
140 """ 143 """
141 Create a wx Image with a mask colour. 144 Create a wx Image with a mask colour.
142 colour: colour in rgb format(0 - 1) 145 colour: colour in rgb format(0 - 1)
143 """ 146 """
144 - print "Colour", colour  
145 image = self.image_gray 147 image = self.image_gray
146 new_image = Image.new("RGB", image.size) 148 new_image = Image.new("RGB", image.size)
147 for x in xrange(image.size[0]): 149 for x in xrange(image.size[0]):
@@ -157,24 +159,19 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -157,24 +159,19 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
157 159
158 def InsertNewItem(self, index=0, label="Mask 1", threshold="(1000, 4500)", 160 def InsertNewItem(self, index=0, label="Mask 1", threshold="(1000, 4500)",
159 colour=None): 161 colour=None):
160 - print "InsertNewItem"  
161 self.InsertStringItem(index, "") 162 self.InsertStringItem(index, "")
162 self.SetStringItem(index, 1, label, 163 self.SetStringItem(index, 1, label,
163 imageId=self.mask_list_index[index]) 164 imageId=self.mask_list_index[index])
164 self.SetStringItem(index, 2, threshold) 165 self.SetStringItem(index, 2, threshold)
165 -  
166 - print "Get item data:", self.GetItemData(index)  
167 - print "Get item position:", self.GetItemPosition(index)  
168 - print "Get next item:", self.GetNextItem(index)  
169 - # FindItem  
170 - # FindItemData  
171 - # FindItemAtPos 166 + self.SetItemImage(index, 1)
  167 + for key in self.mask_list_index.keys():
  168 + if key != index:
  169 + self.SetItemImage(key, 0)
172 170
173 def AddMask(self, pubsub_evt): 171 def AddMask(self, pubsub_evt):
174 index, mask_name, threshold_range, colour = pubsub_evt.data 172 index, mask_name, threshold_range, colour = pubsub_evt.data
175 image = self.CreateColourBitmap(colour) 173 image = self.CreateColourBitmap(colour)
176 image_index = self.imagelist.Add(image) 174 image_index = self.imagelist.Add(image)
177 - print "image_index: ", image_index  
178 self.mask_list_index[index] = image_index 175 self.mask_list_index[index] = image_index
179 self.InsertNewItem(index, mask_name, str(threshold_range)) 176 self.InsertNewItem(index, mask_name, str(threshold_range))
180 177
@@ -292,11 +289,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -292,11 +289,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
292 self.ToggleItem(evt.m_itemIndex) 289 self.ToggleItem(evt.m_itemIndex)
293 290
294 def OnCheckItem(self, index, flag): 291 def OnCheckItem(self, index, flag):
295 - # TODO: use pubsub to communicate to models  
296 - if flag:  
297 - print "checked, ", index  
298 - else:  
299 - print "unchecked, ", index 292 + ps.Publisher().sendMessage('Show surface', (index, not flag))
300 293
301 294
302 295
@@ -417,7 +410,6 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -417,7 +410,6 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
417 self.imagelist = wx.ImageList(16, 16) 410 self.imagelist = wx.ImageList(16, 16)
418 411
419 image = wx.Image("../icons/object_visible.jpg") 412 image = wx.Image("../icons/object_visible.jpg")
420 - #image = wx.Image("../img/object_visible-v2.jpg")  
421 bitmap = wx.BitmapFromImage(image.Scale(16, 16)) 413 bitmap = wx.BitmapFromImage(image.Scale(16, 16))
422 bitmap.SetWidth(16) 414 bitmap.SetWidth(16)
423 bitmap.SetHeight(16) 415 bitmap.SetHeight(16)
@@ -439,6 +431,7 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): @@ -439,6 +431,7 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
439 431
440 def OnItemActivated(self, evt): 432 def OnItemActivated(self, evt):
441 self.ToggleItem(evt.m_itemIndex) 433 self.ToggleItem(evt.m_itemIndex)
  434 + print m_itemIndex
442 435
443 def OnCheckItem(self, index, flag): 436 def OnCheckItem(self, index, flag):
444 # TODO: use pubsub to communicate to models 437 # TODO: use pubsub to communicate to models
invesalius/gui/task_slice.py
@@ -285,12 +285,18 @@ class MaskProperties(wx.Panel): @@ -285,12 +285,18 @@ class MaskProperties(wx.Panel):
285 ps.Publisher().subscribe(self.SetItemsColour, 'Set GUI items colour') 285 ps.Publisher().subscribe(self.SetItemsColour, 'Set GUI items colour')
286 ps.Publisher().subscribe(self.SetThresholdValues, 286 ps.Publisher().subscribe(self.SetThresholdValues,
287 'Set threshold values in gradient') 287 'Set threshold values in gradient')
  288 + ps.Publisher().subscribe(self.SelectMaskName, 'Select mask name in combo')
288 289
289 def __bind_events_wx(self): 290 def __bind_events_wx(self):
290 self.combo_thresh.Bind(wx.EVT_COMBOBOX, self.OnComboThresh) 291 self.combo_thresh.Bind(wx.EVT_COMBOBOX, self.OnComboThresh)
291 self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, 292 self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged,
292 self.gradient) 293 self.gradient)
293 294
  295 + def SelectMaskName(self, pubsub_evt):
  296 + index = pubsub_evt.data
  297 + self.combo_mask_name.SetSelection(index)
  298 + print dir(self.combo_mask_name)
  299 +
294 def SetThresholdValues(self, pubsub_evt): 300 def SetThresholdValues(self, pubsub_evt):
295 thresh_min, thresh_max = pubsub_evt.data 301 thresh_min, thresh_max = pubsub_evt.data
296 self.bind_evt_gradient = False 302 self.bind_evt_gradient = False
@@ -308,6 +314,7 @@ class MaskProperties(wx.Panel): @@ -308,6 +314,7 @@ class MaskProperties(wx.Panel):
308 mask_thresh = evt_pubsub.data[2] 314 mask_thresh = evt_pubsub.data[2]
309 mask_colour = [int(c*255) for c in evt_pubsub.data[3]] 315 mask_colour = [int(c*255) for c in evt_pubsub.data[3]]
310 index = self.combo_mask_name.Append(mask_name) 316 index = self.combo_mask_name.Append(mask_name)
  317 + self.combo_mask_name.SetSelection(index)
311 self.button_colour.SetColour(mask_colour) 318 self.button_colour.SetColour(mask_colour)
312 self.gradient.SetColour(mask_colour) 319 self.gradient.SetColour(mask_colour)
313 self.combo_mask_name.SetSelection(index) 320 self.combo_mask_name.SetSelection(index)
invesalius/invesalius.py
@@ -33,7 +33,6 @@ class InVesalius(wx.App): @@ -33,7 +33,6 @@ class InVesalius(wx.App):
33 self.main = Frame(None) 33 self.main = Frame(None)
34 self.control = Controller(self.main) 34 self.control = Controller(self.main)
35 self.SetAppName("InVesalius 3.0") 35 self.SetAppName("InVesalius 3.0")
36 - self.SetTopWindow(self.main)  
37 return True 36 return True
38 37
39 def ShowFrame(self): 38 def ShowFrame(self):