Commit 3b8f8e1ff7464fd3e9c576eda3d24dae75511c4e

Authored by Renan
Committed by GitHub
2 parents 2d8f59df 6e312c12
Exists in master

Merge pull request #403 from sotodela/278_add_visualization_for_the_direction_of_the_marker

278 add visualization for the direction of the marker
invesalius/constants.py
@@ -671,7 +671,7 @@ Z_COLUMN = 6 @@ -671,7 +671,7 @@ Z_COLUMN = 6
671 671
672 MARKER_COLOUR = (1.0, 1.0, 0.) 672 MARKER_COLOUR = (1.0, 1.0, 0.)
673 MARKER_SIZE = 2 673 MARKER_SIZE = 2
674 - 674 +ARROW_MARKER_SIZE = 10
675 CALIBRATION_TRACKER_SAMPLES = 10 675 CALIBRATION_TRACKER_SAMPLES = 10
676 FIDUCIAL_REGISTRATION_ERROR_THRESHOLD = 3.0 676 FIDUCIAL_REGISTRATION_ERROR_THRESHOLD = 3.0
677 677
invesalius/data/styles.py
@@ -486,7 +486,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): @@ -486,7 +486,7 @@ class CrossInteractorStyle(DefaultInteractorStyle):
486 x, y, z = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) 486 x, y, z = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker)
487 self.viewer.UpdateSlicesPosition([x, y, z]) 487 self.viewer.UpdateSlicesPosition([x, y, z])
488 # This "Set cross" message is needed to update the cross in the other slices 488 # This "Set cross" message is needed to update the cross in the other slices
489 - Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) 489 + Publisher.sendMessage('Set cross focal point', position=[x, y, z, None, None, None])
490 Publisher.sendMessage('Update slice viewer') 490 Publisher.sendMessage('Update slice viewer')
491 491
492 def OnScrollBar(self, *args, **kwargs): 492 def OnScrollBar(self, *args, **kwargs):
@@ -494,7 +494,7 @@ class CrossInteractorStyle(DefaultInteractorStyle): @@ -494,7 +494,7 @@ class CrossInteractorStyle(DefaultInteractorStyle):
494 # the actual orientation. 494 # the actual orientation.
495 x, y, z = self.viewer.cross.GetFocalPoint() 495 x, y, z = self.viewer.cross.GetFocalPoint()
496 self.viewer.UpdateSlicesPosition([x, y, z]) 496 self.viewer.UpdateSlicesPosition([x, y, z])
497 - Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) 497 + Publisher.sendMessage('Set cross focal point', position=[x, y, z, None, None, None])
498 Publisher.sendMessage('Update slice viewer') 498 Publisher.sendMessage('Update slice viewer')
499 499
500 500
invesalius/data/viewer_volume.py
@@ -70,8 +70,8 @@ class Viewer(wx.Panel): @@ -70,8 +70,8 @@ class Viewer(wx.Panel):
70 70
71 self.initial_focus = None 71 self.initial_focus = None
72 72
73 - self.staticballs = []  
74 - 73 + self.static_markers = []
  74 + self.static_arrows = []
75 self.style = None 75 self.style = None
76 76
77 interactor = wxVTKRenderWindowInteractor(self, -1, size = self.GetSize()) 77 interactor = wxVTKRenderWindowInteractor(self, -1, size = self.GetSize())
@@ -278,6 +278,7 @@ class Viewer(wx.Panel): @@ -278,6 +278,7 @@ class Viewer(wx.Panel):
278 278
279 # Related to marker creation in navigation tools 279 # Related to marker creation in navigation tools
280 Publisher.subscribe(self.AddMarker, 'Add marker') 280 Publisher.subscribe(self.AddMarker, 'Add marker')
  281 + Publisher.subscribe(self.AddMarkerwithOrientation, 'Add arrow marker')
