Commit ef7e253bdc3f378e5608530e65f92b8e981a4633

Authored by okahilak
Committed by GitHub
1 parent 054fa427
Exists in master

Fiducial-related refactoring (#288)

* MOD: Set fiducials via 'Set fiducial' event

* MOD: Create 'Set tracker fiducial' event

* MOD: Decouple fiducial name (e.g., 'LE') from marker and button name ('LEI')

Co-authored-by: Olli-Pekka Kahilakoski <olli-pekka.kahilakoski@aalto.fi>
invesalius/constants.py
@@ -698,25 +698,57 @@ TR2 = wx.NewId() @@ -698,25 +698,57 @@ TR2 = wx.NewId()
698 TR3 = wx.NewId() 698 TR3 = wx.NewId()
699 SET = wx.NewId() 699 SET = wx.NewId()
700 700
701 -BTNS_IMG = {IR1: {0: _('LEI')},  
702 - IR2: {1: _('REI')},  
703 - IR3: {2: _('NAI')}}  
704 -  
705 -BTNS_IMG_MKS = {IR1: {0: 'LEI'},  
706 - IR2: {1: 'REI'},  
707 - IR3: {2: 'NAI'}}  
708 -  
709 -TIPS_IMG = [_("Select left ear in image"),  
710 - _("Select right ear in image"),  
711 - _("Select nasion in image")]  
712 -  
713 -BTNS_TRK = {TR1: {3: _('LET')},  
714 - TR2: {4: _('RET')},  
715 - TR3: {5: _('NAT')}}  
716 -  
717 -TIPS_TRK = [_("Select left ear with spatial tracker"),  
718 - _("Select right ear with spatial tracker"),  
719 - _("Select nasion with spatial tracker")] 701 +IMAGE_FIDUCIALS = [
  702 + {
  703 + 'button_id': IR1,
  704 + 'label': 'LEI',
  705 + 'fiducial_name': 'LE',
  706 + 'fiducial_index': 0,
  707 + 'tip': _("Select left ear in image"),
  708 + },
  709 + {
  710 + 'button_id': IR2,
  711 + 'label': 'REI',
  712 + 'fiducial_name': 'RE',
  713 + 'fiducial_index': 1,
  714 + 'tip': _("Select right ear in image"),
  715 + },
  716 + {
  717 + 'button_id': IR3,
  718 + 'label': 'NAI',
  719 + 'fiducial_name': 'NA',
  720 + 'fiducial_index': 2,
  721 + 'tip': _("Select nasion in image"),
  722 + },
  723 +]
  724 +
  725 +TRACKER_FIDUCIALS = [
  726 + {
  727 + 'button_id': TR1,
  728 + 'label': 'LET',
  729 + 'fiducial_name': 'LE',
  730 + 'fiducial_index': 3,
  731 + 'tip': _("Select left ear with spatial tracker"),
  732 + },
  733 + {
  734 + 'button_id': TR2,
  735 + 'label': 'RET',
  736 + 'fiducial_name': 'RE',
  737 + 'fiducial_index': 4,
  738 + 'tip': _("Select right ear with spatial tracker"),
  739 + },
  740 + {
  741 + 'button_id': TR3,
  742 + 'label': 'NAT',
  743 + 'fiducial_name': 'NA',
  744 + 'fiducial_index': 5,
  745 + 'tip': _("Select nasion with spatial tracker"),
  746 + },
  747 +]
  748 +
  749 +BTNS_IMG_MARKERS = {IR1: {0: 'LEI'},
  750 + IR2: {1: 'REI'},
  751 + IR3: {2: 'NAI'}}
720 752
721 OBJL = wx.NewId() 753 OBJL = wx.NewId()
722 OBJR = wx.NewId() 754 OBJR = wx.NewId()
invesalius/gui/task_navigator.py
@@ -369,26 +369,24 @@ class NeuronavigationPanel(wx.Panel): @@ -369,26 +369,24 @@ class NeuronavigationPanel(wx.Panel):
369 choice_ref.Bind(wx.EVT_COMBOBOX, partial(self.OnChoiceRefMode, ctrl=choice_trck)) 369 choice_ref.Bind(wx.EVT_COMBOBOX, partial(self.OnChoiceRefMode, ctrl=choice_trck))
370 370
371 # Toggle buttons for image fiducials 371 # Toggle buttons for image fiducials
372 - btns_img = const.BTNS_IMG  
373 - tips_img = const.TIPS_IMG 372 + for n, fiducial in enumerate(const.IMAGE_FIDUCIALS):
  373 + button_id = fiducial['button_id']
  374 + label = fiducial['label']
  375 + tip = fiducial['tip']
374 376
375 - for k in btns_img:  
376 - n = list(btns_img[k].keys())[0]  
377 - lab = list(btns_img[k].values())[0]  
378 - self.btns_coord[n] = wx.ToggleButton(self, k, label=lab, size=wx.Size(45, 23))  
379 - self.btns_coord[n].SetToolTip(wx.ToolTip(tips_img[n]))  
380 - self.btns_coord[n].Bind(wx.EVT_TOGGLEBUTTON, self.OnImageFiducials) 377 + self.btns_coord[n] = wx.ToggleButton(self, button_id, label=label, size=wx.Size(45, 23))
  378 + self.btns_coord[n].SetToolTip(wx.ToolTip(tip))
  379 + self.btns_coord[n].Bind(wx.EVT_TOGGLEBUTTON, partial(self.OnImageFiducials, n))
381 380
382 # Push buttons for tracker fiducials 381 # Push buttons for tracker fiducials
383 - btns_trk = const.BTNS_TRK  
384 - tips_trk = const.TIPS_TRK 382 + for n, fiducial in enumerate(const.TRACKER_FIDUCIALS):
  383 + button_id = fiducial['button_id']
  384 + label = fiducial['label']
  385 + tip = fiducial['tip']
385 386
386 - for k in btns_trk:  
387 - n = list(btns_trk[k].keys())[0]  
388 - lab = list(btns_trk[k].values())[0]  
389 - self.btns_coord[n] = wx.Button(self, k, label=lab, size=wx.Size(45, 23))  
390 - self.btns_coord[n].SetToolTip(wx.ToolTip(tips_trk[n-3]))  
391 - self.btns_coord[n].Bind(wx.EVT_BUTTON, self.OnTrackerFiducials) 387 + self.btns_coord[n + 3] = wx.Button(self, button_id, label=label, size=wx.Size(45, 23))
  388 + self.btns_coord[n + 3].SetToolTip(wx.ToolTip(tip))
  389 + self.btns_coord[n + 3].Bind(wx.EVT_BUTTON, partial(self.OnTrackerFiducials, n))
392 390
393 # TODO: Find a better allignment between FRE, text and navigate button 391 # TODO: Find a better allignment between FRE, text and navigate button
394 txt_fre = wx.StaticText(self, -1, _('FRE:')) 392 txt_fre = wx.StaticText(self, -1, _('FRE:'))
@@ -462,6 +460,8 @@ class NeuronavigationPanel(wx.Panel): @@ -462,6 +460,8 @@ class NeuronavigationPanel(wx.Panel):
462 460
463 def __bind_events(self): 461 def __bind_events(self):
464 Publisher.subscribe(self.LoadImageFiducials, 'Load image fiducials') 462 Publisher.subscribe(self.LoadImageFiducials, 'Load image fiducials')
  463 + Publisher.subscribe(self.SetImageFiducial, 'Set image fiducial')
  464 + Publisher.subscribe(self.SetTrackerFiducial, 'Set tracker fiducial')
465 Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') 465 Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state')
466 Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') 466 Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state')
467 Publisher.subscribe(self.UpdateImageCoordinates, 'Set cross focal point') 467 Publisher.subscribe(self.UpdateImageCoordinates, 'Set cross focal point')
@@ -481,15 +481,114 @@ class NeuronavigationPanel(wx.Panel): @@ -481,15 +481,114 @@ class NeuronavigationPanel(wx.Panel):
481 Publisher.subscribe(self.UpdateTarget, 'Update target') 481 Publisher.subscribe(self.UpdateTarget, 'Update target')
482 482
483 def LoadImageFiducials(self, marker_id, coord): 483 def LoadImageFiducials(self, marker_id, coord):
484 - for n in const.BTNS_IMG_MKS:  
485 - btn_id = list(const.BTNS_IMG_MKS[n].keys())[0]  
486 - fid_id = list(const.BTNS_IMG_MKS[n].values())[0]  
487 - if marker_id == fid_id and not self.btns_coord[btn_id].GetValue(): 484 + for n in const.BTNS_IMG_MARKERS:
  485 + btn_id = list(const.BTNS_IMG_MARKERS[n].keys())[0]
  486 + fiducial_name = list(const.BTNS_IMG_MARKERS[n].values())[0]
  487 + if marker_id == fiducial_name and not self.btns_coord[btn_id].GetValue():
