Commit f95ee382033e9f87e7452877aba92ddcd57154c1

Authored by otaviocarlos
Committed by Thiago Franco de Moraes
1 parent 12b38b74
Exists in master

Navigation updates and improvements (#146)

* Adição do modo DBS

* Dbs mode added

* Changes in target icon

* Changes in colour picker settings

* Minor adjustments

* Adjustments in target icon

* Minor adjustments

* ISOTRAK py3 support

* Minor adjustments
invesalius/constants.py
@@ -505,11 +505,12 @@ VTK_WARNING = 0 @@ -505,11 +505,12 @@ VTK_WARNING = 0
505 505
506 #---------------------------------------------------------- 506 #----------------------------------------------------------
507 507
  508 +ID_MODE_NAVIGATION: object
508 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, 509 [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE,
509 ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, 510 ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET,
510 ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_PREFERENCES, ID_DICOM_NETWORK, 511 ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_PREFERENCES, ID_DICOM_NETWORK,
511 ID_TIFF_JPG_PNG, ID_VIEW_INTERPOLATED, ID_MODE_NAVIGATION, ID_ANALYZE_IMPORT, 512 ID_TIFF_JPG_PNG, ID_VIEW_INTERPOLATED, ID_MODE_NAVIGATION, ID_ANALYZE_IMPORT,
512 -ID_NIFTI_IMPORT, ID_PARREC_IMPORT] = [wx.NewId() for number in range(18)] 513 +ID_NIFTI_IMPORT, ID_PARREC_IMPORT, ID_MODE_DBS] = [wx.NewId() for number in range(19)]
513 ID_EXIT = wx.ID_EXIT 514 ID_EXIT = wx.ID_EXIT
514 ID_ABOUT = wx.ID_ABOUT 515 ID_ABOUT = wx.ID_ABOUT
515 516
invesalius/data/coordinates.py
@@ -174,33 +174,31 @@ def PolhemusSerialCoord(trck_init, trck_id, ref_mode): @@ -174,33 +174,31 @@ def PolhemusSerialCoord(trck_init, trck_id, ref_mode):
174 # aoflt -> 0:letter 1:x 2:y 3:z 174 # aoflt -> 0:letter 1:x 2:y 3:z
175 # this method is not optimized to work with all trackers, only with ISOTRAK 175 # this method is not optimized to work with all trackers, only with ISOTRAK
176 # serial connection is obsolete, remove in future 176 # serial connection is obsolete, remove in future
177 - trck_init.write("P") 177 + trck_init.write(str.encode("P"))
  178 + scale = 10. * np.array([1., 1.0, 1.0])
178 lines = trck_init.readlines() 179 lines = trck_init.readlines()
179 180
180 - coord = None  
181 -  
182 - if lines[0][0] != '0': 181 + if lines is None:
183 print("The Polhemus is not connected!") 182 print("The Polhemus is not connected!")
184 else: 183 else:
185 - for s in lines:  
186 - if s[1] == '1':  
187 - data = s  
188 - elif s[1] == '2':  
189 - data = s  
190 -  
191 - # single ref mode  
192 - if not ref_mode:  
193 - data = data.replace('-', ' -')  
194 - data = [s for s in data.split()]  
195 - j = 0  
196 - while j == 0:  
197 - try:  
198 - plh1 = [float(s) for s in data[1:len(data)]]  
199 - j = 1  
200 - except:  
201 - print("error!!")  
202 -  
203 - coord = data[0:6] 184 + data = lines[0]
  185 + data = data.replace(str.encode('-'), str.encode(' -'))
  186 + data = [s for s in data.split()]
  187 + data = [float(s) for s in data[1:len(data)]]
  188 + probe = np.array([data[0] * scale[0], data[1] * scale[1], data[2] * scale[2], data[3], data[4], data[5]])
  189 +
  190 + if ref_mode:
  191 + data2 = lines[1]
  192 + data2 = data2.replace(str.encode('-'), str.encode(' -'))
  193 + data2 = [s for s in data2.split()]
  194 + data2 = [float(s) for s in data2[1:len(data2)]]
  195 + reference = np.array(
  196 + [data2[0] * scale[0], data2[1] * scale[1], data2[2] * scale[2], data2[3], data2[4], data2[5]])
  197 + else:
  198 + reference = np.zeros(6)
  199 +
  200 + coord = np.vstack([probe, reference])
  201 +
