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 698 TR3 = wx.NewId()
699 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 753 OBJL = wx.NewId()
722 754 OBJR = wx.NewId()
... ...
invesalius/gui/task_navigator.py
... ... @@ -369,26 +369,24 @@ class NeuronavigationPanel(wx.Panel):
369 369 choice_ref.Bind(wx.EVT_COMBOBOX, partial(self.OnChoiceRefMode, ctrl=choice_trck))
370 370  
371 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 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 391 # TODO: Find a better allignment between FRE, text and navigate button
394 392 txt_fre = wx.StaticText(self, -1, _('FRE:'))
... ... @@ -462,6 +460,8 @@ class NeuronavigationPanel(wx.Panel):
462 460  
463 461 def __bind_events(self):
464 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 465 Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state')
466 466 Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state')
467 467 Publisher.subscribe(self.UpdateImageCoordinates, 'Set cross focal point')
... ... @@ -481,15 +481,114 @@ class NeuronavigationPanel(wx.Panel):
481 481 Publisher.subscribe(self.UpdateTarget, 'Update target')
482 482  
483 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 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 490 for m in [0, 1, 2]:
491 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 592 def UpdateNavigationStatus(self, nav_status, vis_status):
494 593 self.nav_status = nav_status
495 594 if nav_status and (self.m_icp is not None):
... ... @@ -645,65 +744,29 @@ class NeuronavigationPanel(wx.Panel):
645 744 nav_prop=(self.tracker_id, self.trk_init, self.ref_mode_id))
646 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 759 Publisher.sendMessage('Create marker', coord=coord, marker_id=marker_id)
659 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 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 771 def OnICP(self):
709 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 1500 for id_n in range(self.lc.GetItemCount()):
1438 1501 item = self.lc.GetItem(id_n, 4)
1439 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 1505 self.lc.Focus(item.GetId())
1443 1506 index = [self.lc.GetFocusedItem()]
1444 1507 else:
... ... @@ -1519,8 +1582,8 @@ class MarkersPanel(wx.Panel):
1519 1582 # size = float(line[9])
1520 1583  
1521 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 1587 Publisher.sendMessage('Load image fiducials', marker_id=line[10], coord=coord)
1525 1588 elif line[10] == 'TARGET':
1526 1589 target = count_line
... ... @@ -1537,8 +1600,8 @@ class MarkersPanel(wx.Panel):
1537 1600 size = float(line[6])
1538 1601  
1539 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 1605 Publisher.sendMessage('Load image fiducials', marker_id=line[7], coord=coord)
1543 1606 else:
1544 1607 line.append("")
... ...