488 self.btns_coord[btn_id].SetValue(True) 488 self.btns_coord[btn_id].SetValue(True)
489 - self.fiducials[btn_id, :] = coord[0:3] 489 + Publisher.sendMessage('Set image fiducial', fiducial_name=fiducial_name, coord=coord[0:3])
490 for m in [0, 1, 2]: 490 for m in [0, 1, 2]:
491 self.numctrls_coord[btn_id][m].SetValue(coord[m]) 491 self.numctrls_coord[btn_id][m].SetValue(coord[m])
492 492
  493 + def FiducialNameToIndex(self, fiducials, fiducial_name):
  494 + fiducial = [fiducial for fiducial in fiducials if fiducial['fiducial_name'] == fiducial_name][0]
  495 + return fiducial['fiducial_index']
  496 +
  497 + def SetImageFiducial(self, fiducial_name, coord):
  498 + fiducial_index = self.FiducialNameToIndex(const.IMAGE_FIDUCIALS, fiducial_name)
  499 + self.fiducials[fiducial_index, :] = coord
  500 +
  501 + print("Set image fiducial {} to coordinates {}".format(fiducial_name, coord))
  502 +
  503 + def SetTrackerFiducial(self, fiducial_name):
  504 + fiducial_index = self.FiducialNameToIndex(const.TRACKER_FIDUCIALS, fiducial_name)
  505 + coord = None
  506 +
  507 + if not(self.trk_init and self.tracker_id):
  508 + dlg.ShowNavigationTrackerWarning(0, 'choose')
  509 + return
  510 +
  511 + # if self.tracker_id == const.DEBUGTRACK:
  512 + # if btn_id == 3:
  513 + # coord1 = np.array([-120., 0., 0., 0., 0., 0.])
  514 + # elif btn_id == 4:
  515 + # coord1 = np.array([120., 0., 0., 0., 0., 0.])
  516 + # elif btn_id == 5:
  517 + # coord1 = np.array([0., 120., 0., 0., 0., 0.])
  518 + # coord2 = np.zeros([3, 6])
  519 + # coord_raw = np.vstack([coord1, coord2])
  520 + # else:
  521 + coord_raw = dco.GetCoordinates(self.trk_init, self.tracker_id, self.ref_mode_id)
  522 +
  523 + if self.ref_mode_id:
  524 + coord = dco.dynamic_reference_m(coord_raw[0, :], coord_raw[1, :])
  525 + else:
  526 + coord = coord_raw[0, :]
  527 + coord[2] = -coord[2]
  528 +
  529 + # Update tracker fiducial with tracker coordinates
  530 + self.fiducials[fiducial_index, :] = coord[0:3]
  531 +
  532 + if fiducial_index == 3:
  533 + self.fiducials_raw[0, :] = coord_raw[0, :]
  534 + self.fiducials_raw[1, :] = coord_raw[1, :]
  535 + elif fiducial_index == 4:
  536 + self.fiducials_raw[2, :] = coord_raw[0, :]
  537 + self.fiducials_raw[3, :] = coord_raw[1, :]
  538 + else:
  539 + self.fiducials_raw[4, :] = coord_raw[0, :]
  540 + self.fiducials_raw[5, :] = coord_raw[1, :]
  541 +
  542 + # Update tracker location in the UI.
  543 + for n in [0, 1, 2]:
  544 + self.numctrls_coord[fiducial_index][n].SetValue(float(coord[n]))
  545 +
  546 + print("Set tracker fiducial {} to coordinates {}.".format(fiducial_name, coord[0:3]))
  547 +
  548 + def UpdateNavigationStatus(self, nav_status, vis_status):
  549 + self.nav_status = nav_status
  550 + if nav_status and (self.m_icp is not None):
  551 + self.checkicp.Enable(True)
  552 + else:
  553 + self.checkicp.Enable(False)
  554 + #self.checkicp.SetValue(False)
  555 +
  556 + def UpdateFRE(self, fre):
  557 + # TODO: Exhibit FRE in a warning dialog and only starts navigation after user clicks ok
  558 + self.txtctrl_fre.SetValue(str(round(fre, 2)))
  559 + if fre <= 3:
  560 + self.txtctrl_fre.SetBackgroundColour('GREEN')
  561 + else:
  562 + self.txtctrl_fre.SetBackgroundColour('RED')
  563 +
  564 + def UpdateTrekkerObject(self, data):
  565 + # self.trk_inp = data
  566 + self.trekker = data
  567 +
  568 + def UpdateNumTracts(self, data):
  569 + self.n_tracts = data
  570 +
  571 + def UpdateSeedOffset(self, data):
  572 + self.seed_offset = data
  573 +
  574 + def UpdateSeedRadius(self, data):
  575 + self.seed_radius = data
  576 +
  577 + def UpdateSleep(self, data):
  578 + self.sleep_nav = data
  579 +
  580 + def UpdateNumberThreads(self, data):
  581 + self.n_threads = data
  582 +
  583 + def UpdateTractsVisualization(self, data):
  584 + self.view_tracts = data
  585 +
  586 + def UpdateACTData(self, data):
  587 + self.act_data = data
  588 +
  589 + def UpdateTarget(self, coord):
  590 + self.target = coord
  591 +
