コード例 #1
0
ファイル: comedi_utils.py プロジェクト: fvpolpeta/devide
    def __init__(self, rwi, renderer):
        # nnsmit-edit
        self.overlay_active = 0;
        # end edit
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

	    # nnsmit-edit
    	self.overlay_ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut2 = self.overlay_ipws[0].GetLookupTable()
        lut2.SetNumberOfTableValues(3)
        lut2.SetTableValue(0,0,0,0,0)
        lut2.SetTableValue(1,0.5,0,1,1)
        lut2.SetTableValue(2,1,0,0,1)
        lut2.Build()
        for ipw_overlay in self.overlay_ipws:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)

        # now actually connect the sync_overlay observer
        for i,ipw in enumerate(self.ipws):
            ipw.AddObserver('InteractionEvent',lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(self.ipws,i))
        # end edit

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)
コード例 #2
0
    def __init__(self, rwi, renderer):
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)
コード例 #3
0
    def __init__(self, rwi, renderer):
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        #This is a collection of 1- or 3-component image plane widgets. Each entry corresponds to a single overlay.
        self.ipw_triads = {}
        self.add_overlay(
            0, [0, 0, 0, 0.1]
        )  #Almost-transparent black - for showing the pickable plane stored at id = 0.

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipw_triads[0][0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0, 0, 0)
        self.current_index_pos = (0, 0, 0)
コード例 #4
0
    def __init__(self, rwi, renderer):
        self.rwi = rwi        
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        #This is a collection of 1- or 3-component image plane widgets. Each entry corresponds to a single overlay.
        self.ipw_triads = {}
        self.add_overlay(0, [0, 0, 0, 0.1]) #Almost-transparent black - for showing the pickable plane stored at id = 0.
            
        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipw_triads[0][0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)