281 Publisher.subscribe(self.HideAllMarkers, 'Hide all markers') 282 Publisher.subscribe(self.HideAllMarkers, 'Hide all markers')
282 Publisher.subscribe(self.ShowAllMarkers, 'Show all markers') 283 Publisher.subscribe(self.ShowAllMarkers, 'Show all markers')
283 Publisher.subscribe(self.RemoveAllMarkers, 'Remove all markers') 284 Publisher.subscribe(self.RemoveAllMarkers, 'Remove all markers')
@@ -579,7 +580,7 @@ class Viewer(wx.Panel): @@ -579,7 +580,7 @@ class Viewer(wx.Panel):
579 """ 580 """
580 Set all markers, overwriting the previous markers. 581 Set all markers, overwriting the previous markers.
581 """ 582 """
582 - self.RemoveAllMarkers(len(self.staticballs)) 583 + self.RemoveAllMarkers(len(self.static_markers))
583 584
584 target_selected = False 585 target_selected = False
585 for marker in markers: 586 for marker in markers:
@@ -607,6 +608,21 @@ class Viewer(wx.Panel): @@ -607,6 +608,21 @@ class Viewer(wx.Panel):
607 608
608 self.UpdateRender() 609 self.UpdateRender()
609 610
  611 + def AddMarkerwithOrientation(self, arrow_id, size, color, coord):
  612 + """
  613 + Markers arrow with orientation created by navigation tools and rendered in volume viewer.
  614 + """
  615 + self.arrow_marker_id = arrow_id
  616 + coord_flip = list(coord)
  617 + coord_flip[1] = -coord_flip[1]
  618 +
  619 + arrow_actor = self.Add_ObjectArrow(coord_flip[:3], coord_flip[3:6], color, size)
  620 + self.static_markers.append(arrow_actor)
  621 + self.ren.AddActor(self.static_markers[self.arrow_marker_id])
  622 + self.arrow_marker_id += 1
  623 +
  624 + self.Refresh()
  625 +
610 def AddMarker(self, ball_id, size, colour, coord): 626 def AddMarker(self, ball_id, size, colour, coord):
611 """ 627 """
612 Markers created by navigation tools and rendered in volume viewer. 628 Markers created by navigation tools and rendered in volume viewer.
@@ -626,12 +642,12 @@ class Viewer(wx.Panel): @@ -626,12 +642,12 @@ class Viewer(wx.Panel):
626 prop.SetColor(colour) 642 prop.SetColor(colour)
627 643
628 # adding a new actor for the present ball 644 # adding a new actor for the present ball
629 - self.staticballs.append(vtk.vtkActor()) 645 + self.static_markers.append(vtk.vtkActor())
630 646
631 - self.staticballs[self.ball_id].SetMapper(mapper)  
632 - self.staticballs[self.ball_id].SetProperty(prop) 647 + self.static_markers[self.ball_id].SetMapper(mapper)
  648 + self.static_markers[self.ball_id].SetProperty(prop)
633 649
634 - self.ren.AddActor(self.staticballs[self.ball_id]) 650 + self.ren.AddActor(self.static_markers[self.ball_id])
635 self.ball_id += 1 651 self.ball_id += 1
636 652
637 #self.UpdateRender() 653 #self.UpdateRender()
@@ -667,33 +683,33 @@ class Viewer(wx.Panel): @@ -667,33 +683,33 @@ class Viewer(wx.Panel):
667 def HideAllMarkers(self, indexes): 683 def HideAllMarkers(self, indexes):
668 ballid = indexes 684 ballid = indexes
669 for i in range(0, ballid): 685 for i in range(0, ballid):
670 - self.staticballs[i].SetVisibility(0) 686 + self.static_markers[i].SetVisibility(0)
671 self.UpdateRender() 687 self.UpdateRender()
672 688
673 def ShowAllMarkers(self, indexes): 689 def ShowAllMarkers(self, indexes):
674 ballid = indexes 690 ballid = indexes
675 for i in range(0, ballid): 691 for i in range(0, ballid):
676 - self.staticballs[i].SetVisibility(1) 692 + self.static_markers[i].SetVisibility(1)
677 self.UpdateRender() 693 self.UpdateRender()
678 694
679 def RemoveAllMarkers(self, indexes): 695 def RemoveAllMarkers(self, indexes):
680 ballid = indexes 696 ballid = indexes
681 for i in range(0, ballid): 697 for i in range(0, ballid):
682 - self.ren.RemoveActor(self.staticballs[i])  
683 - self.staticballs = [] 698 + self.ren.RemoveActor(self.static_markers[i])
  699 + self.static_markers = []
