Commit c79f0659a38f58644ae9feda327f828b704f2f2c

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent ad7294a7
Exists in master

Select mask part tool (#50)

* Starting to select part to new mask

* Showing the selected part

* Improvement

* Better create_new_mask method and doc

* Removed the old method to add new mask

* Better method to get the position of the clicked voxel

* Option to deselect part

* Not setting new mask as current in task_slice

* Strip white spaces and better doc in Mask create_mask class

* Showing dialog

* Appending the mask only after the proccess is over

* Better gui
invesalius/constants.py
... ... @@ -483,6 +483,7 @@ ID_CLEAN_MASK = wx.NewId()
483 483 ID_REORIENT_IMG = wx.NewId()
484 484 ID_FLOODFILL_MASK = wx.NewId()
485 485 ID_REMOVE_MASK_PART = wx.NewId()
  486 +ID_SELECT_MASK_PART = wx.NewId()
486 487  
487 488 #---------------------------------------------------------
488 489 STATE_DEFAULT = 1000
... ... @@ -502,6 +503,7 @@ SLICE_STATE_WATERSHED = 3009
502 503 SLICE_STATE_REORIENT = 3010
503 504 SLICE_STATE_MASK_FFILL = 3011
504 505 SLICE_STATE_REMOVE_MASK_PARTS = 3012
  506 +SLICE_STATE_SELECT_MASK_PARTS = 3013
505 507  
506 508 VOLUME_STATE_SEED = 2001
507 509 # STATE_LINEAR_MEASURE = 3001
... ... @@ -521,6 +523,7 @@ SLICE_STYLES.append(SLICE_STATE_EDITOR)
521 523 SLICE_STYLES.append(SLICE_STATE_WATERSHED)
522 524 SLICE_STYLES.append(SLICE_STATE_MASK_FFILL)
523 525 SLICE_STYLES.append(SLICE_STATE_REMOVE_MASK_PARTS)
  526 +SLICE_STYLES.append(SLICE_STATE_SELECT_MASK_PARTS)
524 527  
525 528 VOLUME_STYLES = TOOL_STATES + [VOLUME_STATE_SEED, STATE_MEASURE_DISTANCE,
526 529 STATE_MEASURE_ANGLE]
... ... @@ -531,6 +534,7 @@ STYLE_LEVEL = {SLICE_STATE_EDITOR: 1,
531 534 SLICE_STATE_WATERSHED: 1,
532 535 SLICE_STATE_MASK_FFILL: 2,
533 536 SLICE_STATE_REMOVE_MASK_PARTS: 2,
  537 + SLICE_STATE_SELECT_MASK_PARTS: 2,
534 538 SLICE_STATE_CROSS: 2,
535 539 SLICE_STATE_SCROLL: 2,
536 540 SLICE_STATE_REORIENT: 2,
... ...
invesalius/data/mask.py
... ... @@ -126,7 +126,7 @@ class EditionHistory(object):
126 126 h[self.index].commit_history(mvolume)
127 127 self._reload_slice(self.index)
128 128 Publisher.sendMessage("Enable redo", True)
129   -
  129 +
130 130 if self.index == 0:
131 131 Publisher.sendMessage("Enable undo", False)
132 132 print "AT", self.index, len(self.history), self.history[self.index].filename
... ... @@ -154,7 +154,7 @@ class EditionHistory(object):
154 154 h[self.index].commit_history(mvolume)
155 155 self._reload_slice(self.index)
156 156 Publisher.sendMessage("Enable undo", True)
157   -
  157 +
158 158 if self.index == len(h) - 1:
159 159 Publisher.sendMessage("Enable redo", False)
160 160 print "AT", self.index, len(h), h[self.index].filename
... ... @@ -174,7 +174,7 @@ class EditionHistory(object):
174 174 v_undo = False
175 175 elif self.index == len(self.history) - 1:
176 176 v_redo = False
177   -
  177 +
178 178 Publisher.sendMessage("Enable undo", v_undo)
179 179 Publisher.sendMessage("Enable redo", v_redo)
180 180  
... ... @@ -229,7 +229,7 @@ class Mask():
229 229  
230 230 def SavePlist(self, dir_temp, filelist):
231 231 mask = {}
232   - filename = u'mask_%d' % self.index
  232 + filename = u'mask_%d' % self.index
233 233 mask_filename = u'%s.dat' % filename
234 234 mask_filepath = os.path.join(dir_temp, mask_filename)
235 235 filelist[self.temp_file] = mask_filename
... ... @@ -304,7 +304,12 @@ class Mask():
304 304 Mask.general_index = index
305 305  
306 306 def create_mask(self, shape):
307   - print "Creating a mask"
  307 + """
  308 + Creates a new mask object. This method do not append this new mask into the project.
  309 +
  310 + Parameters:
  311 + shape(int, int, int): The shape of the new mask.
  312 + """
308 313 self.temp_file = tempfile.mktemp()
309 314 shape = shape[0] + 1, shape[1] + 1, shape[2] + 1
310 315 self.matrix = numpy.memmap(self.temp_file, mode='w+', dtype='uint8', shape=shape)
... ... @@ -329,7 +334,7 @@ class Mask():
329 334 new_mask.threshold_range = self.threshold_range
330 335 new_mask.edition_threshold_range = self.edition_threshold_range
331 336 new_mask.is_shown = self.is_shown
332   -
  337 +
333 338 new_mask.create_mask(shape=[i-1 for i in self.matrix.shape])
334 339 new_mask.matrix[:] = self.matrix[:]
335 340  
... ...
invesalius/data/slice_.py
... ... @@ -302,14 +302,14 @@ class Slice(object):
302 302  
303 303 def __add_mask(self, pubsub_evt):
304 304 mask_name = pubsub_evt.data
305   - self.CreateMask(name=mask_name)
  305 + self.create_new_mask(name=mask_name)
306 306 self.SetMaskColour(self.current_mask.index, self.current_mask.colour)
307 307  
308 308 def __add_mask_thresh(self, pubsub_evt):
309 309 mask_name = pubsub_evt.data[0]
310 310 thresh = pubsub_evt.data[1]
311 311 colour = pubsub_evt.data[2]
312   - self.CreateMask(name=mask_name, threshold_range=thresh, colour =colour)
  312 + self.create_new_mask(name=mask_name, threshold_range=thresh, colour=colour)
313 313 self.SetMaskColour(self.current_mask.index, self.current_mask.colour)
314 314 self.SelectCurrentMask(self.current_mask.index)
315 315 Publisher.sendMessage('Reload actual slice')
... ... @@ -574,6 +574,14 @@ class Slice(object):
574 574 1: (0.0, 1.0, 0.0, 1.0),
575 575 2: (1.0, 0.0, 0.0, 1.0)})
576 576 final_image = self.do_blend(final_image, cimage)
  577 + elif self.to_show_aux and self.current_mask:
  578 + m = self.get_aux_slice(self.to_show_aux, orientation, slice_number)
  579 + tmp_vimage = converters.to_vtk(m, self.spacing, slice_number, orientation)
  580 + aux_image = self.do_custom_colour(tmp_vimage, {0: (0.0, 0.0, 0.0, 0.0),
  581 + 1: (0.0, 0.0, 0.0, 0.0),
  582 + 254: (1.0, 0.0, 0.0, 1.0),
  583 + 255: (1.0, 0.0, 0.0, 1.0)})
  584 + final_image = self.do_blend(final_image, aux_image)