コード例 #5
0
ファイル: comedi_utils.py プロジェクト: fvpolpeta/devide
class CMSliceViewer:
    """Simple class for enabling 1 or 3 ortho slices in a 3D scene.
    """

    def __init__(self, rwi, renderer):
        # nnsmit-edit
        self.overlay_active = 0;
        # end edit
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

	    # nnsmit-edit
    	self.overlay_ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut2 = self.overlay_ipws[0].GetLookupTable()
        lut2.SetNumberOfTableValues(3)
        lut2.SetTableValue(0,0,0,0,0)
        lut2.SetTableValue(1,0.5,0,1,1)
        lut2.SetTableValue(2,1,0,0,1)
        lut2.Build()
        for ipw_overlay in self.overlay_ipws:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)

        # now actually connect the sync_overlay observer
        for i,ipw in enumerate(self.ipws):
            ipw.AddObserver('InteractionEvent',lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(self.ipws,i))
        # end edit

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)

	# nnsmit-edit
    def observer_sync_overlay(self,ipws,ipw_idx):
	    # get the primary IPW
        pipw = ipws[ipw_idx]
        # get the overlay IPW
        oipw = self.overlay_ipws[ipw_idx] 
        # get plane geometry from primary
        o,p1,p2 = pipw.GetOrigin(),pipw.GetPoint1(),pipw.GetPoint2()
        # and apply to the overlay
        oipw.SetOrigin(o)
        oipw.SetPoint1(p1)
        oipw.SetPoint2(p2)
        oipw.UpdatePlacement()   
    # end edit

    def close(self):
        self.set_input(None)
        self.dv_orientation_widget.close()
        self.set_overlay_input(None)

    def activate_slice(self, idx):
        if idx in [1,2]:
            self.ipws[idx].SetEnabled(1)
            self.ipws[idx].SetPicker(self.picker)


    def deactivate_slice(self, idx):
        if idx in [1,2]:
            self.ipws[idx].SetEnabled(0)
            self.ipws[idx].SetPicker(None)

    def get_input(self):
        return self.ipws[0].GetInput()

    def get_world_pos(self, image_pos):
        """Given image coordinates, return the corresponding world
        position.
        """

        idata = self.get_input()
        if not idata:
            return None

        ispacing = idata.GetSpacing()
        iorigin = idata.GetOrigin()
        # calculate real coords
        world = map(operator.add, iorigin,
                    map(operator.mul, ispacing, image_pos[0:3]))


    def set_perspective(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOff()

    def set_parallel(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOn()
        
    # nnsmit edit    
    def set_opacity(self,opacity):
        lut = self.ipws[0].GetLookupTable()
        lut.SetAlphaRange(opacity, opacity)
        lut.Build()
        self.ipws[0].SetLookupTable(lut)
    # end edit
    
    def _handler_mousewheel(self, event):
        # event.GetWheelRotation() is + or - 120 depending on
        # direction of turning.
        if event.ControlDown():
            delta = 10
        elif event.ShiftDown():
            delta = 1
        else:
            # if user is NOT doing shift / control, we pass on to the
            # default handling which will give control to the VTK
            # mousewheel handlers.
            self.rwi.OnMouseWheel(event)
            return
            
        if event.GetWheelRotation() > 0:
            self._ipw1_delta_slice(+delta)
        else:
            self._ipw1_delta_slice(-delta)

        self.render()
        self.ipws[0].InvokeEvent('InteractionEvent')

    def _ipw1_delta_slice(self, delta):
        """Move to the delta slices fw/bw, IF the IPW is currently
        aligned with one of the axes.
        """

        ipw = self.ipws[0]
        if ipw.GetPlaneOrientation() < 3:
            ci = ipw.GetSliceIndex()
            ipw.SetSliceIndex(ci + delta)

    def render(self):
        self.rwi.GetRenderWindow().Render()
        # nnsmit edit
        # synch those overlays:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
        # end edit    

    def reset_camera(self):
        self.renderer.ResetCamera()
        cam = self.renderer.GetActiveCamera()
        cam.SetViewUp(0,-1,0)

    def reset_to_default_view(self, view_index):
        """
        @param view_index 2 for XY
        """

        if view_index == 2:
            
            cam = self.renderer.GetActiveCamera()
            # then make sure it's up is the right way
            cam.SetViewUp(0,-1,0)
            # just set the X,Y of the camera equal to the X,Y of the
            # focal point.
            fp = cam.GetFocalPoint()
            cp = cam.GetPosition()
            if cp[2] < fp[2]:
                z = fp[2] + (fp[2] - cp[2])
            else:
                z = cp[2]

            cam.SetPosition(fp[0], fp[1], z)

            # first reset the camera
            self.renderer.ResetCamera() 
        # nnsmit edit
        # synch overlays as well:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                ipw_overlay.SetSliceIndex(0)       
        for i, ipw in enumerate(self.ipws):
                ipw.SetWindowLevel(500,-800,0)
        self.render()
        # end edit

    def set_input(self, input):
        ipw = self.ipws[0]
        ipw.DisplayTextOn()
        if input == ipw.GetInput():
            return

        if input is None:
            # remove outline actor, else this will cause errors when
            # we disable the IPWs (they call a render!)
            self.renderer.RemoveViewProp(self.outline_actor)
            self.outline_source.SetInput(None)

            self.dv_orientation_widget.set_input(None)

            for ipw in self.ipws:
                # argh, this disable causes a render
                ipw.SetEnabled(0)
                ipw.SetInput(None)

        else:
            self.outline_source.SetInput(input)
            self.renderer.AddViewProp(self.outline_actor)

            orientations = [2, 0, 1]
            active = [1, 0, 0]
            for i, ipw in enumerate(self.ipws):
                ipw.SetInput(input)
                ipw.SetWindowLevel(500,-800,0)
                ipw.SetPlaneOrientation(orientations[i]) # axial
                ipw.SetSliceIndex(0)
                ipw.SetEnabled(active[i])

            self.dv_orientation_widget.set_input(input)

    # nnsmit-edit
    # FIXME: Create pretty fix for this codeclone.
    def set_overlay_input(self, input):
        self.overlay_active = 1
        ipw = self.overlay_ipws[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active = 0;
            for ipw_overlay in self.overlay_ipws:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
コード例 #6
0
    def __init__(self, rwi, renderer):
        # nnsmit-edit
        self.overlay_active = 0;
        self.overlay_active_voxels = 0;
        self.overlay_active_100band1 = 0;
        self.overlay_active_100band2 = 0;
        self.overlay_active_100band3 = 0;
        self.overlay_active_50band1 = 0;
        self.overlay_active_50band2 = 0;
        self.overlay_active_50band3 = 0;		
		
        # end edit
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

	    # IPWS for overlay
    	self.overlay_ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.overlay_ipws[0].GetLookupTable()
        lut.SetNumberOfTableValues(3)
        lut.SetTableValue(0,0,0,0,0)
        lut.SetTableValue(1,0.5,0,1,1)
        lut.SetTableValue(2,1,0,0,1)
        lut.Build()
        for ipw_overlay in self.overlay_ipws:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)

	
	    # IPWS for voxels selected in scatterplot
    	self.overlay_ipws_voxels = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.overlay_ipws_voxels[0].GetLookupTable()
        lut.SetNumberOfTableValues(3)
        lut.SetTableValue(0,0,0,0,0)
        lut.SetTableValue(1,0.5,0,1,1)
        lut.SetTableValue(2,1,0,0,1)
        lut.Build()
        for ipw_overlay in self.overlay_ipws_voxels:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)	
	
			
			
	    # IPWS for overlay of 100%band in first row
    	self.overlay_ipws_100band1 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut1 = self.overlay_ipws_100band1[0].GetLookupTable()
        lut1.SetNumberOfTableValues(3)
        lut1.SetTableValue(0,0,0,0,0)
        lut1.SetTableValue(1, 1, 1, 0, 1)
        lut1.SetTableValue(2, 1,1,0, 1)
        lut1.Modified()
        lut1.Build()
        for ipw_overlay in self.overlay_ipws_100band1:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut1)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 50%band in first row
    	self.overlay_ipws_50band1 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut1 = self.overlay_ipws_50band1[0].GetLookupTable()
        lut1.SetNumberOfTableValues(3)
        lut1.SetTableValue(0,0,0,0,0)
        lut1.SetTableValue(1, 1, 1, 0, 1)
        lut1.SetTableValue(2, 1,1,0, 1)
        lut1.Modified()
        lut1.Build()
        for ipw_overlay in self.overlay_ipws_50band1:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut1)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
			
	    # IPWS for overlay of 100%band in second row
    	self.overlay_ipws_100band2 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        #lut2 = self.overlay_ipws_100band2[0].GetLookupTable()
        #lut2.SetNumberOfTableValues(3)
        #lut2.SetTableValue(0,0,0,0,0)
        #lut2.SetTableValue(1, 0.98,0,0, 0.37)
        #lut2.SetTableValue(2, 0.98,0,0, 0.37)
        #lut2.Modified()
        #lut2.Build()
        for ipw_overlay in self.overlay_ipws_100band2:
            ipw_overlay.SetInteractor(rwi)
            #ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 100%band in second row
    	self.overlay_ipws_50band2 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        #lut2 = self.overlay_ipws_100band2[0].GetLookupTable()
        #lut2.SetNumberOfTableValues(3)
        #lut2.SetTableValue(0,0,0,0,0)
        #lut2.SetTableValue(1, 0.98,0,0, 0.37)
        #lut2.SetTableValue(2, 0.98,0,0, 0.37)
        #lut2.Modified()
        #lut2.Build()
        for ipw_overlay in self.overlay_ipws_50band2:
            ipw_overlay.SetInteractor(rwi)
            #ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
			
	    # IPWS for overlay of 100%band in third row
    	self.overlay_ipws_100band3 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut3 = self.overlay_ipws_100band3[0].GetLookupTable()
        lut3.SetNumberOfTableValues(3)
        lut3.SetTableValue(0,0,0,0,0)
        lut3.SetTableValue(1,0,0.643,0.941, 0.5)
        lut3.SetTableValue(2,0,0.643,0.941, 0.5)
        lut3.Modified()
        lut3.Build()
        for ipw_overlay in self.overlay_ipws_100band3:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut3)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 50%band in third row
    	self.overlay_ipws_50band3 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut3 = self.overlay_ipws_50band3[0].GetLookupTable()
        lut3.SetNumberOfTableValues(3)
        lut3.SetTableValue(0,0,0,0,0)
        lut3.SetTableValue(1,0,0.643,0.941, 0.5)
        lut3.SetTableValue(2,0,0.643,0.941, 0.5)
        lut3.Modified()
        lut3.Build()
        for ipw_overlay in self.overlay_ipws_50band3:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut3)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
	
	
        # now actually connect the sync_overlay observer
        for i,ipw in enumerate(self.ipws):
            ipw.AddObserver('InteractionEvent',lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(self.ipws,i))
        # end edit

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)
コード例 #7
0
class CMSliceViewer:
    """Simple class for enabling 1 or 3 ortho slices in a 3D scene.
    """

    def __init__(self, rwi, renderer):
        # nnsmit-edit
        self.overlay_active = 0;
        self.overlay_active_voxels = 0;
        self.overlay_active_100band1 = 0;
        self.overlay_active_100band2 = 0;
        self.overlay_active_100band3 = 0;
        self.overlay_active_50band1 = 0;
        self.overlay_active_50band2 = 0;
        self.overlay_active_50band3 = 0;		
		
        # end edit
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

	    # IPWS for overlay
    	self.overlay_ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.overlay_ipws[0].GetLookupTable()
        lut.SetNumberOfTableValues(3)
        lut.SetTableValue(0,0,0,0,0)
        lut.SetTableValue(1,0.5,0,1,1)
        lut.SetTableValue(2,1,0,0,1)
        lut.Build()
        for ipw_overlay in self.overlay_ipws:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)

	
	    # IPWS for voxels selected in scatterplot
    	self.overlay_ipws_voxels = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.overlay_ipws_voxels[0].GetLookupTable()
        lut.SetNumberOfTableValues(3)
        lut.SetTableValue(0,0,0,0,0)
        lut.SetTableValue(1,0.5,0,1,1)
        lut.SetTableValue(2,1,0,0,1)
        lut.Build()
        for ipw_overlay in self.overlay_ipws_voxels:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)	
	
			
			
	    # IPWS for overlay of 100%band in first row
    	self.overlay_ipws_100band1 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut1 = self.overlay_ipws_100band1[0].GetLookupTable()
        lut1.SetNumberOfTableValues(3)
        lut1.SetTableValue(0,0,0,0,0)
        lut1.SetTableValue(1, 1, 1, 0, 1)
        lut1.SetTableValue(2, 1,1,0, 1)
        lut1.Modified()
        lut1.Build()
        for ipw_overlay in self.overlay_ipws_100band1:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut1)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 50%band in first row
    	self.overlay_ipws_50band1 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut1 = self.overlay_ipws_50band1[0].GetLookupTable()
        lut1.SetNumberOfTableValues(3)
        lut1.SetTableValue(0,0,0,0,0)
        lut1.SetTableValue(1, 1, 1, 0, 1)
        lut1.SetTableValue(2, 1,1,0, 1)
        lut1.Modified()
        lut1.Build()
        for ipw_overlay in self.overlay_ipws_50band1:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut1)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
			
	    # IPWS for overlay of 100%band in second row
    	self.overlay_ipws_100band2 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        #lut2 = self.overlay_ipws_100band2[0].GetLookupTable()
        #lut2.SetNumberOfTableValues(3)
        #lut2.SetTableValue(0,0,0,0,0)
        #lut2.SetTableValue(1, 0.98,0,0, 0.37)
        #lut2.SetTableValue(2, 0.98,0,0, 0.37)
        #lut2.Modified()
        #lut2.Build()
        for ipw_overlay in self.overlay_ipws_100band2:
            ipw_overlay.SetInteractor(rwi)
            #ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 100%band in second row
    	self.overlay_ipws_50band2 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        #lut2 = self.overlay_ipws_100band2[0].GetLookupTable()
        #lut2.SetNumberOfTableValues(3)
        #lut2.SetTableValue(0,0,0,0,0)
        #lut2.SetTableValue(1, 0.98,0,0, 0.37)
        #lut2.SetTableValue(2, 0.98,0,0, 0.37)
        #lut2.Modified()
        #lut2.Build()
        for ipw_overlay in self.overlay_ipws_50band2:
            ipw_overlay.SetInteractor(rwi)
            #ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
			
	    # IPWS for overlay of 100%band in third row
    	self.overlay_ipws_100band3 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut3 = self.overlay_ipws_100band3[0].GetLookupTable()
        lut3.SetNumberOfTableValues(3)
        lut3.SetTableValue(0,0,0,0,0)
        lut3.SetTableValue(1,0,0.643,0.941, 0.5)
        lut3.SetTableValue(2,0,0.643,0.941, 0.5)
        lut3.Modified()
        lut3.Build()
        for ipw_overlay in self.overlay_ipws_100band3:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut3)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
			
	    # IPWS for overlay of 50%band in third row
    	self.overlay_ipws_50band3 = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut3 = self.overlay_ipws_50band3[0].GetLookupTable()
        lut3.SetNumberOfTableValues(3)
        lut3.SetTableValue(0,0,0,0,0)
        lut3.SetTableValue(1,0,0.643,0.941, 0.5)
        lut3.SetTableValue(2,0,0.643,0.941, 0.5)
        lut3.Modified()
        lut3.Build()
        for ipw_overlay in self.overlay_ipws_50band3:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut3)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)
	
	
        # now actually connect the sync_overlay observer
        for i,ipw in enumerate(self.ipws):
            ipw.AddObserver('InteractionEvent',lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(self.ipws,i))
        # end edit

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)

	# nnsmit-edit
    def observer_sync_overlay(self,ipws,ipw_idx):
	    # get the primary IPW
        pipw = ipws[ipw_idx]
        # get the overlay IPW
        oipw = self.overlay_ipws[ipw_idx] 
		
        #get the voxels overlay IPW
        oipwvoxels = self.overlay_ipws_voxels[ipw_idx]
		
		#get the overlay IPW for 100%band in first row 
        oipw100r1 = self.overlay_ipws_100band1[ipw_idx]
		#get the overlay IPW for 50%band in first row 
        oipw50r1 = self.overlay_ipws_50band1[ipw_idx] 

		#get the overlay IPW for 100%band in second row 
        oipw100r2 = self.overlay_ipws_100band2[ipw_idx]
		#get the overlay IPW for 100%band in second row 
        oipw50r2 = self.overlay_ipws_50band2[ipw_idx] 
		
		#get the overlay IPW for 100%band in third row 
        oipw100r3 = self.overlay_ipws_100band3[ipw_idx]
		#get the overlay IPW for 50%band in third row 
        oipw50r3 = self.overlay_ipws_50band3[ipw_idx] 
		
        # get plane geometry from primary
        o,p1,p2 = pipw.GetOrigin(),pipw.GetPoint1(),pipw.GetPoint2()
        # and apply to the overlay
        oipw.SetOrigin(o)
        oipw.SetPoint1(p1)
        oipw.SetPoint2(p2)
        oipw.UpdatePlacement()

        oipwvoxels.SetOrigin(o)
        oipwvoxels.SetPoint1(p1)
        oipwvoxels.SetPoint2(p2)
        oipwvoxels.UpdatePlacement()
		
        oipw100r1.SetOrigin(o)
        oipw100r1.SetPoint1(p1)
        oipw100r1.SetPoint2(p2)
        oipw100r1.UpdatePlacement()   
		
        oipw50r1.SetOrigin(o)
        oipw50r1.SetPoint1(p1)
        oipw50r1.SetPoint2(p2)
        oipw50r1.UpdatePlacement()   
		
        oipw100r2.SetOrigin(o)
        oipw100r2.SetPoint1(p1)
        oipw100r2.SetPoint2(p2)
        oipw100r2.UpdatePlacement()
		
        oipw50r2.SetOrigin(o)
        oipw50r2.SetPoint1(p1)
        oipw50r2.SetPoint2(p2)
        oipw50r2.UpdatePlacement()
		
        oipw100r3.SetOrigin(o)
        oipw100r3.SetPoint1(p1)
        oipw100r3.SetPoint2(p2)
        oipw100r3.UpdatePlacement()
		
        oipw50r3.SetOrigin(o)
        oipw50r3.SetPoint1(p1)
        oipw50r3.SetPoint2(p2)
        oipw50r3.UpdatePlacement()  
		
    # end edit

    def close(self):
        self.set_input(None)
        self.dv_orientation_widget.close()
        self.set_overlay_input(None)
        self.set_overlay_input_voxels(None)
        self.set_overlay_input_axial_100band1(None)
        self.set_overlay_input_sagittal_100band1(None)
        self.set_overlay_input_coronal_100band1(None)
        self.set_overlay_input_axial_100band2(None)
        self.set_overlay_input_sagittal_100band2(None)
        self.set_overlay_input_coronal_100band2(None)
        self.set_overlay_input_axial_100band3(None)
        self.set_overlay_input_sagittal_100band3(None)
        self.set_overlay_input_coronal_100band3(None)
        self.set_overlay_input_axial_50band1(None)
        self.set_overlay_input_sagittal_50band1(None)
        self.set_overlay_input_coronal_50band1(None)
        self.set_overlay_input_axial_50band2(None)
        self.set_overlay_input_sagittal_50band2(None)
        self.set_overlay_input_coronal_50band2(None)
        self.set_overlay_input_axial_50band3(None)
        self.set_overlay_input_sagittal_50band3(None)
        self.set_overlay_input_coronal_50band3(None)

    def activate_slice(self, idx):
        if idx in [1,2]:
            self.ipws[idx].SetEnabled(1)
            self.ipws[idx].SetPicker(self.picker)


    def deactivate_slice(self, idx):
        if idx in [1,2]:
            self.ipws[idx].SetEnabled(0)
            self.ipws[idx].SetPicker(None)

    def get_input(self):
        return self.ipws[0].GetInput()

    def get_world_pos(self, image_pos):
        """Given image coordinates, return the corresponding world
        position.
        """

        idata = self.get_input()
        if not idata:
            return None

        ispacing = idata.GetSpacing()
        iorigin = idata.GetOrigin()
        # calculate real coords
        world = map(operator.add, iorigin,
                    map(operator.mul, ispacing, image_pos[0:3]))


    def set_perspective(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOff()

    def set_parallel(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOn()
        
    # nnsmit edit    
    def set_opacity(self,opacity):
        lut = self.ipws[0].GetLookupTable()
        lut.SetAlphaRange(opacity, opacity)
        lut.Build()
        self.ipws[0].SetLookupTable(lut)
    # end edit
    
    def _handler_mousewheel(self, event):
        # event.GetWheelRotation() is + or - 120 depending on
        # direction of turning.
        if event.ControlDown():
            delta = 10
        elif event.ShiftDown():
            delta = 1
        else:
            # if user is NOT doing shift / control, we pass on to the
            # default handling which will give control to the VTK
            # mousewheel handlers.
            self.rwi.OnMouseWheel(event)
            return
            
        if event.GetWheelRotation() > 0:
            self._ipw1_delta_slice(+delta)
        else:
            self._ipw1_delta_slice(-delta)

        self.render()
        self.ipws[0].InvokeEvent('InteractionEvent')

    def _ipw1_delta_slice(self, delta):
        """Move to the delta slices fw/bw, IF the IPW is currently
        aligned with one of the axes.
        """

        ipw = self.ipws[0]
        if ipw.GetPlaneOrientation() < 3:
            ci = ipw.GetSliceIndex()
            ipw.SetSliceIndex(ci + delta)

    def render(self):
        self.rwi.GetRenderWindow().Render()
        # nnsmit edit
        # synch those overlays:
		
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
				
        if self.overlay_active_voxels == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_voxels):
                self.observer_sync_overlay(self.ipws, i)
	
        if self.overlay_active_100band1 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band1):
                self.observer_sync_overlay(self.ipws, i)
        if self.overlay_active_100band2 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band2):
                self.observer_sync_overlay(self.ipws, i)
        if self.overlay_active_100band3 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band3):
                self.observer_sync_overlay(self.ipws, i)
				
        if self.overlay_active_50band1 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band1):
                self.observer_sync_overlay(self.ipws, i)
        if self.overlay_active_50band2 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band2):
                self.observer_sync_overlay(self.ipws, i)
        if self.overlay_active_50band3 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band3):
                self.observer_sync_overlay(self.ipws, i)
				
				
        # end edit    

    def reset_camera(self):
        self.renderer.ResetCamera()
        cam = self.renderer.GetActiveCamera()
        cam.SetViewUp(0,-1,0)

    def reset_to_default_view(self, view_index):
        """
        @param view_index 2 for XY
        """

        if view_index == 2:
            
            cam = self.renderer.GetActiveCamera()
            # then make sure it's up is the right way
            cam.SetViewUp(0,-1,0)
            # just set the X,Y of the camera equal to the X,Y of the
            # focal point.
            fp = cam.GetFocalPoint()
            cp = cam.GetPosition()
            if cp[2] < fp[2]:
                z = fp[2] + (fp[2] - cp[2])
            else:
                z = cp[2]

            cam.SetPosition(fp[0], fp[1], z)

            # first reset the camera
            self.renderer.ResetCamera() 
        # nnsmit edit
        # synch overlays as well:
		
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                ipw_overlay.SetSliceIndex(0)
				
        if self.overlay_active_voxels == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_voxels):
                ipw_overlay.SetSliceIndex(0)
		
        if self.overlay_active_100band1 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band1):
                ipw_overlay.SetSliceIndex(0) 
        if self.overlay_active_100band2 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band2):
                ipw_overlay.SetSliceIndex(0) 	
        if self.overlay_active_100band3 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band3):
                ipw_overlay.SetSliceIndex(0)
				
        if self.overlay_active_50band1 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band1):
                ipw_overlay.SetSliceIndex(0) 
        if self.overlay_active_50band2 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band2):
                ipw_overlay.SetSliceIndex(0) 	
        if self.overlay_active_50band3 == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band3):
                ipw_overlay.SetSliceIndex(0)
				
        for i, ipw in enumerate(self.ipws):
                ipw.SetWindowLevel(500,-800,0)
        self.render()
        # end edit

    def set_input(self, input):
        ipw = self.ipws[0]
        ipw.DisplayTextOn()
        if input == ipw.GetInput():
            return

        if input is None:
            # remove outline actor, else this will cause errors when
            # we disable the IPWs (they call a render!)
            self.renderer.RemoveViewProp(self.outline_actor)
            self.outline_source.SetInput(None)

            self.dv_orientation_widget.set_input(None)

            for ipw in self.ipws:
                # argh, this disable causes a render
                ipw.SetEnabled(0)
                ipw.SetInput(None)

        else:
            self.outline_source.SetInput(input)
            self.renderer.AddViewProp(self.outline_actor)

            orientations = [2, 0, 1]
            active = [1, 0, 0]
            for i, ipw in enumerate(self.ipws):
                ipw.SetInput(input)
                ipw.SetWindowLevel(500,-800,0)
                ipw.SetPlaneOrientation(orientations[i]) # axial
                ipw.SetSliceIndex(0)
                ipw.SetEnabled(active[i])

            self.dv_orientation_widget.set_input(input)

    # nnsmit-edit
	
	#-------------------------- Set the overlays for the average dose plan color mapping ----------------------------
	
    def set_overlay_input(self, input):
        self.overlay_active = 1
        ipw = self.overlay_ipws[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active = 0;
            for ipw_overlay in self.overlay_ipws:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		
    def set_overlay_inputS(self, input):
        self.overlay_active = 1
        ipw = self.overlay_ipws[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active = 0;
            for ipw_overlay in self.overlay_ipws:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_inputC(self, input):
        self.overlay_active = 1
        ipw = self.overlay_ipws[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active = 0;
            for ipw_overlay in self.overlay_ipws:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
		
		
    def set_overlay_input_voxels(self, input):
        self.overlay_active_voxels = 1
        ipw = self.overlay_ipws_voxels[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_voxels = 0;
            for ipw_overlay in self.overlay_ipws_voxels:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_voxels):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		
	#-------------------------- Set the overlays for the contour bands ----------------------------
	
	'''
	An image plan widget has 3 axes: axial, sagittal and coronal. The set_overlay methods use the ipws. Because the 50%band and the 100%band are different files,
	and also because there are 3 rows with changeable isovalues, it's necessary to create an ipws for every band in every row. This is an hack / Hard coded feature, 
	create specifically for Ensemble Viewer. The nomenclature is:
	
	set_overlay_input_axial_100band1 ---------------------------> Set overlay for 100% band in row 1, in axial plane ------------|
	set_overlay_input_sagittal_100band1 ------------------------> Set overlay for 100% band in row 1, in sagittal plane          |  overlay_ipws_100band1, overlay_active_100band1
	set_overlay_input_coronal_100band1	------------------------> Set overlay for 100% band in row 1, in coronal plane-----------|
	
    set_overlay_input_axial_50band1 ---------------------------> Set overlay for 50% band in row 1, in axial plane ------------|
	set_overlay_input_sagittal_50band1 ------------------------> Set overlay for 50% band in row 1, in sagittal plane          |  overlay_ipws_50band1, overlay_active_50band1
	set_overlay_input_coronal_50band1	------------------------> Set overlay for 50% band in row 1, in coronal plane-----------|
	
	--------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	set_overlay_input_axial_100band2 ---------------------------> Set overlay for 100% band in row 2, in axial plane ------------|
	set_overlay_input_sagittal_100band2 ------------------------> Set overlay for 100% band in row 2, in sagittal plane          |  overlay_ipws_100band2, overlay_active_100band2
	set_overlay_input_coronal_100band2	------------------------> Set overlay for 100% band in row 2, in coronal plane-----------|
	
	set_overlay_input_axial_50band2 ---------------------------> Set overlay for 50% band in row 2, in axial plane ------------|
	set_overlay_input_sagittal_50band2 ------------------------> Set overlay for 50% band in row 2, in sagittal plane          |  overlay_ipws_50band2, overlay_active_50band2
	set_overlay_input_coronal_50band2	------------------------> Set overlay for 50% band in row 2, in coronal plane-----------|
	
	---------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	set_overlay_input_axial_100band3 ---------------------------> Set overlay for 100% band in row 3, in axial plane ------------|
	set_overlay_input_sagittal_100band3 ------------------------> Set overlay for 100% band in row 3, in sagittal plane          |  overlay_ipws_100band3, overlay_active_100band3
	set_overlay_input_coronal_100band3	------------------------> Set overlay for 100% band in row 3, in coronal plane-----------|
	
	set_overlay_input_axial_50band3 ---------------------------> Set overlay for 50% band in row 3, in axial plane ------------|
	set_overlay_input_sagittal_50band3 ------------------------> Set overlay for 50% band in row 3, in sagittal plane          |  overlay_ipws_100band3, overlay_active_100band3
	set_overlay_input_coronal_50band3	------------------------> Set overlay for 50% band in row 3, in coronal plane-----------|
	
	'''
		
	###------------------------FIRST ROW---------------------------###
		
    def set_overlay_input_axial_100band1(self, input):
        self.overlay_active_100band1 = 1
        ipw = self.overlay_ipws_100band1[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band1 = 0;
            for ipw_overlay in self.overlay_ipws_100band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band1):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_100band1(self, input):
        self.overlay_active_100band1 = 1
        ipw = self.overlay_ipws_100band1[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band1 = 0;
            for ipw_overlay in self.overlay_ipws_100band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band1):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_100band1(self, input):
        self.overlay_active_100band1 = 1
        ipw = self.overlay_ipws_100band1[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band1 = 0;
            for ipw_overlay in self.overlay_ipws_100band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band1):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()		
		
		
    def set_overlay_input_axial_50band1(self, input):
        self.overlay_active_50band1 = 1
        ipw = self.overlay_ipws_50band1[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band1 = 0;
            for ipw_overlay in self.overlay_ipws_50band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band1):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_50band1(self, input):
        self.overlay_active_50band1 = 1
        ipw = self.overlay_ipws_50band1[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band1 = 0;
            for ipw_overlay in self.overlay_ipws_50band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band1):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_50band1(self, input):
        self.overlay_active_50band1 = 1
        ipw = self.overlay_ipws_50band1[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band1 = 0;
            for ipw_overlay in self.overlay_ipws_50band1:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band1):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
		
	###------------------------SECOND ROW---------------------------###
		
    def set_overlay_input_axial_100band2(self, input):
        self.overlay_active_100band2 = 1
        ipw = self.overlay_ipws_100band2[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band2 = 0;
            for ipw_overlay in self.overlay_ipws_100band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band2):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_100band2(self, input):
        self.overlay_active_100band2 = 1
        ipw = self.overlay_ipws_100band2[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band2 = 0;
            for ipw_overlay in self.overlay_ipws_100band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band2):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_100band2(self, input):
        self.overlay_active_100band2 = 1
        ipw = self.overlay_ipws_100band2[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band2 = 0;
            for ipw_overlay in self.overlay_ipws_100band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band2):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
		
		
    def set_overlay_input_axial_50band2(self, input):
        self.overlay_active_50band2 = 1
        ipw = self.overlay_ipws_50band2[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band2 = 0;
            for ipw_overlay in self.overlay_ipws_50band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band2):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_50band2(self, input):
        self.overlay_active_50band2 = 1
        ipw = self.overlay_ipws_50band2[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band2 = 0;
            for ipw_overlay in self.overlay_ipws_50band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band2):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_50band2(self, input):
        self.overlay_active_50band2 = 1
        ipw = self.overlay_ipws_50band2[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band2 = 0;
            for ipw_overlay in self.overlay_ipws_50band2:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band2):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
		
	###-------------------------THIRD ROW---------------------------###
	
	
    def set_overlay_input_axial_100band3(self, input):
        self.overlay_active_100band3 = 1
        ipw = self.overlay_ipws_100band3[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band3 = 0;
            for ipw_overlay in self.overlay_ipws_100band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band3):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_100band3(self, input):
        self.overlay_active_100band3 = 1
        ipw = self.overlay_ipws_100band3[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band3 = 0;
            for ipw_overlay in self.overlay_ipws_100band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band3):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_100band3(self, input):
        self.overlay_active_100band3 = 1
        ipw = self.overlay_ipws_100band3[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_100band3 = 0;
            for ipw_overlay in self.overlay_ipws_100band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_100band3):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
		
    def set_overlay_input_axial_50band3(self, input):
        self.overlay_active_50band3 = 1
        ipw = self.overlay_ipws_50band3[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band3 = 0;
            for ipw_overlay in self.overlay_ipws_50band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band3):
                self.observer_sync_overlay(self.ipws, i)        
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # axial
                ipw_overlay.SetEnabled(active[i]) 
        self.render()
		

    def set_overlay_input_sagittal_50band3(self, input):
        self.overlay_active_50band3 = 1
        ipw = self.overlay_ipws_50band3[1]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band1 = 0;
            for ipw_overlay in self.overlay_ipws_50band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 1, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band3):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # sagittal
                ipw_overlay.SetEnabled(active[i])
        self.render()


    def set_overlay_input_coronal_50band3(self, input):
        self.overlay_active_50band3 = 1
        ipw = self.overlay_ipws_50band3[2]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active_50band3 = 0;
            for ipw_overlay in self.overlay_ipws_50band3:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [0, 0, 1]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws_50band3):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i]) # coronal
                ipw_overlay.SetEnabled(active[i])
        self.render()