684 self.UpdateRender() 700 self.UpdateRender()
685 701
686 def RemoveMultipleMarkers(self, index): 702 def RemoveMultipleMarkers(self, index):
687 for i in reversed(index): 703 for i in reversed(index):
688 - self.ren.RemoveActor(self.staticballs[i])  
689 - del self.staticballs[i] 704 + self.ren.RemoveActor(self.static_markers[i])
  705 + del self.static_markers[i]
690 self.ball_id = self.ball_id - 1 706 self.ball_id = self.ball_id - 1
691 self.UpdateRender() 707 self.UpdateRender()
692 708
693 def BlinkMarker(self, index): 709 def BlinkMarker(self, index):
694 if self.timer: 710 if self.timer:
695 self.timer.Stop() 711 self.timer.Stop()
696 - self.staticballs[self.index].SetVisibility(1) 712 + self.static_markers[self.index].SetVisibility(1)
697 self.index = index 713 self.index = index
698 self.timer = wx.Timer(self) 714 self.timer = wx.Timer(self)
699 self.Bind(wx.EVT_TIMER, self.OnBlinkMarker, self.timer) 715 self.Bind(wx.EVT_TIMER, self.OnBlinkMarker, self.timer)
@@ -701,7 +717,7 @@ class Viewer(wx.Panel): @@ -701,7 +717,7 @@ class Viewer(wx.Panel):
701 self.timer_count = 0 717 self.timer_count = 0
702 718
703 def OnBlinkMarker(self, evt): 719 def OnBlinkMarker(self, evt):
704 - self.staticballs[self.index].SetVisibility(int(self.timer_count % 2)) 720 + self.static_markers[self.index].SetVisibility(int(self.timer_count % 2))
705 self.Refresh() 721 self.Refresh()
706 self.timer_count += 1 722 self.timer_count += 1
707 723
@@ -709,20 +725,20 @@ class Viewer(wx.Panel): @@ -709,20 +725,20 @@ class Viewer(wx.Panel):
709 if self.timer: 725 if self.timer:
710 self.timer.Stop() 726 self.timer.Stop()
711 if index is None: 727 if index is None:
712 - self.staticballs[self.index].SetVisibility(1) 728 + self.static_markers[self.index].SetVisibility(1)
713 self.Refresh() 729 self.Refresh()
714 self.index = False 730 self.index = False
715 731
716 def SetNewColor(self, index, color): 732 def SetNewColor(self, index, color):
717 - self.staticballs[index].GetProperty().SetColor([round(s/255.0, 3) for s in color]) 733 + self.static_markers[index].GetProperty().SetColor([round(s / 255.0, 3) for s in color])
718 self.Refresh() 734 self.Refresh()
719 735
720 def OnTargetMarkerTransparency(self, status, index): 736 def OnTargetMarkerTransparency(self, status, index):
721 if status: 737 if status:
722 - self.staticballs[index].GetProperty().SetOpacity(1) 738 + self.static_markers[index].GetProperty().SetOpacity(1)
723 # self.staticballs[index].GetProperty().SetOpacity(0.4) 739 # self.staticballs[index].GetProperty().SetOpacity(0.4)
724 else: 740 else:
725 - self.staticballs[index].GetProperty().SetOpacity(1) 741 + self.static_markers[index].GetProperty().SetOpacity(1)
726 742
727 def OnUpdateAngleThreshold(self, angle): 743 def OnUpdateAngleThreshold(self, angle):
728 self.anglethreshold = angle 744 self.anglethreshold = angle
@@ -992,16 +1008,10 @@ class Viewer(wx.Panel): @@ -992,16 +1008,10 @@ class Viewer(wx.Panel):
992 self.RemoveTarget() 1008 self.RemoveTarget()
993 self.DisableCoilTracker() 1009 self.DisableCoilTracker()
994 1010
995 - def CreateTargetAim(self):  
996 - if self.aim_actor:  
997 - self.RemoveTargetAim()  
998 - self.aim_actor = None  
999 -  
1000 - vtk_colors = vtk.vtkNamedColors()  
1001 - 1011 + def CreateVTKObjectMatrix(self, direction, orientation):
1002 m_img = dco.coordinates_to_transformation_matrix( 1012 m_img = dco.coordinates_to_transformation_matrix(
1003 - position=self.target_coord[:3],  
1004 - orientation=self.target_coord[3:], 1013 + position=direction,
  1014 + orientation=orientation,
1005 axes='sxyz', 1015 axes='sxyz',
1006 ) 1016 )
1007 m_img = np.asmatrix(m_img) 1017 m_img = np.asmatrix(m_img)
@@ -1012,7 +1022,16 @@ class Viewer(wx.Panel): @@ -1012,7 +1022,16 @@ class Viewer(wx.Panel):
1012 for col in range(0, 4): 1022 for col in range(0, 4):
1013 m_img_vtk.SetElement(row, col, m_img[row, col]) 1023 m_img_vtk.SetElement(row, col, m_img[row, col])
1014 1024
1015 - self.m_img_vtk = m_img_vtk 1025 + return m_img_vtk
  1026 +
  1027 + def CreateTargetAim(self):
  1028 + if self.aim_actor:
  1029 + self.RemoveTargetAim()
  1030 + self.aim_actor = None
  1031 +
  1032 + vtk_colors = vtk.vtkNamedColors()
  1033 +
  1034 + self.m_img_vtk = self.CreateVTKObjectMatrix(self.target_coord[:3], self.target_coord[3:])