577 585 return final_image
578 586  
579 587 def get_image_slice(self, orientation, slice_number, number_slices=1,
... ... @@ -1026,14 +1034,32 @@ class Slice(object):
1026 1034 #else:
1027 1035 #widget.SetInput(cast.GetOutput())
1028 1036  
1029   -
1030   -
1031   - def CreateMask(self, imagedata=None, name=None, colour=None,
1032   - opacity=None, threshold_range=None,
1033   - edition_threshold_range = None,
1034   - edited_points=None):
1035   -
1036   - # TODO: mask system to new system.
  1037 + def create_new_mask(self, name=None,
  1038 + colour=None,
  1039 + opacity=None,
  1040 + threshold_range=None,
  1041 + edition_threshold_range=None,
  1042 + add_to_project=True,
  1043 + show=True):
  1044 + """
  1045 + Creates a new mask and add it to project.
  1046 +
  1047 + Parameters:
  1048 + name (string): name of the new mask. If name is None a automatic
  1049 + name will be used.
  1050 + colour (R, G, B): a RGB tuple of float number.
  1051 + opacity (float): a float number, from 0 to 1. If opacity is None
  1052 + the default one will be used.
  1053 + threshold_range (int, int): a 2-tuple indicating threshold range.
  1054 + If None the default one will be used.
  1055 + edition_threshold_range (int, int): a 2-tuple indicating threshold
  1056 + range. If None the default one will be used.
  1057 + show (bool): if this new mask will be showed and set as current
  1058 + mask.
  1059 +
  1060 + Returns:
  1061 + new_mask: The new mask object.
  1062 + """
1037 1063 future_mask = Mask()
1038 1064 future_mask.create_mask(self.matrix.shape)
1039 1065  
... ... @@ -1045,12 +1071,13 @@ class Slice(object):
1045 1071 future_mask.opacity = opacity
1046 1072 if edition_threshold_range:
1047 1073 future_mask.edition_threshold_range = edition_threshold_range
1048   - if edited_points:
1049   - future_mask.edited_points = edited_points
1050 1074 if threshold_range:
1051 1075 future_mask.threshold_range = threshold_range
1052 1076  
1053   - self._add_mask_into_proj(future_mask)
  1077 + if add_to_project:
  1078 + self._add_mask_into_proj(future_mask, show=show)
  1079 +
  1080 + return future_mask
1054 1081  
1055 1082  
1056 1083 def _add_mask_into_proj(self, mask, show=True):
... ... @@ -1282,6 +1309,7 @@ class Slice(object):
1282 1309 op, m1, m2 = pubsub_evt.data
1283 1310 self.do_boolean_op(op, m1, m2)
1284 1311  
  1312 +
1285 1313 def do_boolean_op(self, op, m1, m2):
1286 1314 name_ops = {const.BOOLEAN_UNION: _(u"Union"),
1287 1315 const.BOOLEAN_DIFF: _(u"Diff"),
... ...
invesalius/data/styles.py
... ... @@ -1928,6 +1928,98 @@ class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle):
1928 1928 self._progr_msg = _(u"Removing part ...")
1929 1929  
1930 1930  
  1931 +class SelectPartConfig(object):
  1932 + __metaclass__= utils.Singleton
  1933 + def __init__(self):
  1934 + self.mask = None
  1935 + self.con_3d = 6
  1936 + self.dlg_visible = False
  1937 + self.mask_name = ''
  1938 +
  1939 +
  1940 +class SelectMaskPartsInteractorStyle(DefaultInteractorStyle):
  1941 + def __init__(self, viewer):
  1942 + DefaultInteractorStyle.__init__(self, viewer)
  1943 +
  1944 + self.viewer = viewer
  1945 + self.orientation = self.viewer.orientation
  1946 +
  1947 + self.picker = vtk.vtkWorldPointPicker()
  1948 + self.slice_actor = viewer.slice_data.actor
  1949 + self.slice_data = viewer.slice_data
  1950 +
  1951 + self.config = SelectPartConfig()
  1952 + self.dlg = None
  1953 +
  1954 + self.t0 = 254
  1955 + self.t1 = 255
  1956 + self.fill_value = 254
  1957 +
  1958 + self.AddObserver("LeftButtonPressEvent", self.OnSelect)
  1959 +
  1960 + def SetUp(self):
  1961 + if not self.config.dlg_visible:
  1962 + import data.mask as mask
  1963 + default_name = const.MASK_NAME_PATTERN %(mask.Mask.general_index+2)
  1964 +
  1965 + self.config.mask_name = default_name
  1966 + self.config.dlg_visible = True
  1967 + self.dlg= dialogs.SelectPartsOptionsDialog(self.config)
  1968 + self.dlg.Show()
  1969 +
  1970 + def CleanUp(self):
  1971 + if (self.dlg is not None) and (self.config.dlg_visible):
  1972 + self.config.dlg_visible = False
  1973 + self.dlg.Destroy()
  1974 + self.dlg = None
  1975 +
  1976 + if self.config.mask:
  1977 + self.config.mask.name = self.config.mask_name
  1978 + self.viewer.slice_._add_mask_into_proj(self.config.mask)
  1979 + self.viewer.slice_.SelectCurrentMask(self.config.mask.index)
  1980 + Publisher.sendMessage('Change mask selected', self.config.mask.index)
  1981 + self.config.mask = None
  1982 + del self.viewer.slice_.aux_matrices['SELECT']
  1983 + self.viewer.slice_.to_show_aux = ''
  1984 + Publisher.sendMessage('Reload actual slice')
  1985 +
  1986 + def OnSelect(self, obj, evt):
  1987 + if (self.viewer.slice_.buffer_slices[self.orientation].mask is None):
  1988 + return
  1989 +
  1990 + iren = self.viewer.interactor
  1991 + mouse_x, mouse_y = iren.GetEventPosition()
  1992 + x, y, z = self.viewer.get_voxel_clicked(mouse_x, mouse_y, self.picker)
  1993 +
  1994 + mask = self.viewer.slice_.current_mask.matrix[1:, 1:, 1:]
  1995 +
  1996 + bstruct = np.array(generate_binary_structure(3, CON3D[self.config.con_3d]), dtype='uint8')
  1997 + self.viewer.slice_.do_threshold_to_all_slices()
  1998 +
  1999 + if self.config.mask is None:
  2000 + self._create_new_mask()
  2001 +
  2002 + if iren.GetControlKey():
  2003 + floodfill.floodfill_threshold(self.config.mask.matrix[1:, 1:, 1:], [[x, y, z]], 254, 255, 0, bstruct, self.config.mask.matrix[1:, 1:, 1:])
  2004 + else:
  2005 + floodfill.floodfill_threshold(mask, [[x, y, z]], self.t0, self.t1, self.fill_value, bstruct, self.config.mask.matrix[1:, 1:, 1:])
  2006 +
  2007 + self.viewer.slice_.aux_matrices['SELECT'] = self.config.mask.matrix[1:, 1:, 1:]
  2008 + self.viewer.slice_.to_show_aux = 'SELECT'
  2009 +
  2010 + self.config.mask.was_edited = True
  2011 + Publisher.sendMessage('Reload actual slice')
  2012 +
  2013 + def _create_new_mask(self):
  2014 + mask = self.viewer.slice_.create_new_mask(show=False, add_to_project=False)
  2015 + mask.was_edited = True
  2016 + mask.matrix[0, :, :] = 1
  2017 + mask.matrix[:, 0, :] = 1
  2018 + mask.matrix[:, :, 0] = 1
  2019 +
  2020 + self.config.mask = mask
  2021 +
  2022 +
1931 2023 def get_style(style):
1932 2024 STYLES = {
1933 2025 const.STATE_DEFAULT: DefaultInteractorStyle,
... ... @@ -1945,6 +2037,7 @@ def get_style(style):
1945 2037 const.SLICE_STATE_REORIENT: ReorientImageInteractorStyle,
1946 2038 const.SLICE_STATE_MASK_FFILL: FloodFillMaskInteractorStyle,
1947 2039 const.SLICE_STATE_REMOVE_MASK_PARTS: RemoveMaskPartsInteractorStyle,
  2040 + const.SLICE_STATE_SELECT_MASK_PARTS: SelectMaskPartsInteractorStyle,
1948 2041 }
1949 2042 return STYLES[style]
1950 2043  
... ...
invesalius/data/viewer_slice.py
... ... @@ -977,9 +977,12 @@ class Viewer(wx.Panel):
977 977 my = round((z - zi)/self.slice_.spacing[2], 0)
978 978 return my, mx
979 979  
980   - def get_coordinate_cursor(self):
  980 + def get_coordinate_cursor(self, picker=None):
981 981 # Find position
982   - x, y, z = self.pick.GetPickPosition()
  982 + if picker is None:
  983 + picker = self.pick
  984 +
  985 + x, y, z = picker.GetPickPosition()
983 986 bounds = self.slice_data.actor.GetBounds()
984 987 if bounds[0] == bounds[1]:
985 988 x = bounds[0]
... ... @@ -989,11 +992,14 @@ class Viewer(wx.Panel):
989 992 z = bounds[4]
990 993 return x, y, z
991 994  
992   - def get_coordinate_cursor_edition(self, slice_data):
  995 + def get_coordinate_cursor_edition(self, slice_data, picker=None):
993 996 # Find position
994 997 actor = slice_data.actor
995 998 slice_number = slice_data.number
996   - x, y, z = self.pick.GetPickPosition()
  999 + if picker is None:
  1000 + picker = self.pick
  1001 +
  1002 + x, y, z = picker.GetPickPosition()
997 1003  
998 1004 # First we fix the position origin, based on vtkActor bounds
999 1005 bounds = actor.GetBounds()
... ... @@ -1023,6 +1029,41 @@ class Viewer(wx.Panel):
1023 1029  
1024 1030 return x, y, z
1025 1031  
  1032 + def get_voxel_clicked(self, mx, my, picker=None):
  1033 + """
  1034 + Given the (mx, my) mouse clicked position returns the voxel coordinate
  1035 + of the voxel at (that mx, my) position.
  1036 +
  1037 + Parameters:
  1038 + mx (int): x position.
  1039 + my (int): y position
  1040 + picker: the picker used to get calculate the voxel coordinate.
  1041 +
  1042 + Returns:
  1043 + voxel_coordinate (x, y, z): voxel coordinate inside the matrix. Can
  1044 + be used to access the voxel value inside the matrix.
  1045 + """
  1046 + if picker is None:
  1047 + picker = self.pick
  1048 +
  1049 + slice_data = self.slice_data
  1050 + renderer = slice_data.renderer
  1051 +
  1052 + picker.Pick(mx, my, 0, renderer)
  1053 +
  1054 + coord = self.get_coordinate_cursor(picker)
  1055 + position = slice_data.actor.GetInput().FindPoint(coord)
  1056 +
  1057 + if position != -1:
  1058 + coord = slice_data.actor.GetInput().GetPoint(position)
  1059 +
  1060 + if position < 0:
  1061 + position = viewer.calculate_matrix_position(coord)
  1062 +
  1063 + x, y, z = self.calcultate_scroll_position(position)
  1064 +
  1065 + return (x, y, z)
  1066 +
1026 1067 def __bind_events(self):
1027 1068 Publisher.subscribe(self.LoadImagedata,
1028 1069 'Load slice to viewer')
... ... @@ -1044,8 +1085,8 @@ class Viewer(wx.Panel):
1044 1085 Publisher.subscribe(self.Navigation,
1045 1086 'Co-registered Points')
1046 1087 ###
1047   - Publisher.subscribe(self.ChangeBrushColour,
1048   - 'Add mask')
  1088 + # Publisher.subscribe(self.ChangeBrushColour,
  1089 + # 'Add mask')
1049 1090  
1050 1091 Publisher.subscribe(self.UpdateWindowLevelValue,
1051 1092 'Update window level value')
... ...
invesalius/gui/data_notebook.py
... ... @@ -512,11 +512,11 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin):
512 512 self.SetStringItem(index, 1, label,
513 513 imageId=self.mask_list_index[index])
514 514 self.SetStringItem(index, 2, threshold)
515   - self.SetItemImage(index, 1)
516   - for key in self.mask_list_index.keys():
517   - if key != index:
518   - self.SetItemImage(key, 0)
519   - self.current_index = index
  515 + # self.SetItemImage(index, 1)
  516 + # for key in self.mask_list_index.keys():
  517 + # if key != index:
  518 + # self.SetItemImage(key, 0)
  519 + # self.current_index = index
