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) |