1016 1035
1017 filename = os.path.join(inv_paths.OBJ_DIR, "aim.stl") 1036 filename = os.path.join(inv_paths.OBJ_DIR, "aim.stl")
1018 1037
@@ -1023,7 +1042,7 @@ class Viewer(wx.Panel): @@ -1023,7 +1042,7 @@ class Viewer(wx.Panel):
1023 1042
1024 # Transform the polydata 1043 # Transform the polydata
1025 transform = vtk.vtkTransform() 1044 transform = vtk.vtkTransform()
1026 - transform.SetMatrix(m_img_vtk) 1045 + transform.SetMatrix(self.m_img_vtk)
1027 transformPD = vtk.vtkTransformPolyDataFilter() 1046 transformPD = vtk.vtkTransformPolyDataFilter()
1028 transformPD.SetTransform(transform) 1047 transformPD.SetTransform(transform)
1029 transformPD.SetInputConnection(reader.GetOutputPort()) 1048 transformPD.SetInputConnection(reader.GetOutputPort())
@@ -1071,7 +1090,7 @@ class Viewer(wx.Panel): @@ -1071,7 +1090,7 @@ class Viewer(wx.Panel):
1071 self.dummy_coil_actor.GetProperty().SetSpecularPower(10) 1090 self.dummy_coil_actor.GetProperty().SetSpecularPower(10)
1072 self.dummy_coil_actor.GetProperty().SetOpacity(.3) 1091 self.dummy_coil_actor.GetProperty().SetOpacity(.3)
1073 self.dummy_coil_actor.SetVisibility(1) 1092 self.dummy_coil_actor.SetVisibility(1)
1074 - self.dummy_coil_actor.SetUserMatrix(m_img_vtk) 1093 + self.dummy_coil_actor.SetUserMatrix(self.m_img_vtk)
1075 1094
1076 self.ren.AddActor(self.dummy_coil_actor) 1095 self.ren.AddActor(self.dummy_coil_actor)
1077 1096
@@ -1424,8 +1443,9 @@ class Viewer(wx.Panel): @@ -1424,8 +1443,9 @@ class Viewer(wx.Panel):
1424 actor.GetProperty().SetLineWidth(5) 1443 actor.GetProperty().SetLineWidth(5)
1425 actor.AddPosition(0, 0, 0) 1444 actor.AddPosition(0, 0, 0)
1426 actor.SetScale(size) 1445 actor.SetScale(size)
1427 - actor.SetPosition(direction)  
1428 - actor.SetOrientation(orientation) 1446 +
  1447 + m_img_vtk = self.CreateVTKObjectMatrix(direction, orientation)
  1448 + actor.SetUserMatrix(m_img_vtk)