204 return coord 202 return coord
205 203
206 204
invesalius/data/trackers.py
@@ -143,31 +143,26 @@ def PlhWrapperConnection(tracker_id): @@ -143,31 +143,26 @@ def PlhWrapperConnection(tracker_id):
143 143
144 144
145 def PlhSerialConnection(tracker_id): 145 def PlhSerialConnection(tracker_id):
146 - try:  
147 - import serial  
148 -  
149 - trck_init = serial.Serial('COM1', baudrate=115200, timeout=0.2)  
150 -  
151 - if tracker_id == 2:  
152 - # Polhemus FASTRAK needs configurations first  
153 - trck_init.write(0x02, "u")  
154 - trck_init.write(0x02, "F")  
155 - elif tracker_id == 3:  
156 - # Polhemus ISOTRAK needs to set tracking point from  
157 - # center to tip.  
158 - trck_init.write("F")  
159 - trck_init.write("Y")  
160 -  
161 - trck_init.write('P')  
162 - data = trck_init.readlines()  
163 -  
164 - if not data:  
165 - trck_init = None  
166 - print('Could not connect to Polhemus serial without error.')  
167 -  
168 - except: 146 + import serial
  147 +
  148 + trck_init = serial.Serial('COM1', baudrate=115200, timeout=0.03)
  149 +
  150 + if tracker_id == 2:
  151 + # Polhemus FASTRAK needs configurations first
  152 + trck_init.write(0x02, str.encode("u"))
  153 + trck_init.write(0x02, str.encode("F"))
  154 + elif tracker_id == 3:
  155 + # Polhemus ISOTRAK needs to set tracking point from
  156 + # center to tip.
  157 + trck_init.write(str.encode("u"))
  158 + trck_init.write(str.encode("F"))
  159 + trck_init.write(str.encode("Y"))
  160 +
  161 + trck_init.write(str.encode("P"))
  162 + data = trck_init.readlines()
  163 + if not data:
169 trck_init = None 164 trck_init = None
170 - print('Could not connect to Polhemus serial with error.') 165 + print('Could not connect to Polhemus serial without error.')
171 166
172 return trck_init 167 return trck_init
173 168
invesalius/data/viewer_volume.py
@@ -247,6 +247,7 @@ class Viewer(wx.Panel): @@ -247,6 +247,7 @@ class Viewer(wx.Panel):
247 Publisher.subscribe(self.RemoveMarker, 'Remove marker') 247 Publisher.subscribe(self.RemoveMarker, 'Remove marker')
248 Publisher.subscribe(self.BlinkMarker, 'Blink Marker') 248 Publisher.subscribe(self.BlinkMarker, 'Blink Marker')
249 Publisher.subscribe(self.StopBlinkMarker, 'Stop Blink Marker') 249 Publisher.subscribe(self.StopBlinkMarker, 'Stop Blink Marker')
  250 + Publisher.subscribe(self.SetNewColor, 'Set new color')
250 251
251 # Related to object tracking during neuronavigation 252 # Related to object tracking during neuronavigation
252 Publisher.subscribe(self.OnNavigationStatus, 'Navigation status') 253 Publisher.subscribe(self.OnNavigationStatus, 'Navigation status')
@@ -505,7 +506,7 @@ class Viewer(wx.Panel): @@ -505,7 +506,7 @@ class Viewer(wx.Panel):
505 mapper.SetInputConnection(ball_ref.GetOutputPort()) 506 mapper.SetInputConnection(ball_ref.GetOutputPort())
506 507
507 prop = vtk.vtkProperty() 508 prop = vtk.vtkProperty()
508 - prop.SetColor(colour) 509 + prop.SetColor(colour[0:3])
509 510
510 #adding a new actor for the present ball 511 #adding a new actor for the present ball
511 self.staticballs.append(vtk.vtkActor()) 512 self.staticballs.append(vtk.vtkActor())
@@ -567,6 +568,11 @@ class Viewer(wx.Panel): @@ -567,6 +568,11 @@ class Viewer(wx.Panel):
567 self.Refresh() 568 self.Refresh()
568 self.index = False 569 self.index = False
569 570
  571 + def SetNewColor(self, index, color):
  572 + self.staticballs[index].GetProperty().SetColor(color)
  573 + self.Refresh()
  574 +
  575 +