493 def UpdateNavigationStatus(self, nav_status, vis_status): 592 def UpdateNavigationStatus(self, nav_status, vis_status):
494 self.nav_status = nav_status 593 self.nav_status = nav_status
495 if nav_status and (self.m_icp is not None): 594 if nav_status and (self.m_icp is not None):
@@ -645,65 +744,29 @@ class NeuronavigationPanel(wx.Panel): @@ -645,65 +744,29 @@ class NeuronavigationPanel(wx.Panel):
645 nav_prop=(self.tracker_id, self.trk_init, self.ref_mode_id)) 744 nav_prop=(self.tracker_id, self.trk_init, self.ref_mode_id))
646 print("Reference mode changed!") 745 print("Reference mode changed!")
647 746
648 - def OnImageFiducials(self, evt):  
649 - btn_id = list(const.BTNS_IMG_MKS[evt.GetId()].keys())[0]  
650 - marker_id = list(const.BTNS_IMG_MKS[evt.GetId()].values())[0] 747 + def OnImageFiducials(self, n, evt):
  748 + fiducial_name = const.IMAGE_FIDUCIALS[n]['fiducial_name']
651 749
652 - if self.btns_coord[btn_id].GetValue():  
653 - coord = self.numctrls_coord[btn_id][0].GetValue(),\  
654 - self.numctrls_coord[btn_id][1].GetValue(),\  
655 - self.numctrls_coord[btn_id][2].GetValue(), 0, 0, 0 750 + # XXX: This is still a bit hard to read, could be cleaned up.
  751 + marker_id = list(const.BTNS_IMG_MARKERS[evt.GetId()].values())[0]
