Commit a7c8e435747c14b78f0dcac6af9a02e69fcc1a3d
Committed by
Thiago Franco de Moraes
1 parent
5b5760de
Exists in
master
and in
6 other branches
Navigation improvement (#79)
* Added indicator to MTC sensors * Show sensors ID in viewer volume * fix * PLH stylus button * Dialog to confirm all markers delete * Fix remove sensors ID * Disable sensors ID when navigation mode is disabled
Showing
7 changed files
with
92 additions
and
9 deletions
Show diff stats
invesalius/data/coordinates.py
| @@ -22,7 +22,7 @@ import numpy as np | @@ -22,7 +22,7 @@ import numpy as np | ||
| 22 | 22 | ||
| 23 | from time import sleep | 23 | from time import sleep |
| 24 | from random import uniform | 24 | from random import uniform |
| 25 | - | 25 | +from wx.lib.pubsub import pub as Publisher |
| 26 | 26 | ||
| 27 | def GetCoordinates(trck_init, trck_id, ref_mode): | 27 | def GetCoordinates(trck_init, trck_id, ref_mode): |
| 28 | 28 | ||
| @@ -55,6 +55,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode): | @@ -55,6 +55,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode): | ||
| 55 | coord = None | 55 | coord = None |
| 56 | k = 0 | 56 | k = 0 |
| 57 | # TODO: try to replace while and use some Claron internal computation | 57 | # TODO: try to replace while and use some Claron internal computation |
| 58 | + | ||
| 58 | if ref_mode: | 59 | if ref_mode: |
| 59 | while k < 20: | 60 | while k < 20: |
| 60 | try: | 61 | try: |
| @@ -80,6 +81,8 @@ def ClaronCoord(trck_init, trck_id, ref_mode): | @@ -80,6 +81,8 @@ def ClaronCoord(trck_init, trck_id, ref_mode): | ||
| 80 | k += 1 | 81 | k += 1 |
| 81 | print "wait, collecting coordinates ..." | 82 | print "wait, collecting coordinates ..." |
| 82 | 83 | ||
| 84 | + Publisher.sendMessage('Sensors ID', [trck.probeID, trck.refID]) | ||
| 85 | + | ||
| 83 | return coord | 86 | return coord |
| 84 | 87 | ||
| 85 | 88 | ||
| @@ -123,6 +126,9 @@ def PolhemusWrapperCoord(trck, trck_id, ref_mode): | @@ -123,6 +126,9 @@ def PolhemusWrapperCoord(trck, trck_id, ref_mode): | ||
| 123 | float(trck.PositionTooltipZ1) * scale[2], float(trck.AngleX1), float(trck.AngleY1), | 126 | float(trck.PositionTooltipZ1) * scale[2], float(trck.AngleX1), float(trck.AngleY1), |
| 124 | float(trck.AngleZ1)]) | 127 | float(trck.AngleZ1)]) |
| 125 | 128 | ||
| 129 | + if trck.StylusButton: | ||
| 130 | + Publisher.sendMessage('PLH Stylus Button On') | ||
| 131 | + | ||
| 126 | return coord | 132 | return coord |
| 127 | 133 | ||
| 128 | 134 | ||
| @@ -221,6 +227,8 @@ def DebugCoord(trk_init, trck_id, ref_mode): | @@ -221,6 +227,8 @@ def DebugCoord(trk_init, trck_id, ref_mode): | ||
| 221 | coord = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200), | 227 | coord = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200), |
| 222 | uniform(1, 200), uniform(1, 200), uniform(1, 200)]) | 228 | uniform(1, 200), uniform(1, 200), uniform(1, 200)]) |
| 223 | 229 | ||
| 230 | + Publisher.sendMessage('Sensors ID', [int(uniform(0, 5)), int(uniform(0, 5))]) | ||
| 231 | + | ||
| 224 | return coord | 232 | return coord |
| 225 | 233 | ||
| 226 | 234 |
invesalius/data/trackers.py
| @@ -200,6 +200,7 @@ def DisconnectTracker(tracker_id): | @@ -200,6 +200,7 @@ def DisconnectTracker(tracker_id): | ||
| 200 | """ | 200 | """ |
| 201 | from wx.lib.pubsub import pub as Publisher | 201 | from wx.lib.pubsub import pub as Publisher |
| 202 | Publisher.sendMessage('Update status text in GUI', _("Disconnecting tracker ...")) | 202 | Publisher.sendMessage('Update status text in GUI', _("Disconnecting tracker ...")) |
| 203 | + Publisher.sendMessage('Remove sensors ID') | ||
| 203 | trck_init = None | 204 | trck_init = None |
| 204 | # TODO: create individual functions to disconnect each other device, e.g. Polhemus. | 205 | # TODO: create individual functions to disconnect each other device, e.g. Polhemus. |
| 205 | if tracker_id == 1: | 206 | if tracker_id == 1: |
invesalius/data/trigger.py
| @@ -47,12 +47,12 @@ class Trigger(threading.Thread): | @@ -47,12 +47,12 @@ class Trigger(threading.Thread): | ||
| 47 | print 'Connection with port COM1 failed.' | 47 | print 'Connection with port COM1 failed.' |
| 48 | 48 | ||
| 49 | def stop(self): | 49 | def stop(self): |
| 50 | - if self.trigger_init: | ||
| 51 | - self.trigger_init.close() | ||
| 52 | self._pause_ = True | 50 | self._pause_ = True |
| 53 | 51 | ||
| 54 | def run(self): | 52 | def run(self): |
| 55 | while self.nav_id: | 53 | while self.nav_id: |
| 54 | + self.trigger_init.write('0') | ||
| 55 | + sleep(0.3) | ||
| 56 | lines = self.trigger_init.readlines() | 56 | lines = self.trigger_init.readlines() |
| 57 | # Following lines can simulate a trigger in 3 sec repetitions | 57 | # Following lines can simulate a trigger in 3 sec repetitions |
| 58 | # sleep(3) | 58 | # sleep(3) |
| @@ -61,4 +61,6 @@ class Trigger(threading.Thread): | @@ -61,4 +61,6 @@ class Trigger(threading.Thread): | ||
| 61 | wx.CallAfter(Publisher.sendMessage, 'Create marker') | 61 | wx.CallAfter(Publisher.sendMessage, 'Create marker') |
| 62 | sleep(0.175) | 62 | sleep(0.175) |
| 63 | if self._pause_: | 63 | if self._pause_: |
| 64 | + if self.trigger_init: | ||
| 65 | + self.trigger_init.close() | ||
| 64 | return | 66 | return |
invesalius/data/viewer_volume.py
| @@ -120,6 +120,9 @@ class Viewer(wx.Panel): | @@ -120,6 +120,9 @@ class Viewer(wx.Panel): | ||
| 120 | self._to_show_ball = 0 | 120 | self._to_show_ball = 0 |
| 121 | self._ball_ref_visibility = False | 121 | self._ball_ref_visibility = False |
| 122 | 122 | ||
| 123 | + self.sen1 = False | ||
| 124 | + self.sen2 = False | ||
| 125 | + | ||
| 123 | def __bind_events(self): | 126 | def __bind_events(self): |
| 124 | Publisher.subscribe(self.LoadActor, | 127 | Publisher.subscribe(self.LoadActor, |
| 125 | 'Load surface actor into viewer') | 128 | 'Load surface actor into viewer') |
| @@ -191,6 +194,9 @@ class Viewer(wx.Panel): | @@ -191,6 +194,9 @@ class Viewer(wx.Panel): | ||
| 191 | Publisher.subscribe(self._check_ball_reference, 'Enable style') | 194 | Publisher.subscribe(self._check_ball_reference, 'Enable style') |
| 192 | Publisher.subscribe(self._uncheck_ball_reference, 'Disable style') | 195 | Publisher.subscribe(self._uncheck_ball_reference, 'Disable style') |
| 193 | 196 | ||
| 197 | + Publisher.subscribe(self.OnSensors, 'Sensors ID') | ||
| 198 | + Publisher.subscribe(self.OnRemoveSensorsID, 'Remove sensors ID') | ||
| 199 | + | ||
| 194 | # Related to marker creation in navigation tools | 200 | # Related to marker creation in navigation tools |
| 195 | Publisher.subscribe(self.AddMarker, 'Add marker') | 201 | Publisher.subscribe(self.AddMarker, 'Add marker') |
| 196 | Publisher.subscribe(self.HideAllMarkers, 'Hide all markers') | 202 | Publisher.subscribe(self.HideAllMarkers, 'Hide all markers') |
| @@ -241,6 +247,51 @@ class Viewer(wx.Panel): | @@ -241,6 +247,51 @@ class Viewer(wx.Panel): | ||
| 241 | self.RemoveBallReference() | 247 | self.RemoveBallReference() |
| 242 | self.interactor.Render() | 248 | self.interactor.Render() |
| 243 | 249 | ||
| 250 | + def OnSensors(self, pubsub_evt): | ||
| 251 | + probe_id = pubsub_evt.data[0] | ||
| 252 | + ref_id = pubsub_evt.data[1] | ||
| 253 | + if not self.sen1: | ||
| 254 | + self.CreateSensorID() | ||
| 255 | + | ||
| 256 | + if probe_id: | ||
| 257 | + colour1 = (0, 1, 0) | ||
| 258 | + else: | ||
| 259 | + colour1 = (1, 0, 0) | ||
| 260 | + if ref_id: | ||
| 261 | + colour2 = (0, 1, 0) | ||
| 262 | + else: | ||
| 263 | + colour2 = (1, 0, 0) | ||
| 264 | + | ||
| 265 | + self.sen1.SetColour(colour1) | ||
| 266 | + self.sen2.SetColour(colour2) | ||
| 267 | + self.Refresh() | ||
| 268 | + | ||
| 269 | + def CreateSensorID(self): | ||
| 270 | + sen1 = vtku.Text() | ||
| 271 | + sen1.SetSize(const.TEXT_SIZE_LARGE) | ||
| 272 | + sen1.SetPosition((const.X, const.Y)) | ||
| 273 | + sen1.ShadowOff() | ||
| 274 | + sen1.SetValue("O") | ||
| 275 | + self.sen1 = sen1 | ||
| 276 | + self.ren.AddActor(sen1.actor) | ||
| 277 | + | ||
| 278 | + sen2 = vtku.Text() | ||
| 279 | + sen2.SetSize(const.TEXT_SIZE_LARGE) | ||
| 280 | + sen2.SetPosition((const.X+0.04, const.Y)) | ||
| 281 | + sen2.ShadowOff() | ||
| 282 | + sen2.SetValue("O") | ||
| 283 | + self.sen2 = sen2 | ||
| 284 | + self.ren.AddActor(sen2.actor) | ||
| 285 | + | ||
| 286 | + self.interactor.Render() | ||
| 287 | + | ||
| 288 | + def OnRemoveSensorsID(self, pubsub_evt): | ||
| 289 | + if self.sen1: | ||
| 290 | + self.ren.RemoveActor(self.sen1.actor) | ||
| 291 | + self.ren.RemoveActor(self.sen2.actor) | ||
| 292 | + self.sen1 = self.sen2 = False | ||
| 293 | + self.interactor.Render() | ||
| 294 | + | ||
| 244 | def OnShowSurface(self, pubsub_evt): | 295 | def OnShowSurface(self, pubsub_evt): |
| 245 | index, value = pubsub_evt.data | 296 | index, value = pubsub_evt.data |
| 246 | if value: | 297 | if value: |
invesalius/gui/dialogs.py
| @@ -793,11 +793,23 @@ def NoMarkerSelected(): | @@ -793,11 +793,23 @@ def NoMarkerSelected(): | ||
| 793 | dlg = wx.MessageDialog(None, "", msg, | 793 | dlg = wx.MessageDialog(None, "", msg, |
| 794 | wx.ICON_INFORMATION | wx.OK) | 794 | wx.ICON_INFORMATION | wx.OK) |
| 795 | else: | 795 | else: |
| 796 | - dlg = wx.MessageDialog(None,msg, "InVesalius 3 - Neuronavigator", | 796 | + dlg = wx.MessageDialog(None, msg, "InVesalius 3 - Neuronavigator", |
| 797 | wx.ICON_INFORMATION | wx.OK) | 797 | wx.ICON_INFORMATION | wx.OK) |
| 798 | dlg.ShowModal() | 798 | dlg.ShowModal() |
| 799 | dlg.Destroy() | 799 | dlg.Destroy() |
| 800 | 800 | ||
| 801 | +def DeleteAllMarkers(): | ||
| 802 | + msg = _("Do you really want to delete all markers?") | ||
| 803 | + if sys.platform == 'darwin': | ||
| 804 | + dlg = wx.MessageDialog(None, "", msg, | ||
| 805 | + wx.OK | wx.CANCEL | wx.ICON_QUESTION) | ||
| 806 | + else: | ||
| 807 | + dlg = wx.MessageDialog(None, msg, "InVesalius 3 - Neuronavigator", | ||
| 808 | + wx.OK | wx.CANCEL | wx.ICON_QUESTION) | ||
| 809 | + result = dlg.ShowModal() | ||
| 810 | + dlg.Destroy() | ||
| 811 | + return result | ||
| 812 | + | ||
| 801 | 813 | ||
| 802 | def EnterMarkerID(default): | 814 | def EnterMarkerID(default): |
| 803 | msg = _("Edit marker ID") | 815 | msg = _("Edit marker ID") |
invesalius/gui/frame.py
| @@ -486,6 +486,8 @@ class Frame(wx.Frame): | @@ -486,6 +486,8 @@ class Frame(wx.Frame): | ||
| 486 | wx.MessageBox(_('Currently the Navigation mode is only working on Windows'), 'Info', wx.OK | wx.ICON_INFORMATION) | 486 | wx.MessageBox(_('Currently the Navigation mode is only working on Windows'), 'Info', wx.OK | wx.ICON_INFORMATION) |
| 487 | self._show_navigator_message = False | 487 | self._show_navigator_message = False |
| 488 | Publisher.sendMessage('Set navigation mode', status) | 488 | Publisher.sendMessage('Set navigation mode', status) |
| 489 | + if not status: | ||
| 490 | + Publisher.sendMessage('Remove sensors ID') | ||
| 489 | 491 | ||
| 490 | def OnSize(self, evt): | 492 | def OnSize(self, evt): |
| 491 | """ | 493 | """ |
invesalius/gui/task_navigator.py
| @@ -325,6 +325,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -325,6 +325,7 @@ class NeuronavigationPanel(wx.Panel): | ||
| 325 | Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') | 325 | Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') |
| 326 | Publisher.subscribe(self.UpdateImageCoordinates, 'Set ball reference position') | 326 | Publisher.subscribe(self.UpdateImageCoordinates, 'Set ball reference position') |
| 327 | Publisher.subscribe(self.OnDisconnectTracker, 'Disconnect tracker') | 327 | Publisher.subscribe(self.OnDisconnectTracker, 'Disconnect tracker') |
| 328 | + Publisher.subscribe(self.OnStylusButton, 'PLH Stylus Button On') | ||
| 328 | 329 | ||
| 329 | def LoadImageFiducials(self, pubsub_evt): | 330 | def LoadImageFiducials(self, pubsub_evt): |
| 330 | marker_id = pubsub_evt.data[0] | 331 | marker_id = pubsub_evt.data[0] |
| @@ -358,6 +359,10 @@ class NeuronavigationPanel(wx.Panel): | @@ -358,6 +359,10 @@ class NeuronavigationPanel(wx.Panel): | ||
| 358 | if self.tracker_id: | 359 | if self.tracker_id: |
| 359 | dt.TrackerConnection(self.tracker_id, 'disconnect') | 360 | dt.TrackerConnection(self.tracker_id, 'disconnect') |
| 360 | 361 | ||
| 362 | + def OnStylusButton(self, pubsub_evt): | ||
| 363 | + if self.trigger_state: | ||
| 364 | + Publisher.sendMessage('Create marker') | ||
| 365 | + | ||
| 361 | def OnChoiceTracker(self, evt, ctrl): | 366 | def OnChoiceTracker(self, evt, ctrl): |
| 362 | Publisher.sendMessage('Update status text in GUI', _("Configuring tracker ...")) | 367 | Publisher.sendMessage('Update status text in GUI', _("Configuring tracker ...")) |
| 363 | if evt: | 368 | if evt: |
| @@ -642,10 +647,12 @@ class MarkersPanel(wx.Panel): | @@ -642,10 +647,12 @@ class MarkersPanel(wx.Panel): | ||
| 642 | self.list_coord[list_index][7] = str(id_label) | 647 | self.list_coord[list_index][7] = str(id_label) |
| 643 | 648 | ||
| 644 | def OnDeleteAllMarkers(self, pubsub_evt): | 649 | def OnDeleteAllMarkers(self, pubsub_evt): |
| 645 | - self.list_coord = [] | ||
| 646 | - self.marker_ind = 0 | ||
| 647 | - Publisher.sendMessage('Remove all markers', self.lc.GetItemCount()) | ||
| 648 | - self.lc.DeleteAllItems() | 650 | + result = dlg.DeleteAllMarkers() |
| 651 | + if result == wx.ID_OK: | ||
| 652 | + self.list_coord = [] | ||
| 653 | + self.marker_ind = 0 | ||
| 654 | + Publisher.sendMessage('Remove all markers', self.lc.GetItemCount()) | ||
| 655 | + self.lc.DeleteAllItems() | ||
| 649 | 656 | ||
| 650 | def OnDeleteSingleMarker(self, evt): | 657 | def OnDeleteSingleMarker(self, evt): |
| 651 | # OnDeleteSingleMarker is used for both pubsub and button click events | 658 | # OnDeleteSingleMarker is used for both pubsub and button click events |
| @@ -682,7 +689,7 @@ class MarkersPanel(wx.Panel): | @@ -682,7 +689,7 @@ class MarkersPanel(wx.Panel): | ||
| 682 | # OnCreateMarker is used for both pubsub and button click events | 689 | # OnCreateMarker is used for both pubsub and button click events |
| 683 | # Pubsub is used for markers created with fiducial buttons, trigger and create marker button | 690 | # Pubsub is used for markers created with fiducial buttons, trigger and create marker button |
| 684 | if hasattr(evt, 'data'): | 691 | if hasattr(evt, 'data'): |
| 685 | - if evt.data: | 692 | + if evt.data is not None: |
| 686 | self.CreateMarker(evt.data[0], (0.0, 1.0, 0.0), self.marker_size, evt.data[1]) | 693 | self.CreateMarker(evt.data[0], (0.0, 1.0, 0.0), self.marker_size, evt.data[1]) |
| 687 | else: | 694 | else: |
| 688 | self.CreateMarker(self.current_coord, self.marker_colour, self.marker_size) | 695 | self.CreateMarker(self.current_coord, self.marker_colour, self.marker_size) |