570 def OnTargetMarkerTransparency(self, status, index): 576 def OnTargetMarkerTransparency(self, status, index):
571 if status: 577 if status:
572 self.staticballs[index].GetProperty().SetOpacity(1) 578 self.staticballs[index].GetProperty().SetOpacity(1)
@@ -791,6 +797,10 @@ class Viewer(wx.Panel): @@ -791,6 +797,10 @@ class Viewer(wx.Panel):
791 for ind in self.arrow_actor_list: 797 for ind in self.arrow_actor_list:
792 self.ren2.AddActor(ind) 798 self.ren2.AddActor(ind)
793 799
  800 +
  801 + x, y, z = bases.flip_x(coord[0:3])
  802 + self.tactor.SetPosition(x-20, y-30, z+20)
  803 +
794 self.Refresh() 804 self.Refresh()
795 805
796 def OnUpdateTargetCoordinates(self, coord): 806 def OnUpdateTargetCoordinates(self, coord):
@@ -817,7 +827,7 @@ class Viewer(wx.Panel): @@ -817,7 +827,7 @@ class Viewer(wx.Panel):
817 tactor.SetMapper(mapper) 827 tactor.SetMapper(mapper)
818 tactor.GetProperty().SetColor(1.0, 0.25, 0.0) 828 tactor.GetProperty().SetColor(1.0, 0.25, 0.0)
819 tactor.SetScale(5) 829 tactor.SetScale(5)
820 - tactor.SetPosition(self.target_coord[0]+10, self.target_coord[1]+30, self.target_coord[2]+20) 830 + #tactor.SetPosition(self.target_coord[0]+10, self.target_coord[1]+30, self.target_coord[2]+20)
821 self.ren.AddActor(tactor) 831 self.ren.AddActor(tactor)
822 self.tactor = tactor 832 self.tactor = tactor
823 tactor.SetCamera(self.ren.GetActiveCamera()) 833 tactor.SetCamera(self.ren.GetActiveCamera())
@@ -892,7 +902,7 @@ class Viewer(wx.Panel): @@ -892,7 +902,7 @@ class Viewer(wx.Panel):
892 902
893 self.dummy_coil_actor = vtk.vtkActor() 903 self.dummy_coil_actor = vtk.vtkActor()
894 self.dummy_coil_actor.SetMapper(obj_mapper) 904 self.dummy_coil_actor.SetMapper(obj_mapper)
895 - self.dummy_coil_actor.GetProperty().SetOpacity(0.4) 905 + self.dummy_coil_actor.GetProperty().SetOpacity(0.15)
896 self.dummy_coil_actor.SetVisibility(1) 906 self.dummy_coil_actor.SetVisibility(1)
897 self.dummy_coil_actor.SetUserMatrix(m_img_vtk) 907 self.dummy_coil_actor.SetUserMatrix(m_img_vtk)
898 908
@@ -1745,7 +1755,7 @@ class SlicePlane: @@ -1745,7 +1755,7 @@ class SlicePlane:
1745 plane_x.SetRightButtonAction(0) 1755 plane_x.SetRightButtonAction(0)
1746 plane_x.SetMiddleButtonAction(0) 1756 plane_x.SetMiddleButtonAction(0)
1747 cursor_property = plane_x.GetCursorProperty() 1757 cursor_property = plane_x.GetCursorProperty()
1748 - cursor_property.SetOpacity(0) 1758 + cursor_property.SetOpacity(0)
1749 1759
1750 plane_y = self.plane_y = vtk.vtkImagePlaneWidget() 1760 plane_y = self.plane_y = vtk.vtkImagePlaneWidget()
1751 plane_y.DisplayTextOff() 1761 plane_y.DisplayTextOff()
invesalius/gui/default_tasks.py
@@ -346,6 +346,7 @@ class UpperTaskPanel(wx.Panel): @@ -346,6 +346,7 @@ class UpperTaskPanel(wx.Panel):
346 self.fold_panel.GetFoldPanel(4).Show() 346 self.fold_panel.GetFoldPanel(4).Show()
347 347
348 else: 348 else:
  349 + Publisher.sendMessage('Deactive target button')
