Commit 56f7a1283c671a4c09f79436ae308dde88cfb46a
1 parent
295c16a0
Exists in
master
and in
67 other branches
Adapted camera positions to coronal and sagital cases, and added the option to flip image
Showing
11 changed files
with
130 additions
and
59 deletions
Show diff stats
invesalius/constants.py
| @@ -109,11 +109,11 @@ IMPORT_INTERVAL = [_("Keep all slices"), _("Skip 1 for each 2 slices"), | @@ -109,11 +109,11 @@ IMPORT_INTERVAL = [_("Keep all slices"), _("Skip 1 for each 2 slices"), | ||
| 109 | AXIAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)} | 109 | AXIAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, -1, 0), "SAGITAL":(1, 0, 0)} |
| 110 | AXIAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} | 110 | AXIAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} |
| 111 | 111 | ||
| 112 | -SAGITAL_SLICE_CAM_POSITION = {"AXIAL":(0, 1, 0), "CORONAL":(1, 0, 0), "SAGITAL":(0, 0, -1)} | ||
| 113 | -SAGITAL_SLICE_CAM_VIEW_UP = {"AXIAL":(-1, 0, 0), "CORONAL":(0, 1, 0), "SAGITAL":(0, 1, 0)} | 112 | +SAGITAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, 1, 0), "SAGITAL":(-1, 0, 0)} |
| 113 | +SAGITAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, -1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} | ||
| 114 | 114 | ||
| 115 | -CORONAL_SLICE_CAM_POSITION = {"AXIAL":(0, 1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(1, 0, 0)} | ||
| 116 | -CORONAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, 0, -1), "CORONAL":(0, 1, 0), "SAGITAL":(0, 1, 0)} | 115 | +CORONAL_SLICE_CAM_POSITION = {"AXIAL":(0, 0, 1), "CORONAL":(0, 1, 0), "SAGITAL":(-1, 0, 0)} |
| 116 | +CORONAL_SLICE_CAM_VIEW_UP = {"AXIAL":(0, -1, 0), "CORONAL":(0, 0, 1), "SAGITAL":(0, 0, 1)} | ||
| 117 | 117 | ||
| 118 | SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION], | 118 | SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION], |
| 119 | SAGITAL:[SAGITAL_SLICE_CAM_VIEW_UP, SAGITAL_SLICE_CAM_POSITION], | 119 | SAGITAL:[SAGITAL_SLICE_CAM_VIEW_UP, SAGITAL_SLICE_CAM_POSITION], |
| @@ -457,6 +457,9 @@ ID_DICOM_NETWORK] = [wx.NewId() for number in range(14)] | @@ -457,6 +457,9 @@ ID_DICOM_NETWORK] = [wx.NewId() for number in range(14)] | ||
| 457 | ID_ABOUT = wx.NewId() | 457 | ID_ABOUT = wx.NewId() |
| 458 | ID_START = wx.NewId() | 458 | ID_START = wx.NewId() |
| 459 | 459 | ||
| 460 | +ID_FLIP_X = wx.NewId() | ||
| 461 | +ID_FLIP_Y = wx.NewId() | ||
| 462 | +ID_FLIP_Z = wx.NewId() | ||
| 460 | #--------------------------------------------------------- | 463 | #--------------------------------------------------------- |
| 461 | STATE_DEFAULT = 1000 | 464 | STATE_DEFAULT = 1000 |
| 462 | STATE_WL = 1001 | 465 | STATE_WL = 1001 |
invesalius/control.py
| @@ -432,6 +432,7 @@ class Controller(): | @@ -432,6 +432,7 @@ class Controller(): | ||
| 432 | header['glmax']) | 432 | header['glmax']) |
| 433 | proj.window = proj.threshold_range[1] - proj.threshold_range[0] | 433 | proj.window = proj.threshold_range[1] - proj.threshold_range[0] |
| 434 | proj.level = (0.5 * (proj.threshold_range[1] + proj.threshold_range[0])) | 434 | proj.level = (0.5 * (proj.threshold_range[1] + proj.threshold_range[0])) |
| 435 | + proj.spacing = header['pixdim'][1:4] | ||
| 435 | 436 | ||
| 436 | self.Slice = sl.Slice() | 437 | self.Slice = sl.Slice() |
| 437 | self.Slice.matrix = matrix | 438 | self.Slice.matrix = matrix |
| @@ -495,8 +496,11 @@ class Controller(): | @@ -495,8 +496,11 @@ class Controller(): | ||
| 495 | if file_range != None and file_range[1] > file_range[0]: | 496 | if file_range != None and file_range[1] > file_range[0]: |
| 496 | filelist = filelist[file_range[0]:file_range[1] + 1] | 497 | filelist = filelist[file_range[0]:file_range[1] + 1] |
| 497 | 498 | ||
| 498 | - print ">>>>>>>>>>>>>>>>>>",filelist | ||
| 499 | zspacing = dicom_group.zspacing * interval | 499 | zspacing = dicom_group.zspacing * interval |
| 500 | + | ||
| 501 | + print "\n=======================================" | ||
| 502 | + print ">>>>>>>>>>>>>>>>>> zspacing", zspacing, interval | ||
| 503 | + print "\n=======================================" | ||
| 500 | size = dicom.image.size | 504 | size = dicom.image.size |
| 501 | bits = dicom.image.bits_allocad | 505 | bits = dicom.image.bits_allocad |
| 502 | sop_class_uid = dicom.acquisition.sop_class_uid | 506 | sop_class_uid = dicom.acquisition.sop_class_uid |
invesalius/data/imagedata_utils.py
| @@ -457,6 +457,9 @@ def dcm2memmap(files, slice_size, orientation): | @@ -457,6 +457,9 @@ def dcm2memmap(files, slice_size, orientation): | ||
| 457 | matrix[:, n, :] = array | 457 | matrix[:, n, :] = array |
| 458 | elif orientation == 'SAGITTAL': | 458 | elif orientation == 'SAGITTAL': |
| 459 | array.shape = matrix.shape[0], matrix.shape[1] | 459 | array.shape = matrix.shape[0], matrix.shape[1] |
| 460 | + # TODO: Verify if it's necessary to add the slices swapped only in | ||
| 461 | + # sagittal rmi or only in # Rasiane's case or is necessary in all | ||
| 462 | + # sagittal cases. | ||
| 460 | matrix[:, :, n] = array | 463 | matrix[:, :, n] = array |
| 461 | else: | 464 | else: |
| 462 | print array.shape, matrix.shape | 465 | print array.shape, matrix.shape |
invesalius/data/mask.py
| @@ -29,6 +29,8 @@ import vtk | @@ -29,6 +29,8 @@ import vtk | ||
| 29 | import constants as const | 29 | import constants as const |
| 30 | import imagedata_utils as iu | 30 | import imagedata_utils as iu |
| 31 | 31 | ||
| 32 | +from wx.lib.pubsub import pub as Publisher | ||
| 33 | + | ||
| 32 | class Mask(): | 34 | class Mask(): |
| 33 | general_index = -1 | 35 | general_index = -1 |
| 34 | def __init__(self): | 36 | def __init__(self): |
| @@ -43,6 +45,10 @@ class Mask(): | @@ -43,6 +45,10 @@ class Mask(): | ||
| 43 | self.is_shown = 1 | 45 | self.is_shown = 1 |
| 44 | self.edited_points = {} | 46 | self.edited_points = {} |
| 45 | self.was_edited = False | 47 | self.was_edited = False |
| 48 | + self.__bind_events() | ||
| 49 | + | ||
| 50 | + def __bind_events(self): | ||
| 51 | + Publisher.subscribe(self.OnFlipVolume, 'Flip volume') | ||
| 46 | 52 | ||
| 47 | def SavePlist(self, filename): | 53 | def SavePlist(self, filename): |
| 48 | mask = {} | 54 | mask = {} |
| @@ -79,6 +85,19 @@ class Mask(): | @@ -79,6 +85,19 @@ class Mask(): | ||
| 79 | path = os.path.join(dirpath, mask_file) | 85 | path = os.path.join(dirpath, mask_file) |
| 80 | self._open_mask(path, tuple(shape)) | 86 | self._open_mask(path, tuple(shape)) |
| 81 | 87 | ||
| 88 | + def OnFlipVolume(self, pubsub_evt): | ||
| 89 | + axis = pubsub_evt.data | ||
| 90 | + submatrix = self.matrix[1:, 1:, 1:] | ||
| 91 | + if axis == 0: | ||
| 92 | + submatrix[:] = submatrix[::-1] | ||
| 93 | + self.matrix[1::, 0, 0] = self.matrix[:0:-1, 0, 0] | ||
| 94 | + elif axis == 1: | ||
| 95 | + submatrix[:] = submatrix[:, ::-1] | ||
| 96 | + self.matrix[0, 1::, 0] = self.matrix[0, :0:-1, 0] | ||
| 97 | + elif axis == 2: | ||
| 98 | + submatrix[:] = submatrix[:, :, ::-1] | ||
| 99 | + self.matrix[0, 0, 1::] = self.matrix[0, 0, :0:-1] | ||
| 100 | + | ||
| 82 | def _save_mask(self, filename): | 101 | def _save_mask(self, filename): |
| 83 | shutil.copyfile(self.temp_file, filename) | 102 | shutil.copyfile(self.temp_file, filename) |
| 84 | 103 |
invesalius/data/slice_.py
| @@ -132,6 +132,8 @@ class Slice(object): | @@ -132,6 +132,8 @@ class Slice(object): | ||
| 132 | Publisher.subscribe(self.OnRemoveMasks, 'Remove masks') | 132 | Publisher.subscribe(self.OnRemoveMasks, 'Remove masks') |
| 133 | Publisher.subscribe(self.OnDuplicateMasks, 'Duplicate masks') | 133 | Publisher.subscribe(self.OnDuplicateMasks, 'Duplicate masks') |
| 134 | Publisher.subscribe(self.UpdateSlice3D,'Update slice 3D') | 134 | Publisher.subscribe(self.UpdateSlice3D,'Update slice 3D') |
| 135 | + | ||
| 136 | + Publisher.subscribe(self.OnFlipVolume, 'Flip volume') | ||
| 135 | 137 | ||
| 136 | def GetMaxSliceNumber(self, orientation): | 138 | def GetMaxSliceNumber(self, orientation): |
| 137 | shape = self.matrix.shape | 139 | shape = self.matrix.shape |
| @@ -703,15 +705,15 @@ class Slice(object): | @@ -703,15 +705,15 @@ class Slice(object): | ||
| 703 | cast.ClampOverflowOn() | 705 | cast.ClampOverflowOn() |
| 704 | cast.Update() | 706 | cast.Update() |
| 705 | 707 | ||
| 706 | - if (original_orientation == const.AXIAL): | ||
| 707 | - flip = vtk.vtkImageFlip() | ||
| 708 | - flip.SetInput(cast.GetOutput()) | ||
| 709 | - flip.SetFilteredAxis(1) | ||
| 710 | - flip.FlipAboutOriginOn() | ||
| 711 | - flip.Update() | ||
| 712 | - widget.SetInput(flip.GetOutput()) | ||
| 713 | - else: | ||
| 714 | - widget.SetInput(cast.GetOutput()) | 708 | + #if (original_orientation == const.AXIAL): |
| 709 | + flip = vtk.vtkImageFlip() | ||
| 710 | + flip.SetInput(cast.GetOutput()) | ||
| 711 | + flip.SetFilteredAxis(1) | ||
| 712 | + flip.FlipAboutOriginOn() | ||
| 713 | + flip.Update() | ||
| 714 | + widget.SetInput(flip.GetOutput()) | ||
| 715 | + #else: | ||
| 716 | + #widget.SetInput(cast.GetOutput()) | ||
| 715 | 717 | ||
| 716 | def UpdateSlice3D(self, pubsub_evt): | 718 | def UpdateSlice3D(self, pubsub_evt): |
| 717 | widget, orientation = pubsub_evt.data | 719 | widget, orientation = pubsub_evt.data |
| @@ -723,15 +725,15 @@ class Slice(object): | @@ -723,15 +725,15 @@ class Slice(object): | ||
| 723 | cast.ClampOverflowOn() | 725 | cast.ClampOverflowOn() |
| 724 | cast.Update() | 726 | cast.Update() |
| 725 | 727 | ||
| 726 | - if (original_orientation == const.AXIAL): | ||
| 727 | - flip = vtk.vtkImageFlip() | ||
| 728 | - flip.SetInput(cast.GetOutput()) | ||
| 729 | - flip.SetFilteredAxis(1) | ||
| 730 | - flip.FlipAboutOriginOn() | ||
| 731 | - flip.Update() | ||
| 732 | - widget.SetInput(flip.GetOutput()) | ||
| 733 | - else: | ||
| 734 | - widget.SetInput(cast.GetOutput()) | 728 | + #if (original_orientation == const.AXIAL): |
| 729 | + flip = vtk.vtkImageFlip() | ||
| 730 | + flip.SetInput(cast.GetOutput()) | ||
| 731 | + flip.SetFilteredAxis(1) | ||
| 732 | + flip.FlipAboutOriginOn() | ||
| 733 | + flip.Update() | ||
| 734 | + widget.SetInput(flip.GetOutput()) | ||
| 735 | + #else: | ||
| 736 | + #widget.SetInput(cast.GetOutput()) | ||
| 735 | 737 | ||
| 736 | 738 | ||
| 737 | 739 | ||
| @@ -966,6 +968,18 @@ class Slice(object): | @@ -966,6 +968,18 @@ class Slice(object): | ||
| 966 | self.matrix = numpy.memmap(filename, shape=shape, dtype=dtype, | 968 | self.matrix = numpy.memmap(filename, shape=shape, dtype=dtype, |
| 967 | mode='r+') | 969 | mode='r+') |
| 968 | 970 | ||
| 971 | + def OnFlipVolume(self, pubsub_evt): | ||
| 972 | + axis = pubsub_evt.data | ||
| 973 | + if axis == 0: | ||
| 974 | + self.matrix[:] = self.matrix[::-1] | ||
| 975 | + elif axis == 1: | ||
| 976 | + self.matrix[:] = self.matrix[:, ::-1] | ||
| 977 | + elif axis == 2: | ||
| 978 | + self.matrix[:] = self.matrix[:, :, ::-1] | ||
| 979 | + | ||
| 980 | + for buffer_ in self.buffer_slices.values(): | ||
| 981 | + buffer_.discard_buffer() | ||
| 982 | + | ||
| 969 | def OnExportMask(self, pubsub_evt): | 983 | def OnExportMask(self, pubsub_evt): |
| 970 | #imagedata = self.current_mask.imagedata | 984 | #imagedata = self.current_mask.imagedata |
| 971 | imagedata = self.imagedata | 985 | imagedata = self.imagedata |
invesalius/data/surface_process.py
| @@ -97,6 +97,8 @@ class SurfaceProcess(multiprocessing.Process): | @@ -97,6 +97,8 @@ class SurfaceProcess(multiprocessing.Process): | ||
| 97 | flip.FlipAboutOriginOn() | 97 | flip.FlipAboutOriginOn() |
| 98 | flip.Update() | 98 | flip.Update() |
| 99 | 99 | ||
| 100 | + image = flip.GetOutput() | ||
| 101 | + | ||
| 100 | #filename = tempfile.mktemp(suffix='_%s.vti' % (self.pid)) | 102 | #filename = tempfile.mktemp(suffix='_%s.vti' % (self.pid)) |
| 101 | #writer = vtk.vtkXMLImageDataWriter() | 103 | #writer = vtk.vtkXMLImageDataWriter() |
| 102 | #writer.SetInput(mask_vtk) | 104 | #writer.SetInput(mask_vtk) |
| @@ -110,7 +112,8 @@ class SurfaceProcess(multiprocessing.Process): | @@ -110,7 +112,8 @@ class SurfaceProcess(multiprocessing.Process): | ||
| 110 | #if self.mode == "CONTOUR": | 112 | #if self.mode == "CONTOUR": |
| 111 | #print "Contour" | 113 | #print "Contour" |
| 112 | contour = vtk.vtkContourFilter() | 114 | contour = vtk.vtkContourFilter() |
| 113 | - contour.SetInput(flip.GetOutput()) | 115 | + contour.SetInput(image) |
| 116 | + #contour.SetInput(flip.GetOutput()) | ||
| 114 | if self.from_binary: | 117 | if self.from_binary: |
| 115 | contour.SetValue(0, 127) # initial threshold | 118 | contour.SetValue(0, 127) # initial threshold |
| 116 | else: | 119 | else: |
invesalius/data/viewer_slice.py
| @@ -1311,7 +1311,7 @@ class Viewer(wx.Panel): | @@ -1311,7 +1311,7 @@ class Viewer(wx.Panel): | ||
| 1311 | def __update_camera(self): | 1311 | def __update_camera(self): |
| 1312 | orientation = self.orientation | 1312 | orientation = self.orientation |
| 1313 | proj = project.Project() | 1313 | proj = project.Project() |
| 1314 | - orig_orien = 1 #proj.original_orientation | 1314 | + orig_orien = proj.original_orientation |
| 1315 | 1315 | ||
| 1316 | self.cam.SetFocalPoint(0, 0, 0) | 1316 | self.cam.SetFocalPoint(0, 0, 0) |
| 1317 | self.cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation]) | 1317 | self.cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation]) |
invesalius/data/viewer_volume.py
| @@ -180,8 +180,6 @@ class Viewer(wx.Panel): | @@ -180,8 +180,6 @@ class Viewer(wx.Panel): | ||
| 180 | 180 | ||
| 181 | Publisher.subscribe(self.RemoveVolume, 'Remove Volume') | 181 | Publisher.subscribe(self.RemoveVolume, 'Remove Volume') |
| 182 | 182 | ||
| 183 | - | ||
| 184 | - | ||
| 185 | def SetStereoMode(self, pubsub_evt): | 183 | def SetStereoMode(self, pubsub_evt): |
| 186 | mode = pubsub_evt.data | 184 | mode = pubsub_evt.data |
| 187 | ren_win = self.interactor.GetRenderWindow() | 185 | ren_win = self.interactor.GetRenderWindow() |
| @@ -210,7 +208,6 @@ class Viewer(wx.Panel): | @@ -210,7 +208,6 @@ class Viewer(wx.Panel): | ||
| 210 | 208 | ||
| 211 | self.interactor.Render() | 209 | self.interactor.Render() |
| 212 | 210 | ||
| 213 | - | ||
| 214 | def CreateBallReference(self): | 211 | def CreateBallReference(self): |
| 215 | self.ball_reference = vtk.vtkSphereSource() | 212 | self.ball_reference = vtk.vtkSphereSource() |
| 216 | self.ball_reference.SetRadius(5) | 213 | self.ball_reference.SetRadius(5) |
| @@ -271,7 +268,6 @@ class Viewer(wx.Panel): | @@ -271,7 +268,6 @@ class Viewer(wx.Panel): | ||
| 271 | 268 | ||
| 272 | image = image.GetOutput() | 269 | image = image.GetOutput() |
| 273 | 270 | ||
| 274 | - | ||
| 275 | # write image file | 271 | # write image file |
| 276 | if (filetype == const.FILETYPE_BMP): | 272 | if (filetype == const.FILETYPE_BMP): |
| 277 | writer = vtk.vtkBMPWriter() | 273 | writer = vtk.vtkBMPWriter() |
| @@ -289,8 +285,6 @@ class Viewer(wx.Panel): | @@ -289,8 +285,6 @@ class Viewer(wx.Panel): | ||
| 289 | writer.SetFileName(filename) | 285 | writer.SetFileName(filename) |
| 290 | writer.Write() | 286 | writer.Write() |
| 291 | Publisher.sendMessage('End busy cursor') | 287 | Publisher.sendMessage('End busy cursor') |
| 292 | - | ||
| 293 | - | ||
| 294 | 288 | ||
| 295 | def OnCloseProject(self, pubsub_evt): | 289 | def OnCloseProject(self, pubsub_evt): |
| 296 | if self.raycasting_volume: | 290 | if self.raycasting_volume: |
| @@ -844,8 +838,8 @@ class SlicePlane: | @@ -844,8 +838,8 @@ class SlicePlane: | ||
| 844 | def Create(self): | 838 | def Create(self): |
| 845 | plane_x = self.plane_x = vtk.vtkImagePlaneWidget() | 839 | plane_x = self.plane_x = vtk.vtkImagePlaneWidget() |
| 846 | plane_x.InteractionOff() | 840 | plane_x.InteractionOff() |
| 847 | - Publisher.sendMessage('Input Image in the widget', | ||
| 848 | - (plane_x, 'SAGITAL')) | 841 | + #Publisher.sendMessage('Input Image in the widget', |
| 842 | + #(plane_x, 'SAGITAL')) | ||
| 849 | plane_x.SetPlaneOrientationToXAxes() | 843 | plane_x.SetPlaneOrientationToXAxes() |
| 850 | plane_x.TextureVisibilityOn() | 844 | plane_x.TextureVisibilityOn() |
| 851 | plane_x.SetLeftButtonAction(0) | 845 | plane_x.SetLeftButtonAction(0) |
| @@ -856,8 +850,8 @@ class SlicePlane: | @@ -856,8 +850,8 @@ class SlicePlane: | ||
| 856 | 850 | ||
| 857 | plane_y = self.plane_y = vtk.vtkImagePlaneWidget() | 851 | plane_y = self.plane_y = vtk.vtkImagePlaneWidget() |
| 858 | plane_y.DisplayTextOff() | 852 | plane_y.DisplayTextOff() |
| 859 | - Publisher.sendMessage('Input Image in the widget', | ||
| 860 | - (plane_y, 'CORONAL')) | 853 | + #Publisher.sendMessage('Input Image in the widget', |
| 854 | + #(plane_y, 'CORONAL')) | ||
| 861 | plane_y.SetPlaneOrientationToYAxes() | 855 | plane_y.SetPlaneOrientationToYAxes() |
| 862 | plane_y.TextureVisibilityOn() | 856 | plane_y.TextureVisibilityOn() |
| 863 | plane_y.SetLeftButtonAction(0) | 857 | plane_y.SetLeftButtonAction(0) |
| @@ -869,8 +863,8 @@ class SlicePlane: | @@ -869,8 +863,8 @@ class SlicePlane: | ||
| 869 | 863 | ||
| 870 | plane_z = self.plane_z = vtk.vtkImagePlaneWidget() | 864 | plane_z = self.plane_z = vtk.vtkImagePlaneWidget() |
| 871 | plane_z.InteractionOff() | 865 | plane_z.InteractionOff() |
| 872 | - Publisher.sendMessage('Input Image in the widget', | ||
| 873 | - (plane_z, 'AXIAL')) | 866 | + #Publisher.sendMessage('Input Image in the widget', |
| 867 | + #(plane_z, 'AXIAL')) | ||
| 874 | plane_z.SetPlaneOrientationToZAxes() | 868 | plane_z.SetPlaneOrientationToZAxes() |
| 875 | plane_z.TextureVisibilityOn() | 869 | plane_z.TextureVisibilityOn() |
| 876 | plane_z.SetLeftButtonAction(0) | 870 | plane_z.SetLeftButtonAction(0) |
invesalius/data/volume.py
| @@ -85,6 +85,7 @@ class Volume(): | @@ -85,6 +85,7 @@ class Volume(): | ||
| 85 | self.plane = None | 85 | self.plane = None |
| 86 | self.plane_on = False | 86 | self.plane_on = False |
| 87 | self.volume = None | 87 | self.volume = None |
| 88 | + self.image = None | ||
| 88 | self.loaded_image = 0 | 89 | self.loaded_image = 0 |
| 89 | self.__bind_events() | 90 | self.__bind_events() |
| 90 | 91 | ||
| @@ -109,6 +110,8 @@ class Volume(): | @@ -109,6 +110,8 @@ class Volume(): | ||
| 109 | 110 | ||
| 110 | Publisher.subscribe(self.ResetRayCasting, 'Reset Reaycasting') | 111 | Publisher.subscribe(self.ResetRayCasting, 'Reset Reaycasting') |
| 111 | 112 | ||
| 113 | + Publisher.subscribe(self.OnFlipVolume, 'Flip volume') | ||
| 114 | + | ||
| 112 | def ResetRayCasting(self, pub_evt): | 115 | def ResetRayCasting(self, pub_evt): |
| 113 | if self.exist: | 116 | if self.exist: |
| 114 | self.exist = None | 117 | self.exist = None |
| @@ -171,6 +174,13 @@ class Volume(): | @@ -171,6 +174,13 @@ class Volume(): | ||
| 171 | colour = self.GetBackgroundColour() | 174 | colour = self.GetBackgroundColour() |
| 172 | Publisher.sendMessage('Change volume viewer background colour', colour) | 175 | Publisher.sendMessage('Change volume viewer background colour', colour) |
| 173 | Publisher.sendMessage('Change volume viewer gui colour', colour) | 176 | Publisher.sendMessage('Change volume viewer gui colour', colour) |
| 177 | + | ||
| 178 | + def OnFlipVolume(self, pubsub_evt): | ||
| 179 | + print "Flipping Volume" | ||
| 180 | + self.loaded_image = False | ||
| 181 | + del self.image | ||
| 182 | + self.image = None | ||
| 183 | + self.exist = None | ||
| 174 | 184 | ||
| 175 | def __load_preset_config(self): | 185 | def __load_preset_config(self): |
| 176 | self.config = prj.Project().raycasting_preset | 186 | self.config = prj.Project().raycasting_preset |
| @@ -461,19 +471,15 @@ class Volume(): | @@ -461,19 +471,15 @@ class Volume(): | ||
| 461 | return imagedata | 471 | return imagedata |
| 462 | 472 | ||
| 463 | def LoadImage(self): | 473 | def LoadImage(self): |
| 464 | - | ||
| 465 | - | ||
| 466 | slice_data = slice_.Slice() | 474 | slice_data = slice_.Slice() |
| 467 | n_array = slice_data.matrix | 475 | n_array = slice_data.matrix |
| 468 | spacing = slice_data.spacing | 476 | spacing = slice_data.spacing |
| 469 | slice_number = 0 | 477 | slice_number = 0 |
| 470 | orientation = 'AXIAL' | 478 | orientation = 'AXIAL' |
| 471 | 479 | ||
| 472 | - | ||
| 473 | image = converters.to_vtk(n_array, spacing, slice_number, orientation) | 480 | image = converters.to_vtk(n_array, spacing, slice_number, orientation) |
| 474 | self.image = image | 481 | self.image = image |
| 475 | 482 | ||
| 476 | - | ||
| 477 | def LoadVolume(self): | 483 | def LoadVolume(self): |
| 478 | proj = prj.Project() | 484 | proj = prj.Project() |
| 479 | #image = imagedata_utils.to_vtk(n_array, spacing, slice_number, orientation) | 485 | #image = imagedata_utils.to_vtk(n_array, spacing, slice_number, orientation) |
| @@ -491,19 +497,19 @@ class Volume(): | @@ -491,19 +497,19 @@ class Volume(): | ||
| 491 | else: | 497 | else: |
| 492 | flip_image = False | 498 | flip_image = False |
| 493 | 499 | ||
| 494 | - if (flip_image): | ||
| 495 | - update_progress= vtk_utils.ShowProgress(2 + number_filters) | ||
| 496 | - # Flip original vtkImageData | ||
| 497 | - flip = vtk.vtkImageFlip() | ||
| 498 | - flip.SetInput(image) | ||
| 499 | - flip.SetFilteredAxis(1) | ||
| 500 | - flip.FlipAboutOriginOn() | ||
| 501 | - flip.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 502 | - update_progress(flip, "Rendering...")) | ||
| 503 | - flip.Update() | ||
| 504 | - image = flip.GetOutput() | ||
| 505 | - else: | ||
| 506 | - update_progress= vtk_utils.ShowProgress(1 + number_filters) | 500 | + #if (flip_image): |
| 501 | + update_progress= vtk_utils.ShowProgress(2 + number_filters) | ||
| 502 | + # Flip original vtkImageData | ||
| 503 | + flip = vtk.vtkImageFlip() | ||
| 504 | + flip.SetInput(image) | ||
| 505 | + flip.SetFilteredAxis(1) | ||
| 506 | + flip.FlipAboutOriginOn() | ||
| 507 | + flip.AddObserver("ProgressEvent", lambda obj,evt: | ||
| 508 | + update_progress(flip, "Rendering...")) | ||
| 509 | + flip.Update() | ||
| 510 | + image = flip.GetOutput() | ||
| 511 | + #else: | ||
| 512 | + #update_progress= vtk_utils.ShowProgress(1 + number_filters) | ||
| 507 | 513 | ||
| 508 | scale = image.GetScalarRange() | 514 | scale = image.GetScalarRange() |
| 509 | self.scale = scale | 515 | self.scale = scale |
invesalius/gui/dicom_preview_panel.py
| @@ -813,7 +813,12 @@ class SingleImagePreview(wx.Panel): | @@ -813,7 +813,12 @@ class SingleImagePreview(wx.Panel): | ||
| 813 | 813 | ||
| 814 | ## Text related to slice position | 814 | ## Text related to slice position |
| 815 | value1 = STR_SPC %(dicom.image.spacing[2]) | 815 | value1 = STR_SPC %(dicom.image.spacing[2]) |
| 816 | - value2 = STR_LOCAL %(dicom.image.position[2]) | 816 | + if dicom.image.orientation_label == 'AXIAL': |
| 817 | + value2 = STR_LOCAL %(dicom.image.position[2]) | ||
| 818 | + elif dicom.image.orientation_label == 'CORONAL': | ||
| 819 | + value2 = STR_LOCAL %(dicom.image.position[1]) | ||
| 820 | + elif dicom.image.orientation_label == 'SAGITTAL': | ||
| 821 | + value2 = STR_LOCAL %(dicom.image.position[0]) | ||
| 817 | value = "%s\n%s" %(value1, value2) | 822 | value = "%s\n%s" %(value1, value2) |
| 818 | self.text_image_location.SetValue(value) | 823 | self.text_image_location.SetValue(value) |
| 819 | 824 |
invesalius/gui/frame.py
| @@ -339,6 +339,11 @@ class Frame(wx.Frame): | @@ -339,6 +339,11 @@ class Frame(wx.Frame): | ||
| 339 | self.ShowPreferences() | 339 | self.ShowPreferences() |
| 340 | elif id == const.ID_DICOM_NETWORK: | 340 | elif id == const.ID_DICOM_NETWORK: |
| 341 | self.ShowRetrieveDicomPanel() | 341 | self.ShowRetrieveDicomPanel() |
| 342 | + elif id in (const.ID_FLIP_X, const.ID_FLIP_Y, const.ID_FLIP_Z): | ||
| 343 | + axis = {const.ID_FLIP_X: 2, | ||
| 344 | + const.ID_FLIP_Y: 1, | ||
| 345 | + const.ID_FLIP_Z: 0}[id] | ||
| 346 | + self.FlipVolume(axis) | ||
| 342 | 347 | ||
| 343 | def OnSize(self, evt): | 348 | def OnSize(self, evt): |
| 344 | """ | 349 | """ |
| @@ -409,6 +414,10 @@ class Frame(wx.Frame): | @@ -409,6 +414,10 @@ class Frame(wx.Frame): | ||
| 409 | """ | 414 | """ |
| 410 | Publisher.sendMessage('Show analyze dialog', True) | 415 | Publisher.sendMessage('Show analyze dialog', True) |
| 411 | 416 | ||
| 417 | + def FlipVolume(self, axis): | ||
| 418 | + Publisher.sendMessage('Flip volume', axis) | ||
| 419 | + Publisher.sendMessage('Reload actual slice') | ||
| 420 | + | ||
| 412 | # ------------------------------------------------------------------ | 421 | # ------------------------------------------------------------------ |
| 413 | # ------------------------------------------------------------------ | 422 | # ------------------------------------------------------------------ |
| 414 | # ------------------------------------------------------------------ | 423 | # ------------------------------------------------------------------ |
| @@ -474,12 +483,23 @@ class MenuBar(wx.MenuBar): | @@ -474,12 +483,23 @@ class MenuBar(wx.MenuBar): | ||
| 474 | #file_menu.AppendSeparator() | 483 | #file_menu.AppendSeparator() |
| 475 | app(const.ID_EXIT, _("Exit")) | 484 | app(const.ID_EXIT, _("Exit")) |
| 476 | 485 | ||
| 477 | - # EDIT | ||
| 478 | - #file_edit = wx.Menu() | ||
| 479 | - #app = file_edit.Append | 486 | + |
| 487 | + ############################### EDIT############################### | ||
| 488 | + # Flip | ||
| 489 | + flip_menu = wx.Menu() | ||
| 490 | + app = flip_menu.Append | ||
| 491 | + app(const.ID_FLIP_X, _("R <-> L")) | ||
| 492 | + app(const.ID_FLIP_Y, _("A <-> P")) | ||
| 493 | + app(const.ID_FLIP_Z, _("T <-> B")) | ||
| 494 | + | ||
| 495 | + file_edit = wx.Menu() | ||
| 496 | + app = file_edit.Append | ||
| 497 | + file_edit.AppendMenu(wx.NewId(), _('Flip'), flip_menu) | ||
| 480 | #app(wx.ID_UNDO, "Undo\tCtrl+Z") | 498 | #app(wx.ID_UNDO, "Undo\tCtrl+Z") |
| 481 | #app(wx.ID_REDO, "Redo\tCtrl+Y") | 499 | #app(wx.ID_REDO, "Redo\tCtrl+Y") |
| 482 | #app(const.ID_EDIT_LIST, "Show Undo List...") | 500 | #app(const.ID_EDIT_LIST, "Show Undo List...") |
| 501 | + ################################################################# | ||
| 502 | + | ||
| 483 | 503 | ||
| 484 | # VIEW | 504 | # VIEW |
| 485 | #view_tool_menu = wx.Menu() | 505 | #view_tool_menu = wx.Menu() |
| @@ -527,7 +547,7 @@ class MenuBar(wx.MenuBar): | @@ -527,7 +547,7 @@ class MenuBar(wx.MenuBar): | ||
| 527 | 547 | ||
| 528 | # Add all menus to menubar | 548 | # Add all menus to menubar |
| 529 | self.Append(file_menu, _("File")) | 549 | self.Append(file_menu, _("File")) |
| 530 | - #self.Append(file_edit, "Edit") | 550 | + self.Append(file_edit, "Edit") |
| 531 | #self.Append(view_menu, "View") | 551 | #self.Append(view_menu, "View") |
| 532 | #self.Append(tools_menu, "Tools") | 552 | #self.Append(tools_menu, "Tools") |
| 533 | self.Append(options_menu, _("Options")) | 553 | self.Append(options_menu, _("Options")) |