Commit 22434229e7193fec2b24e511f44f8cfb0e0d035c
1 parent
b09b522f
Exists in
master
and in
68 other branches
ADD: Cross reference between slices
Showing
3 changed files
with
62 additions
and
22 deletions
Show diff stats
invesalius/constants.py
| @@ -200,6 +200,7 @@ MODE_WW_WL = 4#:"Bright and contrast adjustment"} | @@ -200,6 +200,7 @@ MODE_WW_WL = 4#:"Bright and contrast adjustment"} | ||
| 200 | #### | 200 | #### |
| 201 | MODE_SLICE_SCROLL = -1 | 201 | MODE_SLICE_SCROLL = -1 |
| 202 | MODE_SLICE_EDITOR = -2 | 202 | MODE_SLICE_EDITOR = -2 |
| 203 | +MODE_SLICE_CROSS = -3 | ||
| 203 | 204 | ||
| 204 | ############ | 205 | ############ |
| 205 | 206 |
invesalius/data/viewer_slice.py
| @@ -44,7 +44,7 @@ class Viewer(wx.Panel): | @@ -44,7 +44,7 @@ class Viewer(wx.Panel): | ||
| 44 | self.SetBackgroundColour(colour) | 44 | self.SetBackgroundColour(colour) |
| 45 | 45 | ||
| 46 | # Interactor additional style | 46 | # Interactor additional style |
| 47 | - self.modes = [] #['DEFAULT'] | 47 | + self.modes = []#['DEFAULT'] |
| 48 | self.mouse_pressed = 0 | 48 | self.mouse_pressed = 0 |
| 49 | 49 | ||
| 50 | # All renderers and image actors in this viewer | 50 | # All renderers and image actors in this viewer |
| @@ -105,7 +105,7 @@ class Viewer(wx.Panel): | @@ -105,7 +105,7 @@ class Viewer(wx.Panel): | ||
| 105 | def SetLayout(self, layout): | 105 | def SetLayout(self, layout): |
| 106 | self.layout = layout | 106 | self.layout = layout |
| 107 | slice_ = sl.Slice() | 107 | slice_ = sl.Slice() |
| 108 | - self.load_renderers(slice_.GetOutput()) | 108 | + self.LoadRenderers(slice_.GetOutput()) |
| 109 | self.__configure_renderers() | 109 | self.__configure_renderers() |
| 110 | self.__configure_scroll() | 110 | self.__configure_scroll() |
| 111 | 111 | ||
| @@ -132,10 +132,10 @@ class Viewer(wx.Panel): | @@ -132,10 +132,10 @@ class Viewer(wx.Panel): | ||
| 132 | self.modes.append(mode) | 132 | self.modes.append(mode) |
| 133 | 133 | ||
| 134 | # All modes and bindings | 134 | # All modes and bindings |
| 135 | - action = {'DEFAULT': { | 135 | + action = {'CROSS': { |
| 136 | "MouseMoveEvent": self.OnCrossMove, | 136 | "MouseMoveEvent": self.OnCrossMove, |
| 137 | - "LeftButtonPressEvent": self.OnMouseClick, | ||
| 138 | - "LeftButtonReleaseEvent": self.OnMouseRelease | 137 | + "LeftButtonPressEvent": self.OnCrossMouseClick, |
| 138 | + "LeftButtonReleaseEvent": self.OnCrossMouseRelease | ||
| 139 | }, | 139 | }, |
| 140 | 'EDITOR': { | 140 | 'EDITOR': { |
| 141 | "MouseMoveEvent": self.OnBrushMove, | 141 | "MouseMoveEvent": self.OnBrushMove, |
| @@ -229,6 +229,11 @@ class Viewer(wx.Panel): | @@ -229,6 +229,11 @@ class Viewer(wx.Panel): | ||
| 229 | self.mouse_pressed = 0 | 229 | self.mouse_pressed = 0 |
| 230 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS)) | 230 | self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZENS)) |
| 231 | 231 | ||
| 232 | + def __set_mode_cross(self, pubsub_evt): | ||
| 233 | + self.append_mode('CROSS') | ||
| 234 | + self.mouse_pressed = 0 | ||
| 235 | + self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_NONE)) | ||
| 236 | + | ||
| 232 | def OnWindowLevelMove(self, evt, obj): | 237 | def OnWindowLevelMove(self, evt, obj): |
| 233 | if self.mouse_pressed: | 238 | if self.mouse_pressed: |
| 234 | position = self.interactor.GetLastEventPosition() | 239 | position = self.interactor.GetLastEventPosition() |
| @@ -523,7 +528,6 @@ class Viewer(wx.Panel): | @@ -523,7 +528,6 @@ class Viewer(wx.Panel): | ||
| 523 | elif self._brush_cursor_op == const.BRUSH_THRESH: | 528 | elif self._brush_cursor_op == const.BRUSH_THRESH: |
| 524 | evt_msg = 'Edit mask pixel' | 529 | evt_msg = 'Edit mask pixel' |
| 525 | 530 | ||
| 526 | - self.__update_cross_position(*coord) | ||
| 527 | 531 | ||
| 528 | if self.mouse_pressed: | 532 | if self.mouse_pressed: |
| 529 | pixels = itertools.ifilter(self.test_operation_position, | 533 | pixels = itertools.ifilter(self.test_operation_position, |
| @@ -533,17 +537,38 @@ class Viewer(wx.Panel): | @@ -533,17 +537,38 @@ class Viewer(wx.Panel): | ||
| 533 | self.interactor.Render() | 537 | self.interactor.Render() |
| 534 | 538 | ||
| 535 | def OnCrossMove(self, obj, evt_vtk): | 539 | def OnCrossMove(self, obj, evt_vtk): |
| 536 | - coord = self.get_coordinate() | ||
| 537 | # Update position in other slices | 540 | # Update position in other slices |
| 538 | if self.mouse_pressed: | 541 | if self.mouse_pressed: |
| 539 | - ps.Publisher().sendMessage('Update cursor position in slice', | ||
| 540 | - coord) | 542 | + mouse_x, mouse_y = self.interactor.GetEventPosition() |
| 543 | + renderer = self.slice_data_list[0].renderer | ||
| 544 | + self.pick.Pick(mouse_x, mouse_y, 0, renderer) | ||
| 545 | + coord_cross = self.get_coordinate_cursor() | ||
| 546 | + coord = self.get_coordinate() | ||
| 547 | + ps.Publisher().sendMessage('Update cross position', coord_cross) | ||
| 541 | ps.Publisher().sendMessage(('Set scroll position', 'SAGITAL'), | 548 | ps.Publisher().sendMessage(('Set scroll position', 'SAGITAL'), |
| 542 | - coord[0]) | 549 | + coord[0]) |
| 543 | ps.Publisher().sendMessage(('Set scroll position', 'CORONAL'), | 550 | ps.Publisher().sendMessage(('Set scroll position', 'CORONAL'), |
| 544 | - coord[1]) | 551 | + coord[1]) |
| 545 | ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'), | 552 | ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'), |
| 546 | - coord[2]) | 553 | + coord[2]) |
| 554 | + | ||
| 555 | + def OnCrossMouseClick(self, obj, evt_vtk): | ||
| 556 | + mouse_x, mouse_y = self.interactor.GetEventPosition() | ||
| 557 | + renderer = self.slice_data_list[0].renderer | ||
| 558 | + self.pick.Pick(mouse_x, mouse_y, 0, renderer) | ||
| 559 | + coord_cross = self.get_coordinate_cursor() | ||
| 560 | + coord = self.get_coordinate() | ||
| 561 | + ps.Publisher().sendMessage('Update cross position', coord_cross) | ||
| 562 | + ps.Publisher().sendMessage(('Set scroll position', 'SAGITAL'), | ||
| 563 | + coord[0]) | ||
| 564 | + ps.Publisher().sendMessage(('Set scroll position', 'CORONAL'), | ||
| 565 | + coord[1]) | ||
| 566 | + ps.Publisher().sendMessage(('Set scroll position', 'AXIAL'), | ||
| 567 | + coord[2]) | ||
| 568 | + self.mouse_pressed = 1 | ||
| 569 | + | ||
| 570 | + def OnCrossMouseRelease(self, obj, evt_vtk): | ||
| 571 | + self.mouse_pressed = 0 | ||
| 547 | 572 | ||
| 548 | def get_slice_data(self, render): | 573 | def get_slice_data(self, render): |
| 549 | for slice_data in self.slice_data_list: | 574 | for slice_data in self.slice_data_list: |
| @@ -637,6 +662,8 @@ class Viewer(wx.Panel): | @@ -637,6 +662,8 @@ class Viewer(wx.Panel): | ||
| 637 | ps.Publisher().subscribe(self.ChangeSliceNumber, | 662 | ps.Publisher().subscribe(self.ChangeSliceNumber, |
| 638 | ('Set scroll position', | 663 | ('Set scroll position', |
| 639 | self.orientation)) | 664 | self.orientation)) |
| 665 | + ps.Publisher().subscribe(self.__update_cross_position, | ||
| 666 | + 'Update cross position') | ||
| 640 | ### | 667 | ### |
| 641 | ps.Publisher().subscribe(self.ChangeBrushSize, | 668 | ps.Publisher().subscribe(self.ChangeBrushSize, |
| 642 | 'Set edition brush size') | 669 | 'Set edition brush size') |
| @@ -669,6 +696,9 @@ class Viewer(wx.Panel): | @@ -669,6 +696,9 @@ class Viewer(wx.Panel): | ||
| 669 | ps.Publisher().subscribe(self.__set_mode_window_level, | 696 | ps.Publisher().subscribe(self.__set_mode_window_level, |
| 670 | ('Set interaction mode', | 697 | ('Set interaction mode', |
| 671 | const.MODE_WW_WL)) | 698 | const.MODE_WW_WL)) |
| 699 | + ps.Publisher().subscribe(self.__set_mode_cross, | ||
| 700 | + ('Set interaction mode', | ||
| 701 | + const.MODE_SLICE_CROSS)) | ||
| 672 | #### | 702 | #### |
| 673 | ps.Publisher().subscribe(self.UpdateText,\ | 703 | ps.Publisher().subscribe(self.UpdateText,\ |
| 674 | 'Update window and level text') | 704 | 'Update window and level text') |
| @@ -692,7 +722,7 @@ class Viewer(wx.Panel): | @@ -692,7 +722,7 @@ class Viewer(wx.Panel): | ||
| 692 | imagedata = pubsub_evt.data | 722 | imagedata = pubsub_evt.data |
| 693 | self.SetInput(imagedata) | 723 | self.SetInput(imagedata) |
| 694 | 724 | ||
| 695 | - def load_renderers(self, image): | 725 | + def LoadRenderers(self, image): |
| 696 | number_renderers = self.layout[0] * self.layout[1] | 726 | number_renderers = self.layout[0] * self.layout[1] |
| 697 | diff = number_renderers - len(self.slice_data_list) | 727 | diff = number_renderers - len(self.slice_data_list) |
| 698 | if diff > 0: | 728 | if diff > 0: |
| @@ -744,7 +774,7 @@ class Viewer(wx.Panel): | @@ -744,7 +774,7 @@ class Viewer(wx.Panel): | ||
| 744 | 774 | ||
| 745 | #actor = vtk.vtkImageActor() | 775 | #actor = vtk.vtkImageActor() |
| 746 | #actor.SetInput(slice_.GetOutput()) | 776 | #actor.SetInput(slice_.GetOutput()) |
| 747 | - self.load_renderers(slice_.GetOutput()) | 777 | + self.LoadRenderers(slice_.GetOutput()) |
| 748 | self.__configure_renderers() | 778 | self.__configure_renderers() |
| 749 | ren = self.slice_data_list[0].renderer | 779 | ren = self.slice_data_list[0].renderer |
| 750 | actor = self.slice_data_list[0].actor | 780 | actor = self.slice_data_list[0].actor |
| @@ -830,10 +860,12 @@ class Viewer(wx.Panel): | @@ -830,10 +860,12 @@ class Viewer(wx.Panel): | ||
| 830 | cross_actor.SetProperty(property) | 860 | cross_actor.SetProperty(property) |
| 831 | # Only the slices are pickable | 861 | # Only the slices are pickable |
| 832 | cross_actor.PickableOff() | 862 | cross_actor.PickableOff() |
| 863 | + self.cross_actor = cross_actor | ||
| 833 | 864 | ||
| 834 | renderer.AddActor(cross_actor) | 865 | renderer.AddActor(cross_actor) |
| 835 | 866 | ||
| 836 | - def __update_cross_position(self, x, y, z): | 867 | + def __update_cross_position(self, pubsub_evt): |
| 868 | + x, y, z = pubsub_evt.data | ||
| 837 | #xi, yi, zi = self.vline.GetPoint1() | 869 | #xi, yi, zi = self.vline.GetPoint1() |
| 838 | #xf, yf, zf = self.vline.GetPoint2() | 870 | #xf, yf, zf = self.vline.GetPoint2() |
| 839 | #self.vline.SetPoint1(x, yi, z) | 871 | #self.vline.SetPoint1(x, yi, z) |
| @@ -863,7 +895,7 @@ class Viewer(wx.Panel): | @@ -863,7 +895,7 @@ class Viewer(wx.Panel): | ||
| 863 | else: | 895 | else: |
| 864 | coordinates = {"SAGITAL": yz, "CORONAL": xz, "AXIAL": xy} | 896 | coordinates = {"SAGITAL": yz, "CORONAL": xz, "AXIAL": xy} |
| 865 | 897 | ||
| 866 | - self.cross.SetFocalPoint(coordinates[self.orientation]) | 898 | + self.cross.SetFocalPoint(x, y, z) |
| 867 | 899 | ||
| 868 | 900 | ||
| 869 | #print slice_number | 901 | #print slice_number |
| @@ -1012,10 +1044,10 @@ class Viewer(wx.Panel): | @@ -1012,10 +1044,10 @@ class Viewer(wx.Panel): | ||
| 1012 | "CORONAL": {1: slice_data.number}, | 1044 | "CORONAL": {1: slice_data.number}, |
| 1013 | "AXIAL": {2: slice_data.number}} | 1045 | "AXIAL": {2: slice_data.number}} |
| 1014 | 1046 | ||
| 1015 | - if 'DEFAULT' in self.modes: | ||
| 1016 | - ps.Publisher().sendMessage( | ||
| 1017 | - 'Update cursor single position in slice', | ||
| 1018 | - position[self.orientation]) | 1047 | + #if 'DEFAULT' in self.modes: |
| 1048 | + # ps.Publisher().sendMessage( | ||
| 1049 | + # 'Update cursor single position in slice', | ||
| 1050 | + # position[self.orientation]) | ||
| 1019 | 1051 | ||
| 1020 | def ChangeSliceNumber(self, pubsub_evt): | 1052 | def ChangeSliceNumber(self, pubsub_evt): |
| 1021 | index = pubsub_evt.data | 1053 | index = pubsub_evt.data |
invesalius/gui/frame.py
| @@ -43,8 +43,9 @@ MODE_BY_ID = {ID_ZOOM: const.MODE_ZOOM, | @@ -43,8 +43,9 @@ MODE_BY_ID = {ID_ZOOM: const.MODE_ZOOM, | ||
| 43 | ID_CONTRAST: const.MODE_WW_WL} | 43 | ID_CONTRAST: const.MODE_WW_WL} |
| 44 | 44 | ||
| 45 | # Slice toolbar | 45 | # Slice toolbar |
| 46 | -SLICE_TOOLS = [ID_SLICE_SCROLL] = [wx.NewId() for number in range(1)] | ||
| 47 | -SLICE_MODE_BY_ID = {ID_SLICE_SCROLL: const.MODE_SLICE_SCROLL} | 46 | +SLICE_TOOLS = [ID_SLICE_SCROLL, ID_CROSS] = [wx.NewId() for number in range(2)] |
| 47 | +SLICE_MODE_BY_ID = {ID_SLICE_SCROLL: const.MODE_SLICE_SCROLL, | ||
| 48 | + ID_CROSS: const.MODE_SLICE_CROSS} | ||
| 48 | 49 | ||
| 49 | class Frame(wx.Frame): | 50 | class Frame(wx.Frame): |
| 50 | def __init__(self, prnt): | 51 | def __init__(self, prnt): |
| @@ -508,9 +509,15 @@ class SliceToolBar(wx.ToolBar): | @@ -508,9 +509,15 @@ class SliceToolBar(wx.ToolBar): | ||
| 508 | BMP_SLICE = wx.Bitmap("../icons/slice.png", | 509 | BMP_SLICE = wx.Bitmap("../icons/slice.png", |
| 509 | wx.BITMAP_TYPE_PNG) | 510 | wx.BITMAP_TYPE_PNG) |
| 510 | 511 | ||
| 512 | + BMP_CROSS = wx.Bitmap("../icons/cross.png", | ||
| 513 | + wx.BITMAP_TYPE_PNG) | ||
| 514 | + | ||
| 511 | self.AddLabelTool(ID_SLICE_SCROLL, "Scroll slice", | 515 | self.AddLabelTool(ID_SLICE_SCROLL, "Scroll slice", |
| 512 | BMP_SLICE, kind = wx.ITEM_CHECK) | 516 | BMP_SLICE, kind = wx.ITEM_CHECK) |
| 513 | 517 | ||
| 518 | + self.AddLabelTool(ID_CROSS, "Cross", | ||
| 519 | + BMP_CROSS, kind = wx.ITEM_CHECK) | ||
| 520 | + | ||
| 514 | self.Realize() | 521 | self.Realize() |
| 515 | 522 | ||
| 516 | def __bind_events_wx(self): | 523 | def __bind_events_wx(self): |