1429 1449
1430 return actor 1450 return actor
1431 1451
invesalius/gui/task_navigator.py
@@ -359,7 +359,7 @@ class NeuronavigationPanel(wx.Panel): @@ -359,7 +359,7 @@ class NeuronavigationPanel(wx.Panel):
359 359
360 self.nav_status = False 360 self.nav_status = False
361 self.tracker_fiducial_being_set = None 361 self.tracker_fiducial_being_set = None
362 - self.current_coord = 0, 0, 0 362 + self.current_coord = 0, 0, 0, None, None, None
363 363
364 # Initialize list of buttons and numctrls for wx objects 364 # Initialize list of buttons and numctrls for wx objects
365 self.btns_set_fiducial = [None, None, None, None, None, None] 365 self.btns_set_fiducial = [None, None, None, None, None, None]
@@ -704,7 +704,7 @@ class NeuronavigationPanel(wx.Panel): @@ -704,7 +704,7 @@ class NeuronavigationPanel(wx.Panel):
704 if self.btns_set_fiducial[n].GetValue(): 704 if self.btns_set_fiducial[n].GetValue():
705 coord = self.numctrls_fiducial[n][0].GetValue(),\ 705 coord = self.numctrls_fiducial[n][0].GetValue(),\
706 self.numctrls_fiducial[n][1].GetValue(),\ 706 self.numctrls_fiducial[n][1].GetValue(),\
707 - self.numctrls_fiducial[n][2].GetValue(), 0, 0, 0 707 + self.numctrls_fiducial[n][2].GetValue(), None, None, None
708 708
709 Publisher.sendMessage('Set image fiducial', fiducial_name=fiducial_name, coord=coord[0:3]) 709 Publisher.sendMessage('Set image fiducial', fiducial_name=fiducial_name, coord=coord[0:3])
710 710
@@ -1144,9 +1144,9 @@ class MarkersPanel(wx.Panel): @@ -1144,9 +1144,9 @@ class MarkersPanel(wx.Panel):
1144 x : float = 0 1144 x : float = 0
1145 y : float = 0 1145 y : float = 0
1146 z : float = 0 1146 z : float = 0
1147 - alpha : float = 0  
1148 - beta : float = 0  
1149 - gamma : float = 0 1147 + alpha : float = dataclasses.field(default = None)
  1148 + beta : float = dataclasses.field(default = None)
  1149 + gamma : float = dataclasses.field(default = None)
