Commit 3043ba903884aea3fe13f9e3fcd885fa5fd76690
1 parent
7aabaaed
Exists in
master
and in
68 other branches
ENC: Masks relation with GUI (both data_notebook and tab)
Showing
7 changed files
with
97 additions
and
67 deletions
Show diff stats
invesalius/data/mask.py
invesalius/data/slice_.py
| ... | ... | @@ -17,6 +17,7 @@ class Slice(object): |
| 17 | 17 | def __init__(self): |
| 18 | 18 | self.imagedata = None |
| 19 | 19 | self.__bind_events() |
| 20 | + self.current_mask = None | |
| 20 | 21 | |
| 21 | 22 | def __bind_events(self): |
| 22 | 23 | ps.Publisher().subscribe(self.SetThresholdRange, 'Set threshold values') |
| ... | ... | @@ -30,9 +31,33 @@ class Slice(object): |
| 30 | 31 | 'Create surface from index') |
| 31 | 32 | ps.Publisher().subscribe(self.UpdateCursorPosition, |
| 32 | 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 | 58 | def CreateSurfaceFromIndex(self, pubsub_evt): |
| 35 | 59 | mask_index = pubsub_evt.data |
| 60 | + | |
| 36 | 61 | |
| 37 | 62 | proj = Project() |
| 38 | 63 | mask = proj.mask_dict[mask_index] |
| ... | ... | @@ -65,24 +90,29 @@ class Slice(object): |
| 65 | 90 | self.current_mask = future_mask |
| 66 | 91 | |
| 67 | 92 | colour = future_mask.colour |
| 68 | - self.ChangeCurrentMaskColour(colour) | |
| 93 | + self.ChangeCurrentMaskColour(colour, update=False) | |
| 69 | 94 | |
| 70 | 95 | imagedata = future_mask.imagedata |
| 71 | 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 | 105 | ps.Publisher().sendMessage('Set mask threshold in notebook', |
| 74 | 106 | (self.current_mask.index, |
| 75 | 107 | self.current_mask.threshold_range)) |
| 76 | 108 | ps.Publisher().sendMessage('Set threshold values in gradient', |
| 77 | 109 | self.current_mask.threshold_range) |
| 110 | + ps.Publisher().sendMessage('Select mask name in combo', mask_index) | |
| 78 | 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 | 116 | (r,g,b) = colour |
| 87 | 117 | scalar_range = int(self.imagedata.GetScalarRange()[1]) |
| 88 | 118 | self.current_mask.colour = colour |
| ... | ... | @@ -94,11 +124,12 @@ class Slice(object): |
| 94 | 124 | ps.Publisher().sendMessage('Change mask colour in notebook', |
| 95 | 125 | (self.current_mask.index, (r,g,b))) |
| 96 | 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 | 131 | def GetOutput(self): |
| 101 | - return self.blend_imagedata.GetOutput() | |
| 132 | + return self.cast_filter.GetOutput() | |
| 102 | 133 | |
| 103 | 134 | def SetInput(self, imagedata): |
| 104 | 135 | self.imagedata = imagedata |
| ... | ... | @@ -110,18 +141,18 @@ class Slice(object): |
| 110 | 141 | mask_opacity = self.current_mask.opacity |
| 111 | 142 | |
| 112 | 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 | 157 | # global values |
| 127 | 158 | CURSOR_X = -1 # SAGITAL |
| ... | ... | @@ -133,7 +164,7 @@ class Slice(object): |
| 133 | 164 | |
| 134 | 165 | cross = vtk.vtkImageCursor3D() |
| 135 | 166 | cross.GetOutput().ReleaseDataFlagOn() |
| 136 | - cross.SetInput(blend_imagedata.GetOutput()) | |
| 167 | + cross.SetInput(blend_filter.GetOutput()) | |
| 137 | 168 | cross.SetCursorPosition(CURSOR_X, CURSOR_Y, CURSOR_Z) |
| 138 | 169 | cross.SetCursorValue(CURSOR_VALUE) |
| 139 | 170 | cross.SetCursorRadius(CURSOR_RADIUS) |
| ... | ... | @@ -146,7 +177,7 @@ class Slice(object): |
| 146 | 177 | cast.SetOutputScalarTypeToUnsignedChar() |
| 147 | 178 | cast.Update() |
| 148 | 179 | |
| 149 | - self.blend_imagedata = cast | |
| 180 | + self.cast_filter = cast | |
| 150 | 181 | |
| 151 | 182 | |
| 152 | 183 | def UpdateCursorPosition(self, pubsub_evt): |
| ... | ... | @@ -154,11 +185,9 @@ class Slice(object): |
| 154 | 185 | new_pos = pubsub_evt.data |
| 155 | 186 | self.cross.SetCursorPosition(new_pos) |
| 156 | 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 | 191 | def __create_background(self, imagedata): |
| 163 | 192 | |
| 164 | 193 | thresh_min, thresh_max = imagedata.GetScalarRange() |
| ... | ... | @@ -208,15 +237,19 @@ class Slice(object): |
| 208 | 237 | |
| 209 | 238 | # when this is not the first instance, user will have defined a name |
| 210 | 239 | if name is not None: |
| 240 | + print "new mask, we will check if it will be shown" | |
| 211 | 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 | 248 | # insert new mask into project and retrieve its index |
| 214 | 249 | proj = Project() |
| 215 | 250 | proj.AddMask(future_mask.index, future_mask) |
| 216 | 251 | |
| 217 | 252 | |
| 218 | - imagedata1 = proj.mask_dict[0].imagedata | |
| 219 | - | |
| 220 | 253 | # update gui related to mask |
| 221 | 254 | ps.Publisher().sendMessage('Add mask', |
| 222 | 255 | (future_mask.index, |
| ... | ... | @@ -227,7 +260,6 @@ class Slice(object): |
| 227 | 260 | self.current_mask = future_mask |
| 228 | 261 | |
| 229 | 262 | |
| 230 | - | |
| 231 | 263 | def __create_mask(self, imagedata): |
| 232 | 264 | # create new mask instance and insert it into project |
| 233 | 265 | self.CreateMask(imagedata=imagedata) | ... | ... |
invesalius/data/surface.py
invesalius/data/viewer_slice.py
| ... | ... | @@ -173,8 +173,7 @@ class Viewer(wx.Panel): |
| 173 | 173 | coord[index] = extent_max[index] |
| 174 | 174 | elif coord[index] < extent_min[index]: |
| 175 | 175 | coord[index] = extent_min[index] |
| 176 | - | |
| 177 | - print "New coordinate: ", coord | |
| 176 | + #print "New coordinate: ", coord | |
| 178 | 177 | |
| 179 | 178 | return coord |
| 180 | 179 | ... | ... |
invesalius/gui/data_notebook.py
| ... | ... | @@ -93,17 +93,17 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
| 93 | 93 | def __init_image_list(self): |
| 94 | 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 | 97 | bitmap = wx.BitmapFromImage(image.Scale(16, 16)) |
| 98 | 98 | bitmap.SetWidth(16) |
| 99 | 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 | 103 | bitmap = wx.BitmapFromImage(image.Scale(16, 16)) |
| 104 | 104 | bitmap.SetWidth(16) |
| 105 | 105 | bitmap.SetHeight(16) |
| 106 | - img_null = self.imagelist.Add(bitmap) | |
| 106 | + img_check = self.imagelist.Add(bitmap) | |
| 107 | 107 | |
| 108 | 108 | self.SetImageList(self.imagelist, wx.IMAGE_LIST_SMALL) |
| 109 | 109 | |
| ... | ... | @@ -113,35 +113,37 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
| 113 | 113 | print "Editing label", evt.GetLabel() |
| 114 | 114 | #print evt.GetImage() |
| 115 | 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 | 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 | 126 | evt.Skip() |
| 127 | 127 | |
| 128 | 128 | def OnItemActivated(self, evt): |
| 129 | 129 | print "OnItemActivated" |
| 130 | 130 | self.ToggleItem(evt.m_itemIndex) |
| 131 | 131 | |
| 132 | + | |
| 132 | 133 | def OnCheckItem(self, index, flag): |
| 133 | - # TODO: use pubsub to communicate to models | |
| 134 | + | |
| 134 | 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 | 142 | def CreateColourBitmap(self, colour): |
| 140 | 143 | """ |
| 141 | 144 | Create a wx Image with a mask colour. |
| 142 | 145 | colour: colour in rgb format(0 - 1) |
| 143 | 146 | """ |
| 144 | - print "Colour", colour | |
| 145 | 147 | image = self.image_gray |
| 146 | 148 | new_image = Image.new("RGB", image.size) |
| 147 | 149 | for x in xrange(image.size[0]): |
| ... | ... | @@ -157,24 +159,19 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
| 157 | 159 | |
| 158 | 160 | def InsertNewItem(self, index=0, label="Mask 1", threshold="(1000, 4500)", |
| 159 | 161 | colour=None): |
| 160 | - print "InsertNewItem" | |
| 161 | 162 | self.InsertStringItem(index, "") |
| 162 | 163 | self.SetStringItem(index, 1, label, |
| 163 | 164 | imageId=self.mask_list_index[index]) |
| 164 | 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 | 171 | def AddMask(self, pubsub_evt): |
| 174 | 172 | index, mask_name, threshold_range, colour = pubsub_evt.data |
| 175 | 173 | image = self.CreateColourBitmap(colour) |
| 176 | 174 | image_index = self.imagelist.Add(image) |
| 177 | - print "image_index: ", image_index | |
| 178 | 175 | self.mask_list_index[index] = image_index |
| 179 | 176 | self.InsertNewItem(index, mask_name, str(threshold_range)) |
| 180 | 177 | |
| ... | ... | @@ -292,11 +289,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
| 292 | 289 | self.ToggleItem(evt.m_itemIndex) |
| 293 | 290 | |
| 294 | 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 | 410 | self.imagelist = wx.ImageList(16, 16) |
| 418 | 411 | |
| 419 | 412 | image = wx.Image("../icons/object_visible.jpg") |
| 420 | - #image = wx.Image("../img/object_visible-v2.jpg") | |
| 421 | 413 | bitmap = wx.BitmapFromImage(image.Scale(16, 16)) |
| 422 | 414 | bitmap.SetWidth(16) |
| 423 | 415 | bitmap.SetHeight(16) |
| ... | ... | @@ -439,6 +431,7 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): |
| 439 | 431 | |
| 440 | 432 | def OnItemActivated(self, evt): |
| 441 | 433 | self.ToggleItem(evt.m_itemIndex) |
| 434 | + print m_itemIndex | |
| 442 | 435 | |
| 443 | 436 | def OnCheckItem(self, index, flag): |
| 444 | 437 | # TODO: use pubsub to communicate to models | ... | ... |
invesalius/gui/task_slice.py
| ... | ... | @@ -285,12 +285,18 @@ class MaskProperties(wx.Panel): |
| 285 | 285 | ps.Publisher().subscribe(self.SetItemsColour, 'Set GUI items colour') |
| 286 | 286 | ps.Publisher().subscribe(self.SetThresholdValues, |
| 287 | 287 | 'Set threshold values in gradient') |
| 288 | + ps.Publisher().subscribe(self.SelectMaskName, 'Select mask name in combo') | |
| 288 | 289 | |
| 289 | 290 | def __bind_events_wx(self): |
| 290 | 291 | self.combo_thresh.Bind(wx.EVT_COMBOBOX, self.OnComboThresh) |
| 291 | 292 | self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, |
| 292 | 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 | 300 | def SetThresholdValues(self, pubsub_evt): |
| 295 | 301 | thresh_min, thresh_max = pubsub_evt.data |
| 296 | 302 | self.bind_evt_gradient = False |
| ... | ... | @@ -308,6 +314,7 @@ class MaskProperties(wx.Panel): |
| 308 | 314 | mask_thresh = evt_pubsub.data[2] |
| 309 | 315 | mask_colour = [int(c*255) for c in evt_pubsub.data[3]] |
| 310 | 316 | index = self.combo_mask_name.Append(mask_name) |
| 317 | + self.combo_mask_name.SetSelection(index) | |
| 311 | 318 | self.button_colour.SetColour(mask_colour) |
| 312 | 319 | self.gradient.SetColour(mask_colour) |
| 313 | 320 | self.combo_mask_name.SetSelection(index) | ... | ... |
invesalius/invesalius.py