349 self.fold_panel.GetFoldPanel(4).Hide() 350 self.fold_panel.GetFoldPanel(4).Hide()
350 self.sizer.Layout() 351 self.sizer.Layout()
351 352
invesalius/gui/default_viewers.py
@@ -34,6 +34,8 @@ from invesalius.gui.widgets.clut_raycasting import CLUTRaycastingWidget, \ @@ -34,6 +34,8 @@ from invesalius.gui.widgets.clut_raycasting import CLUTRaycastingWidget, \
34 EVT_CLUT_CURVE_WL_CHANGE 34 EVT_CLUT_CURVE_WL_CHANGE
35 35
36 from invesalius.constants import ID_TO_BMP 36 from invesalius.constants import ID_TO_BMP
  37 +
  38 +import invesalius.session as ses
37 import invesalius.constants as const 39 import invesalius.constants as const
38 40
39 class Panel(wx.Panel): 41 class Panel(wx.Panel):
@@ -121,6 +123,9 @@ class Panel(wx.Panel): @@ -121,6 +123,9 @@ class Panel(wx.Panel):
121 123
122 self.aui_manager.Update() 124 self.aui_manager.Update()
123 125
  126 + if int(ses.Session().mode) != const.MODE_NAVIGATOR:
  127 + Publisher.sendMessage('Deactive target button')
  128 +
124 def __bind_events_wx(self): 129 def __bind_events_wx(self):
125 self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_MAXIMIZE, self.OnMaximize) 130 self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_MAXIMIZE, self.OnMaximize)
126 self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_RESTORE, self.OnRestore) 131 self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_RESTORE, self.OnRestore)
@@ -313,8 +318,6 @@ import wx.lib.buttons as btn @@ -313,8 +318,6 @@ import wx.lib.buttons as btn
313 import wx.lib.pubsub as ps 318 import wx.lib.pubsub as ps
314 import wx.lib.colourselect as csel 319 import wx.lib.colourselect as csel
315 320
316 -import invesalius.constants as const  
317 -  
318 [BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE, BUTTON_3D_STEREO, BUTTON_TARGET] = [wx.NewId() for num in range(5)] 321 [BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE, BUTTON_3D_STEREO, BUTTON_TARGET] = [wx.NewId() for num in range(5)]
319 RAYCASTING_TOOLS = wx.NewId() 322 RAYCASTING_TOOLS = wx.NewId()
320 323
@@ -431,6 +434,8 @@ class VolumeToolPanel(wx.Panel): @@ -431,6 +434,8 @@ class VolumeToolPanel(wx.Panel):
431 Publisher.subscribe(self.DisableVolumeCutMenu, 'Disable volume cut menu') 434 Publisher.subscribe(self.DisableVolumeCutMenu, 'Disable volume cut menu')
432 Publisher.subscribe(self.StatusTargetSelect, 'Disable or enable coil tracker') 435 Publisher.subscribe(self.StatusTargetSelect, 'Disable or enable coil tracker')
433 Publisher.subscribe(self.StatusObjTracker, 'Status target button') 436 Publisher.subscribe(self.StatusObjTracker, 'Status target button')
  437 + Publisher.subscribe(self.ActiveTarget, 'Active target button')
  438 + Publisher.subscribe(self.DeactiveTarget, 'Deactive target button')
434 439
435 def DisablePreset(self): 440 def DisablePreset(self):
436 self.off_item.Check(1) 441 self.off_item.Check(1)
@@ -465,6 +470,12 @@ class VolumeToolPanel(wx.Panel): @@ -465,6 +470,12 @@ class VolumeToolPanel(wx.Panel):
465 self.status_target_select = status 470 self.status_target_select = status
466 self.StatusNavigation() 471 self.StatusNavigation()
467 472
  473 + def ActiveTarget(self):
  474 + self.button_target.Show()
  475 +
  476 + def DeactiveTarget(self):
  477 + self.button_target.Hide()
  478 +
