Commit ec2dd6ddb1ce3fc3306b15deca7478f7e7da22f8

Authored by okahilak
Committed by GitHub
1 parent 1de518dc
Exists in master

ADD: Checkbox to allow stimulating when coil is not at target (#393)

Add a "Lock to target" checkbox to the UI. When checked, only allow
triggering stimulation pulse if the coil is at the target. When unchecked,
allow triggering stimulation pulse regardless of the coil location.

Keep the checkbox disabled until a target is selected. When a target
is selected, enable and automatically check the checkbox so that the
default mode of operation is to allow triggering stimulation pulse
only when the coil is at the target.
invesalius/gui/task_navigator.py
... ... @@ -397,16 +397,10 @@ class NeuronavigationPanel(wx.Panel):
397 397  
398 398 self.btns_set_fiducial[n + 3] = ctrl
399 399  
400   - # TODO: Find a better allignment between FRE, text and navigate button
401   - txt_fre = wx.StaticText(self, -1, _('FRE:'))
402   - txt_icp = wx.StaticText(self, -1, _('Refine:'))
  400 + # TODO: Find a better alignment between FRE, text and navigate button
403 401  
404   - if pedal_connection is not None and pedal_connection.in_use:
405   - txt_pedal_pressed = wx.StaticText(self, -1, _('Pedal pressed:'))
406   - else:
407   - txt_pedal_pressed = None
408   -
409   - # Fiducial registration error text box
  402 + # Fiducial registration error text and checkbox
  403 + txt_fre = wx.StaticText(self, -1, _('FRE:'))
410 404 tooltip = wx.ToolTip(_("Fiducial registration error"))
411 405 txtctrl_fre = wx.TextCtrl(self, value="", size=wx.Size(60, -1), style=wx.TE_CENTRE)
412 406 txtctrl_fre.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.BOLD))
... ... @@ -421,6 +415,8 @@ class NeuronavigationPanel(wx.Panel):
421 415 btn_nav.SetToolTip(tooltip)
422 416 btn_nav.Bind(wx.EVT_TOGGLEBUTTON, partial(self.OnNavigate, btn_nav=btn_nav))
423 417  
  418 + # "Refine" text and checkbox
  419 + txt_icp = wx.StaticText(self, -1, _('Refine:'))
424 420 tooltip = wx.ToolTip(_(u"Refine the coregistration"))
425 421 checkbox_icp = wx.CheckBox(self, -1, _(' '))
426 422 checkbox_icp.SetValue(False)
... ... @@ -429,8 +425,9 @@ class NeuronavigationPanel(wx.Panel):
429 425 checkbox_icp.SetToolTip(tooltip)
430 426 self.checkbox_icp = checkbox_icp
431 427  
432   - # An indicator for pedal trigger
  428 + # "Pedal pressed" text and an indicator (checkbox) for pedal press
433 429 if pedal_connection is not None and pedal_connection.in_use:
  430 + txt_pedal_pressed = wx.StaticText(self, -1, _('Pedal pressed:'))
434 431 tooltip = wx.ToolTip(_(u"Is the pedal pressed"))
435 432 checkbox_pedal_pressed = wx.CheckBox(self, -1, _(' '))
436 433 checkbox_pedal_pressed.SetValue(False)
... ... @@ -441,15 +438,27 @@ class NeuronavigationPanel(wx.Panel):
441 438  
442 439 self.checkbox_pedal_pressed = checkbox_pedal_pressed
443 440 else:
  441 + txt_pedal_pressed = None
444 442 self.checkbox_pedal_pressed = None
445 443  
  444 + # "Lock to target" text and checkbox
  445 + tooltip = wx.ToolTip(_(u"Allow triggering stimulation pulse only if the coil is at the target"))
  446 + lock_to_target_text = wx.StaticText(self, -1, _('Lock to target:'))
  447 + lock_to_target_checkbox = wx.CheckBox(self, -1, _(' '))
  448 + lock_to_target_checkbox.SetValue(False)
  449 + lock_to_target_checkbox.Enable(False)
  450 + lock_to_target_checkbox.Bind(wx.EVT_CHECKBOX, partial(self.OnLockToTargetCheckbox, ctrl=lock_to_target_checkbox))
  451 + lock_to_target_checkbox.SetToolTip(tooltip)
  452 +
  453 + self.lock_to_target_checkbox = lock_to_target_checkbox
  454 +
446 455 # Image and tracker coordinates number controls
447 456 for m in range(len(self.btns_set_fiducial)):
448 457 for n in range(3):
449 458 self.numctrls_fiducial[m].append(
450 459 wx.lib.masked.numctrl.NumCtrl(parent=self, integerWidth=4, fractionWidth=1))
451 460  
452   - # Sizer to group all GUI objects
  461 + # Sizers to group all GUI objects
