diff --git a/invesalius/constants.py b/invesalius/constants.py index ad539cf..9c3725c 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -43,11 +43,18 @@ MASK_COLOUR = [(0.33, 1, 0.33), #(0.66666666666666663, 0.792156862745098, 1.0)] # Related to slice editor brush -BRUSH_FORMAT = 0 # 0: circle, 1: square -BRUSH_SIZE = 30 -BRUSH_OP = 0 # 0: erase, 1: add, 2: threshold -BRUSH_COLOUR = (0,0,1.0) +BRUSH_CIRCLE = 0 # +BRUSH_SQUARE = 1 +DEFAULT_BRUSH_FORMAT = BRUSH_CIRCLE + +BRUSH_DRAW = 0 +BRUSH_ERASE = 1 +BRUSH_THRESH = 2 +DEFAULT_BRUSH_OP = BRUSH_THRESH +BRUSH_OP_NAME = ["Draw", "Erase", "Threshold"] +BRUSH_COLOUR = (0,0,1.0) +BRUSH_SIZE = 30 # Surface creation values. Each element's list contains: # 0: imagedata reformat ratio diff --git a/invesalius/control.py b/invesalius/control.py index cfee9be..cf208c3 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -7,7 +7,7 @@ import data.imagedata_utils as utils import data.surface as surface import data.volume as volume import reader.dicom_reader as dicom -#import reader.analyze_reader as analyze +import reader.analyze_reader as analyze DEFAULT_THRESH_MODE = 0 diff --git a/invesalius/data/slice_.py b/invesalius/data/slice_.py index b4f4346..0f77252 100644 --- a/invesalius/data/slice_.py +++ b/invesalius/data/slice_.py @@ -50,6 +50,21 @@ class Slice(object): ps.Publisher().subscribe(self.__edit_mask_pixel, 'Edit mask pixel') ps.Publisher().subscribe(self.__add_mask_pixel, 'Add mask pixel') + ps.Publisher().subscribe(self.__set_current_mask_threshold_limits, + 'Update threshold limits') + + def __set_current_mask_threshold_limits(self, pubsub_evt): + thresh_min = pubsub_evt.data[0] + thresh_max = pubsub_evt.data[1] + print "***********" + print thresh_min, thresh_max + print "***********" + if self.current_mask: + index = self.current_mask.index + self.SetMaskEditionThreshold(index, (thresh_min, thresh_max)) + + + #--------------------------------------------------------------------------- # BEGIN PUBSUB_EVT METHODS #--------------------------------------------------------------------------- @@ -75,7 +90,6 @@ class Slice(object): def __set_current_mask_threshold(self, evt_pubsub): threshold_range = evt_pubsub.data index = self.current_mask.index - self.current_mask.edited_points = {} self.SetMaskThreshold(index, threshold_range) def __set_current_mask_colour(self, pubsub_evt): @@ -98,19 +112,16 @@ class Slice(object): self.ShowMask(index, value) #--------------------------------------------------------------------------- def __erase_mask_pixel(self, pubsub_evt): - positions = pubsub_evt.data - for position in positions: - self.ErasePixel(position) + position = pubsub_evt.data + self.ErasePixel(position) def __edit_mask_pixel(self, pubsub_evt): - positions = pubsub_evt.data - for position in positions: - self.EditPixelBasedOnThreshold(position) + position = pubsub_evt.data + self.EditPixelBasedOnThreshold(position) def __add_mask_pixel(self, pubsub_evt): - positions = pubsub_evt.data - for position in positions: - self.DrawPixel(position) + position = pubsub_evt.data + self.DrawPixel(position) #--------------------------------------------------------------------------- # END PUBSUB_EVT METHODS #--------------------------------------------------------------------------- @@ -191,19 +202,19 @@ class Slice(object): def ErasePixel(self, position): "Delete pixel, based on x, y and z position coordinates." x, y, z = position - colour = self.imagedata.GetScalarRange()[0]# - 1 # Important to effect erase + colour = self.imagedata.GetScalarRange()[0] imagedata = self.current_mask.imagedata imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) - #imagedata.Update() + imagedata.Update() self.current_mask.edited_points[(x, y, z)] = colour def DrawPixel(self, position, colour=None): "Draw pixel, based on x, y and z position coordinates." x, y, z = position - #if not colour: colour = self.imagedata.GetScalarRange()[1] imagedata = self.current_mask.imagedata imagedata.SetScalarComponentFromDouble(x, y, z, 0, colour) + imagedata.Update() self.current_mask.edited_points[(x, y, z)] = colour def EditPixelBasedOnThreshold(self, position): @@ -392,7 +403,6 @@ class Slice(object): # if not defined in the method call, this will have been computed on # previous if - #future_mask.imagedata = imagedata future_mask.imagedata = vtk.vtkImageData() future_mask.imagedata.DeepCopy(imagedata) future_mask.imagedata.Update() @@ -421,7 +431,6 @@ class Slice(object): self.current_mask = future_mask ps.Publisher().sendMessage('Change mask selected', future_mask.index) - #ps.Publisher().sendMessage('Show mask', (future_mask.index, 1)) ps.Publisher().sendMessage('Update slice viewer') diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index 32a68d9..27ba837 100755 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -46,10 +46,10 @@ class Viewer(wx.Panel): self.orientation = orientation self.slice_number = 0 - self._brush_cursor_op = 'Draw' - self._brush_cursor_size = 30 - self._brush_cursor_colour = None - self._brush_cursor_type = 'circle' + self._brush_cursor_op = const.DEFAULT_BRUSH_OP + self._brush_cursor_size = const.BRUSH_SIZE + self._brush_cursor_colour = const.BRUSH_COLOUR + self._brush_cursor_type = const.DEFAULT_BRUSH_OP self.cursor = None # VTK pipeline and actors self.__config_interactor() @@ -130,7 +130,6 @@ class Viewer(wx.Panel): self.interactor.Render() def ChangeBrushColour(self, pubsub_evt): - print "********************* ChangeBrushColour" vtk_colour = pubsub_evt.data[3] self._brush_cursor_colour = vtk_colour if (self.cursor): @@ -150,9 +149,9 @@ class Viewer(wx.Panel): self._brush_cursor_type = brush_type self.ren.RemoveActor(self.cursor.actor) - if brush_type == 'square': + if brush_type == const.BRUSH_SQUARE: cursor = ca.CursorRectangle() - elif brush_type == 'circle': + elif brush_type == const.BRUSH_CIRCLE: cursor = ca.CursorCircle() self.cursor = cursor @@ -188,16 +187,16 @@ class Viewer(wx.Panel): self.__update_cursor_position(coord) self.ren.Render() - if self._brush_cursor_op == 'Erase': - evt_msg = 'Erase mask pixel' - elif self._brush_cursor_op == 'Draw': - evt_msg = 'Add mask pixel' - elif self._brush_cursor_op == 'Threshold': - evt_msg = 'Edit mask pixel' + evt_msg = {const.BRUSH_ERASE: 'Erase mask pixel', + const.BRUSH_DRAW: 'Add mask pixel', + const.BRUSH_THRESH: 'Edit mask pixel'} + msg = evt_msg[self._brush_cursor_op] pixels = itertools.ifilter(self.TestOperationPosition, self.cursor.GetPixels()) - ps.Publisher().sendMessage(evt_msg, pixels) + for coord in pixels: + print coord + ps.Publisher().sendMessage(msg, coord) # FIXME: This is idiot, but is the only way that brush operations are # working when cross is disabled @@ -212,19 +211,20 @@ class Viewer(wx.Panel): self.cursor.SetEditionPosition(self.GetCoordinateCursorEdition()) self.__update_cursor_position(coord) - if self._brush_cursor_op == 'Erase': + if self._brush_cursor_op == const.BRUSH_ERASE: evt_msg = 'Erase mask pixel' - elif self._brush_cursor_op == 'Draw': + elif self._brush_cursor_op == const.BRUSH_DRAW: evt_msg = 'Add mask pixel' - elif self._brush_cursor_op == 'Threshold': + elif self._brush_cursor_op == const.BRUSH_THRESH: evt_msg = 'Edit mask pixel' if self.mouse_pressed: pixels = itertools.ifilter(self.TestOperationPosition, self.cursor.GetPixels()) - ps.Publisher().sendMessage(evt_msg, pixels) - ps.Publisher().sendMessage('Update slice viewer') + for coord in pixels: + ps.Publisher().sendMessage(evt_msg, coord) self.interactor.Render() + ps.Publisher().sendMessage('Update slice viewer') def OnCrossMove(self, obj, evt_vtk): coord = self.GetCoordinate() @@ -477,8 +477,9 @@ class Viewer(wx.Panel): "CORONAL": {1: self.slice_number}, "AXIAL": {2: self.slice_number}} - ps.Publisher().sendMessage('Update cursor single position in slice', - position[self.orientation]) + if 'DEFAULT' in self.modes: + ps.Publisher().sendMessage('Update cursor single position in slice', + position[self.orientation]) def ChangeSliceNumber(self, pubsub_evt): index = pubsub_evt.data diff --git a/invesalius/gui/task_slice.py b/invesalius/gui/task_slice.py index b32543a..c4c64d7 100644 --- a/invesalius/gui/task_slice.py +++ b/invesalius/gui/task_slice.py @@ -31,21 +31,15 @@ import gui.widgets.foldpanelbar as fpb from project import Project BTN_NEW = wx.NewId() -MENU_SQUARE = wx.NewId() -MENU_CIRCLE = wx.NewId() - -#THRESHOLD_LIST = ["Bone (CT)", "Soft Tissue (CT)", "Enamel (CT, Adult)", -# "Enamel (CT, Child)", "Compact Bone (CT, Adult)", -# "Compact Bone (CT, Child)", "Spongial Bone (CT, Adult)", -# "Spongial Bone (CT, Child)", "Muscle Tissue (CT, Adult)", -# "Muscle Tissue (CT, Child)", "Fat Tissue (CT, Adult)", -# "Fat Tissue (CT, Adult)", "Skin Tissue (CT, Adult)", -# "Skin Tissue (CT, Child)"] -MASK_LIST = [] +MENU_BRUSH_SQUARE = wx.NewId() +MENU_BRUSH_CIRCLE = wx.NewId() -OP_LIST = ["Draw", "Erase", "Threshold"] +MENU_BRUSH_ADD = wx.NewId() +MENU_BRUSH_DEL = wx.NewId() +MENU_BRUSH_THRESH = wx.NewId() +MASK_LIST = [] class TaskPanel(wx.Panel): def __init__(self, parent): @@ -227,12 +221,10 @@ class MaskProperties(wx.Panel): style=wx.CB_DROPDOWN|wx.CB_READONLY) combo_mask_name.SetSelection(0) # wx.CB_SORT combo_mask_name.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) - combo_mask_name.Bind(wx.EVT_COMBOBOX, self.OnComboName) self.combo_mask_name = combo_mask_name # Mask colour button_colour= csel.ColourSelect(self, 111,colour=(0,255,0),size=(-1,22)) - button_colour.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.button_colour = button_colour # Sizer which represents the first line @@ -290,21 +282,20 @@ class MaskProperties(wx.Panel): ps.Publisher().subscribe(self.ChangeMaskName, 'Change mask name') def __bind_events_wx(self): + self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, self.gradient) self.combo_thresh.Bind(wx.EVT_COMBOBOX, self.OnComboThresh) - self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, - self.gradient) - + self.combo_mask_name.Bind(wx.EVT_COMBOBOX, self.OnComboName) + self.button_colour.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) + def SelectMaskName(self, pubsub_evt): index = pubsub_evt.data self.combo_mask_name.SetSelection(index) - def ChangeMaskName(self, pubsub_evt): index, name = pubsub_evt.data self.combo_mask_name.SetString(index, name) self.combo_mask_name.Refresh() - def SetThresholdValues(self, pubsub_evt): thresh_min, thresh_max = pubsub_evt.data self.bind_evt_gradient = False @@ -376,42 +367,44 @@ class EditionTools(wx.Panel): text1 = wx.StaticText(self, -1, "Choose brush type, size or operation:") ## LINE 2 - - SQUARE_BMP = wx.Bitmap("../icons/brush_square.jpg", wx.BITMAP_TYPE_JPEG) - CIRCLE_BMP = wx.Bitmap("../icons/brush_circle.jpg", wx.BITMAP_TYPE_JPEG) - menu = wx.Menu() - - item = wx.MenuItem(menu, MENU_CIRCLE,"Circle") + + CIRCLE_BMP = wx.Bitmap("../icons/brush_circle.jpg", wx.BITMAP_TYPE_JPEG) + item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, "Circle") item.SetBitmap(CIRCLE_BMP) - item2 = wx.MenuItem(menu, MENU_SQUARE, "Square") + + SQUARE_BMP = wx.Bitmap("../icons/brush_square.jpg", wx.BITMAP_TYPE_JPEG) + item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, "Square") item2.SetBitmap(SQUARE_BMP) - self.Bind(wx.EVT_MENU, self.OnMenu) - + menu.AppendItem(item) menu.AppendItem(item2) - btn_brush_type = pbtn.PlateButton(self, wx.ID_ANY,"", CIRCLE_BMP, + bmp_brush_format = {const.BRUSH_CIRCLE: CIRCLE_BMP, + const.BRUSH_SQUARE: SQUARE_BMP} + selected_bmp = bmp_brush_format[const.DEFAULT_BRUSH_FORMAT] + + btn_brush_format = pbtn.PlateButton(self, wx.ID_ANY,"", selected_bmp, style=pbtn.PB_STYLE_SQUARE) - btn_brush_type.SetMenu(menu) - self.btn_brush_type = btn_brush_type + btn_brush_format.SetMenu(menu) + self.btn_brush_format = btn_brush_format spin_brush_size = wx.SpinCtrl(self, -1, "", (30, 50)) spin_brush_size.SetRange(1,100) - spin_brush_size.SetValue(30) + spin_brush_size.SetValue(const.BRUSH_SIZE) spin_brush_size.Bind(wx.EVT_TEXT, self.OnBrushSize) self.spin = spin_brush_size combo_brush_op = wx.ComboBox(self, -1, "", size=(15,-1), - choices= OP_LIST, - style=wx.CB_DROPDOWN|wx.CB_READONLY) - combo_brush_op.SetSelection(0) + choices = const.BRUSH_OP_NAME, + style = wx.CB_DROPDOWN|wx.CB_READONLY) + combo_brush_op.SetSelection(const.DEFAULT_BRUSH_OP) combo_brush_op.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) - combo_brush_op.Bind(wx.EVT_COMBOBOX, self.OnComboBrushOp) + self.combo_brush_op = combo_brush_op # Sizer which represents the second line line2 = wx.BoxSizer(wx.HORIZONTAL) - line2.Add(btn_brush_type, 0, wx.EXPAND|wx.GROW|wx.TOP|wx.RIGHT, 0) + line2.Add(btn_brush_format, 0, wx.EXPAND|wx.GROW|wx.TOP|wx.RIGHT, 0) line2.Add(spin_brush_size, 0, wx.RIGHT, 5) line2.Add(combo_brush_op, 1, wx.TOP|wx.RIGHT|wx.LEFT, 5) @@ -429,7 +422,8 @@ class EditionTools(wx.Panel): sizer.Add(text1, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) sizer.Add(line2, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) sizer.Add(text_thresh, 0, wx.GROW|wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5) - sizer.Add(gradient_thresh, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT|wx.BOTTOM, 6) + sizer.Add(gradient_thresh, 0, wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT| + wx.BOTTOM, 6) sizer.Fit(self) self.SetSizer(sizer) @@ -441,14 +435,14 @@ class EditionTools(wx.Panel): def __bind_events_wx(self): + self.Bind(wx.EVT_MENU, self.OnMenu) self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnGradientChanged, self.gradient_thresh) + self.combo_brush_op.Bind(wx.EVT_COMBOBOX, self.OnComboBrushOp) def __bind_events(self): ps.Publisher().subscribe(self.SetThresholdBounds, 'Update threshold limits') - #ps.Publisher().subscribe(self.SetThresholdValues, - # 'Set threshold values in gradient') ps.Publisher().subscribe(self.ChangeMaskColour, 'Change mask colour') ps.Publisher().subscribe(self.SetGradientColour, 'Add mask') @@ -471,7 +465,6 @@ class EditionTools(wx.Panel): def SetThresholdBounds(self, pubsub_evt): thresh_min = pubsub_evt.data[0] thresh_max = pubsub_evt.data[1] - print thresh_min, thresh_max self.gradient_thresh.SetMinRange(thresh_min) self.gradient_thresh.SetMaxRange(thresh_max) self.gradient_thresh.SetMinValue(thresh_min) @@ -485,17 +478,17 @@ class EditionTools(wx.Panel): (thresh_min, thresh_max)) def OnMenu(self, evt): - """Button's menu event""" SQUARE_BMP = wx.Bitmap("../icons/brush_square.jpg", wx.BITMAP_TYPE_JPEG) CIRCLE_BMP = wx.Bitmap("../icons/brush_circle.jpg", wx.BITMAP_TYPE_JPEG) - name = {MENU_CIRCLE:"circle", MENU_SQUARE:"square"} - bitmap = {MENU_CIRCLE:CIRCLE_BMP, MENU_SQUARE:SQUARE_BMP} + brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE, + MENU_BRUSH_SQUARE: const.BRUSH_SQUARE} + bitmap = {MENU_BRUSH_CIRCLE: CIRCLE_BMP, + MENU_BRUSH_SQUARE: SQUARE_BMP} - self.btn_brush_type.SetBitmap(bitmap[evt.GetId()]) + self.btn_brush_format.SetBitmap(bitmap[evt.GetId()]) - print "TODO: Send Signal - Change brush format to %s"% name[evt.GetId()] - ps.Publisher().sendMessage('Set brush format', name[evt.GetId()]) + ps.Publisher().sendMessage('Set brush format', brush[evt.GetId()]) def OnBrushSize(self, evt): """ """ @@ -505,7 +498,7 @@ class EditionTools(wx.Panel): ps.Publisher().sendMessage('Set edition brush size',self.spin.GetValue()) def OnComboBrushOp(self, evt): - print "TODO: Send Signal - Change brush operation: %s" %(evt.GetString()) - ps.Publisher().sendMessage('Set edition operation',evt.GetString()) + brush_op_id = evt.GetSelection() + ps.Publisher().sendMessage('Set edition operation', brush_op_id) -- libgit2 0.21.2