コード例 #8
0
class CMSliceViewer:
    """Simple class for enabling 1 or 3 ortho slices in a 3D scene.
    """
    def __init__(self, rwi, renderer):
        # nnsmit-edit
        self.overlay_active = 0
        # end edit
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        self.ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut = self.ipws[0].GetLookupTable()
        for ipw in self.ipws:
            ipw.SetInteractor(rwi)
            ipw.SetLookupTable(lut)

# nnsmit-edit
        self.overlay_ipws = [vtk.vtkImagePlaneWidget() for _ in range(3)]
        lut2 = self.overlay_ipws[0].GetLookupTable()
        lut2.SetNumberOfTableValues(3)
        lut2.SetTableValue(0, 0, 0, 0, 0)
        lut2.SetTableValue(1, 0.5, 0, 1, 1)
        lut2.SetTableValue(2, 1, 0, 0, 1)
        lut2.Build()
        for ipw_overlay in self.overlay_ipws:
            ipw_overlay.SetInteractor(rwi)
            ipw_overlay.SetLookupTable(lut2)
            ipw_overlay.AddObserver('InteractionEvent', wx.EVT_MOUSEWHEEL)

        # now actually connect the sync_overlay observer
        for i, ipw in enumerate(self.ipws):
            ipw.AddObserver('InteractionEvent',
                            lambda vtk_o, vtk_e, i=i: self.
                            observer_sync_overlay(self.ipws, i))
        # end edit

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipws[0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0, 0, 0)
        self.current_index_pos = (0, 0, 0)

