diff --git a/invesalius/constants.py b/invesalius/constants.py index fe7455f..98fddbf 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -505,11 +505,12 @@ VTK_WARNING = 0 #---------------------------------------------------------- +ID_MODE_NAVIGATION: object [ID_DICOM_IMPORT, ID_PROJECT_OPEN, ID_PROJECT_SAVE_AS, ID_PROJECT_SAVE, ID_PROJECT_CLOSE, ID_PROJECT_INFO, ID_SAVE_SCREENSHOT, ID_DICOM_LOAD_NET, ID_PRINT_SCREENSHOT, ID_IMPORT_OTHERS_FILES, ID_PREFERENCES, ID_DICOM_NETWORK, ID_TIFF_JPG_PNG, ID_VIEW_INTERPOLATED, ID_MODE_NAVIGATION, ID_ANALYZE_IMPORT, -ID_NIFTI_IMPORT, ID_PARREC_IMPORT] = [wx.NewId() for number in range(18)] +ID_NIFTI_IMPORT, ID_PARREC_IMPORT, ID_MODE_DBS] = [wx.NewId() for number in range(19)] ID_EXIT = wx.ID_EXIT ID_ABOUT = wx.ID_ABOUT diff --git a/invesalius/data/coordinates.py b/invesalius/data/coordinates.py index 8de78ba..7bc762a 100644 --- a/invesalius/data/coordinates.py +++ b/invesalius/data/coordinates.py @@ -174,33 +174,31 @@ def PolhemusSerialCoord(trck_init, trck_id, ref_mode): # aoflt -> 0:letter 1:x 2:y 3:z # this method is not optimized to work with all trackers, only with ISOTRAK # serial connection is obsolete, remove in future - trck_init.write("P") + trck_init.write(str.encode("P")) + scale = 10. * np.array([1., 1.0, 1.0]) lines = trck_init.readlines() - coord = None - - if lines[0][0] != '0': + if lines is None: print("The Polhemus is not connected!") else: - for s in lines: - if s[1] == '1': - data = s - elif s[1] == '2': - data = s - - # single ref mode - if not ref_mode: - data = data.replace('-', ' -') - data = [s for s in data.split()] - j = 0 - while j == 0: - try: - plh1 = [float(s) for s in data[1:len(data)]] - j = 1 - except: - print("error!!") - - coord = data[0:6] + data = lines[0] + data = data.replace(str.encode('-'), str.encode(' -')) + data = [s for s in data.split()] + data = [float(s) for s in data[1:len(data)]] + probe = np.array([data[0] * scale[0], data[1] * scale[1], data[2] * scale[2], data[3], data[4], data[5]]) + + if ref_mode: + data2 = lines[1] + data2 = data2.replace(str.encode('-'), str.encode(' -')) + data2 = [s for s in data2.split()] + data2 = [float(s) for s in data2[1:len(data2)]] + reference = np.array( + [data2[0] * scale[0], data2[1] * scale[1], data2[2] * scale[2], data2[3], data2[4], data2[5]]) + else: + reference = np.zeros(6) + + coord = np.vstack([probe, reference]) + return coord diff --git a/invesalius/data/trackers.py b/invesalius/data/trackers.py index 5d355e5..191093d 100644 --- a/invesalius/data/trackers.py +++ b/invesalius/data/trackers.py @@ -143,31 +143,26 @@ def PlhWrapperConnection(tracker_id): def PlhSerialConnection(tracker_id): - try: - import serial - - trck_init = serial.Serial('COM1', baudrate=115200, timeout=0.2) - - if tracker_id == 2: - # Polhemus FASTRAK needs configurations first - trck_init.write(0x02, "u") - trck_init.write(0x02, "F") - elif tracker_id == 3: - # Polhemus ISOTRAK needs to set tracking point from - # center to tip. - trck_init.write("F") - trck_init.write("Y") - - trck_init.write('P') - data = trck_init.readlines() - - if not data: - trck_init = None - print('Could not connect to Polhemus serial without error.') - - except: + import serial + + trck_init = serial.Serial('COM1', baudrate=115200, timeout=0.03) + + if tracker_id == 2: + # Polhemus FASTRAK needs configurations first + trck_init.write(0x02, str.encode("u")) + trck_init.write(0x02, str.encode("F")) + elif tracker_id == 3: + # Polhemus ISOTRAK needs to set tracking point from + # center to tip. + trck_init.write(str.encode("u")) + trck_init.write(str.encode("F")) + trck_init.write(str.encode("Y")) + + trck_init.write(str.encode("P")) + data = trck_init.readlines() + if not data: trck_init = None - print('Could not connect to Polhemus serial with error.') + print('Could not connect to Polhemus serial without error.') return trck_init diff --git a/invesalius/data/viewer_volume.py b/invesalius/data/viewer_volume.py index 233e2b1..53ef78a 100644 --- a/invesalius/data/viewer_volume.py +++ b/invesalius/data/viewer_volume.py @@ -247,6 +247,7 @@ class Viewer(wx.Panel): Publisher.subscribe(self.RemoveMarker, 'Remove marker') Publisher.subscribe(self.BlinkMarker, 'Blink Marker') Publisher.subscribe(self.StopBlinkMarker, 'Stop Blink Marker') + Publisher.subscribe(self.SetNewColor, 'Set new color') # Related to object tracking during neuronavigation Publisher.subscribe(self.OnNavigationStatus, 'Navigation status') @@ -505,7 +506,7 @@ class Viewer(wx.Panel): mapper.SetInputConnection(ball_ref.GetOutputPort()) prop = vtk.vtkProperty() - prop.SetColor(colour) + prop.SetColor(colour[0:3]) #adding a new actor for the present ball self.staticballs.append(vtk.vtkActor()) @@ -567,6 +568,11 @@ class Viewer(wx.Panel): self.Refresh() self.index = False + def SetNewColor(self, index, color): + self.staticballs[index].GetProperty().SetColor(color) + self.Refresh() + + def OnTargetMarkerTransparency(self, status, index): if status: self.staticballs[index].GetProperty().SetOpacity(1) @@ -791,6 +797,10 @@ class Viewer(wx.Panel): for ind in self.arrow_actor_list: self.ren2.AddActor(ind) + + x, y, z = bases.flip_x(coord[0:3]) + self.tactor.SetPosition(x-20, y-30, z+20) + self.Refresh() def OnUpdateTargetCoordinates(self, coord): @@ -817,7 +827,7 @@ class Viewer(wx.Panel): tactor.SetMapper(mapper) tactor.GetProperty().SetColor(1.0, 0.25, 0.0) tactor.SetScale(5) - tactor.SetPosition(self.target_coord[0]+10, self.target_coord[1]+30, self.target_coord[2]+20) + #tactor.SetPosition(self.target_coord[0]+10, self.target_coord[1]+30, self.target_coord[2]+20) self.ren.AddActor(tactor) self.tactor = tactor tactor.SetCamera(self.ren.GetActiveCamera()) @@ -892,7 +902,7 @@ class Viewer(wx.Panel): self.dummy_coil_actor = vtk.vtkActor() self.dummy_coil_actor.SetMapper(obj_mapper) - self.dummy_coil_actor.GetProperty().SetOpacity(0.4) + self.dummy_coil_actor.GetProperty().SetOpacity(0.15) self.dummy_coil_actor.SetVisibility(1) self.dummy_coil_actor.SetUserMatrix(m_img_vtk) @@ -1745,7 +1755,7 @@ class SlicePlane: plane_x.SetRightButtonAction(0) plane_x.SetMiddleButtonAction(0) cursor_property = plane_x.GetCursorProperty() - cursor_property.SetOpacity(0) + cursor_property.SetOpacity(0) plane_y = self.plane_y = vtk.vtkImagePlaneWidget() plane_y.DisplayTextOff() diff --git a/invesalius/gui/default_tasks.py b/invesalius/gui/default_tasks.py index 000a063..788568d 100644 --- a/invesalius/gui/default_tasks.py +++ b/invesalius/gui/default_tasks.py @@ -346,6 +346,7 @@ class UpperTaskPanel(wx.Panel): self.fold_panel.GetFoldPanel(4).Show() else: + Publisher.sendMessage('Deactive target button') self.fold_panel.GetFoldPanel(4).Hide() self.sizer.Layout() diff --git a/invesalius/gui/default_viewers.py b/invesalius/gui/default_viewers.py index 27f4611..68605cb 100644 --- a/invesalius/gui/default_viewers.py +++ b/invesalius/gui/default_viewers.py @@ -34,6 +34,8 @@ from invesalius.gui.widgets.clut_raycasting import CLUTRaycastingWidget, \ EVT_CLUT_CURVE_WL_CHANGE from invesalius.constants import ID_TO_BMP + +import invesalius.session as ses import invesalius.constants as const class Panel(wx.Panel): @@ -121,6 +123,9 @@ class Panel(wx.Panel): self.aui_manager.Update() + if int(ses.Session().mode) != const.MODE_NAVIGATOR: + Publisher.sendMessage('Deactive target button') + def __bind_events_wx(self): self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_MAXIMIZE, self.OnMaximize) self.aui_manager.Bind(wx.aui.EVT_AUI_PANE_RESTORE, self.OnRestore) @@ -313,8 +318,6 @@ import wx.lib.buttons as btn import wx.lib.pubsub as ps import wx.lib.colourselect as csel -import invesalius.constants as const - [BUTTON_RAYCASTING, BUTTON_VIEW, BUTTON_SLICE_PLANE, BUTTON_3D_STEREO, BUTTON_TARGET] = [wx.NewId() for num in range(5)] RAYCASTING_TOOLS = wx.NewId() @@ -431,6 +434,8 @@ class VolumeToolPanel(wx.Panel): Publisher.subscribe(self.DisableVolumeCutMenu, 'Disable volume cut menu') Publisher.subscribe(self.StatusTargetSelect, 'Disable or enable coil tracker') Publisher.subscribe(self.StatusObjTracker, 'Status target button') + Publisher.subscribe(self.ActiveTarget, 'Active target button') + Publisher.subscribe(self.DeactiveTarget, 'Deactive target button') def DisablePreset(self): self.off_item.Check(1) @@ -465,6 +470,12 @@ class VolumeToolPanel(wx.Panel): self.status_target_select = status self.StatusNavigation() + def ActiveTarget(self): + self.button_target.Show() + + def DeactiveTarget(self): + self.button_target.Hide() + def StatusNavigation(self): if self.status_target_select and self.status_obj_tracker: self.button_target.Enable(1) @@ -622,7 +633,7 @@ class VolumeToolPanel(wx.Panel): preset_name=ID_TO_NAME[id]) # Enable or disable tools if name != const.RAYCASTING_OFF_LABEL: - self.menu_raycasting.Enable(RAYCASTING_TOOLS, 1) + self.menu_raycasting.Enable(RAYCASTING_TOOLS, 1) else: self.menu_raycasting.Enable(RAYCASTING_TOOLS, 0) diff --git a/invesalius/gui/frame.py b/invesalius/gui/frame.py index dbe7852..d6047c3 100644 --- a/invesalius/gui/frame.py +++ b/invesalius/gui/frame.py @@ -107,6 +107,7 @@ class Frame(wx.Frame): self.actived_interpolated_slices = main_menu.view_menu self.actived_navigation_mode = main_menu.mode_menu + self.actived_dbs_mode = main_menu.mode_dbs # Set menus, status and task bar self.SetMenuBar(main_menu) @@ -490,10 +491,17 @@ class Frame(wx.Frame): else: self.OnInterpolatedSlices(False) + elif id == const.ID_MODE_NAVIGATION: + Publisher.sendMessage('Deactive dbs folder') + Publisher.sendMessage('Active target button') + self.actived_dbs_mode.Check(0) st = self.actived_navigation_mode.IsChecked(const.ID_MODE_NAVIGATION) self.OnNavigationMode(st) + elif id == const.ID_MODE_DBS: + self.OnDbsMode() + elif id == const.ID_CROP_MASK: self.OnCropMask() @@ -503,6 +511,17 @@ class Frame(wx.Frame): elif id == const.ID_CREATE_MASK: Publisher.sendMessage('New mask from shortcut') + def OnDbsMode(self): + st = self.actived_dbs_mode.IsChecked() + Publisher.sendMessage('Deactive target button') + if st: + self.OnNavigationMode(st) + Publisher.sendMessage('Active dbs folder') + else: + self.OnNavigationMode(st) + Publisher.sendMessage('Deactive dbs folder') + self.actived_navigation_mode.Check(const.ID_MODE_NAVIGATION,0) + def OnInterpolatedSlices(self, status): Publisher.sendMessage('Set interpolated slices', flag=status) @@ -907,7 +926,12 @@ class MenuBar(wx.MenuBar): #Mode self.mode_menu = mode_menu = wx.Menu() - mode_menu.Append(const.ID_MODE_NAVIGATION, _(u'Navigation mode'), "", wx.ITEM_CHECK) + nav_menu = wx.Menu() + nav_menu.Append(const.ID_MODE_NAVIGATION, _(u'Transcranial Magnetic Stimulation Mode\tCtrl+T'), "", wx.ITEM_CHECK) + #Under development + self.mode_dbs = nav_menu.Append(const.ID_MODE_DBS, _(u'Deep Brain Stimulation Mode\tCtrl+B'), "", wx.ITEM_CHECK) + self.mode_dbs.Enable(0) + mode_menu.Append(-1,_('Navigation Mode'),nav_menu) v = self.NavigationModeStatus() self.mode_menu.Check(const.ID_MODE_NAVIGATION, v) @@ -950,7 +974,6 @@ class MenuBar(wx.MenuBar): def NavigationModeStatus(self): status = int(ses.Session().mode) - if status == 1: return True else: diff --git a/invesalius/gui/task_navigator.py b/invesalius/gui/task_navigator.py index dea81d7..f89485b 100644 --- a/invesalius/gui/task_navigator.py +++ b/invesalius/gui/task_navigator.py @@ -172,6 +172,15 @@ class InnerFoldPanel(wx.Panel): fold_panel.AddFoldPanelWindow(item, mtw, spacing= 0, leftSpacing=0, rightSpacing=0) + # Fold 4 - DBS + + self.dbs_item = fold_panel.AddFoldPanel(_("Deep Brain Stimulation"), collapsed=True) + dtw = DbsPanel(self.dbs_item) #Atribuir nova var, criar panel + + fold_panel.ApplyCaptionStyle(self.dbs_item, style) + fold_panel.AddFoldPanelWindow(self.dbs_item, dtw, spacing= 0, + leftSpacing=0, rightSpacing=0) + self.dbs_item.Hide() # Check box for camera update in volume rendering during navigation tooltip = wx.ToolTip(_("Update camera in volume")) @@ -220,11 +229,21 @@ class InnerFoldPanel(wx.Panel): self.SetSizer(sizer) self.Update() self.SetAutoLayout(1) - + def __bind_events(self): Publisher.subscribe(self.OnCheckStatus, 'Navigation status') Publisher.subscribe(self.OnShowObject, 'Update track object state') Publisher.subscribe(self.OnVolumeCamera, 'Target navigation mode') + Publisher.subscribe(self.OnShowDbs, "Active dbs folder") + Publisher.subscribe(self.OnHideDbs, "Deactive dbs folder") + + def OnShowDbs(self): + self.dbs_item.Show() + + + def OnHideDbs(self): + self.dbs_item.Hide() + def OnCheckStatus(self, status): if status: @@ -258,7 +277,6 @@ class InnerFoldPanel(wx.Panel): self.checkcamera.SetValue(0) Publisher.sendMessage('Update volume camera state', camera_state=self.checkcamera.GetValue()) - class NeuronavigationPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) @@ -1078,8 +1096,12 @@ class MarkersPanel(wx.Panel): menu_id = wx.Menu() edit_id = menu_id.Append(0, _('Edit ID')) menu_id.Bind(wx.EVT_MENU, self.OnMenuEditMarkerId, edit_id) + color_id = menu_id.Append(2, _('Edit color')) + menu_id.Bind(wx.EVT_MENU, self.OnMenuSetColor, color_id) + menu_id.AppendSeparator() target_menu = menu_id.Append(1, _('Set as target')) menu_id.Bind(wx.EVT_MENU, self.OnMenuSetTarget, target_menu) + target_menu.Enable(status) self.PopupMenu(menu_id) menu_id.Destroy() @@ -1130,6 +1152,26 @@ class MarkersPanel(wx.Panel): self.tgt_flag = True dlg.NewTarget() + def OnMenuSetColor(self, evt): + index = self.lc.GetFocusedItem() + cdata = wx.ColourData() + cdata.SetColour(wx.Colour(self.list_coord[index][6]*255,self.list_coord[index][7]*255,self.list_coord[index][8]*255)) + dlg = wx.ColourDialog(self, data=cdata) + dlg.GetColourData().SetChooseFull(True) + if dlg.ShowModal() == wx.ID_OK: + self.r, self.g, self.b = dlg.GetColourData().GetColour().Get(includeAlpha=False) + r = float(self.r) / 255.0 + g = float(self.g) / 255.0 + b = float(self.b) / 255.0 + dlg.Destroy() + color = [r,g,b] + + Publisher.sendMessage('Set new color', index=index, color=color) + + self.list_coord[index][6] = r + self.list_coord[index][7] = g + self.list_coord[index][8] = b + def OnDeleteAllMarkers(self, evt=None): if self.list_coord: if evt is None: @@ -1316,3 +1358,12 @@ class MarkersPanel(wx.Panel): index = self.lc.GetNextSelected(index) selection.append(index) return selection + +class DbsPanel(wx.Panel): + def __init__(self, parent): + wx.Panel.__init__(self, parent) + try: + default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) + except AttributeError: + default_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR) + -- libgit2 0.21.2