Commit 1d943e8d147ffac0538373624700f23c076a8d60

Authored by tfmoraes
1 parent fe94b6bb

ENH: Loading images from memmap in viewer slices without the masks.

* The images are being loaded in viewer slices without the masks;
* The imagedata with all slices are being loaded too, but not showed
* The images are loaded with a hardcoded WL & WW
invesalius/control.py
@@ -27,6 +27,7 @@ import constants as const @@ -27,6 +27,7 @@ import constants as const
27 import data.imagedata_utils as utils 27 import data.imagedata_utils as utils
28 import data.mask as msk 28 import data.mask as msk
29 import data.measures 29 import data.measures
  30 +import data.slice_ as sl
30 import data.surface as srf 31 import data.surface as srf
31 import data.volume as volume 32 import data.volume as volume
32 import gui.dialogs as dialog 33 import gui.dialogs as dialog
@@ -76,7 +77,6 @@ class Controller(): @@ -76,7 +77,6 @@ class Controller():
76 ps.Publisher().subscribe(self.OnOpenProject, 'Open project') 77 ps.Publisher().subscribe(self.OnOpenProject, 'Open project')
77 ps.Publisher().subscribe(self.OnOpenRecentProject, 'Open recent project') 78 ps.Publisher().subscribe(self.OnOpenRecentProject, 'Open recent project')
78 ps.Publisher().subscribe(self.OnShowAnalyzeFile, 'Show analyze dialog') 79 ps.Publisher().subscribe(self.OnShowAnalyzeFile, 'Show analyze dialog')
79 -  
80 80
81 def OnCancelImport(self, pubsub_evt): 81 def OnCancelImport(self, pubsub_evt):
82 #self.cancel_import = True 82 #self.cancel_import = True
@@ -466,6 +466,10 @@ class Controller(): @@ -466,6 +466,10 @@ class Controller():
466 tilt_value = -1*tilt_value 466 tilt_value = -1*tilt_value
467 imagedata = utils.FixGantryTilt(imagedata, tilt_value) 467 imagedata = utils.FixGantryTilt(imagedata, tilt_value)
468 468
  469 + self.matrix, self.filename = utils.dcm2memmap(filelist, size)
  470 + self.Slice = sl.Slice()
  471 + self.Slice.matrix = self.matrix
  472 + self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing
469 return imagedata, dicom 473 return imagedata, dicom
470 474
471 def LoadImagedataInfo(self): 475 def LoadImagedataInfo(self):
@@ -524,7 +528,3 @@ class Controller(): @@ -524,7 +528,3 @@ class Controller():
524 preset_name + '.plist') 528 preset_name + '.plist')
525 plistlib.writePlist(preset, preset_dir) 529 plistlib.writePlist(preset, preset_dir)
526 530
527 -  
528 -  
529 -  
530 -  
invesalius/data/imagedata_utils.py
@@ -478,7 +478,7 @@ def get_numpy_array_type(gdcm_pixel_format): @@ -478,7 +478,7 @@ def get_numpy_array_type(gdcm_pixel_format):
478 def dcm2memmap(files, slice_size): 478 def dcm2memmap(files, slice_size):
479 """ 479 """
480 From a list of dicom files it creates memmap file in the temp folder and 480 From a list of dicom files it creates memmap file in the temp folder and
481 - returns. 481 + returns it and its related filename.
482 """ 482 """
483 temp_file = tempfile.mktemp() 483 temp_file = tempfile.mktemp()
484 shape = len(files), slice_size[0], slice_size[1] 484 shape = len(files), slice_size[0], slice_size[1]
@@ -498,3 +498,30 @@ def dcm2memmap(files, slice_size): @@ -498,3 +498,30 @@ def dcm2memmap(files, slice_size):
498 array = numpy.frombuffer(dcm_array, dtype) 498 array = numpy.frombuffer(dcm_array, dtype)
499 array.shape = slice_size 499 array.shape = slice_size
500 matrix[n] = array 500 matrix[n] = array
  501 +
  502 + matrix.flush()
  503 + return matrix, temp_file
  504 +
  505 +def to_vtk(n_array, spacing):
  506 + dy, dx = n_array.shape
  507 + n_array.shape = dx * dy
  508 +
  509 + v_image = numpy_support.numpy_to_vtk(n_array)
  510 +
  511 + # Generating the vtkImageData
  512 + image = vtk.vtkImageData()
  513 + image.SetDimensions(dx, dy, 1)
  514 + image.SetOrigin(0, 0, 0)
  515 + image.SetSpacing(spacing)
  516 + image.SetNumberOfScalarComponents(1)
  517 + image.SetExtent(0, dx -1, 0, dy -1, 0, 0)
  518 + image.SetScalarType(numpy_support.get_vtk_array_type(n_array.dtype))
  519 + image.AllocateScalars()
  520 + image.GetPointData().SetScalars(v_image)
  521 + image.Update()
  522 +
  523 + image_copy = vtk.vtkImageData()
  524 + image_copy.DeepCopy(image)
  525 + image_copy.Update()
  526 +
  527 + return image_copy
