Commit 50cad05c75d947d97239c0ec408666cdd1924890
Committed by
GitHub
1 parent
27f1cd9f
Exists in
master
FIX: Failed to fetch image coordinates from cross move (#257)
* FIX: Failed to fetch image coordinates from cross move - Previous changes to the cross style disrupted the navigation - Enhanced how image coordinates are communicated through pubsub * WIP: Fix scroll and cross focal point difference in coordinate * FIX: Scroll and cross coordinates did not match - Removed debugging prints - Commented and removed unnecessary calls and function - Tested on niftis with 1.0 and 0.488 pixel spacings * Rename UpdateSlices
Showing
5 changed files
with
55 additions
and
78 deletions
Show diff stats
invesalius/data/record_coords.py
@@ -43,9 +43,9 @@ class Record(threading.Thread): | @@ -43,9 +43,9 @@ class Record(threading.Thread): | ||
43 | 43 | ||
44 | def __bind_events(self): | 44 | def __bind_events(self): |
45 | # Publisher.subscribe(self.UpdateCurrentCoords, 'Co-registered points') | 45 | # Publisher.subscribe(self.UpdateCurrentCoords, 'Co-registered points') |
46 | - Publisher.subscribe(self.UpdateCurrentCoords, 'Update cross position') | 46 | + Publisher.subscribe(self.UpdateCurrentCoords, 'Set cross focal point') |
47 | 47 | ||
48 | - def UpdateCurrentCoords(self, arg, position): | 48 | + def UpdateCurrentCoords(self, position): |
49 | self.coord = asarray(position) | 49 | self.coord = asarray(position) |
50 | 50 | ||
51 | def stop(self): | 51 | def stop(self): |
invesalius/data/styles.py
@@ -473,18 +473,6 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -473,18 +473,6 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
473 | self.slice_actor = viewer.slice_data.actor | 473 | self.slice_actor = viewer.slice_data.actor |
474 | self.slice_data = viewer.slice_data | 474 | self.slice_data = viewer.slice_data |
475 | 475 | ||
476 | - # tracts | ||
477 | - # self.seed = [0., 0., 0.] | ||
478 | - # slic = sl.Slice() | ||
479 | - # self.affine = slic.affine | ||
480 | - # self.tracker = slic.tracker | ||
481 | - # | ||
482 | - # self.affine_vtk = vtk.vtkMatrix4x4() | ||
483 | - # for row in range(0, 4): | ||
484 | - # for col in range(0, 4): | ||
485 | - # self.affine_vtk.SetElement(row, col, self.affine[row, col]) | ||
486 | - # --- | ||
487 | - | ||
488 | self.picker = vtk.vtkWorldPointPicker() | 476 | self.picker = vtk.vtkWorldPointPicker() |
489 | 477 | ||
490 | self.AddObserver("MouseMoveEvent", self.OnCrossMove) | 478 | self.AddObserver("MouseMoveEvent", self.OnCrossMove) |
@@ -514,48 +502,18 @@ class CrossInteractorStyle(DefaultInteractorStyle): | @@ -514,48 +502,18 @@ class CrossInteractorStyle(DefaultInteractorStyle): | ||
514 | 502 | ||
515 | def ChangeCrossPosition(self, iren): | 503 | def ChangeCrossPosition(self, iren): |
516 | mouse_x, mouse_y = iren.GetEventPosition() | 504 | mouse_x, mouse_y = iren.GetEventPosition() |
517 | - wx, wy, wz = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) | ||
518 | - px, py = self.viewer.get_slice_pixel_coord_by_world_pos(wx, wy, wz) | ||
519 | - coord = self.viewer.calcultate_scroll_position(px, py) | ||
520 | - | ||
521 | - # Tracts | ||
522 | - # pos_world_aux = np.ones([4, 1]) | ||
523 | - # pos_world_aux[:3, -1] = bases.flip_x((wx, wy, wz))[:3] | ||
524 | - # pos_world = np.linalg.inv(self.affine) @ pos_world_aux | ||
525 | - # seed_aux = pos_world.reshape([1, 4])[0, :3] | ||
526 | - # self.seed = seed_aux[np.newaxis, :] | ||
527 | - # print("Check the seed: ", self.seed) | ||
528 | - # | ||
529 | - self.viewer.UpdateSlicesNavigation(None, (wx, wy, wz, 0.0, 0.0, 0.0)) | ||
530 | - Publisher.sendMessage('Set cross focal point', position=(wx, wy, wz)) | 505 | + x, y, z = self.viewer.get_coordinate_cursor(mouse_x, mouse_y, self.picker) |
506 | + self.viewer.UpdateSlicesPosition([x, y, z]) | ||
507 | + # This "Set cross" message is needed to update the cross in the other slices | ||
508 | + Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) | ||
531 | Publisher.sendMessage('Update slice viewer') | 509 | Publisher.sendMessage('Update slice viewer') |
532 | - # self.ScrollSlice(coord) | ||
533 | - | ||
534 | - # iren.Render() | ||
535 | - | ||
536 | - def ScrollSlice(self, coord): | ||
537 | - if self.orientation == "AXIAL": | ||
538 | - Publisher.sendMessage(('Set scroll position', 'SAGITAL'), | ||
539 | - index=coord[0]) | ||
540 | - Publisher.sendMessage(('Set scroll position', 'CORONAL'), | ||
541 | - index=coord[1]) | ||
542 | - elif self.orientation == "SAGITAL": | ||
543 | - Publisher.sendMessage(('Set scroll position', 'AXIAL'), | ||
544 | - index=coord[2]) | ||
545 | - Publisher.sendMessage(('Set scroll position', 'CORONAL'), | ||
546 | - index=coord[1]) | ||
547 | - elif self.orientation == "CORONAL": | ||
548 | - Publisher.sendMessage(('Set scroll position', 'AXIAL'), | ||
549 | - index=coord[2]) | ||
550 | - Publisher.sendMessage(('Set scroll position', 'SAGITAL'), | ||
551 | - index=coord[0]) | ||
552 | 510 | ||
553 | def OnScrollBar(self, *args, **kwargs): | 511 | def OnScrollBar(self, *args, **kwargs): |
554 | # Update other slice's cross according to the new focal point from | 512 | # Update other slice's cross according to the new focal point from |
555 | # the actual orientation. | 513 | # the actual orientation. |
556 | x, y, z = self.viewer.cross.GetFocalPoint() | 514 | x, y, z = self.viewer.cross.GetFocalPoint() |
557 | - self.viewer.UpdateSlicesNavigation(None, (x, y, z, 0.0, 0.0, 0.0)) | ||
558 | - Publisher.sendMessage('Set cross focal point', position=(x, y, z)) | 515 | + self.viewer.UpdateSlicesPosition([x, y, z]) |
516 | + Publisher.sendMessage('Set cross focal point', position=[x, y, z, 0., 0., 0.]) | ||
559 | Publisher.sendMessage('Update slice viewer') | 517 | Publisher.sendMessage('Update slice viewer') |
560 | 518 | ||
561 | 519 |
invesalius/data/viewer_slice.py
@@ -565,17 +565,31 @@ class Viewer(wx.Panel): | @@ -565,17 +565,31 @@ class Viewer(wx.Panel): | ||
565 | if self.slice_data.cursor: | 565 | if self.slice_data.cursor: |
566 | self.slice_data.cursor.SetColour(colour_vtk) | 566 | self.slice_data.cursor.SetColour(colour_vtk) |
567 | 567 | ||
568 | - def UpdateSlicesNavigation(self, arg, position): | 568 | + def UpdateSlicesPosition(self, position): |
569 | # Get point from base change | 569 | # Get point from base change |
570 | - ux, uy, uz = position[:3] | ||
571 | - px, py = self.get_slice_pixel_coord_by_world_pos(ux, uy, uz) | 570 | + px, py = self.get_slice_pixel_coord_by_world_pos(*position) |
572 | coord = self.calcultate_scroll_position(px, py) | 571 | coord = self.calcultate_scroll_position(px, py) |
572 | + # Debugging coordinates. For a 1.0 spacing axis the coord and position is the same, | ||
573 | + # but for a spacing dimension =! 1, the coord and position are different | ||
574 | + # print("\nPosition: {}".format(position)) | ||
575 | + # print("Scroll position: {}".format(coord)) | ||
576 | + # print("Slice actor bounds: {}".format(self.slice_data.actor.GetBounds())) | ||
577 | + # print("Scroll from int of position: {}\n".format([round(s) for s in position])) | ||
573 | 578 | ||
574 | - self.cross.SetFocalPoint((ux, uy, uz)) | 579 | + # this call did not affect the working code |
580 | + # self.cross.SetFocalPoint(coord) | ||
581 | + | ||
582 | + # update the image slices in all three orientations | ||
575 | self.ScrollSlice(coord) | 583 | self.ScrollSlice(coord) |
576 | 584 | ||
577 | def SetCrossFocalPoint(self, position): | 585 | def SetCrossFocalPoint(self, position): |
578 | - self.cross.SetFocalPoint(position) | 586 | + """ |
587 | + Sets the cross focal point for all slice panels (axial, coronal, sagittal). This function is also called via | ||
588 | + pubsub messaging and may receive a list of 6 coordinates. Thus, limiting the number of list elements in the | ||
589 | + SetFocalPoint call is required. | ||
590 | + :param position: list of 6 coordinates in vtk world coordinate system wx, wy, wz | ||
591 | + """ | ||
592 | + self.cross.SetFocalPoint(position[:3]) | ||
579 | 593 | ||
580 | def ScrollSlice(self, coord): | 594 | def ScrollSlice(self, coord): |
581 | if self.orientation == "AXIAL": | 595 | if self.orientation == "AXIAL": |
@@ -818,12 +832,12 @@ class Viewer(wx.Panel): | @@ -818,12 +832,12 @@ class Viewer(wx.Panel): | ||
818 | Publisher.subscribe(self.ChangeSliceNumber, | 832 | Publisher.subscribe(self.ChangeSliceNumber, |
819 | ('Set scroll position', | 833 | ('Set scroll position', |
820 | self.orientation)) | 834 | self.orientation)) |
821 | - Publisher.subscribe(self.__update_cross_position, | ||
822 | - 'Update cross position') | ||
823 | - Publisher.subscribe(self.__update_cross_position, | ||
824 | - 'Update cross position %s' % self.orientation) | 835 | + # Publisher.subscribe(self.__update_cross_position, |
836 | + # 'Update cross position') | ||
837 | + # Publisher.subscribe(self.__update_cross_position, | ||
838 | + # 'Update cross position %s' % self.orientation) | ||
825 | Publisher.subscribe(self.SetCrossFocalPoint, 'Set cross focal point') | 839 | Publisher.subscribe(self.SetCrossFocalPoint, 'Set cross focal point') |
826 | - # Publisher.subscribe(self.UpdateSlicesNavigation, | 840 | + # Publisher.subscribe(self.UpdateSlicesPosition, |
827 | # 'Co-registered points') | 841 | # 'Co-registered points') |
828 | ### | 842 | ### |
829 | # Publisher.subscribe(self.ChangeBrushColour, | 843 | # Publisher.subscribe(self.ChangeBrushColour, |
@@ -1141,9 +1155,9 @@ class Viewer(wx.Panel): | @@ -1141,9 +1155,9 @@ class Viewer(wx.Panel): | ||
1141 | 1155 | ||
1142 | renderer.AddActor(cross_actor) | 1156 | renderer.AddActor(cross_actor) |
1143 | 1157 | ||
1144 | - def __update_cross_position(self, arg, position): | ||
1145 | - # self.cross.SetFocalPoint(position[:3]) | ||
1146 | - self.UpdateSlicesNavigation(None, position) | 1158 | + # def __update_cross_position(self, arg, position): |
1159 | + # # self.cross.SetFocalPoint(position[:3]) | ||
1160 | + # self.UpdateSlicesPosition(None, position) | ||
1147 | 1161 | ||
1148 | def _set_cross_visibility(self, visibility): | 1162 | def _set_cross_visibility(self, visibility): |
1149 | self.cross_actor.SetVisibility(visibility) | 1163 | self.cross_actor.SetVisibility(visibility) |
@@ -1300,12 +1314,16 @@ class Viewer(wx.Panel): | @@ -1300,12 +1314,16 @@ class Viewer(wx.Panel): | ||
1300 | if update3D: | 1314 | if update3D: |
1301 | self.UpdateSlice3D(pos) | 1315 | self.UpdateSlice3D(pos) |
1302 | 1316 | ||
1317 | + # This Render needs to come before the self.style.OnScrollBar, otherwise the GetFocalPoint will sometimes | ||
1318 | + # provide the non-updated coordinate and the cross focal point will lag one pixel behind the actual | ||
1319 | + # scroll position | ||
1320 | + self.interactor.Render() | ||
1321 | + | ||
1303 | try: | 1322 | try: |
1304 | self.style.OnScrollBar() | 1323 | self.style.OnScrollBar() |
1305 | except AttributeError: | 1324 | except AttributeError: |
1306 | print("Do not have OnScrollBar") | 1325 | print("Do not have OnScrollBar") |
1307 | 1326 | ||
1308 | - self.interactor.Render() | ||
1309 | if evt: | 1327 | if evt: |
1310 | if self._flush_buffer: | 1328 | if self._flush_buffer: |
1311 | self.slice_.apply_slice_buffer_to_mask(self.orientation) | 1329 | self.slice_.apply_slice_buffer_to_mask(self.orientation) |
invesalius/data/viewer_volume.py
@@ -270,9 +270,9 @@ class Viewer(wx.Panel): | @@ -270,9 +270,9 @@ class Viewer(wx.Panel): | ||
270 | 270 | ||
271 | Publisher.subscribe(self.RemoveVolume, 'Remove Volume') | 271 | Publisher.subscribe(self.RemoveVolume, 'Remove Volume') |
272 | 272 | ||
273 | - Publisher.subscribe(self.UpdateCameraBallPosition, | ||
274 | - 'Update cross position') | ||
275 | - Publisher.subscribe(self.SetCrossFocalPoint, 'Set cross focal point') | 273 | + # Publisher.subscribe(self.UpdateCameraBallPosition, |
274 | + # 'Update cross position') | ||
275 | + Publisher.subscribe(self.UpdateCameraBallPosition, 'Set cross focal point') | ||
276 | Publisher.subscribe(self._check_ball_reference, 'Enable style') | 276 | Publisher.subscribe(self._check_ball_reference, 'Enable style') |
277 | Publisher.subscribe(self._uncheck_ball_reference, 'Disable style') | 277 | Publisher.subscribe(self._uncheck_ball_reference, 'Disable style') |
278 | 278 | ||
@@ -1191,10 +1191,10 @@ class Viewer(wx.Panel): | @@ -1191,10 +1191,10 @@ class Viewer(wx.Panel): | ||
1191 | 1191 | ||
1192 | self.ren.AddActor(self.ball_actor) | 1192 | self.ren.AddActor(self.ball_actor) |
1193 | 1193 | ||
1194 | - def SetCrossFocalPoint(self, position): | ||
1195 | - self.UpdateCameraBallPosition(None, position) | 1194 | + # def SetCrossFocalPoint(self, position): |
1195 | + # self.UpdateCameraBallPosition(None, position) | ||
1196 | 1196 | ||
1197 | - def UpdateCameraBallPosition(self, arg, position): | 1197 | + def UpdateCameraBallPosition(self, position): |
1198 | coord_flip = list(position[:3]) | 1198 | coord_flip = list(position[:3]) |
1199 | coord_flip[1] = -coord_flip[1] | 1199 | coord_flip[1] = -coord_flip[1] |
1200 | self.ball_actor.SetPosition(coord_flip) | 1200 | self.ball_actor.SetPosition(coord_flip) |
invesalius/gui/task_navigator.py
@@ -446,7 +446,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -446,7 +446,7 @@ class NeuronavigationPanel(wx.Panel): | ||
446 | Publisher.subscribe(self.LoadImageFiducials, 'Load image fiducials') | 446 | Publisher.subscribe(self.LoadImageFiducials, 'Load image fiducials') |
447 | Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') | 447 | Publisher.subscribe(self.UpdateTriggerState, 'Update trigger state') |
448 | Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') | 448 | Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') |
449 | - Publisher.subscribe(self.UpdateImageCoordinates, 'Update cross position') | 449 | + Publisher.subscribe(self.UpdateImageCoordinates, 'Set cross focal point') |
450 | Publisher.subscribe(self.OnDisconnectTracker, 'Disconnect tracker') | 450 | Publisher.subscribe(self.OnDisconnectTracker, 'Disconnect tracker') |
451 | Publisher.subscribe(self.UpdateObjectRegistration, 'Update object registration') | 451 | Publisher.subscribe(self.UpdateObjectRegistration, 'Update object registration') |
452 | Publisher.subscribe(self.OnCloseProject, 'Close project data') | 452 | Publisher.subscribe(self.OnCloseProject, 'Close project data') |
@@ -506,7 +506,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -506,7 +506,7 @@ class NeuronavigationPanel(wx.Panel): | ||
506 | def EnableACT(self, data): | 506 | def EnableACT(self, data): |
507 | self.enable_act = data | 507 | self.enable_act = data |
508 | 508 | ||
509 | - def UpdateImageCoordinates(self, arg, position): | 509 | + def UpdateImageCoordinates(self, position): |
510 | # TODO: Change from world coordinates to matrix coordinates. They are better for multi software communication. | 510 | # TODO: Change from world coordinates to matrix coordinates. They are better for multi software communication. |
511 | self.current_coord = position | 511 | self.current_coord = position |
512 | for m in [0, 1, 2]: | 512 | for m in [0, 1, 2]: |
@@ -1213,15 +1213,15 @@ class MarkersPanel(wx.Panel): | @@ -1213,15 +1213,15 @@ class MarkersPanel(wx.Panel): | ||
1213 | 1213 | ||
1214 | def __bind_events(self): | 1214 | def __bind_events(self): |
1215 | # Publisher.subscribe(self.UpdateCurrentCoord, 'Co-registered points') | 1215 | # Publisher.subscribe(self.UpdateCurrentCoord, 'Co-registered points') |
1216 | - Publisher.subscribe(self.UpdateCurrentCoord, 'Update cross position') | 1216 | + Publisher.subscribe(self.UpdateCurrentCoord, 'Set cross focal point') |
1217 | Publisher.subscribe(self.OnDeleteSingleMarker, 'Delete fiducial marker') | 1217 | Publisher.subscribe(self.OnDeleteSingleMarker, 'Delete fiducial marker') |
1218 | Publisher.subscribe(self.OnDeleteAllMarkers, 'Delete all markers') | 1218 | Publisher.subscribe(self.OnDeleteAllMarkers, 'Delete all markers') |
1219 | Publisher.subscribe(self.OnCreateMarker, 'Create marker') | 1219 | Publisher.subscribe(self.OnCreateMarker, 'Create marker') |
1220 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') | 1220 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') |
1221 | Publisher.subscribe(self.UpdateSeedCoordinates, 'Update tracts') | 1221 | Publisher.subscribe(self.UpdateSeedCoordinates, 'Update tracts') |
1222 | 1222 | ||
1223 | - def UpdateCurrentCoord(self, arg, position): | ||
1224 | - self.current_coord = position[:] | 1223 | + def UpdateCurrentCoord(self, position): |
1224 | + self.current_coord = position | ||
1225 | #self.current_angle = pubsub_evt.data[1][3:] | 1225 | #self.current_angle = pubsub_evt.data[1][3:] |
1226 | 1226 | ||
1227 | def UpdateNavigationStatus(self, nav_status, vis_status): | 1227 | def UpdateNavigationStatus(self, nav_status, vis_status): |
@@ -1747,7 +1747,7 @@ class TractographyPanel(wx.Panel): | @@ -1747,7 +1747,7 @@ class TractographyPanel(wx.Panel): | ||
1747 | 1747 | ||
1748 | def __bind_events(self): | 1748 | def __bind_events(self): |
1749 | Publisher.subscribe(self.OnCloseProject, 'Close project data') | 1749 | Publisher.subscribe(self.OnCloseProject, 'Close project data') |
1750 | - Publisher.subscribe(self.OnUpdateTracts, 'Update cross position') | 1750 | + Publisher.subscribe(self.OnUpdateTracts, 'Set cross focal point') |
1751 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') | 1751 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') |
1752 | 1752 | ||
1753 | def OnSelectPeelingDepth(self, evt, ctrl): | 1753 | def OnSelectPeelingDepth(self, evt, ctrl): |
@@ -1941,7 +1941,7 @@ class TractographyPanel(wx.Panel): | @@ -1941,7 +1941,7 @@ class TractographyPanel(wx.Panel): | ||
1941 | wx.MessageBox(_("File incompatible, using default configuration."), _("InVesalius 3")) | 1941 | wx.MessageBox(_("File incompatible, using default configuration."), _("InVesalius 3")) |
1942 | Publisher.sendMessage('Update status text in GUI', label="") | 1942 | Publisher.sendMessage('Update status text in GUI', label="") |
1943 | 1943 | ||
1944 | - def OnUpdateTracts(self, arg, position): | 1944 | + def OnUpdateTracts(self, position): |
1945 | """ | 1945 | """ |
1946 | Minimal working version of tract computation. Updates when cross sends Pubsub message to update. | 1946 | Minimal working version of tract computation. Updates when cross sends Pubsub message to update. |
1947 | Position refers to the coordinates in InVesalius 2D space. To represent the same coordinates in the 3D space, | 1947 | 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): | @@ -2055,7 +2055,8 @@ class UpdateNavigationScene(threading.Thread): | ||
2055 | 2055 | ||
2056 | #TODO: If using the view_tracts substitute the raw coord from the offset coordinate, so the user | 2056 | #TODO: If using the view_tracts substitute the raw coord from the offset coordinate, so the user |
2057 | # see the red cross in the position of the offset marker | 2057 | # see the red cross in the position of the offset marker |
2058 | - wx.CallAfter(Publisher.sendMessage, 'Update cross position', arg=m_img, position=coord) | 2058 | + wx.CallAfter(Publisher.sendMessage, 'Set cross focal point', position=coord) |
2059 | + wx.CallAfter(Publisher.sendMessage, 'Update slice viewer') | ||
2059 | 2060 | ||
2060 | if view_obj: | 2061 | if view_obj: |
2061 | wx.CallAfter(Publisher.sendMessage, 'Update object matrix', m_img=m_img, coord=coord) | 2062 | wx.CallAfter(Publisher.sendMessage, 'Update object matrix', m_img=m_img, coord=coord) |