656 752
657 - self.fiducials[btn_id, :] = coord[0:3] 753 + if self.btns_coord[n].GetValue():
  754 + coord = self.numctrls_coord[n][0].GetValue(),\
  755 + self.numctrls_coord[n][1].GetValue(),\
  756 + self.numctrls_coord[n][2].GetValue(), 0, 0, 0
  757 +
  758 + Publisher.sendMessage('Set image fiducial', fiducial_name=fiducial_name, coord=coord[0:3])
658 Publisher.sendMessage('Create marker', coord=coord, marker_id=marker_id) 759 Publisher.sendMessage('Create marker', coord=coord, marker_id=marker_id)
659 else: 760 else:
660 - for n in [0, 1, 2]:  
661 - self.numctrls_coord[btn_id][n].SetValue(float(self.current_coord[n])) 761 + for m in [0, 1, 2]:
  762 + self.numctrls_coord[n][m].SetValue(float(self.current_coord[m]))
662 763
663 - self.fiducials[btn_id, :] = np.nan 764 + Publisher.sendMessage('Set image fiducial', fiducial_name=fiducial_name, coord=np.nan)
664 Publisher.sendMessage('Delete fiducial marker', marker_id=marker_id) 765 Publisher.sendMessage('Delete fiducial marker', marker_id=marker_id)
665 766
666 - def OnTrackerFiducials(self, evt):  
667 - btn_id = list(const.BTNS_TRK[evt.GetId()].keys())[0]  
668 - coord = None  
669 -  
670 - if self.trk_init and self.tracker_id:  
671 - # if self.tracker_id == const.DEBUGTRACK:  
672 - # if btn_id == 3:  
673 - # coord1 = np.array([-120., 0., 0., 0., 0., 0.])  
674 - # elif btn_id == 4:  
675 - # coord1 = np.array([120., 0., 0., 0., 0., 0.])  
676 - # elif btn_id == 5:  
677 - # coord1 = np.array([0., 120., 0., 0., 0., 0.])  
678 - # coord2 = np.zeros([3, 6])  
679 - # coord_raw = np.vstack([coord1, coord2])  
680 - # else:  
681 - coord_raw = dco.GetCoordinates(self.trk_init, self.tracker_id, self.ref_mode_id)  
682 -  
683 - if self.ref_mode_id:  
684 - coord = dco.dynamic_reference_m(coord_raw[0, :], coord_raw[1, :])  
685 - else:  
686 - coord = coord_raw[0, :]  
687 - coord[2] = -coord[2]  
688 -  
689 - else:  
690 - dlg.ShowNavigationTrackerWarning(0, 'choose')  
691 -  
692 - # Update number controls with tracker coordinates  
693 - if coord is not None:  
694 - self.fiducials[btn_id, :] = coord[0:3]  
695 - if btn_id == 3:  
696 - self.fiducials_raw[0, :] = coord_raw[0, :]  
697 - self.fiducials_raw[1, :] = coord_raw[1, :]  
698 - elif btn_id == 4:  
699 - self.fiducials_raw[2, :] = coord_raw[0, :]  
700 - self.fiducials_raw[3, :] = coord_raw[1, :]  
701 - else:  
702 - self.fiducials_raw[4, :] = coord_raw[0, :]  
703 - self.fiducials_raw[5, :] = coord_raw[1, :]  
704 -  
705 - for n in [0, 1, 2]:  
706 - self.numctrls_coord[btn_id][n].SetValue(float(coord[n])) 767 + def OnTrackerFiducials(self, n, evt):
  768 + fiducial_name = const.TRACKER_FIDUCIALS[n]['fiducial_name']
  769 + Publisher.sendMessage('Set tracker fiducial', fiducial_name=fiducial_name)