520 520  
521 521 def AddMask(self, pubsub_evt):
522 522 index, mask_name, threshold_range, colour = pubsub_evt.data
... ...
invesalius/gui/dialogs.py
... ... @@ -1940,3 +1940,94 @@ class FFillOptionsDialog(wx.Dialog):
1940 1940 Publisher.sendMessage('Disable style', const.SLICE_STATE_MASK_FFILL)
1941 1941 evt.Skip()
1942 1942 self.Destroy()
  1943 +
  1944 +
  1945 +class SelectPartsOptionsDialog(wx.Dialog):
  1946 + def __init__(self, config):
  1947 + pre = wx.PreDialog()
  1948 + pre.Create(wx.GetApp().GetTopWindow(), -1, _(u"Select mask parts"), style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT)
  1949 + self.PostCreate(pre)
  1950 +
  1951 + self.config = config
  1952 +
  1953 + self._init_gui()
  1954 +
  1955 + def _init_gui(self):
  1956 + self.target_name = wx.TextCtrl(self, -1)
  1957 + self.target_name.SetValue(self.config.mask_name)
  1958 +
  1959 + # Connectivity 3D
  1960 + self.conect3D_6 = wx.RadioButton(self, -1, "6", style=wx.RB_GROUP)
  1961 + self.conect3D_18 = wx.RadioButton(self, -1, "18")
  1962 + self.conect3D_26 = wx.RadioButton(self, -1, "26")
  1963 +
  1964 + if self.config.con_3d == 18:
  1965 + self.conect3D_18.SetValue(1)
  1966 + elif self.config.con_3d == 26:
  1967 + self.conect3D_26.SetValue(1)
  1968 + else:
  1969 + self.conect3D_6.SetValue(1)
  1970 +
  1971 + sizer_t = wx.BoxSizer(wx.HORIZONTAL)
  1972 + sizer_t.AddSpacer(7)
  1973 + sizer_t.Add(wx.StaticText(self, -1, _(u"Target mask name")), 1, wx.ALIGN_CENTRE_VERTICAL)
  1974 + sizer_t.AddSpacer(7)
  1975 + sizer_t.Add(self.target_name, 1, wx.EXPAND)
  1976 + sizer_t.AddSpacer(7)
  1977 +
  1978 + sizer_c = wx.BoxSizer(wx.HORIZONTAL)
  1979 + sizer_c.AddSpacer(7)
  1980 + sizer_c.Add(self.conect3D_6)
  1981 + sizer_c.AddSpacer(7)
  1982 + sizer_c.Add(self.conect3D_18)
  1983 + sizer_c.AddSpacer(7)
  1984 + sizer_c.Add(self.conect3D_26)
  1985 +
  1986 + sizer = wx.BoxSizer(wx.VERTICAL)
  1987 + sizer.AddSpacer(7)
  1988 + sizer.Add(sizer_t, 1, wx.EXPAND)
  1989 + sizer.AddSpacer(7)
  1990 + sizer.Add(wx.StaticText(self, -1, _(u"3D Connectivity")), 0, wx.LEFT, 7)
  1991 + sizer.AddSpacer(5)
  1992 + sizer.Add(sizer_c)
  1993 + sizer.AddSpacer(7)
  1994 +
  1995 + # sizer = wx.GridBagSizer(11, 6)
  1996 + # sizer.AddStretchSpacer((0, 0))
  1997 +
  1998 + # sizer.Add(wx.StaticText(self, -1, _(u"Target mask name")), (1, 0), (1, 6), flag=wx.LEFT|wx.ALIGN_BOTTOM|wx.EXPAND, border=7)
  1999 + # sizer.Add(self.target_name, (2, 0), (1, 6), flag=wx.LEFT|wx.EXPAND|wx.RIGHT|wx.ALIGN_TOP, border=9)
  2000 +
  2001 + # # sizer.AddStretchSpacer((3, 0))
  2002 +
  2003 + # sizer.Add(wx.StaticText(self, -1, _(u"3D Connectivity")), (3, 0), (1, 6), flag=wx.LEFT, border=7)
  2004 + # sizer.Add(self.conect3D_6, (4, 0), flag=wx.LEFT, border=9)
  2005 + # sizer.Add(self.conect3D_18, (4, 1), flag=wx.LEFT, border=9)
  2006 + # sizer.Add(self.conect3D_26, (4, 2), flag=wx.LEFT, border=9)
  2007 + # sizer.AddStretchSpacer((5, 0))
  2008 +
  2009 + self.SetSizer(sizer)
  2010 + sizer.Fit(self)
  2011 + self.Layout()
  2012 +
  2013 + self.target_name.Bind(wx.EVT_CHAR, self.OnChar)
  2014 + self.Bind(wx.EVT_RADIOBUTTON, self.OnSetRadio)
  2015 + self.Bind(wx.EVT_CLOSE, self.OnClose)
  2016 +
  2017 + def OnChar(self, evt):
  2018 + evt.Skip()
  2019 + self.config.mask_name = self.target_name.GetValue()
  2020 +
  2021 + def OnSetRadio(self, evt):
  2022 + if self.conect3D_6.GetValue():
  2023 + self.config.con_3d = 6
  2024 + elif self.conect3D_18.GetValue():
  2025 + self.config.con_3d = 18
  2026 + elif self.conect3D_26.GetValue():
  2027 + self.config.con_3d = 26
  2028 +
  2029 + def OnClose(self, evt):
  2030 + if self.config.dlg_visible:
  2031 + Publisher.sendMessage('Disable style', const.SLICE_STATE_SELECT_MASK_PARTS)
  2032 + evt.Skip()
  2033 + self.Destroy()
