From f7a5655a4a0ea49900ba20f7ecef1926b2bf70c5 Mon Sep 17 00:00:00 2001 From: tfmoraes Date: Mon, 18 Oct 2010 18:11:05 +0000 Subject: [PATCH] ENH: Handle sagittal and coronal images. --- invesalius/control.py | 28 ++++++++++++++++++++++------ invesalius/data/imagedata_utils.py | 38 +++++++++++++++++++++++++++++++------- invesalius/data/slice_.py | 14 ++++++-------- invesalius/data/viewer_slice.py | 124 ++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------------------- 4 files changed, 91 insertions(+), 113 deletions(-) diff --git a/invesalius/control.py b/invesalius/control.py index 3f3b7fc..3e4f194 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -357,7 +357,7 @@ class Controller(): ps.Publisher().sendMessage('Load slice to viewer', (proj.imagedata, proj.mask_dict)) - ps.Publisher().sendMessage('Load slice plane') + #ps.Publisher().sendMessage('Load slice plane') ps.Publisher().sendMessage('Bright and contrast adjustment image',\ (proj.window, proj.level)) ps.Publisher().sendMessage('Update window level value',\ @@ -409,7 +409,7 @@ class Controller(): name_to_const[dicom.image.orientation_label] proj.window = float(dicom.image.window) proj.level = float(dicom.image.level) - proj.threshold_range = imagedata.GetScalarRange() + proj.threshold_range = (-1024, 3033) ###### @@ -445,14 +445,17 @@ class Controller(): bits = dicom.image.bits_allocad sop_class_uid = dicom.acquisition.sop_class_uid xyspacing = dicom.image.spacing + orientation = dicom.image.orientation_label if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage use_dcmspacing = 1 else: use_dcmspacing = 0 - imagedata = utils.CreateImageData(filelist, zspacing, xyspacing,size, - bits, use_dcmspacing) + #imagedata = utils.CreateImageData(filelist, zspacing, xyspacing,size, + #bits, use_dcmspacing) + + imagedata = None # 1(a): Fix gantry tilt, if any tilt_value = dicom.acquisition.tilt @@ -466,10 +469,23 @@ class Controller(): tilt_value = -1*tilt_value imagedata = utils.FixGantryTilt(imagedata, tilt_value) - self.matrix, self.filename = utils.dcm2memmap(filelist, size) + wl = float(dicom.image.level) + ww = float(dicom.image.window) + + self.matrix, self.filename = utils.dcm2memmap(filelist, size, + orientation) self.Slice = sl.Slice() self.Slice.matrix = self.matrix - self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing + + if orientation == 'AXIAL': + self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing + elif orientation == 'CORONAL': + self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1] + elif orientation == 'SAGITTAL': + self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0] + + self.Slice.window_level = wl + self.Slice.window_width = ww return imagedata, dicom def LoadImagedataInfo(self): diff --git a/invesalius/data/imagedata_utils.py b/invesalius/data/imagedata_utils.py index 7a41241..c7a9190 100644 --- a/invesalius/data/imagedata_utils.py +++ b/invesalius/data/imagedata_utils.py @@ -456,13 +456,19 @@ class ImageCreator: return imagedata -def dcm2memmap(files, slice_size): +def dcm2memmap(files, slice_size, orientation): """ From a list of dicom files it creates memmap file in the temp folder and returns it and its related filename. """ temp_file = tempfile.mktemp() - shape = len(files), slice_size[1], slice_size[0] + + if orientation == 'SAGITTAL': + shape = slice_size[0], slice_size[1], len(files) + elif orientation == 'CORONAL': + shape = slice_size[1], len(files), slice_size[0] + else: + shape = len(files), slice_size[1], slice_size[0] matrix = numpy.memmap(temp_file, mode='w+', dtype='int16', shape=shape) dcm_reader = vtkgdcm.vtkGDCMImageReader() @@ -471,25 +477,43 @@ def dcm2memmap(files, slice_size): dcm_reader.Update() image = dcm_reader.GetOutput() array = numpy_support.vtk_to_numpy(image.GetPointData().GetScalars()) - array.shape = matrix.shape[1], matrix.shape[2] - matrix[n] = array + if orientation == 'CORONAL': + array.shape = matrix.shape[0], matrix.shape[2] + matrix[:, n, :] = array + elif orientation == 'SAGITTAL': + array.shape = matrix.shape[0], matrix.shape[1] + matrix[:, :, n] = array + else: + array.shape = matrix.shape[1], matrix.shape[2] + matrix[n] = array matrix.flush() return matrix, temp_file -def to_vtk(n_array, spacing): +def to_vtk(n_array, spacing, slice_number, orientation): dy, dx = n_array.shape n_array.shape = dx * dy v_image = numpy_support.numpy_to_vtk(n_array) + print orientation + if orientation == 'AXIAL': + dz = 1 + extent = (0, dx -1, 0, dy -1, slice_number, slice_number) + elif orientation == 'SAGITAL': + dx, dy, dz = 1, dx, dy + extent = (slice_number, slice_number, 0, dy - 1, 0, dz - 1) + elif orientation == 'CORONAL': + dx, dy, dz = dx, 1, dy + extent = (0, dx - 1, slice_number, slice_number, 0, dz - 1) + # Generating the vtkImageData image = vtk.vtkImageData() - image.SetDimensions(dx, dy, 1) image.SetOrigin(0, 0, 0) image.SetSpacing(spacing) image.SetNumberOfScalarComponents(1) - image.SetExtent(0, dx -1, 0, dy -1, 0, 0) + image.SetDimensions(dx, dy, dz) + image.SetExtent(extent) image.SetScalarType(numpy_support.get_vtk_array_type(n_array.dtype)) image.AllocateScalars() image.GetPointData().SetScalars(v_image) diff --git a/invesalius/data/slice_.py b/invesalius/data/slice_.py index 6b8b798..97a6f85 100644 --- a/invesalius/data/slice_.py +++ b/invesalius/data/slice_.py @@ -239,15 +239,11 @@ class Slice(object): def GetSlices(self, orientation, slice_number): if orientation == 'AXIAL': n_array = numpy.array(self.matrix[slice_number]) - spacing = self.spacing elif orientation == 'CORONAL': n_array = numpy.array(self.matrix[..., slice_number, ...]) - spacing = self.spacing[0], self.spacing[2], self.spacing[1] elif orientation == 'SAGITAL': n_array = numpy.array(self.matrix[..., ..., slice_number]) - spacing = self.spacing[1], self.spacing[2], self.spacing[0] - - image = iu.to_vtk(n_array, spacing) + image = iu.to_vtk(n_array, self.spacing, slice_number, orientation) image = self.do_ww_wl(image) return image @@ -619,11 +615,13 @@ class Slice(object): ps.Publisher().sendMessage('Update slice viewer') def do_ww_wl(self, image): + print self.window_width, self.window_level + print image.GetScalarRange() colorer = vtk.vtkImageMapToWindowLevelColors() colorer.SetInput(image) - colorer.SetWindow(255) - colorer.SetLevel(127) - colorer.SetOutputFormatToRGBA() + colorer.SetWindow(self.window_width) + colorer.SetLevel(self.window_level) + colorer.SetOutputFormatToRGB() colorer.Update() return colorer.GetOutput() diff --git a/invesalius/data/viewer_slice.py b/invesalius/data/viewer_slice.py index 37e6353..ba79522 100755 --- a/invesalius/data/viewer_slice.py +++ b/invesalius/data/viewer_slice.py @@ -173,7 +173,6 @@ class Viewer(wx.Panel): self.cam = ren.GetActiveCamera() self.ren = ren - def SetInteractorStyle(self, state): self.state = state action = {const.SLICE_STATE_CROSS: @@ -1056,26 +1055,26 @@ class Viewer(wx.Panel): return cursor def SetInput(self, imagedata, mask_dict): - pass - #self.imagedata = imagedata + self.slice_ = sl.Slice() - ##ren = self.ren - #interactor = self.interactor + max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation) + self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, + max_slice_number) - ## Slice pipeline, to be inserted into current viewer - #slice_ = sl.Slice() + self.actor = vtk.vtkImageActor() + self.ren.AddActor(self.actor) + self.set_slice_number(0) + self.__update_camera() + self.ren.ResetCamera() #if slice_.imagedata is None: #slice_.SetInput(imagedata, mask_dict) - actor = vtk.vtkImageActor() ##actor.SetInput(slice_.GetOutput()) #self.LoadRenderers(slice_.GetOutput()) #self.__configure_renderers() #ren = self.slice_data_list[0].renderer #actor = self.slice_data_list[0].actor #actor_bound = actor.GetBounds() - self.actor = actor - self.ren.AddActor(self.actor) #self.cam = ren.GetActiveCamera() #for slice_data in self.slice_data_list: @@ -1088,12 +1087,10 @@ class Viewer(wx.Panel): #if actor.GetSliceNumberMax() % number_of_slices: #max_slice_number += 1 - max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation) - self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number, - max_slice_number) #self.set_scroll_position(0) #actor_bound = actor.GetBounds() + self.interactor.Render() #self.EnableText() ## Insert cursor @@ -1268,43 +1265,23 @@ class Viewer(wx.Panel): renderer.AddViewProp(slice_data.box_actor) return slice_data - def __update_camera(self, slice_data): + def __update_camera(self): orientation = self.orientation proj = project.Project() - orig_orien = proj.original_orientation + orig_orien = 1 #proj.original_orientation - cam = slice_data.renderer.GetActiveCamera() - cam.SetFocalPoint(0, 0, 0) - cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation]) - cam.SetPosition(const.SLICE_POSITION[orig_orien][1][self.orientation]) - cam.ComputeViewPlaneNormal() - cam.OrthogonalizeViewUp() - cam.ParallelProjectionOn() - - self.__update_display_extent(slice_data) + self.cam.SetFocalPoint(0, 0, 0) + self.cam.SetViewUp(const.SLICE_POSITION[orig_orien][0][self.orientation]) + self.cam.SetPosition(const.SLICE_POSITION[orig_orien][1][self.orientation]) + self.cam.ComputeViewPlaneNormal() + self.cam.OrthogonalizeViewUp() + self.cam.ParallelProjectionOn() - slice_data.renderer.ResetCamera() #slice_data.renderer.Render() - def __update_display_extent(self, slice_data): - e = self.imagedata.GetWholeExtent() - proj = project.Project() - - pos = slice_data.number - - x = (pos, pos, e[2], e[3], e[4], e[5]) - y = (e[0], e[1], pos, pos, e[4], e[5]) - z = (e[0], e[1], e[2], e[3], pos, pos) - - if (proj.original_orientation == const.AXIAL): - new_extent = {"SAGITAL": x, "CORONAL": y, "AXIAL": z} - elif(proj.original_orientation == const.SAGITAL): - new_extent = {"SAGITAL": z,"CORONAL": x,"AXIAL": y} - elif(proj.original_orientation == const.CORONAL): - new_extent = {"SAGITAL": x,"CORONAL": z,"AXIAL": y} - - slice_data.actor.SetDisplayExtent(new_extent[self.orientation]) - slice_data.renderer.ResetCameraClippingRange() + def __update_display_extent(self, image): + self.actor.SetDisplayExtent(image.GetExtent()) + self.ren.ResetCameraClippingRange() def UpdateRender(self, evt): self.interactor.Render() @@ -1341,18 +1318,10 @@ class Viewer(wx.Panel): def OnScrollBar(self, evt=None): pos = self.scroll.GetThumbPosition() - slice_ = sl.Slice() - image = slice_.GetSlices(self.orientation, pos) - self.actor.SetInput(image) - self.ren.ResetCamera() + self.set_slice_number(pos) self.interactor.Render() - print "slice", pos - #self.set_slice_number(pos) - ##self.UpdateSlice3D(pos) - #self.pos = pos - #self.interactor.Render() - #if evt: - #evt.Skip() + if evt: + evt.Skip() def OnScrollBarRelease(self, evt): #self.UpdateSlice3D(self.pos) @@ -1409,43 +1378,14 @@ class Viewer(wx.Panel): evt.Skip() def set_slice_number(self, index): - self.slice_number = index - # for m in self.actors_by_slice_number.values(): - # for actor in m: - # actor.SetVisibility(0) - # Removing actor from the previous renderers/slice. - for n in self.renderers_by_slice_number: - renderer = self.renderers_by_slice_number[n] - for actor in self.actors_by_slice_number.get(n, []): - renderer.RemoveActor(actor) - - self.renderers_by_slice_number = {} - - for n, slice_data in enumerate(self.slice_data_list): - ren = slice_data.renderer - actor = slice_data.actor - pos = self.layout[0] * self.layout[1] * index + n - max = actor.GetSliceNumberMax() + 1 - if pos < max: - self.renderers_by_slice_number[pos] = ren - for m_actor in self.actors_by_slice_number.get(pos, []): - ren.AddActor(m_actor) - slice_data.SetNumber(pos) - # for actor in self.actors_by_slice_number.get(pos, []): - # actor.SetVisibility(1) - self.__update_display_extent(slice_data) - slice_data.Show() - else: - slice_data.Hide() - - position = {"SAGITAL": {0: slice_data.number}, - "CORONAL": {1: slice_data.number}, - "AXIAL": {2: slice_data.number}} - - #if 'DEFAULT' in self.modes: - # ps.Publisher().sendMessage( - # 'Update cursor single position in slice', - # position[self.orientation]) + image = self.slice_.GetSlices(self.orientation, index) + self.actor.SetInput(image) + self.__update_display_extent(image) + print "slice", index + print "display extent", self.actor.GetDisplayExtent() + print "whole extent", image.GetWholeExtent() + print "boundsa", self.actor.GetBounds() + print "camera", self.cam.GetPosition(), self.cam.GetFocalPoint() def ChangeSliceNumber(self, pubsub_evt): index = pubsub_evt.data -- libgit2 0.21.2