invesalius/data/slice_.py
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais 16 # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17 # detalhes. 17 # detalhes.
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
  19 +import numpy
19 import vtk 20 import vtk
20 import wx.lib.pubsub as ps 21 import wx.lib.pubsub as ps
21 22
@@ -38,6 +39,7 @@ class Slice(object): @@ -38,6 +39,7 @@ class Slice(object):
38 self.imagedata = None 39 self.imagedata = None
39 self.current_mask = None 40 self.current_mask = None
40 self.blend_filter = None 41 self.blend_filter = None
  42 + self.matrix = None
41 43
42 self.num_gradient = 0 44 self.num_gradient = 0
43 self.interaction_style = st.StyleStateManager() 45 self.interaction_style = st.StyleStateManager()
@@ -234,6 +236,28 @@ class Slice(object): @@ -234,6 +236,28 @@ class Slice(object):
234 # END PUBSUB_EVT METHODS 236 # END PUBSUB_EVT METHODS
235 #--------------------------------------------------------------------------- 237 #---------------------------------------------------------------------------
236 238
  239 + def GetSlices(self, orientation, slice_number):
  240 + if orientation == 'AXIAL':
  241 + n_array = numpy.array(self.matrix[slice_number])
  242 + spacing = self.spacing
  243 + elif orientation == 'CORONAL':
  244 + n_array = numpy.array(self.matrix[..., slice_number, ...])
  245 + spacing = self.spacing[0], self.spacing[2], self.spacing[1]
  246 + elif orientation == 'SAGITAL':
  247 + n_array = numpy.array(self.matrix[..., ..., slice_number])
  248 + spacing = self.spacing[1], self.spacing[2], self.spacing[0]
  249 +
  250 + image = iu.to_vtk(n_array, spacing)
  251 + image = self.do_ww_wl(image)
  252 + return image
  253 +
  254 + def GetNumberOfSlices(self, orientation):
  255 + if orientation == 'AXIAL':
  256 + return self.matrix.shape[0]
  257 + elif orientation == 'CORONAL':
  258 + return self.matrix.shape[1]
  259 + elif orientation == 'SAGITAL':
  260 + return self.matrix.shape[2]
