Commit 56f7a1283c671a4c09f79436ae308dde88cfb46a

Authored by tfmoraes
1 parent 295c16a0

Adapted camera positions to coronal and sagital cases, and added the option to flip image

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"))