From 50cad05c75d947d97239c0ec408666cdd1924890 Mon Sep 17 00:00:00 2001 From: Victor Hugo Souza Date: Tue, 9 Mar 2021 19:42:56 +0200 Subject: [PATCH] FIX: Failed to fetch image coordinates from cross move (#257) --- invesalius/data/record_coords.py | 4 ++-- invesalius/data/styles.py | 54 ++++++------------------------------------------------ invesalius/data/viewer_slice.py | 46 ++++++++++++++++++++++++++++++++-------------- invesalius/data/viewer_volume.py | 12 ++++++------ invesalius/gui/task_navigator.py | 17 +++++++++-------- 5 files changed, 55 insertions(+), 78 deletions(-) diff --git a/invesalius/data/record_coords.py b/invesalius/data/record_coords.py index ce29f34..4382e05 100644 --- a/invesalius/data/record_coords.py +++ b/invesalius/data/record_coords.py @@ -43,9 +43,9 @@ class Record(threading.Thread): def __bind_events(self): # Publisher.subscribe(self.UpdateCurrentCoords, 'Co-registered points') - Publisher.subscribe(self.UpdateCurrentCoords, 'Update cross position') + Publisher.subscribe(self.UpdateCurrentCoords, 'Set cross focal point') - def UpdateCurrentCoords(self, arg, position): + def UpdateCurrentCoords(self, position): self.coord = asarray(position) def stop(self): diff --git a/invesalius/data/styles.py b/invesalius/data/styles.py index 828cf64..a2b8b60 100644 --- a/invesalius/data/styles.py +++ b/invesalius/data/styles.py @@ -473,18 +473,6 @@ class CrossInteractorStyle(DefaultInteractorStyle): self.slice_actor = viewer.slice_data.actor self.slice_data = viewer.slice_data - # tracts - # self.seed = [0., 0., 0.] - # slic = sl.Slice() - # self.affine = slic.affine - # self.tracker = slic.tracker - # - # self.affine_vtk = vtk.vtkMatrix4x4() - # for row in range(0, 4): - # for col in range(0, 4): - # self.affine_vtk.SetElement(row, col, self.affine[row, col]) - # --- - self.picker = vtk.vtkWorldPointPicker() self.AddObserver("MouseMoveEvent", self.OnCrossMove) @@ -514,48 +502,18 @@ class CrossInteractorStyle(DefaultInteractorStyle): def ChangeCrossPosition(self, iren): mouse_x, mouse_y = iren.GetEventPosition() - wx, wy, wz = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) - px, py = self.viewer.get_slice_pixel_coord_by_world_pos(wx, wy, wz) - coord = self.viewer.calcultate_scroll_position(px, py) - - # Tracts - # pos_world_aux = np.ones([4, 1]) - # pos_world_aux[:3, -1] = bases.flip_x((wx, wy, wz))[:3] - # pos_world = np.linalg.inv(self.affine) @ pos_world_aux - # seed_aux = pos_world.reshape([1, 4])[0, :3] - # self.seed = seed_aux[np.newaxis, :] - # print("Check the seed: ", self.seed) - # - self.viewer.UpdateSlicesNavigation(None, (wx, wy, wz, 0.0, 0.0, 0.0)) - Publisher.sendMessage('Set cross focal point', position=(wx, wy, wz)) + x, y, z = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) + self.viewer.UpdateSlicesPosition([x, y, z]) + # This "Set cross" message is needed to update the cross in the other slices + Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) Publisher.sendMessage('Update slice viewer') - # self.ScrollSlice(coord) - - # iren.Render() - - def ScrollSlice(self, coord): - if self.orientation == "AXIAL": - Publisher.sendMessage(('Set scroll position', 'SAGITAL'), - index=coord[0]) - Publisher.sendMessage(('Set scroll position', 'CORONAL'), - index=coord[1]) - elif self.orientation == "SAGITAL": - Publisher.sendMessage(('Set scroll position', 'AXIAL'), - index=coord[2]) - Publisher.sendMessage(('Set scroll position', 'CORONAL'), - index=coord[1]) - elif self.orientation == "CORONAL": - Publisher.sendMessage(('Set scroll position', 'AXIAL'), - index=coord[2]) - Publisher.sendMessage(('Set scroll position', 'SAGITAL'), - index=coord[0]) def OnScrollBar(self, *args, **kwargs): # Update other slice's cross according to the new focal point from # the actual orientation. x, y, z = self.viewer.cross.GetFocalPoint() - self.viewer.UpdateSlicesNavigation(None, (x, y, z, 0.0, 0.0, 0.0)) - Publisher.sendMessage('Set cross focal point', position=(x, y, z)) + self.viewer.UpdateSlicesPosition([x, y, z]) + Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) Publisher.sendMessage('Update slice viewer') diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index 97ebe39..9f5f078 100644 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -565,17 +565,31 @@ class Viewer(wx.Panel): if self.slice_data.cursor: self.slice_data.cursor.SetColour(colour_vtk) - def UpdateSlicesNavigation(self, arg, position): + def UpdateSlicesPosition(self, position): # Get point from base change - ux, uy, uz = position[:3] - px, py = self.get_slice_pixel_coord_by_world_pos(ux, uy, uz) + px, py = self.get_slice_pixel_coord_by_world_pos(*position) coord = self.calcultate_scroll_position(px, py) + # Debugging coordinates. For a 1.0 spacing axis the coord and position is the same, + # but for a spacing dimension =! 1, the coord and position are different + # print("\nPosition: {}".format(position)) + # print("Scroll position: {}".format(coord)) + # print("Slice actor bounds: {}".format(self.slice_data.actor.GetBounds())) + # print("Scroll from int of position: {}\n".format([round(s) for s in position])) - self.cross.SetFocalPoint((ux, uy, uz)) + # this call did not affect the working code + # self.cross.SetFocalPoint(coord) + + # update the image slices in all three orientations self.ScrollSlice(coord) def SetCrossFocalPoint(self, position): - self.cross.SetFocalPoint(position) + """ + Sets the cross focal point for all slice panels (axial, coronal, sagittal). This function is also called via + pubsub messaging and may receive a list of 6 coordinates. Thus, limiting the number of list elements in the + SetFocalPoint call is required. + :param position: list of 6 coordinates in vtk world coordinate system wx, wy, wz + """ + self.cross.SetFocalPoint(position[:3]) def ScrollSlice(self, coord): if self.orientation == "AXIAL": @@ -818,12 +832,12 @@ class Viewer(wx.Panel): Publisher.subscribe(self.ChangeSliceNumber, ('Set scroll position', self.orientation)) - Publisher.subscribe(self.__update_cross_position, - 'Update cross position') - Publisher.subscribe(self.__update_cross_position, - 'Update cross position %s' % self.orientation) + # Publisher.subscribe(self.__update_cross_position, + # 'Update cross position') + # Publisher.subscribe(self.__update_cross_position, + # 'Update cross position %s' % self.orientation) Publisher.subscribe(self.SetCrossFocalPoint, 'Set cross focal point') - # Publisher.subscribe(self.UpdateSlicesNavigation, + # Publisher.subscribe(self.UpdateSlicesPosition, # 'Co-registered points') ### # Publisher.subscribe(self.ChangeBrushColour, @@ -1141,9 +1155,9 @@ class Viewer(wx.Panel): renderer.AddActor(cross_actor) - def __update_cross_position(self, arg, position): - # self.cross.SetFocalPoint(position[:3]) - self.UpdateSlicesNavigation(None, position) + # def __update_cross_position(self, arg, position): + # # self.cross.SetFocalPoint(position[:3]) + # self.UpdateSlicesPosition(None, position) def _set_cross_visibility(self, visibility): self.cross_actor.SetVisibility(visibility) @@ -1300,12 +1314,16 @@ class Viewer(wx.Panel): if update3D: self.UpdateSlice3D(pos) + # This Render needs to come before the self.style.OnScrollBar, otherwise the GetFocalPoint will sometimes + # provide the non-updated coordinate and the cross focal point will lag one pixel behind the actual + # scroll position + self.interactor.Render() + try: self.style.OnScrollBar() except AttributeError: print("Do not have OnScrollBar") - self.interactor.Render() if evt: if self._flush_buffer: self.slice_.apply_slice_buffer_to_mask(self.orientation) diff --git a/invesalius/data/viewer_volume.py b/invesalius/data/viewer_volume.py index db50054..ccb1256 100644 --- a/invesalius/data/viewer_volume.py +++ b/invesalius/data/viewer_volume.py @@ -270,9 +270,9 @@ class Viewer(wx.Panel): Publisher.subscribe(self.RemoveVolume, 'Remove Volume') - Publisher.subscribe(self.UpdateCameraBallPosition, - 'Update cross position') - Publisher.subscribe(self.SetCrossFocalPoint, 'Set cross focal point') + # Publisher.subscribe(self.UpdateCameraBallPosition, + # 'Update cross position') + Publisher.subscribe(self.UpdateCameraBallPosition, 'Set cross focal point') Publisher.subscribe(self._check_ball_reference, 'Enable style') Publisher.subscribe(self._uncheck_ball_reference, 'Disable style') @@ -1191,10 +1191,10 @@ class Viewer(wx.Panel): self.ren.AddActor(self.ball_actor) - def SetCrossFocalPoint(self, position): - self.UpdateCameraBallPosition(None, position) + # def SetCrossFocalPoint(self, position): + # self.UpdateCameraBallPosition(None, position) - def UpdateCameraBallPosition(self, arg, position): + def UpdateCameraBallPosition(self, position): coord_flip = list(position[:3]) coord_flip[1] = -coord_flip[1] self.ball_actor.SetPosition(coord_flip) diff --git a/invesalius/gui/task_navigator.py b/invesalius/gui/task_navigator.py index d7ab4ca..2ef37f7 100644 --- a/invesalius/gui/task_navigator.py +++ b/invesalius/gui/task_navigator.py @@ -446,7 +446,7 @@ class NeuronavigationPanel(wx.Panel): Publisher.subscribe(self.LoadImageFiducials, 'Load image fiducials') Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') - Publisher.subscribe(self.UpdateImageCoordinates, 'Update cross position') + Publisher.subscribe(self.UpdateImageCoordinates, 'Set cross focal point') Publisher.subscribe(self.OnDisconnectTracker, 'Disconnect tracker') Publisher.subscribe(self.UpdateObjectRegistration, 'Update object registration') Publisher.subscribe(self.OnCloseProject, 'Close project data') @@ -506,7 +506,7 @@ class NeuronavigationPanel(wx.Panel): def EnableACT(self, data): self.enable_act = data - def UpdateImageCoordinates(self, arg, position): + def UpdateImageCoordinates(self, position): # TODO: Change from world coordinates to matrix coordinates. They are better for multi software communication. self.current_coord = position for m in [0, 1, 2]: @@ -1213,15 +1213,15 @@ class MarkersPanel(wx.Panel): def __bind_events(self): # Publisher.subscribe(self.UpdateCurrentCoord, 'Co-registered points') - Publisher.subscribe(self.UpdateCurrentCoord, 'Update cross position') + Publisher.subscribe(self.UpdateCurrentCoord, 'Set cross focal point') Publisher.subscribe(self.OnDeleteSingleMarker, 'Delete fiducial marker') Publisher.subscribe(self.OnDeleteAllMarkers, 'Delete all markers') Publisher.subscribe(self.OnCreateMarker, 'Create marker') Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') Publisher.subscribe(self.UpdateSeedCoordinates, 'Update tracts') - def UpdateCurrentCoord(self, arg, position): - self.current_coord = position[:] + def UpdateCurrentCoord(self, position): + self.current_coord = position #self.current_angle = pubsub_evt.data[1][3:] def UpdateNavigationStatus(self, nav_status, vis_status): @@ -1747,7 +1747,7 @@ class TractographyPanel(wx.Panel): def __bind_events(self): Publisher.subscribe(self.OnCloseProject, 'Close project data') - Publisher.subscribe(self.OnUpdateTracts, 'Update cross position') + Publisher.subscribe(self.OnUpdateTracts, 'Set cross focal point') Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') def OnSelectPeelingDepth(self, evt, ctrl): @@ -1941,7 +1941,7 @@ class TractographyPanel(wx.Panel): wx.MessageBox(_("File incompatible, using default configuration."), _("InVesalius 3")) Publisher.sendMessage('Update status text in GUI', label="") - def OnUpdateTracts(self, arg, position): + def OnUpdateTracts(self, position): """ Minimal working version of tract computation. Updates when cross sends Pubsub message to update. Position refers to the coordinates in InVesalius 2D space. To represent the same coordinates in the 3D space, @@ -2055,7 +2055,8 @@ class UpdateNavigationScene(threading.Thread): #TODO: If using the view_tracts substitute the raw coord from the offset coordinate, so the user # see the red cross in the position of the offset marker - wx.CallAfter(Publisher.sendMessage, 'Update cross position', arg=m_img, position=coord) + wx.CallAfter(Publisher.sendMessage, 'Set cross focal point', position=coord) + wx.CallAfter(Publisher.sendMessage, 'Update slice viewer') if view_obj: wx.CallAfter(Publisher.sendMessage, 'Update object matrix', m_img=m_img, coord=coord) -- libgit2 0.21.2