468 def StatusNavigation(self): 479 def StatusNavigation(self):
469 if self.status_target_select and self.status_obj_tracker: 480 if self.status_target_select and self.status_obj_tracker:
470 self.button_target.Enable(1) 481 self.button_target.Enable(1)
@@ -622,7 +633,7 @@ class VolumeToolPanel(wx.Panel): @@ -622,7 +633,7 @@ class VolumeToolPanel(wx.Panel):
622 preset_name=ID_TO_NAME[id]) 633 preset_name=ID_TO_NAME[id])
623 # Enable or disable tools 634 # Enable or disable tools
624 if name != const.RAYCASTING_OFF_LABEL: 635 if name != const.RAYCASTING_OFF_LABEL:
625 - self.menu_raycasting.Enable(RAYCASTING_TOOLS, 1) 636 + self.menu_raycasting.Enable(RAYCASTING_TOOLS, 1)
626 else: 637 else:
627 self.menu_raycasting.Enable(RAYCASTING_TOOLS, 0) 638 self.menu_raycasting.Enable(RAYCASTING_TOOLS, 0)
628 639
invesalius/gui/frame.py
@@ -107,6 +107,7 @@ class Frame(wx.Frame): @@ -107,6 +107,7 @@ class Frame(wx.Frame):
107 107
108 self.actived_interpolated_slices = main_menu.view_menu 108 self.actived_interpolated_slices = main_menu.view_menu
109 self.actived_navigation_mode = main_menu.mode_menu 109 self.actived_navigation_mode = main_menu.mode_menu
  110 + self.actived_dbs_mode = main_menu.mode_dbs
110 111
111 # Set menus, status and task bar 112 # Set menus, status and task bar
112 self.SetMenuBar(main_menu) 113 self.SetMenuBar(main_menu)
@@ -490,10 +491,17 @@ class Frame(wx.Frame): @@ -490,10 +491,17 @@ class Frame(wx.Frame):
490 else: 491 else:
491 self.OnInterpolatedSlices(False) 492 self.OnInterpolatedSlices(False)
492 493
  494 +
493 elif id == const.ID_MODE_NAVIGATION: 495 elif id == const.ID_MODE_NAVIGATION:
  496 + Publisher.sendMessage('Deactive dbs folder')
  497 + Publisher.sendMessage('Active target button')
  498 + self.actived_dbs_mode.Check(0)
494 st = self.actived_navigation_mode.IsChecked(const.ID_MODE_NAVIGATION) 499 st = self.actived_navigation_mode.IsChecked(const.ID_MODE_NAVIGATION)
495 self.OnNavigationMode(st) 500 self.OnNavigationMode(st)
496 501
  502 + elif id == const.ID_MODE_DBS:
  503 + self.OnDbsMode()
  504 +
497 elif id == const.ID_CROP_MASK: 505 elif id == const.ID_CROP_MASK:
498 self.OnCropMask() 506 self.OnCropMask()
499 507
@@ -503,6 +511,17 @@ class Frame(wx.Frame): @@ -503,6 +511,17 @@ class Frame(wx.Frame):
503 elif id == const.ID_CREATE_MASK: 511 elif id == const.ID_CREATE_MASK:
504 Publisher.sendMessage('New mask from shortcut') 512 Publisher.sendMessage('New mask from shortcut')
505 513
  514 + def OnDbsMode(self):
  515 + st = self.actived_dbs_mode.IsChecked()
  516 + Publisher.sendMessage('Deactive target button')
  517 + if st:
  518 + self.OnNavigationMode(st)
  519 + Publisher.sendMessage('Active dbs folder')
  520 + else:
  521 + self.OnNavigationMode(st)
  522 + Publisher.sendMessage('Deactive dbs folder')
  523 + self.actived_navigation_mode.Check(const.ID_MODE_NAVIGATION,0)
  524 +
506 def OnInterpolatedSlices(self, status): 525 def OnInterpolatedSlices(self, status):
507 Publisher.sendMessage('Set interpolated slices', flag=status) 526 Publisher.sendMessage('Set interpolated slices', flag=status)
508 527
@@ -907,7 +926,12 @@ class MenuBar(wx.MenuBar): @@ -907,7 +926,12 @@ class MenuBar(wx.MenuBar):
907 926
908 #Mode 927 #Mode
909 self.mode_menu = mode_menu = wx.Menu() 928 self.mode_menu = mode_menu = wx.Menu()
910 - mode_menu.Append(const.ID_MODE_NAVIGATION, _(u'Navigation mode'), "", wx.ITEM_CHECK) 929 + nav_menu = wx.Menu()
  930 + nav_menu.Append(const.ID_MODE_NAVIGATION, _(u'Transcranial Magnetic Stimulation Mode\tCtrl+T'), "", wx.ITEM_CHECK)
  931 + #Under development
  932 + self.mode_dbs = nav_menu.Append(const.ID_MODE_DBS, _(u'Deep Brain Stimulation Mode\tCtrl+B'), "", wx.ITEM_CHECK)
  933 + self.mode_dbs.Enable(0)
  934 + mode_menu.Append(-1,_('Navigation Mode'),nav_menu)
