Commit 9092a27045f7f97833ac607e4bcdd9ad121759c8

Authored by Olli-Pekka Kahilakoski
1 parent c3593caa
Exists in master

MOD: Change logic for when to use coil without handle to mark the target

- Previously, coil without handle was used to mark the target only if
  object calibration had not been done yet. After object calibration
  was done, the variable polydata stored the coil mesh that was selected
  by the user when doing the calibration, and hence that coil mesh
  (typically containing the handle) was used to mark the target.

- Change the logic to follow these rules:

  * When the default coil is selected in object calibration, use the
    default coil with a handle to mark the coil location, and default
	coil without a handle to mark the target.

  * When object calibration is not yet done, use default coil without
    a handle to mark the target.

  * When a custom coil is selected in object calibration, use the custom
    coil to mark both the coil location and the target, regardless of if
    the mesh contains handle or not. This is done because otherwise the user
    would need to select two custom meshes, one that is used to mark the coil
    location and another for the target.
invesalius/data/viewer_volume.py
@@ -192,6 +192,7 @@ class Viewer(wx.Panel): @@ -192,6 +192,7 @@ class Viewer(wx.Panel):
192 self.dummy_coil_actor = None 192 self.dummy_coil_actor = None
193 self.target_mode = False 193 self.target_mode = False
194 self.polydata = None 194 self.polydata = None
  195 + self.use_default_object = True
195 self.anglethreshold = const.COIL_ANGLES_THRESHOLD 196 self.anglethreshold = const.COIL_ANGLES_THRESHOLD
196 self.distthreshold = const.COIL_COORD_THRESHOLD 197 self.distthreshold = const.COIL_COORD_THRESHOLD
197 self.angle_arrow_projection_threshold = const.COIL_ANGLE_ARROW_PROJECTION_THRESHOLD 198 self.angle_arrow_projection_threshold = const.COIL_ANGLE_ARROW_PROJECTION_THRESHOLD
@@ -1017,10 +1018,10 @@ class Viewer(wx.Panel): @@ -1017,10 +1018,10 @@ class Viewer(wx.Panel):
1017 self.aim_actor = aim_actor 1018 self.aim_actor = aim_actor
1018 self.ren.AddActor(aim_actor) 1019 self.ren.AddActor(aim_actor)
1019 1020
1020 - if self.polydata:  
1021 - obj_polydata = self.polydata  
1022 - else: 1021 + if self.use_default_object:
1023 obj_polydata = self.CreateObjectPolyData(os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil_no_handle.stl")) 1022 obj_polydata = self.CreateObjectPolyData(os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil_no_handle.stl"))
  1023 + else:
  1024 + obj_polydata = self.polydata
1024 1025
1025 transform = vtk.vtkTransform() 1026 transform = vtk.vtkTransform()
1026 transform.RotateZ(90) 1027 transform.RotateZ(90)
@@ -1597,10 +1598,11 @@ class Viewer(wx.Panel): @@ -1597,10 +1598,11 @@ class Viewer(wx.Panel):
1597 self.GetCellIntersection(p1, norm, coil_norm, coil_dir) 1598 self.GetCellIntersection(p1, norm, coil_norm, coil_dir)
1598 self.Refresh() 1599 self.Refresh()
1599 1600
1600 - def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None): 1601 + def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None, use_default_object=True):
1601 if flag: 1602 if flag:
1602 self.obj_name = obj_name 1603 self.obj_name = obj_name
1603 self.polydata = polydata 1604 self.polydata = polydata
  1605 + self.use_default_object = use_default_object
1604 if not self.obj_actor: 1606 if not self.obj_actor:
1605 self.AddObjectActor(self.obj_name) 1607 self.AddObjectActor(self.obj_name)
1606 else: 1608 else:
invesalius/gui/dialogs.py
@@ -3267,6 +3267,7 @@ class ObjectCalibrationDialog(wx.Dialog): @@ -3267,6 +3267,7 @@ class ObjectCalibrationDialog(wx.Dialog):
3267 self.obj_ref_id = 2 3267 self.obj_ref_id = 2
3268 self.obj_name = None 3268 self.obj_name = None
3269 self.polydata = None 3269 self.polydata = None
  3270 + self.use_default_object = False
3270 3271
3271 self.obj_fiducials = np.full([5, 3], np.nan) 3272 self.obj_fiducials = np.full([5, 3], np.nan)
3272 self.obj_orients = np.full([5, 3], np.nan) 3273 self.obj_orients = np.full([5, 3], np.nan)
@@ -3379,8 +3380,9 @@ class ObjectCalibrationDialog(wx.Dialog): @@ -3379,8 +3380,9 @@ class ObjectCalibrationDialog(wx.Dialog):
3379 return 0 3380 return 0
3380 3381
3381 def LoadObject(self): 3382 def LoadObject(self):
3382 - default = self.ObjectImportDialog()  
3383 - if not default: 3383 + self.use_default_object = self.ObjectImportDialog()
  3384 +
  3385 + if not self.use_default_object:
3384 filename = ShowImportMeshFilesDialog() 3386 filename = ShowImportMeshFilesDialog()
3385 3387
3386 if filename: 3388 if filename:
@@ -3398,6 +3400,12 @@ class ObjectCalibrationDialog(wx.Dialog): @@ -3398,6 +3400,12 @@ class ObjectCalibrationDialog(wx.Dialog):
3398 else: 3400 else:
3399 filename = os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil.stl") 3401 filename = os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil.stl")
3400 reader = vtk.vtkSTLReader() 3402 reader = vtk.vtkSTLReader()
  3403 +
  3404 + # XXX: If the user cancels the dialog for importing the coil mesh file, the current behavior is to
  3405 + # use the default object after all. A more logical behavior in that case would be to cancel the
  3406 + # whole object calibration, but implementing that would need larger refactoring.
  3407 + #
  3408 + self.use_default_object = True
3401 else: 3409 else:
3402 filename = os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil.stl") 3410 filename = os.path.join(inv_paths.OBJ_DIR, "magstim_fig8_coil.stl")
3403 reader = vtk.vtkSTLReader() 3411 reader = vtk.vtkSTLReader()
@@ -3531,7 +3539,7 @@ class ObjectCalibrationDialog(wx.Dialog): @@ -3531,7 +3539,7 @@ class ObjectCalibrationDialog(wx.Dialog):
3531 self.obj_ref_id = 0 3539 self.obj_ref_id = 0
3532 3540
3533 def GetValue(self): 3541 def GetValue(self):
3534 - return self.obj_fiducials, self.obj_orients, self.obj_ref_id, self.obj_name, self.polydata 3542 + return self.obj_fiducials, self.obj_orients, self.obj_ref_id, self.obj_name, self.polydata, self.use_default_object
3535 3543
3536 class ICPCorregistrationDialog(wx.Dialog): 3544 class ICPCorregistrationDialog(wx.Dialog):
3537 3545
invesalius/gui/task_navigator.py
@@ -287,7 +287,7 @@ class InnerFoldPanel(wx.Panel): @@ -287,7 +287,7 @@ class InnerFoldPanel(wx.Panel):
287 287
288 Publisher.sendMessage('Update serial port', serial_port=com_port) 288 Publisher.sendMessage('Update serial port', serial_port=com_port)
289 289
290 - def OnShowObject(self, evt=None, flag=None, obj_name=None, polydata=None): 290 + def OnShowObject(self, evt=None, flag=None, obj_name=None, polydata=None, use_default_object=True):
291 if not evt: 291 if not evt:
292 if flag: 292 if flag:
293 self.checkobj.Enable(True) 293 self.checkobj.Enable(True)
@@ -966,7 +966,7 @@ class NeuronavigationPanel(wx.Panel): @@ -966,7 +966,7 @@ class NeuronavigationPanel(wx.Panel):
966 def UpdateObjectRegistration(self, data=None): 966 def UpdateObjectRegistration(self, data=None):
967 self.navigation.obj_reg = data 967 self.navigation.obj_reg = data
968 968
969 - def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None): 969 + def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None, use_default_object=True):
970 self.navigation.track_obj = flag 970 self.navigation.track_obj = flag
971 971
972 def UpdateSerialPort(self, serial_port): 972 def UpdateSerialPort(self, serial_port):
@@ -1320,7 +1320,7 @@ class ObjectRegistrationPanel(wx.Panel): @@ -1320,7 +1320,7 @@ class ObjectRegistrationPanel(wx.Panel):
1320 dialog = dlg.ObjectCalibrationDialog(self.nav_prop) 1320 dialog = dlg.ObjectCalibrationDialog(self.nav_prop)
1321 try: 1321 try:
1322 if dialog.ShowModal() == wx.ID_OK: 1322 if dialog.ShowModal() == wx.ID_OK:
1323 - self.obj_fiducials, self.obj_orients, self.obj_ref_mode, self.obj_name, polydata = dialog.GetValue() 1323 + self.obj_fiducials, self.obj_orients, self.obj_ref_mode, self.obj_name, polydata, use_default_object = dialog.GetValue()
1324 if np.isfinite(self.obj_fiducials).all() and np.isfinite(self.obj_orients).all(): 1324 if np.isfinite(self.obj_fiducials).all() and np.isfinite(self.obj_orients).all():
1325 self.checktrack.Enable(1) 1325 self.checktrack.Enable(1)
1326 Publisher.sendMessage('Update object registration', 1326 Publisher.sendMessage('Update object registration',
@@ -1329,7 +1329,13 @@ class ObjectRegistrationPanel(wx.Panel): @@ -1329,7 +1329,13 @@ class ObjectRegistrationPanel(wx.Panel):
1329 label=_("Ready")) 1329 label=_("Ready"))
1330 # Enable automatically Track object, Show coil and disable Vol. Camera 1330 # Enable automatically Track object, Show coil and disable Vol. Camera
1331 self.checktrack.SetValue(True) 1331 self.checktrack.SetValue(True)
1332 - Publisher.sendMessage('Update track object state', flag=True, obj_name=self.obj_name, polydata=polydata) 1332 + Publisher.sendMessage(
  1333 + 'Update track object state',
  1334 + flag=True,
  1335 + obj_name=self.obj_name,
  1336 + polydata=polydata,
  1337 + use_default_object=use_default_object,
  1338 + )
1333 Publisher.sendMessage('Change camera checkbox', status=False) 1339 Publisher.sendMessage('Change camera checkbox', status=False)
1334 1340
1335 except wx._core.PyAssertionError: # TODO FIX: win64 1341 except wx._core.PyAssertionError: # TODO FIX: win64