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 27 import data.imagedata_utils as utils
28 28 import data.mask as msk
29 29 import data.measures
  30 +import data.slice_ as sl
30 31 import data.surface as srf
31 32 import data.volume as volume
32 33 import gui.dialogs as dialog
... ... @@ -76,7 +77,6 @@ class Controller():
76 77 ps.Publisher().subscribe(self.OnOpenProject, 'Open project')
77 78 ps.Publisher().subscribe(self.OnOpenRecentProject, 'Open recent project')
78 79 ps.Publisher().subscribe(self.OnShowAnalyzeFile, 'Show analyze dialog')
79   -
80 80  
81 81 def OnCancelImport(self, pubsub_evt):
82 82 #self.cancel_import = True
... ... @@ -466,6 +466,10 @@ class Controller():
466 466 tilt_value = -1*tilt_value
467 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 473 return imagedata, dicom
470 474  
471 475 def LoadImagedataInfo(self):
... ... @@ -524,7 +528,3 @@ class Controller():
524 528 preset_name + '.plist')
525 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 478 def dcm2memmap(files, slice_size):
479 479 """
480 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 483 temp_file = tempfile.mktemp()
484 484 shape = len(files), slice_size[0], slice_size[1]
... ... @@ -498,3 +498,30 @@ def dcm2memmap(files, slice_size):
498 498 array = numpy.frombuffer(dcm_array, dtype)
499 499 array.shape = slice_size
500 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 16 # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais
17 17 # detalhes.
18 18 #--------------------------------------------------------------------------
  19 +import numpy
19 20 import vtk
20 21 import wx.lib.pubsub as ps
21 22  
... ... @@ -38,6 +39,7 @@ class Slice(object):
38 39 self.imagedata = None
39 40 self.current_mask = None
40 41 self.blend_filter = None
  42 + self.matrix = None
41 43  
42 44 self.num_gradient = 0
43 45 self.interaction_style = st.StyleStateManager()
... ... @@ -234,6 +236,28 @@ class Slice(object):
234 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 262 def SetMaskColour(self, index, colour, update=True):
239 263 "Set a mask colour given its index and colour (RGB 0-1 values)"
... ... @@ -448,8 +472,6 @@ class Slice(object):
448 472 self.window_level.SetInput(self.imagedata)
449 473  
450 474 def __create_background(self, imagedata):
451   - self.imagedata = imagedata
452   -
453 475 thresh_min, thresh_max = imagedata.GetScalarRange()
454 476 ps.Publisher().sendMessage('Update threshold limits list', (thresh_min,
455 477 thresh_max))
... ... @@ -471,21 +493,21 @@ class Slice(object):
471 493 return img_colours_bg.GetOutput()
472 494  
473 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 512 def UpdateColourTableBackground(self, pubsub_evt):
491 513 values = pubsub_evt.data
... ... @@ -502,15 +524,16 @@ class Slice(object):
502 524  
503 525  
504 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 539 def CreateMask(self, imagedata=None, name=None, colour=None,
... ... @@ -595,6 +618,16 @@ class Slice(object):
595 618 ps.Publisher().sendMessage('Change mask selected', mask.index)
596 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 631 def __build_mask(self, imagedata, create=True):
599 632 # create new mask instance and insert it into project
600 633 if create:
... ...
invesalius/data/viewer_slice.py
... ... @@ -88,7 +88,7 @@ class Viewer(wx.Panel):
88 88 self.on_wl = False
89 89 self.on_text = False
90 90 # VTK pipeline and actors
91   - #self.__config_interactor()
  91 + self.__config_interactor()
92 92 self.pick = vtk.vtkPropPicker()
93 93 self.cross_actor = vtk.vtkActor()
94 94  
... ... @@ -102,7 +102,6 @@ class Viewer(wx.Panel):
102 102  
103 103 scroll = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
104 104 self.scroll = scroll
105   -
106 105 sizer = wx.BoxSizer(wx.HORIZONTAL)
107 106 sizer.Add(interactor, 1, wx.EXPAND|wx.GROW)
108 107  
... ... @@ -164,10 +163,11 @@ class Viewer(wx.Panel):
164 163 self.SetLayout(layout)
165 164  
166 165 def __config_interactor(self):
167   -
168 166 ren = vtk.vtkRenderer()
  167 + style = vtk.vtkInteractorStyleImage()
169 168  
170 169 interactor = self.interactor
  170 + interactor.SetInteractorStyle(style)
171 171 interactor.GetRenderWindow().AddRenderer(ren)
172 172  
173 173 self.cam = ren.GetActiveCamera()
... ... @@ -1056,48 +1056,50 @@ class Viewer(wx.Panel):
1056 1056 return cursor
1057 1057  
1058 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 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 1092 self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
1091 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 1104 def __build_cross_lines(self):
1103 1105 actor = self.slice_data_list[0].actor
... ... @@ -1339,15 +1341,21 @@ class Viewer(wx.Panel):
1339 1341  
1340 1342 def OnScrollBar(self, evt=None):
1341 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 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 1357 def OnScrollBarRelease(self, evt):
1350   - self.UpdateSlice3D(self.pos)
  1358 + #self.UpdateSlice3D(self.pos)
1351 1359 evt.Skip()
1352 1360  
1353 1361 def OnKeyDown(self, evt=None, obj=None):
... ...