911 935
912 v = self.NavigationModeStatus() 936 v = self.NavigationModeStatus()
913 self.mode_menu.Check(const.ID_MODE_NAVIGATION, v) 937 self.mode_menu.Check(const.ID_MODE_NAVIGATION, v)
@@ -950,7 +974,6 @@ class MenuBar(wx.MenuBar): @@ -950,7 +974,6 @@ class MenuBar(wx.MenuBar):
950 974
951 def NavigationModeStatus(self): 975 def NavigationModeStatus(self):
952 status = int(ses.Session().mode) 976 status = int(ses.Session().mode)
953 -  
954 if status == 1: 977 if status == 1:
955 return True 978 return True
956 else: 979 else:
invesalius/gui/task_navigator.py
@@ -172,6 +172,15 @@ class InnerFoldPanel(wx.Panel): @@ -172,6 +172,15 @@ class InnerFoldPanel(wx.Panel):
172 fold_panel.AddFoldPanelWindow(item, mtw, spacing= 0, 172 fold_panel.AddFoldPanelWindow(item, mtw, spacing= 0,
173 leftSpacing=0, rightSpacing=0) 173 leftSpacing=0, rightSpacing=0)
174 174
  175 + # Fold 4 - DBS
  176 +
  177 + self.dbs_item = fold_panel.AddFoldPanel(_("Deep Brain Stimulation"), collapsed=True)
  178 + dtw = DbsPanel(self.dbs_item) #Atribuir nova var, criar panel
  179 +
  180 + fold_panel.ApplyCaptionStyle(self.dbs_item, style)
  181 + fold_panel.AddFoldPanelWindow(self.dbs_item, dtw, spacing= 0,
  182 + leftSpacing=0, rightSpacing=0)
  183 + self.dbs_item.Hide()
175 184
176 # Check box for camera update in volume rendering during navigation 185 # Check box for camera update in volume rendering during navigation
177 tooltip = wx.ToolTip(_("Update camera in volume")) 186 tooltip = wx.ToolTip(_("Update camera in volume"))
@@ -220,11 +229,21 @@ class InnerFoldPanel(wx.Panel): @@ -220,11 +229,21 @@ class InnerFoldPanel(wx.Panel):
220 self.SetSizer(sizer) 229 self.SetSizer(sizer)
221 self.Update() 230 self.Update()
222 self.SetAutoLayout(1) 231 self.SetAutoLayout(1)
223 - 232 +
224 def __bind_events(self): 233 def __bind_events(self):
225 Publisher.subscribe(self.OnCheckStatus, 'Navigation status') 234 Publisher.subscribe(self.OnCheckStatus, 'Navigation status')
226 Publisher.subscribe(self.OnShowObject, 'Update track object state') 235 Publisher.subscribe(self.OnShowObject, 'Update track object state')
227 Publisher.subscribe(self.OnVolumeCamera, 'Target navigation mode') 236 Publisher.subscribe(self.OnVolumeCamera, 'Target navigation mode')
  237 + Publisher.subscribe(self.OnShowDbs, "Active dbs folder")
  238 + Publisher.subscribe(self.OnHideDbs, "Deactive dbs folder")
  239 +
  240 + def OnShowDbs(self):
  241 + self.dbs_item.Show()
  242 +
  243 +
  244 + def OnHideDbs(self):
  245 + self.dbs_item.Hide()
  246 +