453 462 choice_sizer = wx.FlexGridSizer(rows=1, cols=2, hgap=5, vgap=5)
454 463 choice_sizer.AddMany([(select_tracker_elem, wx.LEFT),
455 464 (choice_ref, wx.RIGHT)])
... ... @@ -470,10 +479,13 @@ class NeuronavigationPanel(wx.Panel):
470 479 (txt_icp, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL),
471 480 (checkbox_icp, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)])
472 481  
473   - pedal_sizer = wx.FlexGridSizer(rows=1, cols=2, hgap=5, vgap=5)
474   - if HAS_PEDAL_CONNECTION and pedal_connection.in_use:
475   - pedal_sizer.AddMany([(txt_pedal_pressed, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL),
476   - (checkbox_pedal_pressed, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)])
  482 + checkboxes_sizer = wx.FlexGridSizer(rows=1, cols=4, hgap=5, vgap=5)
  483 + checkboxes_sizer.AddMany([(lock_to_target_text, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL),
  484 + (lock_to_target_checkbox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)])
  485 +
  486 + if pedal_connection is not None and pedal_connection.in_use:
  487 + checkboxes_sizer.AddMany([(txt_pedal_pressed, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL),
  488 + (checkbox_pedal_pressed, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)])
477 489  
478 490 group_sizer = wx.FlexGridSizer(rows=10, cols=1, hgap=5, vgap=5)
479 491 group_sizer.AddGrowableCol(0, 1)
... ... @@ -484,7 +496,7 @@ class NeuronavigationPanel(wx.Panel):
484 496 group_sizer.AddMany([(choice_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL),
485 497 (coord_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL),
486 498 (nav_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL),
487   - (pedal_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
  499 + (checkboxes_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
488 500  
489 501 main_sizer = wx.BoxSizer(wx.HORIZONTAL)
490 502 main_sizer.Add(group_sizer, 1)# wx.ALIGN_CENTER_HORIZONTAL, 10)
... ... @@ -562,7 +574,6 @@ class NeuronavigationPanel(wx.Panel):
562 574 self.ResetICP()
563 575 self.tracker.UpdateUI(self.select_tracker_elem, self.numctrls_fiducial[3:6], self.txtctrl_fre)
564 576  
565   -
566 577 def UpdatePeelVisualization(self, data):
567 578 self.navigation.peel_loaded = data
568 579  
... ... @@ -601,6 +612,10 @@ class NeuronavigationPanel(wx.Panel):
601 612 def UpdateTarget(self, coord):
602 613 self.navigation.target = coord
603 614  
  615 + self.lock_to_target_checkbox.Enable(True)
  616 + self.lock_to_target_checkbox.SetValue(True)
  617 + self.navigation.SetLockToTarget(True)
  618 +
604 619 def EnableACT(self, data):
605 620 self.navigation.enable_act = data
606 621  
... ... @@ -629,6 +644,10 @@ class NeuronavigationPanel(wx.Panel):
629 644 self.ResetICP()
630 645 self.tracker.UpdateUI(self.select_tracker_elem, self.numctrls_fiducial[3:6], self.txtctrl_fre)
631 646  
  647 + def OnLockToTargetCheckbox(self, evt, ctrl):
  648 + value = ctrl.GetValue()
  649 + self.navigation.SetLockToTarget(value)
  650 +
632 651 def OnChooseTracker(self, evt, ctrl):
633 652 Publisher.sendMessage('Update status text in GUI',
634 653 label=_("Configuring tracker ..."))
... ... @@ -1352,7 +1371,7 @@ class MarkersPanel(wx.Panel):
1352 1371  
1353 1372 @staticmethod
1354 1373 def __list_fiducial_labels():
1355   - """Return the list of marker labels denoting fucials."""
  1374 + """Return the list of marker labels denoting fiducials."""
1356 1375 return list(itertools.chain(*(const.BTNS_IMG_MARKERS[i].values() for i in const.BTNS_IMG_MARKERS)))
1357 1376  
1358 1377 def UpdateCurrentCoord(self, position):
... ...
invesalius/navigation/navigation.py
... ... @@ -174,6 +174,7 @@ class Navigation():
174 174 self.serial_port_connection = None
175 175  
176 176 # During navigation
  177 + self.lock_to_target = False
177 178 self.coil_at_target = False
178 179  
179 180 self.__bind_events()
... ... @@ -194,6 +195,9 @@ class Navigation():
194 195 self.com_port = com_port
195 196 self.baud_rate = baud_rate
196 197  
  198 + def SetLockToTarget(self, value):
  199 + self.lock_to_target = value
  200 +
197 201 def SetReferenceMode(self, value):
198 202 self.ref_mode_id = value
199 203  
... ... @@ -220,7 +224,13 @@ class Navigation():
220 224 return fre, fre <= const.FIDUCIAL_REGISTRATION_ERROR_THRESHOLD
221 225  
222 226 def PedalStateChanged(self, state):
223   - if state is True and self.coil_at_target and self.serial_port_in_use:
  227 + if not self.serial_port_in_use:
  228 + return
  229 +
  230 + permission_to_stimulate = (self.lock_to_target and self.coil_at_target) or \
  231 + not self.lock_to_target
  232 +
  233 + if state and permission_to_stimulate:
224 234 self.serial_port_connection.SendPulse()
225 235  
226 236 def StartNavigation(self, tracker):
... ...