707 770
708 def OnICP(self): 771 def OnICP(self):
709 dialog = dlg.ICPCorregistrationDialog(nav_prop=(self.tracker_id, self.trk_init, self.ref_mode_id)) 772 dialog = dlg.ICPCorregistrationDialog(nav_prop=(self.tracker_id, self.trk_init, self.ref_mode_id))
@@ -1437,8 +1500,8 @@ class MarkersPanel(wx.Panel): @@ -1437,8 +1500,8 @@ class MarkersPanel(wx.Panel):
1437 for id_n in range(self.lc.GetItemCount()): 1500 for id_n in range(self.lc.GetItemCount()):
1438 item = self.lc.GetItem(id_n, 4) 1501 item = self.lc.GetItem(id_n, 4)
1439 if item.GetText() == marker_id: 1502 if item.GetText() == marker_id:
1440 - for i in const.BTNS_IMG_MKS:  
1441 - if marker_id in list(const.BTNS_IMG_MKS[i].values())[0]: 1503 + for i in const.BTNS_IMG_MARKERS:
  1504 + if marker_id in list(const.BTNS_IMG_MARKERS[i].values())[0]:
1442 self.lc.Focus(item.GetId()) 1505 self.lc.Focus(item.GetId())
1443 index = [self.lc.GetFocusedItem()] 1506 index = [self.lc.GetFocusedItem()]
1444 else: 1507 else:
@@ -1519,8 +1582,8 @@ class MarkersPanel(wx.Panel): @@ -1519,8 +1582,8 @@ class MarkersPanel(wx.Panel):
1519 # size = float(line[9]) 1582 # size = float(line[9])
1520 1583
1521 if len(line) >= 11: 1584 if len(line) >= 11:
1522 - for i in const.BTNS_IMG_MKS:  
1523 - if line[10] in list(const.BTNS_IMG_MKS[i].values())[0]: 1585 + for i in const.BTNS_IMG_MARKERS:
  1586 + if line[10] in list(const.BTNS_IMG_MARKERS[i].values())[0]:
1524 Publisher.sendMessage('Load image fiducials', marker_id=line[10], coord=coord) 1587 Publisher.sendMessage('Load image fiducials', marker_id=line[10], coord=coord)
1525 elif line[10] == 'TARGET': 1588 elif line[10] == 'TARGET':
1526 target = count_line 1589 target = count_line
@@ -1537,8 +1600,8 @@ class MarkersPanel(wx.Panel): @@ -1537,8 +1600,8 @@ class MarkersPanel(wx.Panel):
1537 size = float(line[6]) 1600 size = float(line[6])
1538 1601
1539 if len(line) == 8: 1602 if len(line) == 8:
1540 - for i in const.BTNS_IMG_MKS:  
1541 - if line[7] in list(const.BTNS_IMG_MKS[i].values())[0]: 1603 + for i in const.BTNS_IMG_MARKERS:
  1604 + if line[7] in list(const.BTNS_IMG_MARKERS[i].values())[0]:
1542 Publisher.sendMessage('Load image fiducials', marker_id=line[7], coord=coord) 1605 Publisher.sendMessage('Load image fiducials', marker_id=line[7], coord=coord)
1543 else: 1606 else:
1544 line.append("") 1607 line.append("")