237 261
238 def SetMaskColour(self, index, colour, update=True): 262 def SetMaskColour(self, index, colour, update=True):
239 "Set a mask colour given its index and colour (RGB 0-1 values)" 263 "Set a mask colour given its index and colour (RGB 0-1 values)"
@@ -448,8 +472,6 @@ class Slice(object): @@ -448,8 +472,6 @@ class Slice(object):
448 self.window_level.SetInput(self.imagedata) 472 self.window_level.SetInput(self.imagedata)
449 473
450 def __create_background(self, imagedata): 474 def __create_background(self, imagedata):
451 - self.imagedata = imagedata  
452 -  
453 thresh_min, thresh_max = imagedata.GetScalarRange() 475 thresh_min, thresh_max = imagedata.GetScalarRange()
454 ps.Publisher().sendMessage('Update threshold limits list', (thresh_min, 476 ps.Publisher().sendMessage('Update threshold limits list', (thresh_min,
455 thresh_max)) 477 thresh_max))
@@ -471,21 +493,21 @@ class Slice(object): @@ -471,21 +493,21 @@ class Slice(object):
471 return img_colours_bg.GetOutput() 493 return img_colours_bg.GetOutput()
472 494
473 def UpdateWindowLevelBackground(self, pubsub_evt): 495 def UpdateWindowLevelBackground(self, pubsub_evt):
  496 + pass
  497 + #window, level = pubsub_evt.data
  498 + #window_level = self.window_level
474 499
475 - window, level = pubsub_evt.data  
476 - window_level = self.window_level  
477 -  
478 - if not((window == window_level.GetWindow()) and\  
479 - (level == window_level.GetLevel())): 500 + #if not((window == window_level.GetWindow()) and\
  501 + #(level == window_level.GetLevel())):
480 502
481 - window_level.SetWindow(window)  
482 - window_level.SetLevel(level)  
483 - window_level.SetOutputFormatToLuminance()  
484 - window_level.Update() 503 + #window_level.SetWindow(window)
  504 + #window_level.SetLevel(level)
  505 + #window_level.SetOutputFormatToLuminance()
  506 + #window_level.Update()
485 507
486 - thresh_min, thresh_max = window_level.GetOutput().GetScalarRange()  
487 - self.lut_bg.SetTableRange(thresh_min, thresh_max)  
488 - self.img_colours_bg.SetInput(window_level.GetOutput()) 508 + #thresh_min, thresh_max = window_level.GetOutput().GetScalarRange()
  509 + #self.lut_bg.SetTableRange(thresh_min, thresh_max)
  510 + #self.img_colours_bg.SetInput(window_level.GetOutput())
489 511
490 def UpdateColourTableBackground(self, pubsub_evt): 512 def UpdateColourTableBackground(self, pubsub_evt):
491 values = pubsub_evt.data 513 values = pubsub_evt.data
@@ -502,15 +524,16 @@ class Slice(object): @@ -502,15 +524,16 @@ class Slice(object):
502 524
503 525
504 def InputImageWidget(self, pubsub_evt): 526 def InputImageWidget(self, pubsub_evt):
505 - widget = pubsub_evt.data 527 + #widget = pubsub_evt.data
506 528
507 - flip = vtk.vtkImageFlip()  
508 - flip.SetInput(self.window_level.GetOutput())  
509 - flip.SetFilteredAxis(1)  
510 - flip.FlipAboutOriginOn()  
511 - flip.Update() 529 + #flip = vtk.vtkImageFlip()
  530 + #flip.SetInput(self.window_level.GetOutput())
  531 + #flip.SetFilteredAxis(1)
  532 + #flip.FlipAboutOriginOn()
  533 + #flip.Update()
512 534
513 - widget.SetInput(flip.GetOutput()) 535 + #widget.SetInput(flip.GetOutput())
  536 + pass