1150 r : float = 0 1150 r : float = 0
1151 g : float = 1 1151 g : float = 1
1152 b : float = 0 1152 b : float = 0
@@ -1161,7 +1161,7 @@ class MarkersPanel(wx.Panel): @@ -1161,7 +1161,7 @@ class MarkersPanel(wx.Panel):
1161 # x, y, z, alpha, beta, gamma can be jointly accessed as coord 1161 # x, y, z, alpha, beta, gamma can be jointly accessed as coord
1162 @property 1162 @property
1163 def coord(self): 1163 def coord(self):
1164 - return list((self.x, self.y, self.z, self.alpha, self.beta, self.gamma),) 1164 + return list((self.x, self.y, self.z, self.alpha, self.beta, self.gamma))
1165 1165
1166 @coord.setter 1166 @coord.setter
1167 def coord(self, new_coord): 1167 def coord(self, new_coord):
@@ -1201,11 +1201,18 @@ class MarkersPanel(wx.Panel): @@ -1201,11 +1201,18 @@ class MarkersPanel(wx.Panel):
1201 else: 1201 else:
1202 res += ('%s\t' % str(getattr(self, field.name))) 1202 res += ('%s\t' % str(getattr(self, field.name)))
1203 1203
1204 - # Add world coordinates (in addition to the internal ones).  
1205 - position_world, orientation_world = imagedata_utils.convert_invesalius_to_world(  
1206 - position=[self.x, self.y, self.z],  
1207 - orientation=[self.alpha, self.beta, self.gamma],  
1208 - ) 1204 + if self.alpha is not None and self.beta is not None and self.gamma is not None:
  1205 + # Add world coordinates (in addition to the internal ones).
  1206 + position_world, orientation_world = imagedata_utils.convert_invesalius_to_world(
  1207 + position=[self.x, self.y, self.z],
  1208 + orientation=[self.alpha, self.beta, self.gamma],
  1209 + )
  1210 +
  1211 + else:
  1212 + position_world, orientation_world = imagedata_utils.convert_invesalius_to_world(
  1213 + position=[self.x, self.y, self.z],
  1214 + orientation=[0,0,0],
  1215 + )
1209 1216
1210 res += '\t'.join(map(lambda x: 'N/A' if x is None else str(x), (*position_world, *orientation_world))) 1217 res += '\t'.join(map(lambda x: 'N/A' if x is None else str(x), (*position_world, *orientation_world)))
1211 return res 1218 return res
@@ -1215,8 +1222,10 @@ class MarkersPanel(wx.Panel): @@ -1215,8 +1222,10 @@ class MarkersPanel(wx.Panel):
1215 properly formatted, might throw an exception and leave the object 1222 properly formatted, might throw an exception and leave the object
1216 in an inconsistent state.""" 1223 in an inconsistent state."""
1217 for field, str_val in zip(dataclasses.fields(self.__class__), inp_str.split('\t')): 1224 for field, str_val in zip(dataclasses.fields(self.__class__), inp_str.split('\t')):
1218 - if field.type is float: 1225 + if field.type is float and str_val != 'None':
1219 setattr(self, field.name, float(str_val)) 1226 setattr(self, field.name, float(str_val))
  1227 + if field.type is float and str_val == 'None':
  1228 + setattr(self, field.name, None)
1220 if field.type is int: 1229 if field.type is int:
1221 setattr(self, field.name, int(str_val)) 1230 setattr(self, field.name, int(str_val))
1222 if field.type is str: 1231 if field.type is str:
@@ -1253,8 +1262,7 @@ class MarkersPanel(wx.Panel): @@ -1253,8 +1262,7 @@ class MarkersPanel(wx.Panel):
1253 1262
1254 self.session = ses.Session() 1263 self.session = ses.Session()
1255 1264
1256 - self.current_coord = 0, 0, 0, 0, 0, 0  
1257 - self.current_angle = 0, 0, 0 1265 + self.current_coord = 0, 0, 0, None, None, None
1258 self.current_seed = 0, 0, 0 1266 self.current_seed = 0, 0, 0
1259 self.current_robot_target_matrix = [None] * 9 1267 self.current_robot_target_matrix = [None] * 9
1260 self.markers = [] 1268 self.markers = []
@@ -1264,6 +1272,7 @@ class MarkersPanel(wx.Panel): @@ -1264,6 +1272,7 @@ class MarkersPanel(wx.Panel):
1264 1272
1265 self.marker_colour = const.MARKER_COLOUR 1273 self.marker_colour = const.MARKER_COLOUR
1266 self.marker_size = const.MARKER_SIZE 1274 self.marker_size = const.MARKER_SIZE
  1275 + self.arrow_marker_size = const.ARROW_MARKER_SIZE