228 247
229 def OnCheckStatus(self, status): 248 def OnCheckStatus(self, status):
230 if status: 249 if status:
@@ -258,7 +277,6 @@ class InnerFoldPanel(wx.Panel): @@ -258,7 +277,6 @@ class InnerFoldPanel(wx.Panel):
258 self.checkcamera.SetValue(0) 277 self.checkcamera.SetValue(0)
259 Publisher.sendMessage('Update volume camera state', camera_state=self.checkcamera.GetValue()) 278 Publisher.sendMessage('Update volume camera state', camera_state=self.checkcamera.GetValue())
260 279
261 -  
262 class NeuronavigationPanel(wx.Panel): 280 class NeuronavigationPanel(wx.Panel):
263 def __init__(self, parent): 281 def __init__(self, parent):
264 wx.Panel.__init__(self, parent) 282 wx.Panel.__init__(self, parent)
@@ -1078,8 +1096,12 @@ class MarkersPanel(wx.Panel): @@ -1078,8 +1096,12 @@ class MarkersPanel(wx.Panel):
1078 menu_id = wx.Menu() 1096 menu_id = wx.Menu()
1079 edit_id = menu_id.Append(0, _('Edit ID')) 1097 edit_id = menu_id.Append(0, _('Edit ID'))
1080 menu_id.Bind(wx.EVT_MENU, self.OnMenuEditMarkerId, edit_id) 1098 menu_id.Bind(wx.EVT_MENU, self.OnMenuEditMarkerId, edit_id)
  1099 + color_id = menu_id.Append(2, _('Edit color'))
  1100 + menu_id.Bind(wx.EVT_MENU, self.OnMenuSetColor, color_id)
  1101 + menu_id.AppendSeparator()
1081 target_menu = menu_id.Append(1, _('Set as target')) 1102 target_menu = menu_id.Append(1, _('Set as target'))
1082 menu_id.Bind(wx.EVT_MENU, self.OnMenuSetTarget, target_menu) 1103 menu_id.Bind(wx.EVT_MENU, self.OnMenuSetTarget, target_menu)
  1104 +
1083 target_menu.Enable(status) 1105 target_menu.Enable(status)
1084 self.PopupMenu(menu_id) 1106 self.PopupMenu(menu_id)
1085 menu_id.Destroy() 1107 menu_id.Destroy()
@@ -1130,6 +1152,26 @@ class MarkersPanel(wx.Panel): @@ -1130,6 +1152,26 @@ class MarkersPanel(wx.Panel):
1130 self.tgt_flag = True 1152 self.tgt_flag = True
1131 dlg.NewTarget() 1153 dlg.NewTarget()
1132 1154
  1155 + def OnMenuSetColor(self, evt):
  1156 + index = self.lc.GetFocusedItem()
  1157 + cdata = wx.ColourData()
  1158 + cdata.SetColour(wx.Colour(self.list_coord[index][6]*255,self.list_coord[index][7]*255,self.list_coord[index][8]*255))
  1159 + dlg = wx.ColourDialog(self, data=cdata)
  1160 + dlg.GetColourData().SetChooseFull(True)
  1161 + if dlg.ShowModal() == wx.ID_OK:
  1162 + self.r, self.g, self.b = dlg.GetColourData().GetColour().Get(includeAlpha=False)
  1163 + r = float(self.r) / 255.0
  1164 + g = float(self.g) / 255.0
  1165 + b = float(self.b) / 255.0
  1166 + dlg.Destroy()
  1167 + color = [r,g,b]
  1168 +
  1169 + Publisher.sendMessage('Set new color', index=index, color=color)
  1170 +
  1171 + self.list_coord[index][6] = r
  1172 + self.list_coord[index][7] = g
  1173 + self.list_coord[index][8] = b
  1174 +
1133 def OnDeleteAllMarkers(self, evt=None): 1175 def OnDeleteAllMarkers(self, evt=None):
1134 if self.list_coord: 1176 if self.list_coord:
1135 if evt is None: 1177 if evt is None:
@@ -1316,3 +1358,12 @@ class MarkersPanel(wx.Panel): @@ -1316,3 +1358,12 @@ class MarkersPanel(wx.Panel):
1316 index = self.lc.GetNextSelected(index) 1358 index = self.lc.GetNextSelected(index)
1317 selection.append(index) 1359 selection.append(index)
1318 return selection 1360 return selection
  1361 +
  1362 +class DbsPanel(wx.Panel):
  1363 + def __init__(self, parent):
  1364 + wx.Panel.__init__(self, parent)
  1365 + try:
  1366 + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR)
  1367 + except AttributeError:
  1368 + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
  1369 +