514 537
515 538
516 def CreateMask(self, imagedata=None, name=None, colour=None, 539 def CreateMask(self, imagedata=None, name=None, colour=None,
@@ -595,6 +618,16 @@ class Slice(object): @@ -595,6 +618,16 @@ class Slice(object):
595 ps.Publisher().sendMessage('Change mask selected', mask.index) 618 ps.Publisher().sendMessage('Change mask selected', mask.index)
596 ps.Publisher().sendMessage('Update slice viewer') 619 ps.Publisher().sendMessage('Update slice viewer')
597 620
  621 + def do_ww_wl(self, image):
  622 + colorer = vtk.vtkImageMapToWindowLevelColors()
  623 + colorer.SetInput(image)
  624 + colorer.SetWindow(255)
  625 + colorer.SetLevel(127)
  626 + colorer.SetOutputFormatToRGBA()
  627 + colorer.Update()
  628 +
  629 + return colorer.GetOutput()
  630 +
598 def __build_mask(self, imagedata, create=True): 631 def __build_mask(self, imagedata, create=True):
599 # create new mask instance and insert it into project 632 # create new mask instance and insert it into project
600 if create: 633 if create:
invesalius/data/viewer_slice.py
@@ -88,7 +88,7 @@ class Viewer(wx.Panel): @@ -88,7 +88,7 @@ class Viewer(wx.Panel):
88 self.on_wl = False 88 self.on_wl = False
89 self.on_text = False 89 self.on_text = False
90 # VTK pipeline and actors 90 # VTK pipeline and actors
91 - #self.__config_interactor() 91 + self.__config_interactor()
92 self.pick = vtk.vtkPropPicker() 92 self.pick = vtk.vtkPropPicker()
93 self.cross_actor = vtk.vtkActor() 93 self.cross_actor = vtk.vtkActor()
94 94
@@ -102,7 +102,6 @@ class Viewer(wx.Panel): @@ -102,7 +102,6 @@ class Viewer(wx.Panel):
102 102
103 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL) 103 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
104 self.scroll = scroll 104 self.scroll = scroll
105 -  
106 sizer = wx.BoxSizer(wx.HORIZONTAL) 105 sizer = wx.BoxSizer(wx.HORIZONTAL)
107 sizer.Add(interactor, 1, wx.EXPAND|wx.GROW) 106 sizer.Add(interactor, 1, wx.EXPAND|wx.GROW)
108 107
@@ -164,10 +163,11 @@ class Viewer(wx.Panel): @@ -164,10 +163,11 @@ class Viewer(wx.Panel):
164 self.SetLayout(layout) 163 self.SetLayout(layout)
165 164
166 def __config_interactor(self): 165 def __config_interactor(self):
167 -  
168 ren = vtk.vtkRenderer() 166 ren = vtk.vtkRenderer()
  167 + style = vtk.vtkInteractorStyleImage()
169 168
170 interactor = self.interactor 169 interactor = self.interactor
  170 + interactor.SetInteractorStyle(style)
171 interactor.GetRenderWindow().AddRenderer(ren) 171 interactor.GetRenderWindow().AddRenderer(ren)
172 172
173 self.cam = ren.GetActiveCamera() 173 self.cam = ren.GetActiveCamera()
@@ -1056,48 +1056,50 @@ class Viewer(wx.Panel): @@ -1056,48 +1056,50 @@ class Viewer(wx.Panel):
1056 return cursor 1056 return cursor
1057 1057
1058 def SetInput(self, imagedata, mask_dict): 1058 def SetInput(self, imagedata, mask_dict):
1059 - self.imagedata = imagedata 1059 + pass
  1060 + #self.imagedata = imagedata
1060 1061
1061 - #ren = self.ren  
1062 - interactor = self.interactor 1062 + ##ren = self.ren
  1063 + #interactor = self.interactor
1063 1064
1064 - # Slice pipeline, to be inserted into current viewer  
1065 - slice_ = sl.Slice()  
1066 - if slice_.imagedata is None:  
1067 - slice_.SetInput(imagedata, mask_dict) 1065 + ## Slice pipeline, to be inserted into current viewer
  1066 + #slice_ = sl.Slice()
  1067 + #if slice_.imagedata is None:
  1068 + #slice_.SetInput(imagedata, mask_dict)
1068 1069
1069 - #actor = vtk.vtkImageActor()  
1070 - #actor.SetInput(slice_.GetOutput())  
1071 - self.LoadRenderers(slice_.GetOutput())  
1072 - self.__configure_renderers()  
1073 - ren = self.slice_data_list[0].renderer  
1074 - actor = self.slice_data_list[0].actor  
1075 - actor_bound = actor.GetBounds() 1070 + actor = vtk.vtkImageActor()
  1071 + ##actor.SetInput(slice_.GetOutput())
  1072 + #self.LoadRenderers(slice_.GetOutput())
  1073 + #self.__configure_renderers()
  1074 + #ren = self.slice_data_list[0].renderer
  1075 + #actor = self.slice_data_list[0].actor
  1076 + #actor_bound = actor.GetBounds()
1076 self.actor = actor 1077 self.actor = actor
1077 - self.ren = ren  
1078 - self.cam = ren.GetActiveCamera() 1078 + self.ren.AddActor(self.actor)
  1079 + #self.cam = ren.GetActiveCamera()
1079 1080
1080 - for slice_data in self.slice_data_list:  
1081 - self.__update_camera(slice_data)  
1082 - self.Reposition(slice_data) 1081 + #for slice_data in self.slice_data_list:
  1082 + #self.__update_camera(slice_data)
  1083 + #self.Reposition(slice_data)
1083 1084
1084 - number_of_slices = self.layout[0] * self.layout[1]  
1085 - max_slice_number = actor.GetSliceNumberMax() + 1/ \  
1086 - number_of_slices 1085 + #number_of_slices = self.layout[0] * self.layout[1]
  1086 + #max_slice_number = actor.GetSliceNumberMax() + 1/ \
  1087 + #number_of_slices
1087 1088
1088 - if actor.GetSliceNumberMax() % number_of_slices:  
1089 - max_slice_number += 1 1089 + #if actor.GetSliceNumberMax() % number_of_slices:
  1090 + #max_slice_number += 1
  1091 + max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation)