1267 self.current_session = 1 1276 self.current_session = 1
1268 1277
1269 # Change marker size 1278 # Change marker size
@@ -1431,13 +1440,11 @@ class MarkersPanel(wx.Panel): @@ -1431,13 +1440,11 @@ class MarkersPanel(wx.Panel):
1431 return list(itertools.chain(*(const.BTNS_IMG_MARKERS[i].values() for i in const.BTNS_IMG_MARKERS))) 1440 return list(itertools.chain(*(const.BTNS_IMG_MARKERS[i].values() for i in const.BTNS_IMG_MARKERS)))
1432 1441
1433 def UpdateCurrentCoord(self, position): 1442 def UpdateCurrentCoord(self, position):
1434 - self.current_coord = position  
1435 - #self.current_angle = pubsub_evt.data[1][3:] 1443 + self.current_coord = list(position)
1436 1444
1437 def UpdateNavigationStatus(self, nav_status, vis_status): 1445 def UpdateNavigationStatus(self, nav_status, vis_status):
1438 if not nav_status: 1446 if not nav_status:
1439 - sleep(0.5)  
1440 - #self.current_coord[3:] = 0, 0, 0 1447 + self.current_coord[3:] = None, None, None
1441 self.nav_status = False 1448 self.nav_status = False
1442 else: 1449 else:
1443 self.nav_status = True 1450 self.nav_status = True
@@ -1615,8 +1622,8 @@ class MarkersPanel(wx.Panel): @@ -1615,8 +1622,8 @@ class MarkersPanel(wx.Panel):
1615 if marker.is_target: 1622 if marker.is_target:
1616 self.__set_marker_as_target(len(self.markers) - 1) 1623 self.__set_marker_as_target(len(self.markers) - 1)
1617 1624
1618 - except:  
1619 - wx.MessageBox(_("Invalid markers file."), _("InVesalius 3")) 1625 + except Exception as e:
  1626 + wx.MessageBox(_("Invalid markers file."), _("InVesalius 3"))
1620 1627
1621 def OnMarkersVisibility(self, evt, ctrl): 1628 def OnMarkersVisibility(self, evt, ctrl):
1622 if ctrl.GetValue(): 1629 if ctrl.GetValue():
@@ -1681,10 +1688,18 @@ class MarkersPanel(wx.Panel): @@ -1681,10 +1688,18 @@ class MarkersPanel(wx.Panel):
1681 new_robot_marker.robot_target_matrix = self.current_robot_target_matrix 1688 new_robot_marker.robot_target_matrix = self.current_robot_target_matrix
1682 1689
1683 # Note that ball_id is zero-based, so we assign it len(self.markers) before the new marker is added 1690 # Note that ball_id is zero-based, so we assign it len(self.markers) before the new marker is added
1684 - Publisher.sendMessage('Add marker', ball_id=len(self.markers),  
1685 - size=new_marker.size,  
1686 - colour=new_marker.colour,  
1687 - coord=new_marker.coord[:3]) 1691 + if all([elem is not None for elem in new_marker.coord[3:]]):
  1692 + Publisher.sendMessage('Add arrow marker', arrow_id=len(self.markers),
  1693 + size=self.arrow_marker_size,
  1694 + color=new_marker.colour,
  1695 + coord=new_marker.coord)
  1696 + else:
  1697 + Publisher.sendMessage('Add marker', ball_id=len(self.markers),
  1698 + size=new_marker.size,
  1699 + colour=new_marker.colour,
  1700 + coord=new_marker.coord[:3])
  1701 +
  1702 +
1688 self.markers.append(new_marker) 1703 self.markers.append(new_marker)
1689 self.robot_markers.append(new_robot_marker) 1704 self.robot_markers.append(new_robot_marker)
1690 1705