... ...
invesalius/gui/frame.py
... ... @@ -451,20 +451,16 @@ class Frame(wx.Frame):
451 451 elif id == const.ID_REMOVE_MASK_PART:
452 452 self.OnRemoveMaskParts()
453 453  
  454 + elif id == const.ID_SELECT_MASK_PART:
  455 + self.OnSelectMaskParts()
  456 +
454 457 elif id == const.ID_VIEW_INTERPOLATED:
455   -
456 458 st = self.actived_interpolated_slices.IsChecked(const.ID_VIEW_INTERPOLATED)
457   -
458 459 if st:
459 460 self.OnInterpolatedSlices(True)
460 461 else:
461 462 self.OnInterpolatedSlices(False)
462 463  
463   - def OnInterpolatedSlices(self, status):
464   -
465   - Publisher.sendMessage('Set interpolated slices', status)
466   -
467   -
468 464 def OnSize(self, evt):
469 465 """
470 466 Refresh GUI when frame is resized.
... ... @@ -594,6 +590,12 @@ class Frame(wx.Frame):
594 590 def OnRemoveMaskParts(self):
595 591 Publisher.sendMessage('Enable style', const.SLICE_STATE_REMOVE_MASK_PARTS)
596 592  
  593 + def OnSelectMaskParts(self):
  594 + Publisher.sendMessage('Enable style', const.SLICE_STATE_SELECT_MASK_PARTS)
  595 +
  596 + def OnInterpolatedSlices(self, status):
  597 + Publisher.sendMessage('Set interpolated slices', status)
  598 +
597 599 # ------------------------------------------------------------------
598 600 # ------------------------------------------------------------------
599 601 # ------------------------------------------------------------------
... ... @@ -615,7 +617,8 @@ class MenuBar(wx.MenuBar):
615 617 const.ID_PROJECT_CLOSE,
616 618 const.ID_REORIENT_IMG,
617 619 const.ID_FLOODFILL_MASK,
618   - const.ID_REMOVE_MASK_PART,]
  620 + const.ID_REMOVE_MASK_PART,
  621 + const.ID_SELECT_MASK_PART,]
619 622 self.__init_items()
620 623 self.__bind_events()
621 624  
... ... @@ -733,6 +736,9 @@ class MenuBar(wx.MenuBar):
733 736 self.remove_mask_part_menu = mask_menu.Append(const.ID_REMOVE_MASK_PART, _(u"Remove parts"))
734 737 self.remove_mask_part_menu.Enable(False)
735 738  
  739 + self.select_mask_part_menu = mask_menu.Append(const.ID_SELECT_MASK_PART, _(u"Select parts"))
  740 + self.select_mask_part_menu.Enable(False)
  741 +
736 742 tools_menu.AppendMenu(-1, _(u"Mask"), mask_menu)
737 743  
738 744 # Image menu
... ...
invesalius/gui/task_slice.py
... ... @@ -562,10 +562,10 @@ class MaskProperties(wx.Panel):
562 562 mask_thresh = evt_pubsub.data[2]
563 563 mask_colour = [int(c*255) for c in evt_pubsub.data[3]]
564 564 index = self.combo_mask_name.Append(mask_name)
565   - self.combo_mask_name.SetSelection(index)
566   - self.button_colour.SetColour(mask_colour)
567   - self.gradient.SetColour(mask_colour)
568   - self.combo_mask_name.SetSelection(index)
  565 + # self.combo_mask_name.SetSelection(index)
  566 + # self.button_colour.SetColour(mask_colour)
  567 + # self.gradient.SetColour(mask_colour)
  568 + # self.combo_mask_name.SetSelection(index)
569 569  
570 570 def GetMaskSelected(self):
571 571 x = self.combo_mask_name.GetSelection()
... ...