# nnsmit-edit

    def observer_sync_overlay(self, ipws, ipw_idx):
        # get the primary IPW
        pipw = ipws[ipw_idx]
        # get the overlay IPW
        oipw = self.overlay_ipws[ipw_idx]
        # get plane geometry from primary
        o, p1, p2 = pipw.GetOrigin(), pipw.GetPoint1(), pipw.GetPoint2()
        # and apply to the overlay
        oipw.SetOrigin(o)
        oipw.SetPoint1(p1)
        oipw.SetPoint2(p2)
        oipw.UpdatePlacement()

    # end edit

    def close(self):
        self.set_input(None)
        self.dv_orientation_widget.close()
        self.set_overlay_input(None)

    def activate_slice(self, idx):
        if idx in [1, 2]:
            self.ipws[idx].SetEnabled(1)
            self.ipws[idx].SetPicker(self.picker)

    def deactivate_slice(self, idx):
        if idx in [1, 2]:
            self.ipws[idx].SetEnabled(0)
            self.ipws[idx].SetPicker(None)

    def get_input(self):
        return self.ipws[0].GetInput()

    def get_world_pos(self, image_pos):
        """Given image coordinates, return the corresponding world
        position.
        """

        idata = self.get_input()
        if not idata:
            return None

        ispacing = idata.GetSpacing()
        iorigin = idata.GetOrigin()
        # calculate real coords
        world = map(operator.add, iorigin,
                    map(operator.mul, ispacing, image_pos[0:3]))

    def set_perspective(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOff()

    def set_parallel(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOn()

    # nnsmit edit
    def set_opacity(self, opacity):
        lut = self.ipws[0].GetLookupTable()
        lut.SetAlphaRange(opacity, opacity)
        lut.Build()
        self.ipws[0].SetLookupTable(lut)

    # end edit

    def _handler_mousewheel(self, event):
        # event.GetWheelRotation() is + or - 120 depending on
        # direction of turning.
        if event.ControlDown():
            delta = 10
        elif event.ShiftDown():
            delta = 1
        else:
            # if user is NOT doing shift / control, we pass on to the
            # default handling which will give control to the VTK
            # mousewheel handlers.
            self.rwi.OnMouseWheel(event)
            return

        if event.GetWheelRotation() > 0:
            self._ipw1_delta_slice(+delta)
        else:
            self._ipw1_delta_slice(-delta)

        self.render()
        self.ipws[0].InvokeEvent('InteractionEvent')

    def _ipw1_delta_slice(self, delta):
        """Move to the delta slices fw/bw, IF the IPW is currently
        aligned with one of the axes.
        """

        ipw = self.ipws[0]
        if ipw.GetPlaneOrientation() < 3:
            ci = ipw.GetSliceIndex()
            ipw.SetSliceIndex(ci + delta)

    def render(self):
        self.rwi.GetRenderWindow().Render()
        # nnsmit edit
        # synch those overlays:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
        # end edit

    def reset_camera(self):
        self.renderer.ResetCamera()
        cam = self.renderer.GetActiveCamera()
        cam.SetViewUp(0, -1, 0)

    def reset_to_default_view(self, view_index):
        """
        @param view_index 2 for XY
        """

        if view_index == 2:

            cam = self.renderer.GetActiveCamera()
            # then make sure it's up is the right way
            cam.SetViewUp(0, -1, 0)
            # just set the X,Y of the camera equal to the X,Y of the
            # focal point.
            fp = cam.GetFocalPoint()
            cp = cam.GetPosition()
            if cp[2] < fp[2]:
                z = fp[2] + (fp[2] - cp[2])
            else:
                z = cp[2]

            cam.SetPosition(fp[0], fp[1], z)

            # first reset the camera
            self.renderer.ResetCamera()
        # nnsmit edit
        # synch overlays as well:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                ipw_overlay.SetSliceIndex(0)
        for i, ipw in enumerate(self.ipws):
            ipw.SetWindowLevel(500, -800, 0)
        self.render()
        # end edit

    def set_input(self, input):
        ipw = self.ipws[0]
        ipw.DisplayTextOn()
        if input == ipw.GetInput():
            return

        if input is None:
            # remove outline actor, else this will cause errors when
            # we disable the IPWs (they call a render!)
            self.renderer.RemoveViewProp(self.outline_actor)
            self.outline_source.SetInput(None)

            self.dv_orientation_widget.set_input(None)

            for ipw in self.ipws:
                # argh, this disable causes a render
                ipw.SetEnabled(0)
                ipw.SetInput(None)

        else:
            self.outline_source.SetInput(input)
            self.renderer.AddViewProp(self.outline_actor)

            orientations = [2, 0, 1]
            active = [1, 0, 0]
            for i, ipw in enumerate(self.ipws):
                ipw.SetInput(input)
                ipw.SetWindowLevel(500, -800, 0)
                ipw.SetPlaneOrientation(orientations[i])  # axial
                ipw.SetSliceIndex(0)
                ipw.SetEnabled(active[i])

            self.dv_orientation_widget.set_input(input)

    # nnsmit-edit
    # FIXME: Create pretty fix for this codeclone.
    def set_overlay_input(self, input):
        self.overlay_active = 1
        ipw = self.overlay_ipws[0]
        if input == ipw.GetInput():
            return
        if input is None:
            self.overlay_active = 0
            for ipw_overlay in self.overlay_ipws:
                ipw_overlay.SetEnabled(0)
                ipw_overlay.SetInput(None)
        else:
            active = [1, 0, 0]
            orientations = [2, 0, 1]
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipws, i)
                ipw_overlay.SetInput(input)
                ipw_overlay.SetPlaneOrientation(orientations[i])  # axial
                ipw_overlay.SetEnabled(active[i])
        self.render()
コード例 #9
0
class OverlaySliceViewer:
    """Class for viewing 3D binary masks in a slice-view.
    Supports arbitrary number of overlays in user-definable colours.
    """

    has_active_slices = False

    def __init__(self, rwi, renderer):
        self.rwi = rwi        
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        #This is a collection of 1- or 3-component image plane widgets. Each entry corresponds to a single overlay.
        self.ipw_triads = {}
        self.add_overlay(0, [0, 0, 0, 0.1]) #Almost-transparent black - for showing the pickable plane stored at id = 0.
            
        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipw_triads[0][0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0,0,0)
        self.current_index_pos = (0,0,0)


    def add_overlay(self, id, rgba_colour):
        """Creates and ads a new (set of) image plane widgets corresponding to a new overlay.
           id : the string id which will be used to identify this overlay for future lookups.
           rgba_colour : a length 4 vector giving the red,green,blue,opacity value for this overlay. Range = [0,1]
        """
        if self.ipw_triads.has_key(id):
            raise ValueError('The overlay id = "%s" is already in use! Cannot this id - aborting.' % id)
        else:
            new_ipw_triad = [vtk.vtkImagePlaneWidget() for _ in range(3)]
            lut = new_ipw_triad[0].GetLookupTable()
            lut.SetNumberOfTableValues(2)
            if len(self.ipw_triads) == 0:
                lut.SetTableValue(0,0,0,0,0.1)                    #Almost-transparent black - for showing the pickable plane
            else:
                lut.SetTableValue(0,0,0,0,0)                    #Transparent: for non-interfering overlay on existing layers
            lut.SetTableValue(1,rgba_colour[0],rgba_colour[1],rgba_colour[2],rgba_colour[3]) #Specified RGBA for binary "true"
            lut.Build()

            for ipw in new_ipw_triad:
                ipw.SetInteractor(self.rwi)
                ipw.SetLookupTable(lut)

            self.ipw_triads[id] = new_ipw_triad
            base_ipw_triad = self.ipw_triads[0]

            # now actually connect the sync_overlay observer
            for i,ipw in enumerate(base_ipw_triad):
                ipw.AddObserver('InteractionEvent',lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(base_ipw_triad, new_ipw_triad, i))

    #fmalan-edit based on nnsmit-edit
    def observer_sync_overlay(self, master_ipw_triad, slave_ipw_triad, ipw_idx):
        # get the primary IPW
        master_ipw = master_ipw_triad[ipw_idx]
        # get the overlay IPW
        slave_ipw = slave_ipw_triad[ipw_idx]
        # get plane geometry from primary
        o,p1,p2 = master_ipw.GetOrigin(),master_ipw.GetPoint1(),master_ipw.GetPoint2()
        # and apply to the overlay
        slave_ipw.SetOrigin(o)
        slave_ipw.SetPoint1(p1)
        slave_ipw.SetPoint2(p2)
        slave_ipw.UpdatePlacement()
    # end edit

    def close(self):
        for id in self.ipw_triads.keys():
            self.set_input(id, None)
        self.dv_orientation_widget.close()

    def activate_slice(self, id, idx):
        if idx in [1,2]:
            self.ipw_triads[id][idx].SetEnabled(1)
            self.ipw_triads[id][idx].SetPicker(self.picker)

    def deactivate_slice(self, id, idx):
        if idx in [1,2]:
            self.ipw_triads[id][idx].SetEnabled(0)
            self.ipw_triads[id][idx].SetPicker(None)

    def _get_input(self, id):
        return self.ipw_triads[id].GetInput()

    def get_world_pos(self, image_pos):
        """Given image coordinates, return the corresponding world
        position.
        """
        idata = self._get_input(0)
        if not idata:
            return None
        ispacing = idata.GetSpacing()
        iorigin = idata.GetOrigin()
        # calculate real coords
        world = map(operator.add, iorigin,
                    map(operator.mul, ispacing, image_pos[0:3]))
        return world

    def set_perspective(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOff()

    def set_parallel(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOn()

    def _handler_mousewheel(self, event):
        # event.GetWheelRotation() is + or - 120 depending on
        # direction of turning.
        if event.ControlDown():
            delta = 10
        elif event.ShiftDown():
            delta = 1
        else:
            # if user is NOT doing shift / control, we pass on to the
            # default handling which will give control to the VTK
            # mousewheel handlers.
            self.rwi.OnMouseWheel(event)
            return
            
        if event.GetWheelRotation() > 0:
            self._ipw1_delta_slice(+delta)
        else:
            self._ipw1_delta_slice(-delta)

        self.render()
        for id in self.ipw_triads.keys():
            self.ipw_triads[id][0].InvokeEvent('InteractionEvent')

    def _ipw1_delta_slice(self, delta):
        """Move to the delta slices fw/bw, IF the IPW is currently
        aligned with one of the axes.
        """

        ipw = self.ipw_triads[0][0]
        if ipw.GetPlaneOrientation() < 3:
            ci = ipw.GetSliceIndex()
            ipw.SetSliceIndex(ci + delta)

    def render(self):
        self.rwi.GetRenderWindow().Render()
        #TODO: Check this code        
        # nnsmit edit
        # synch those overlays:

        '''
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipw_triads, i, 0)
                self.observer_sync_overlay(self.ipw_triads, i, 1)
                self.observer_sync_overlay(self.ipw_triads, i, 2)
        '''
        # end edit


    def reset_camera(self):
        self.renderer.ResetCamera()

    def reset_to_default_view(self, view_index):
        """
        @param view_index 2 for XY
        """

        if view_index == 2:
            
            cam = self.renderer.GetActiveCamera()
            # then make sure it's up is the right way
            cam.SetViewUp(0,1,0)
            # just set the X,Y of the camera equal to the X,Y of the
            # focal point.
            fp = cam.GetFocalPoint()
            cp = cam.GetPosition()
            if cp[2] < fp[2]:
                z = fp[2] + (fp[2] - cp[2])
            else:
                z = cp[2]

            cam.SetPosition(fp[0], fp[1], z)

            # first reset the camera
            self.renderer.ResetCamera()
        
        '''
        # nnsmit edit
        # synch overlays as well:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                ipw_overlay.SetSliceIndex(0)
        '''

        self.render()
        
    def set_input(self, id, input):
        if self.ipw_triads.has_key(id):
            selected_ipw_triad = self.ipw_triads[id]
            if input == selected_ipw_triad[0].GetInput():
                return

            if input is None:
                ipw_triad = self.ipw_triads[id]
                for ipw in ipw_triad:
                    # argh, this disable causes a render
                    ipw.SetEnabled(0)
                    ipw.SetInput(None)

                remaining_active_slices = False
                if self.has_active_slices:                    
                    for key in self.ipw_triads:
                        if key != 0:                            
                            ipw_triad = self.ipw_triads[key]
                            for ipw in ipw_triad:
                                if ipw.GetEnabled():
                                    remaining_active_slices = True
                                    break
                            if remaining_active_slices:
                                break
                            
                    if not remaining_active_slices:
                        self.has_active_slices = False
                        self.outline_source.SetInput(None)
                        self.renderer.RemoveViewProp(self.outline_actor)
                        self.dv_orientation_widget.set_input(None)
                        base_ipw_triad = self.ipw_triads[0]
                        for i, ipw in enumerate(base_ipw_triad):
                            ipw.SetInput(None)
                            ipw.SetEnabled(0)
            else:
                orientations = [2, 0, 1]
                active = [1, 0, 0]
                if not self.has_active_slices:
                    self.outline_source.SetInput(input)
                    self.renderer.AddViewProp(self.outline_actor)
                    self.dv_orientation_widget.set_input(input)
                    base_ipw_triad = self.ipw_triads[0]
                    for i, ipw in enumerate(base_ipw_triad):
                        ipw.SetInput(input)
                        ipw.SetPlaneOrientation(orientations[i]) # axial
                        ipw.SetSliceIndex(0)
                        ipw.SetEnabled(active[i])
                    self.has_active_slices = True

                base_ipw_triad = self.ipw_triads[0]
                for i, ipw in enumerate(selected_ipw_triad):
                    ipw.SetInput(input)
                    ipw.SetPlaneOrientation(orientations[i]) # axial
                    ipw.SetSliceIndex(0)
                    ipw.SetEnabled(active[i])
                    self.observer_sync_overlay(base_ipw_triad, selected_ipw_triad, i) #sync to the current position of the base (pickable) triad
                
        else:
            raise ValueError('The overlay with id = "%s" was not found!' % id)
コード例 #10
0
class OverlaySliceViewer:
    """Class for viewing 3D binary masks in a slice-view.
    Supports arbitrary number of overlays in user-definable colours.
    """

    has_active_slices = False

    def __init__(self, rwi, renderer):
        self.rwi = rwi
        self.renderer = renderer

        istyle = vtk.vtkInteractorStyleTrackballCamera()
        rwi.SetInteractorStyle(istyle)

        # we unbind the existing mousewheel handler so it doesn't
        # interfere
        rwi.Unbind(wx.EVT_MOUSEWHEEL)
        rwi.Bind(wx.EVT_MOUSEWHEEL, self._handler_mousewheel)

        #This is a collection of 1- or 3-component image plane widgets. Each entry corresponds to a single overlay.
        self.ipw_triads = {}
        self.add_overlay(
            0, [0, 0, 0, 0.1]
        )  #Almost-transparent black - for showing the pickable plane stored at id = 0.

        # we only set the picker on the visible IPW, else the
        # invisible IPWs block picking!
        self.picker = vtk.vtkCellPicker()
        self.picker.SetTolerance(0.005)
        self.ipw_triads[0][0].SetPicker(self.picker)

        self.outline_source = vtk.vtkOutlineCornerFilter()
        m = vtk.vtkPolyDataMapper()
        m.SetInput(self.outline_source.GetOutput())
        a = vtk.vtkActor()
        a.SetMapper(m)
        a.PickableOff()
        self.outline_actor = a

        self.dv_orientation_widget = DVOrientationWidget(rwi)

        # this can be used by clients to store the current world
        # position
        self.current_world_pos = (0, 0, 0)
        self.current_index_pos = (0, 0, 0)

    def add_overlay(self, id, rgba_colour):
        """Creates and ads a new (set of) image plane widgets corresponding to a new overlay.
           id : the string id which will be used to identify this overlay for future lookups.
           rgba_colour : a length 4 vector giving the red,green,blue,opacity value for this overlay. Range = [0,1]
        """
        if self.ipw_triads.has_key(id):
            raise ValueError(
                'The overlay id = "%s" is already in use! Cannot this id - aborting.'
                % id)
        else:
            new_ipw_triad = [vtk.vtkImagePlaneWidget() for _ in range(3)]
            lut = new_ipw_triad[0].GetLookupTable()
            lut.SetNumberOfTableValues(2)
            if len(self.ipw_triads) == 0:
                lut.SetTableValue(
                    0, 0, 0, 0, 0.1
                )  #Almost-transparent black - for showing the pickable plane
            else:
                lut.SetTableValue(
                    0, 0, 0, 0, 0
                )  #Transparent: for non-interfering overlay on existing layers
            lut.SetTableValue(
                1, rgba_colour[0], rgba_colour[1], rgba_colour[2],
                rgba_colour[3])  #Specified RGBA for binary "true"
            lut.Build()

            for ipw in new_ipw_triad:
                ipw.SetInteractor(self.rwi)
                ipw.SetLookupTable(lut)

            self.ipw_triads[id] = new_ipw_triad
            base_ipw_triad = self.ipw_triads[0]

            # now actually connect the sync_overlay observer
            for i, ipw in enumerate(base_ipw_triad):
                ipw.AddObserver(
                    'InteractionEvent',
                    lambda vtk_o, vtk_e, i=i: self.observer_sync_overlay(
                        base_ipw_triad, new_ipw_triad, i))

    #fmalan-edit based on nnsmit-edit
    def observer_sync_overlay(self, master_ipw_triad, slave_ipw_triad,
                              ipw_idx):
        # get the primary IPW
        master_ipw = master_ipw_triad[ipw_idx]
        # get the overlay IPW
        slave_ipw = slave_ipw_triad[ipw_idx]
        # get plane geometry from primary
        o, p1, p2 = master_ipw.GetOrigin(), master_ipw.GetPoint1(
        ), master_ipw.GetPoint2()
        # and apply to the overlay
        slave_ipw.SetOrigin(o)
        slave_ipw.SetPoint1(p1)
        slave_ipw.SetPoint2(p2)
        slave_ipw.UpdatePlacement()

    # end edit

    def close(self):
        for id in self.ipw_triads.keys():
            self.set_input(id, None)
        self.dv_orientation_widget.close()

    def activate_slice(self, id, idx):
        if idx in [1, 2]:
            self.ipw_triads[id][idx].SetEnabled(1)
            self.ipw_triads[id][idx].SetPicker(self.picker)

    def deactivate_slice(self, id, idx):
        if idx in [1, 2]:
            self.ipw_triads[id][idx].SetEnabled(0)
            self.ipw_triads[id][idx].SetPicker(None)

    def _get_input(self, id):
        return self.ipw_triads[id].GetInput()

    def get_world_pos(self, image_pos):
        """Given image coordinates, return the corresponding world
        position.
        """
        idata = self._get_input(0)
        if not idata:
            return None
        ispacing = idata.GetSpacing()
        iorigin = idata.GetOrigin()
        # calculate real coords
        world = map(operator.add, iorigin,
                    map(operator.mul, ispacing, image_pos[0:3]))
        return world

    def set_perspective(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOff()

    def set_parallel(self):
        cam = self.renderer.GetActiveCamera()
        cam.ParallelProjectionOn()

    def _handler_mousewheel(self, event):
        # event.GetWheelRotation() is + or - 120 depending on
        # direction of turning.
        if event.ControlDown():
            delta = 10
        elif event.ShiftDown():
            delta = 1
        else:
            # if user is NOT doing shift / control, we pass on to the
            # default handling which will give control to the VTK
            # mousewheel handlers.
            self.rwi.OnMouseWheel(event)
            return

        if event.GetWheelRotation() > 0:
            self._ipw1_delta_slice(+delta)
        else:
            self._ipw1_delta_slice(-delta)

        self.render()
        for id in self.ipw_triads.keys():
            self.ipw_triads[id][0].InvokeEvent('InteractionEvent')

    def _ipw1_delta_slice(self, delta):
        """Move to the delta slices fw/bw, IF the IPW is currently
        aligned with one of the axes.
        """

        ipw = self.ipw_triads[0][0]
        if ipw.GetPlaneOrientation() < 3:
            ci = ipw.GetSliceIndex()
            ipw.SetSliceIndex(ci + delta)

    def render(self):
        self.rwi.GetRenderWindow().Render()
        #TODO: Check this code
        # nnsmit edit
        # synch those overlays:
        '''
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                self.observer_sync_overlay(self.ipw_triads, i, 0)
                self.observer_sync_overlay(self.ipw_triads, i, 1)
                self.observer_sync_overlay(self.ipw_triads, i, 2)
        '''
        # end edit

    def reset_camera(self):
        self.renderer.ResetCamera()

    def reset_to_default_view(self, view_index):
        """
        @param view_index 2 for XY
        """

        if view_index == 2:

            cam = self.renderer.GetActiveCamera()
            # then make sure it's up is the right way
            cam.SetViewUp(0, 1, 0)
            # just set the X,Y of the camera equal to the X,Y of the
            # focal point.
            fp = cam.GetFocalPoint()
            cp = cam.GetPosition()
            if cp[2] < fp[2]:
                z = fp[2] + (fp[2] - cp[2])
            else:
                z = cp[2]

            cam.SetPosition(fp[0], fp[1], z)

            # first reset the camera
            self.renderer.ResetCamera()
        '''
        # nnsmit edit
        # synch overlays as well:
        if self.overlay_active == 1:
            for i, ipw_overlay in enumerate(self.overlay_ipws):
                ipw_overlay.SetSliceIndex(0)
        '''

        self.render()

    def set_input(self, id, input):
        if self.ipw_triads.has_key(id):
            selected_ipw_triad = self.ipw_triads[id]
            if input == selected_ipw_triad[0].GetInput():
                return

            if input is None:
                ipw_triad = self.ipw_triads[id]
                for ipw in ipw_triad:
                    # argh, this disable causes a render
                    ipw.SetEnabled(0)
                    ipw.SetInput(None)

                remaining_active_slices = False
                if self.has_active_slices:
                    for key in self.ipw_triads:
                        if key != 0:
                            ipw_triad = self.ipw_triads[key]
                            for ipw in ipw_triad:
                                if ipw.GetEnabled():
                                    remaining_active_slices = True
                                    break
                            if remaining_active_slices:
                                break

                    if not remaining_active_slices:
                        self.has_active_slices = False
                        self.outline_source.SetInput(None)
                        self.renderer.RemoveViewProp(self.outline_actor)
                        self.dv_orientation_widget.set_input(None)
                        base_ipw_triad = self.ipw_triads[0]
                        for i, ipw in enumerate(base_ipw_triad):
                            ipw.SetInput(None)
                            ipw.SetEnabled(0)
            else:
                orientations = [2, 0, 1]
                active = [1, 0, 0]
                if not self.has_active_slices:
                    self.outline_source.SetInput(input)
                    self.renderer.AddViewProp(self.outline_actor)
                    self.dv_orientation_widget.set_input(input)
                    base_ipw_triad = self.ipw_triads[0]
                    for i, ipw in enumerate(base_ipw_triad):
                        ipw.SetInput(input)
                        ipw.SetPlaneOrientation(orientations[i])  # axial
                        ipw.SetSliceIndex(0)
                        ipw.SetEnabled(active[i])
                    self.has_active_slices = True

                base_ipw_triad = self.ipw_triads[0]
                for i, ipw in enumerate(selected_ipw_triad):
                    ipw.SetInput(input)
                    ipw.SetPlaneOrientation(orientations[i])  # axial
                    ipw.SetSliceIndex(0)
                    ipw.SetEnabled(active[i])
                    self.observer_sync_overlay(
                        base_ipw_triad, selected_ipw_triad, i
                    )  #sync to the current position of the base (pickable) triad

        else:
            raise ValueError('The overlay with id = "%s" was not found!' % id)