1090 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, 1092 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
1091 max_slice_number) 1093 max_slice_number)
1092 - self.set_scroll_position(0) 1094 + #self.set_scroll_position(0)
1093 1095
1094 - actor_bound = actor.GetBounds() 1096 + #actor_bound = actor.GetBounds()
1095 1097
1096 - self.EnableText()  
1097 - # Insert cursor  
1098 - self.SetInteractorStyle(const.STATE_DEFAULT) 1098 + #self.EnableText()
  1099 + ## Insert cursor
  1100 + #self.SetInteractorStyle(const.STATE_DEFAULT)
1099 1101
1100 - self.__build_cross_lines() 1102 + #self.__build_cross_lines()
1101 1103
1102 def __build_cross_lines(self): 1104 def __build_cross_lines(self):
1103 actor = self.slice_data_list[0].actor 1105 actor = self.slice_data_list[0].actor
@@ -1339,15 +1341,21 @@ class Viewer(wx.Panel): @@ -1339,15 +1341,21 @@ class Viewer(wx.Panel):
1339 1341
1340 def OnScrollBar(self, evt=None): 1342 def OnScrollBar(self, evt=None):
1341 pos = self.scroll.GetThumbPosition() 1343 pos = self.scroll.GetThumbPosition()
1342 - self.set_slice_number(pos)  
1343 - #self.UpdateSlice3D(pos)  
1344 - self.pos = pos 1344 + slice_ = sl.Slice()
  1345 + image = slice_.GetSlices(self.orientation, pos)
  1346 + self.actor.SetInput(image)
  1347 + self.ren.ResetCamera()
1345 self.interactor.Render() 1348 self.interactor.Render()
1346 - if evt:  
1347 - evt.Skip() 1349 + print "slice", pos
  1350 + #self.set_slice_number(pos)
  1351 + ##self.UpdateSlice3D(pos)
  1352 + #self.pos = pos
  1353 + #self.interactor.Render()
  1354 + #if evt:
  1355 + #evt.Skip()
1348 1356
1349 def OnScrollBarRelease(self, evt): 1357 def OnScrollBarRelease(self, evt):
1350 - self.UpdateSlice3D(self.pos) 1358 + #self.UpdateSlice3D(self.pos)
1351 evt.Skip() 1359 evt.Skip()
1352 1360
1353 def OnKeyDown(self, evt=None, obj=None): 1361 def OnKeyDown(self, evt=None, obj=None):