# Allan Spale # CS 526 - Project 2 import Tkinter import tkFont import time import os import sys import vtk from vtk.tk.vtkTkRenderWindowInteractor import vtkTkRenderWindowInteractor global I_TRUE global I_FALSE I_TRUE = 1 I_FALSE = 0 #------------------------- GUI BUILDER CLASSES ----------------------------------- """ This class is more like a factory than an instantiatable class. It helps create Tkinter widgets without a lot of repetitive configuration. """ class GUIFactory: global I_TRUE, I_FALSE def __init__( self ): self.__dictStandardGridSettings = { 'padx':5, 'pady':5, 'sticky':Tkinter.SW} self.__defaultFont = tkFont.Font( size=11 ) def newLabel( self, rootPanel, labelText, dictExtraConfig ): l = Tkinter.Label( rootPanel, font=self.__defaultFont, text=labelText ) if ( self.__isConfigEmpty( dictExtraConfig ) == I_FALSE ): l.config( dictExtraConfig ) return l def newEntry( self, rootPanel, fieldIdentifier, dictExtraConfig ): e = Tkinter.Entry( rootPanel, font=self.__defaultFont, text=fieldIdentifier ) if ( self.__isConfigEmpty( dictExtraConfig ) == I_FALSE ): e.config( dictExtraConfig ) print "Entry...", e return e def newButton( self, rootPanel, buttonText, buttonCommand, dictExtraConfig ): b = Tkinter.Button( rootPanel, font=self.__defaultFont, text=buttonText, command=buttonCommand ) if ( self.__isConfigEmpty( dictExtraConfig ) == I_FALSE ): b.config( dictExtraConfig ) return b def newCheckbox( self, rootPanel, checkText, checkCommand, dictExtraConfig ): c = Tkinter.Checkbutton( rootPanel, font=self.__defaultFont, text=checkText, command=checkCommand, indicatoron=I_FALSE ) if ( self.__isConfigEmpty( dictExtraConfig ) == I_FALSE ): c.config( dictExtraConfig ) return c def newRadiobutton( self, rootPanel, radioText, radioCommand, sharedVariable, radioValue, dictExtraConfig ): r = Tkinter.Radiobutton( rootPanel, font=self.__defaultFont, text=radioText, command=radioCommand, variable=sharedVariable, value=radioValue, indicatoron=I_FALSE ) if ( self.__isConfigEmpty( dictExtraConfig ) == I_FALSE ): r.config( dictExtraConfig ) return r def newSlider( self, rootPanel, sliderCommand, valueStart, valueEnd, dictExtraConfig ): dictExtraConfig[ 'from' ] = valueStart dictExtraConfig[ 'to' ] = valueEnd dictExtraConfig[ 'orient' ] = Tkinter.HORIZONTAL dictExtraConfig[ 'showvalue' ] = I_FALSE s = Tkinter.Scale( rootPanel ) s.config( dictExtraConfig ) s.bind( '', sliderCommand ) s.bind( '', sliderCommand ) s.bind( '', sliderCommand ) s.bind( '', sliderCommand ) s.bind( '', sliderCommand ) s.bind( '', sliderCommand ) return s def newListbox( self, rootPanel, dictExtraConfig ): dictExtraConfig[ 'selectmode' ] = Tkinter.SINGLE l = Tkinter.Listbox( rootPanel, font=self.__defaultFont ) l.config( dictExtraConfig ) return l def packItem( self, object, gridSettings ): items = self.__dictStandardGridSettings.keys() for x in items: gridSettings[ x ] = self.__dictStandardGridSettings[ x ] object.grid( gridSettings ) def __isConfigEmpty( self, dictConfig ): if ( dictConfig == None ): return I_TRUE elif ( len( dictConfig ) > 0 ): return I_FALSE else: return I_TRUE """ This is a composited widget made from Tkinter.Scale and Tkinter.Label. Class methods are available to allow some level of customizability. """ class SliderWithValue: global I_TRUE, I_FALSE def __init__( self, rootPanel, startValue, endValue ): guiFactory = GUIFactory() #self.count = 0 self.__root = rootPanel self.__frame = Tkinter.Frame( self.__root ) self.__label = guiFactory.newLabel( self.__frame, '', { 'padx':5, 'pady':5, 'anchor':Tkinter.SW, 'width':3, 'justify':Tkinter.RIGHT} ) self.__label.grid(row=0, rowspan=1, column=0, columnspan=3, sticky=Tkinter.NW ) filler = guiFactory.newLabel( self.__frame, ' ', None ) filler.grid( row=0, rowspan=1, column=3, columnspan=1 ) self.__slider = guiFactory.newSlider( self.__frame, self.__updateLabel, startValue, endValue, {} ) self.__slider.grid( row=0, rowspan=1, column=4, columnspan=3, sticky=Tkinter.NE) self.__slider.set( startValue ) self.__modified = I_FALSE self.__sliderValue = startValue self.__updateLabel() def addSliderCommandBinding( self, callback ): self.__slider.bind( '', callback ) self.__slider.bind( '', callback ) self.__slider.bind( '', callback ) self.__slider.bind( '', callback ) self.__slider.bind( '', callback ) self.__slider.bind( '', callback ) def configureScale( self, dictConfiguration ): self.__slider.config( dictConfiguration ) def setScaleValue( self, value ): self.__slider.set( value ) self.__updateLabel() def reset( self ): value = self.__slider.cget( 'from' ) self.__slider.set( value ) self.__updateLabel() self.__modified = I_FALSE def configureLabel( self, dictConfiguration ): self.__label.config( dictConfiguration ) def getWidget( self ): return self.__frame def getValue( self ): return self.__slider.get() def getValue2( self ): return int( self.__label.cget( 'text' ) ) def getValue3( self ): return self.__sliderValue def __updateLabel( self, *unusedArgument ): #print self.count, self.__valueLabel #self.count = self.count+1 #self.__label = self.__slider.get() self.__label.config( text=self.__slider.get() ) self.__modified = I_TRUE self.__sliderValue = self.__slider.get() def getModifiedStatus(): return self.__modified """ This is a class that creates a modal dialog. To prevent confusion of having the same dialog appear twice (if the user made a selection that would cause multiple (conflicting) copies of the dialog to appear twice), all dialogs will be modal. All dialog boxes will extend this class. """ class ModalDialog: global I_TRUE, I_FALSE def __init__( self, topWindow, dialogTitle, useStatusBarFlag ): self.__firstTime = I_TRUE self.__buildDialog( topWindow, dialogTitle, useStatusBarFlag ) self.config = {} self.config[ 'text' ] = '' self.config[ 'foreground' ] = '' self.config[ 'background' ] = '' def __buildDialog( self, root, title, statusBarFlag ): self.__rootWindow = root self.__title = title self.__statusBarFlag = statusBarFlag self.__root = Tkinter.Toplevel( self.__rootWindow ) self.__root.title( title ) #self.__root.resizable( 0,0 ) self.dialog = Tkinter.Frame( self.__root ) self.dialog.pack() # constants self.B_USE_ERROR_COLOR = I_TRUE self.B_NO_ERROR_COLOR = I_FALSE """if ( self.__statusBarFlag == I_TRUE ): self.__statusBar = Tkinter.Label( self.__root, relief=Tkinter.SUNKEN, text=' ', justify=Tkinter.LEFT, anchor=Tkinter.W ) self.__statusBar.pack() self.__statusOriginalBGColor = self.__statusBar.cget( 'background' ) self.__statusOriginalFGColor = self.__statusBar.cget( 'foreground' ) """ self.hide() def rebuildDialog( self, newRoot ): self.__rootWindow = newRoot self.__buildDialog( newRoot, self.__title, self.__statusBarFlag ) def show( self ): # modal dialog settings...adopted from "An Introduction to Tkinter" print self.__root.state() if ( self.__firstTime == I_TRUE ): #self.__root.transient( self.__rootWindow ) self.__firstTime = I_FALSE self.__root.deiconify() #self.__root.grab_set() #events sent to this dialog #self.__root.focus_set() #self.__root.wait_window( self.__root ) def destroy( self ): #self.__root.grab_release() self.__root.destroy() def hide( self ): #self.__root.grab_release() #self.__root.withdraw() self.__root.iconify() def setStatusBarMessage( self, useErrorColorFlag, statusText ): if ( self.__statusBarFlag == I_TRUE ): self.config[ 'text' ] = statusText if ( useErrorColorFlag == I_TRUE ): self.config[ 'foreground' ] = '#0000AA' self.config[ 'background' ] = '#FFFFFF' else: self.config[ 'foreground' ] = self.__statusOriginalFGColor self.config[ 'background' ] = self.__statusOriginalBGColor self.__statusBar.config( self.config ) def configStatusBar( self, dictConfiguration ): self.__statusBar.config( dictConfiguration ) #------------------------- GUI BUILDER CLASS ----------------------------------- #------------------------- VTK CLASS ---------------------------------------- class VTKRender: def __init__(self, frame): self.__frame = frame self.NONE = 0 self.ISO = 10 self.COMP = 20 self.MIP = 30 # ID numbers, not isovalue self.SKIN = 100 self.BONE = 200 self.OTHER = 300 self.HEAD = 1000 self.FEET = 2000 self.SKIN_ISOSURFACE = 860 self.BONE_ISOSURFACE = 1250 self.__otherIso = 1100 self.__lastActorID = self.NONE self.readerVolume = vtk.vtkImageReader() self.readerVolume.SetDataScalarType( vtk.VTK_UNSIGNED_SHORT ) self.readerVolume.SetDataScalarType( 5 ) self.readerVolume.SetDataByteOrder( 0 ) self.readerVolume.SetFileDimensionality( 3 ) self.readerVolume.SetDataExtent ( 0,255, 0,255, 0,576) self.readerVolume.SetDataSpacing( 1,1,1 ) self.readerVolume.SetNumberOfScalarComponents( 1 ) self.readerVolume.SetFileName( "./Female.raw" ) self.voiFeet = vtk.vtkExtractVOI() self.voiFeet.SetInput( self.readerVolume.GetOutput() ) self.voiFeet.SetVOI( 0,255, 60,255, 500,576 ) self.voiFeet.SetSampleRate( 1,1,1 ) self.voiHead = vtk.vtkExtractVOI() self.voiHead.SetInput( self.readerVolume.GetOutput() ) self.voiHead.SetVOI( 0,255, 60,255, 0,100 ) self.voiHead.SetSampleRate( 1,1,1 ) self.compositeFunction = vtk.vtkVolumeRayCastCompositeFunction() self.opacityFunctionComp = vtk.vtkPiecewiseFunction() for x in range( self.BONE_ISOSURFACE, 5000, 10 ): self.opacityFunctionComp.AddPoint( x, 1.0 )#0.3 for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+200, 5 ): self.opacityFunctionComp.AddPoint( y, 0.05 ) #self.opacityFunctionComp.AddPoint( self.BONE_ISOSURFACE, 1.0 ) #self.opacityFunctionComp.AddPoint( 860, 0.3 ) self.opacityFunctionComp.ClampingOff() self.colorTransferFunctionComp = vtk.vtkColorTransferFunction() #self.colorTransferFunctionComp.AddRGBPoint( self.BONE_ISOSURFACE, 1, 1, 1 ) #self.colorTransferFunctionComp.AddRGBPoint( self.SKIN_ISOSURFACE, 1, 0.547237, 0.319073 ) for x in range( self.BONE_ISOSURFACE, self.BONE_ISOSURFACE+259, 1 ): self.colorTransferFunctionComp.AddRGBPoint( x, 1, 1, 1 ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+100, 1 ): self.colorTransferFunctionComp.AddRGBPoint( y, 1, 0.547237, 0.319073 ) self.volumePropertyComp = vtk.vtkVolumeProperty() self.volumePropertyComp.SetScalarOpacity( self.opacityFunctionComp ) self.volumePropertyComp.SetColor( self.colorTransferFunctionComp ) self.volumePropertyComp.ShadeOn() self.volumePropertyComp.SetInterpolationTypeToLinear() self.mapperCompHead = vtk.vtkVolumeRayCastMapper() self.mapperCompHead.SetVolumeRayCastFunction( self.compositeFunction ) self.mapperCompHead.SetInput( self.voiHead.GetOutput() ) self.mapperCompFeet = vtk.vtkVolumeRayCastMapper() self.mapperCompFeet.SetVolumeRayCastFunction( self.compositeFunction ) self.mapperCompFeet.SetInput( self.voiFeet.GetOutput() ) self.volumeComp = vtk.vtkVolume() self.volumeComp.SetOrigin( 0,0,0 ) self.volumeComp.SetScale( 1,1,1 ) self.volumeComp.SetMapper( self.mapperCompHead ) self.volumeComp.SetProperty( self.volumePropertyComp ) #compositeFunction = vtk.vtkVolumeRayCastCompositeFunction() self.compositeFunctionMIP = vtk.vtkVolumeRayCastMIPFunction() self.compositeFunctionMIP.SetMaximizeMethodToOpacity() self.opacityFunctionMIP = vtk.vtkPiecewiseFunction() self.opacityFunctionMIP.AddPoint( self.BONE_ISOSURFACE, 1.0 ) #opacityFunction.AddPoint( 1200, 1.0 ) self.opacityFunctionMIP.AddPoint( self.SKIN_ISOSURFACE, 0.3 ) self.opacityFunctionMIP.ClampingOff() for x in range( self.BONE_ISOSURFACE, 5000, 1 ): self.opacityFunctionMIP.AddPoint( x, 0.7 ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.opacityFunctionMIP.AddPoint( y, 0.5 ) self.colorTransferFunctionMIP = vtk.vtkColorTransferFunction() self.colorTransferFunctionMIP.AddRGBPoint( self.BONE_ISOSURFACE, 1,1,1 ) #colorTransferFunction.AddRGBPoint( 1200, 1,1,1 ) self.colorTransferFunctionMIP.AddRGBPoint( self.SKIN_ISOSURFACE, 1, 0.547237, 0.319073 ) #colorTransferFunction.SetClamping( 2 ) for x in range( self.BONE_ISOSURFACE, 5000, 100 ): self.colorTransferFunctionMIP.AddRGBPoint( x, 1, 1, 1 ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.colorTransferFunctionMIP.AddRGBPoint( y, 1, 0.547237, 0.319073 ) self.volumePropertyMIP = vtk.vtkVolumeProperty() self.volumePropertyMIP.SetScalarOpacity( self.opacityFunctionMIP ) self.volumePropertyMIP.SetColor( self.colorTransferFunctionMIP ) self.volumePropertyMIP.ShadeOn() self.volumePropertyMIP.SetInterpolationTypeToLinear() self.mapperMIPHead = vtk.vtkVolumeRayCastMapper() self.mapperMIPHead.SetVolumeRayCastFunction( self.compositeFunctionMIP ) self.mapperMIPHead.SetInput( self.voiHead.GetOutput() ) self.mapperMIPFeet = vtk.vtkVolumeRayCastMapper() self.mapperMIPFeet.SetVolumeRayCastFunction( self.compositeFunctionMIP ) self.mapperMIPFeet.SetInput( self.voiFeet.GetOutput() ) self.volumeMIP = vtk.vtkVolume() self.volumeMIP.SetOrigin( 0,0,0 ) self.volumeMIP.SetScale( 1,1,1 ) self.volumeMIP.SetMapper( self.mapperMIPHead ) self.volumeMIP.SetProperty( self.volumePropertyMIP ) #### BONE self.contourBoneHead = vtk.vtkMarchingCubes() self.contourBoneHead.SetInput( self.voiHead.GetOutput() ) self.contourBoneHead.ComputeNormalsOn() self.contourBoneHead.SetValue( 0, self.BONE_ISOSURFACE ) self.contourBoneFeet = vtk.vtkMarchingCubes() self.contourBoneFeet.SetInput( self.voiFeet.GetOutput() ) self.contourBoneFeet.ComputeNormalsOn() self.contourBoneFeet.SetValue( 0, self.BONE_ISOSURFACE ) self.geoVolumeBone = vtk.vtkPVGeometryFilter() self.geoVolumeBone.SetInput( self.contourBoneHead.GetOutput() ) self.geoBoneMapper = vtk.vtkPolyDataMapper() self.geoBoneMapper.SetInput( self.geoVolumeBone.GetOutput() ) self.geoBoneMapper.ScalarVisibilityOff() self.actorBone = vtk.vtkLODActor() self.actorBone.SetNumberOfCloudPoints( 1000000 ) self.actorBone.SetMapper( self.geoBoneMapper ) self.actorBone.GetProperty().SetColor( 1, 1, 1 ) ### SKIN self.contourSkinTop = vtk.vtkMarchingCubes() self.contourSkinTop.SetInput( self.voiHead.GetOutput() ) self.contourSkinTop.SetValue( 0, self.SKIN_ISOSURFACE ) #860 self.contourSkinTop.ComputeNormalsOn() self.contourSkinFeet = vtk.vtkMarchingCubes() self.contourSkinFeet.SetInput( self.voiFeet.GetOutput() ) self.contourSkinFeet.ComputeNormalsOn() self.contourSkinFeet.SetValue( 0, self.SKIN_ISOSURFACE ) self.geoVolumeSkin= vtk.vtkPVGeometryFilter() self.geoVolumeSkin.SetInput( self.contourSkinTop.GetOutput() ) self.geoSkinMapper = vtk.vtkPolyDataMapper() self.geoSkinMapper.SetInput( self.geoVolumeSkin.GetOutput() ) self.geoSkinMapper.ScalarVisibilityOff() self.actorSkin = vtk.vtkLODActor() self.actorSkin.SetNumberOfCloudPoints( 1000000 ) self.actorSkin.SetMapper( self.geoSkinMapper ) self.actorSkin.GetProperty().SetColor( 1, 0.547237, 0.319073 ) self.actorSkin.GetProperty().SetOpacity( 0.3 ) # Rendering structure taken from VTK Python example given by VTK self.renWin = vtk.vtkRenderWindow() self.ren = vtk.vtkRenderer() self.ren.SetBackground( 0.329412, 0.34902, 0.427451 ) #self.cam = self.ren.GetActiveCamera() #self.cam.SetPosition( 0,0,0 ) self.ren.ResetCameraClippingRange() self.renWin.AddRenderer(self.ren) self.vtkw = vtkTkRenderWindowInteractor(self.__frame, rw=self.renWin, width=400, height=400) self.renWin.Render() self.renWin.PolygonSmoothingOn() self.vtkw.Initialize() self.vtkw.pack(side="top", fill='both', expand=1) self.vtkw.Start() def showIsosurfaceHead( self ): self.__removeOldActorsAndSetNewActor( self.ISO ) self.geoVolumeSkin.SetInput( self.contourSkinTop.GetOutput() ) self.geoVolumeBone.SetInput( self.contourBoneHead.GetOutput() ) self.ren.AddActor( self.actorSkin ) self.ren.AddActor( self.actorBone ) def showIsosurfaceFeet( self ): self.__removeOldActorsAndSetNewActor( self.ISO ) self.geoVolumeSkin.SetInput( self.contourSkinFeet.GetOutput() ) self.geoVolumeBone.SetInput( self.contourBoneFeet.GetOutput() ) self.ren.AddActor( self.actorSkin ) self.ren.AddActor( self.actorBone ) def showCompHead( self ): self.__removeOldActorsAndSetNewActor( self.COMP ) self.volumeComp.SetMapper( self.mapperCompHead ) self.ren.AddActor( self.volumeComp ) def showCompFeet( self ): self.__removeOldActorsAndSetNewActor( self.COMP ) self.volumeComp.SetMapper( self.mapperCompFeet ) self.ren.AddActor( self.volumeComp ) def showMIPHead( self ): self.__removeOldActorsAndSetNewActor( self.MIP ) self.volumeMIP.SetMapper( self.mapperMIPHead ) self.ren.AddActor( self.volumeMIP ) def showMIPFeet( self ): self.__removeOldActorsAndSetNewActor( self.MIP ) self.volumeMIP.SetMapper( self.mapperMIPFeet) self.ren.AddActor( self.volumeMIP ) def updateSurface( self, dictSettings ): if ( dictSettings[ 'tissue' ] == self.SKIN ): # ISOSURFACE self.actorSkin.GetProperty().SetColor( dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.actorSkin.GetProperty().SetOpacity( dictSettings[ 'opaque' ]/100.0 ) self.actorSkin.GetMapper().Update() # COMPOSITE for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+200, 5 ): self.opacityFunctionComp.RemovePoint( y ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+100, 1 ): self.colorTransferFunctionComp.RemovePoint( y ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+200, 5 ): self.opacityFunctionComp.AddPoint( y, dictSettings[ 'opaque' ]/100.0 ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+100, 1 ): self.colorTransferFunctionComp.AddRGBPoint( y, dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.volumeComp.GetMapper().Update() # MIP for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.opacityFunctionMIP.RemovePoint( y ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.colorTransferFunctionMIP.RemovePoint( y ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.opacityFunctionMIP.AddPoint( y, dictSettings[ 'opaque' ]/100.0 ) for y in range( self.SKIN_ISOSURFACE,self.SKIN_ISOSURFACE+10, 1 ): self.colorTransferFunctionMIP.AddRGBPoint( y, dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.volumeMIP.GetMapper().Update() elif ( dictSettings[ 'tissue' ] == self.BONE ): # ISOSURFACE self.actorBone.GetProperty().SetColor( dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.actorBone.GetProperty().SetOpacity( dictSettings[ 'opaque' ]/100.0 ) self.actorBone.GetMapper().Update() # COMPOSITE for x in range( self.BONE_ISOSURFACE, 5000, 10 ): self.opacityFunctionComp.RemovePoint( x ) for x in range( self.BONE_ISOSURFACE, self.BONE_ISOSURFACE+259, 1 ): self.colorTransferFunctionComp.RemovePoint( x ) for x in range( self.BONE_ISOSURFACE, 5000, 10 ): self.opacityFunctionComp.AddPoint( x, dictSettings[ 'opaque' ]/100.0 ) for x in range( self.BONE_ISOSURFACE, self.BONE_ISOSURFACE+259, 1 ): self.colorTransferFunctionComp.AddRGBPoint( x, dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.volumeComp.GetMapper().Update() # MIP for x in range( self.BONE_ISOSURFACE, 5000, 1 ): self.opacityFunctionMIP.RemovePoint( x ) for x in range( self.BONE_ISOSURFACE, 5000, 100 ): self.colorTransferFunctionMIP.RemovePoint( x ) for x in range( self.BONE_ISOSURFACE, 5000, 1 ): self.opacityFunctionMIP.AddPoint( x, dictSettings[ 'opaque' ]/100.0 ) for x in range( self.BONE_ISOSURFACE, 5000, 100 ): self.colorTransferFunctionMIP.AddRGBPoint( x, dictSettings[ 'red' ]/256.0, dictSettings[ 'green' ]/256.0, dictSettings[ 'blue' ]/256.0 ) self.volumeMIP.GetMapper().Update() def updateSamplingRate( self, xSample, ySample, zSample ): self.voiHead.SetSampleRate( xSample,ySample,zSample ) self.voiFeet.SetSampleRate( xSample,ySample,zSample ) self.volumeComp.SetScale( xSample,ySample,zSample ) self.volumeMIP.SetScale( xSample,ySample,zSample ) self.actorSkin.GetMapper().Update() self.actorBone.GetMapper().Update() self.volumeComp.GetMapper().Update() self.volumeMIP.GetMapper().Update() def __removeOldActorsAndSetNewActor( self, actorID ): if ( self.__lastActorID == self.ISO ): self.ren.RemoveActor( self.actorSkin ) self.ren.RemoveActor( self.actorBone ) elif ( self.__lastActorID == self.COMP ): self.ren.RemoveActor( self.volumeComp ) elif ( self.__lastActorID == self.MIP ): self.ren.RemoveActor( self.volumeMIP ) self.__lastActorID = actorID def destroy( self ): del self.ren del self.renWin del self.vtkw #------------------------- VTK CLASS ---------------------------------------- #-------------- VOLUME OF INTEREST DIALOG ------------------------------------- class DialogOptionVOI( ModalDialog ): def __init__( self, topWindow, vtkWindow ): ModalDialog.__init__( self, topWindow, 'Global Sampling Level', I_TRUE ) self.__vtkWindow = vtkWindow # Constants self.I_ERROR = -5 self.I_OK = 0 self.I_CANCEL = -10 self.__action = self.I_CANCEL self.__xSampleRate = 1.0 self.__ySampleRate = 1.0 self.__zSampleRate = 1.0 self.__buildDialog() def __setErrorMessage( self, message ): self.setStatusBarMessage( B_USE_ERROR_COLOR, message ) def __buildDialog( self ): guiFactory = GUIFactory() gridSettings = { 'padx':5, 'pady':5, 'sticky':Tkinter.SW, 'row':0, 'rowspan':1, 'column':0, 'columnspan':1 } labelX = guiFactory.newLabel( self.dialog, 'X', {'justify':Tkinter.RIGHT} ) gridSettings[ 'sticky' ] = Tkinter.NW gridSettings[ 'row' ] = 0 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelX, gridSettings ) self.__sliderSampleX = SliderWithValue( self.dialog, 1,8 ) #self.__sliderSampleX.configureScale( {'variable':self.__xSampleRate} ) self.__widgetSampleX = self.__sliderSampleX.getWidget() gridSettings[ 'column' ] = 1 self.__sliderSampleX.addSliderCommandBinding( self.__doUpdateSample ) guiFactory.packItem( self.__widgetSampleX, gridSettings ) labelY = guiFactory.newLabel( self.dialog, 'Y', {'justify':Tkinter.RIGHT} ) gridSettings[ 'sticky' ] = Tkinter.NW gridSettings[ 'row' ] = 1 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelY, gridSettings ) self.__sliderSampleY = SliderWithValue( self.dialog, 1,8 ) self.__widgetSampleY = self.__sliderSampleY.getWidget() gridSettings[ 'column' ] = 1 self.__sliderSampleY.addSliderCommandBinding( self.__doUpdateSample ) guiFactory.packItem( self.__widgetSampleY, gridSettings ) labelZ = guiFactory.newLabel( self.dialog, 'Z', {'justify':Tkinter.RIGHT} ) gridSettings[ 'sticky' ] = Tkinter.NW gridSettings[ 'row' ] = 2 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelZ, gridSettings ) self.__sliderSampleZ = SliderWithValue( self.dialog, 1,8 ) self.__widgetSampleZ = self.__sliderSampleZ.getWidget() gridSettings[ 'column' ] = 1 self.__sliderSampleZ.addSliderCommandBinding( self.__doUpdateSample ) guiFactory.packItem( self.__widgetSampleZ, gridSettings ) def __doUpdateSample( self, *unusedArgument ): self.__xSampleRate = self.__sliderSampleX.getValue() self.__ySampleRate = self.__sliderSampleY.getValue() self.__zSampleRate = self.__sliderSampleZ.getValue() self.__sliderSampleX.configureLabel( { 'text':self.__xSampleRate } ) self.__sliderSampleY.configureLabel( { 'text':self.__ySampleRate } ) self.__sliderSampleZ.configureLabel( { 'text':self.__zSampleRate } ) self.__vtkWindow.updateSamplingRate( self.__xSampleRate, self.__ySampleRate, self.__zSampleRate ) #-------------- END OF VOLUME OF INTEREST DIALOG -------------------------------- #-------------- CONTOURS DIALOG ------------------------------------------- class DialogIsosurfaces( ModalDialog ): global I_TRUE, I_FALSE def __init__( self, topWindow, vtkWindow, vizType ): ModalDialog.__init__( self, topWindow, 'Surface Properties', I_TRUE ) self.__vtkWindow = vtkWindow self.__vizType = vizType self.__tissue = Tkinter.IntVar() self.__skinValuesDict = {} self.__boneValuesDict = {} self.__skinValuesDict[ 'tissue' ] = self.__vtkWindow.SKIN self.__skinValuesDict[ 'red' ] = 0 self.__skinValuesDict[ 'green' ] = 0 self.__skinValuesDict[ 'blue' ] = 0 self.__skinValuesDict[ 'opaque' ] = 0 self.__boneValuesDict[ 'tissue' ] = self.__vtkWindow.BONE self.__boneValuesDict[ 'red' ] = 0 self.__boneValuesDict[ 'green' ] = 0 self.__boneValuesDict[ 'blue' ] = 0 self.__boneValuesDict[ 'opaque' ] = 0 self.__buildDialog() self.__doSetSkinTissue() def __buildDialog( self ): guiFactory = GUIFactory() gridSettings = { 'padx':5, 'pady':5, 'sticky':Tkinter.SW, 'row':0, 'rowspan':1, 'column':0, 'columnspan':1 } ###### Tissue Type labelType = guiFactory.newLabel( self.dialog, 'Tissue', {} ) gridSettings[ 'row' ] = 0 gridSettings[ 'rowspan' ] = 1 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelType, gridSettings ) ############ Radiobutton Types self.__radioMarchingCubes = guiFactory.newRadiobutton( self.dialog, 'Skin', self.__doSetSkinTissue, self.__tissue, self.__vtkWindow.SKIN, {} ) gridSettings[ 'column' ] = 1 guiFactory.packItem( self.__radioMarchingCubes, gridSettings ) self.__radioRaycastComposite = guiFactory.newRadiobutton( self.dialog, 'Bone', self.__doSetBoneTissue, self.__tissue, self.__vtkWindow.BONE, {} ) gridSettings[ 'column' ] = 2 guiFactory.packItem( self.__radioRaycastComposite, gridSettings ) ###### Color Picker labelColor = guiFactory.newLabel( self.dialog, 'Color', {'justify':Tkinter.LEFT} ) gridSettings[ 'row' ] = 1 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelColor, gridSettings ) self.__labelColorChanger = guiFactory.newLabel( self.dialog, '', {'justify':Tkinter.LEFT, 'width':18} ) gridSettings[ 'column' ] = 1 gridSettings[ 'columnspan' ] = 2 guiFactory.packItem( self.__labelColorChanger, gridSettings ) labelRed = guiFactory.newLabel( self.dialog, 'Red', {'justify':Tkinter.LEFT} ) gridSettings[ 'row' ] = 2 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelRed, gridSettings ) self.__sliderRed = SliderWithValue( self.dialog, 0, 255 ) self.__sliderRed.addSliderCommandBinding( self.__doUpdateColorLabelsEtc ) self.__widgetRed = self.__sliderRed.getWidget() gridSettings[ 'column' ] = 1 gridSettings[ 'columnspan' ] = 2 guiFactory.packItem( self.__widgetRed, gridSettings ) labelGreen = guiFactory.newLabel( self.dialog, 'Green', {'justify':Tkinter.LEFT} ) gridSettings[ 'row' ] = 3 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelGreen, gridSettings ) self.__sliderGreen = SliderWithValue( self.dialog, 0, 255 ) self.__sliderGreen.addSliderCommandBinding( self.__doUpdateColorLabelsEtc ) self.__widgetGreen = self.__sliderGreen.getWidget() gridSettings[ 'column' ] = 1 gridSettings[ 'columnspan' ] = 2 guiFactory.packItem( self.__widgetGreen, gridSettings ) labelBlue = guiFactory.newLabel( self.dialog, 'Blue', {'justify':Tkinter.LEFT} ) gridSettings[ 'row' ] = 4 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( labelBlue, gridSettings ) self.__sliderBlue = SliderWithValue( self.dialog, 0, 255 ) self.__sliderBlue.addSliderCommandBinding( self.__doUpdateColorLabelsEtc ) self.__widgetBlue = self.__sliderBlue.getWidget() gridSettings[ 'column' ] = 1 gridSettings[ 'columnspan' ] = 2 guiFactory.packItem( self.__widgetBlue, gridSettings ) self.__doUpdateColorLabelsEtc() ###### Opacity Value self.__labelOpacity = guiFactory.newLabel( self.dialog, 'Opaque (%)', {'justify':Tkinter.LEFT} ) gridSettings[ 'row' ] = 5 gridSettings[ 'column' ] = 0 gridSettings[ 'columnspan' ] = 1 guiFactory.packItem( self.__labelOpacity, gridSettings ) self.__sliderOpacity = SliderWithValue( self.dialog, 0, 100 ) self.__widgetOpacity = self.__sliderOpacity.getWidget() gridSettings[ 'column' ] = 1 guiFactory.packItem( self.__widgetOpacity, gridSettings ) self.__sliderOpacity.addSliderCommandBinding( self.__doUpdateOpacity ) # Color extraction function adapted from that given in the web resource # "An Introduction to Tkinter". def __doUpdateColorLabelsEtc( self, *unusedArgument ): redValue = self.__sliderRed.getValue() greenValue = self.__sliderGreen.getValue() blueValue = self.__sliderBlue.getValue() self.__sliderRed.configureLabel( { 'text':redValue } ) self.__sliderGreen.configureLabel( { 'text':greenValue } ) self.__sliderBlue.configureLabel( { 'text':blueValue } ) self.__rgbColor = "#%02x%02x%02x" % ( redValue, greenValue, blueValue ) self.__labelColorChanger.config( background=self.__rgbColor ) tissueValue = self.__tissue.get() if ( tissueValue == self.__vtkWindow.SKIN ): self.__skinValuesDict[ 'red' ] = redValue self.__skinValuesDict[ 'green' ] = greenValue self.__skinValuesDict[ 'blue' ] = blueValue print "skin...", redValue, greenValue, blueValue self.__vtkWindow.updateSurface( self.__skinValuesDict ) elif ( tissueValue == self.__vtkWindow.BONE ): self.__boneValuesDict[ 'red' ] = redValue self.__boneValuesDict[ 'green' ] = greenValue self.__boneValuesDict[ 'blue' ] = blueValue print "bone...", redValue, greenValue, blueValue self.__vtkWindow.updateSurface( self.__boneValuesDict ) def __doUpdateOpacity( self, *unusedArgument ): tissueValue = self.__tissue.get() opacityValue = self.__sliderOpacity.getValue() self.__sliderOpacity.configureLabel( { 'text':opacityValue } ) if ( tissueValue == self.__vtkWindow.SKIN ): self.__skinValuesDict[ 'opaque' ] = opacityValue print "skin opacity...", opacityValue self.__vtkWindow.updateSurface( self.__skinValuesDict ) elif ( tissueValue == self.__vtkWindow.BONE ): self.__boneValuesDict[ 'opaque' ] = opacityValue print "bone opacity...", opacityValue self.__vtkWindow.updateSurface( self.__boneValuesDict ) def __doSetSkinTissue( self ): print ">>> SET SKIN" self.__tissue.set( self.__vtkWindow.SKIN ) self.__sliderOpacity.setScaleValue( self.__skinValuesDict[ 'opaque' ] ) self.__doUpdateOpacity() self.__sliderRed.setScaleValue( self.__skinValuesDict[ 'red' ] ) self.__sliderGreen.setScaleValue( self.__skinValuesDict[ 'green' ] ) self.__sliderBlue.setScaleValue( self.__skinValuesDict[ 'blue' ] ) self.__doUpdateColorLabelsEtc() def __doSetBoneTissue( self ): print ">>> SET BONE" self.__tissue.set( self.__vtkWindow.BONE ) self.__sliderOpacity.setScaleValue( self.__boneValuesDict[ 'opaque' ] ) self.__doUpdateOpacity() self.__sliderRed.setScaleValue( self.__boneValuesDict[ 'red' ] ) self.__sliderGreen.setScaleValue( self.__boneValuesDict[ 'green' ] ) self.__sliderBlue.setScaleValue( self.__boneValuesDict[ 'blue' ] ) self.__doUpdateColorLabelsEtc() #----------------------- END OF CONTOURS DIALOG -------------------------------- #------------------------ GUI CLASS --------------------------------------- class GUI: def __init__( self, rootWindow ): global I_TRUE, I_FALSE # Constants self.I_OK = 0 self.I_NO_FILE = -10 self.__vizType = Tkinter.IntVar() self.__vizDataset = Tkinter.IntVar() self.__vizSmooth = Tkinter.IntVar() guiFactory = GUIFactory() # Create window frame self.__rootWindow = rootWindow self.__rootWindow.title( 'CS 526 :: Project 2' ) self.__frame = Tkinter.Frame( self.__rootWindow ) self.__frame.pack( fill=Tkinter.BOTH, expand=1, side=Tkinter.TOP ) self.__openFileFlag = I_FALSE #self.__openFileFlag = I_TRUE print "Add window frame" #<<<< # Add VTK rendering viewport self.__vtkViewport = VTKRender( self.__frame ) # Add menu bar menuBar = Tkinter.Menu( self.__frame ) self.__rootWindow.config( menu=menuBar ) self.__buildMenu( menuBar ) print "Add menu bar" #<<<< # Add pseudo-status bar (from "An Introduction to Tkinter" ) self.__statusLabel = guiFactory.newLabel( self.__frame, 'by: Allan Spale', {'relief':Tkinter.SUNKEN,'justify':Tkinter.LEFT, 'anchor':Tkinter.W } ) self.__statusErrorSettings = { 'background':'#ffffff', 'foreground':'#000099' } self.__statusOKSettings = { 'background':self.__statusLabel.cget( 'background' ), 'foreground':self.__statusLabel.cget( 'foreground' ) } self.__statusLabel.pack( fill=Tkinter.BOTH, side=Tkinter.BOTTOM ) print "Done with window" #<<<< self.__dialogGlobalDetail = DialogOptionVOI( self.__rootWindow, self.__vtkViewport ) self.__dialogDatasetProps = DialogIsosurfaces( self.__rootWindow, self.__vtkViewport, self.__vizType.get() ) # Initialize self.__vizType.set( self.__vtkViewport.ISO ) self.__vizDataset.set( self.__vtkViewport.HEAD ) self.__doSetVizType() #self.__vizSmooth.set( I_TRUE ) #self.__doSetVizSmooth() def __buildMenu( self, menuMainMenu ): menuFile = Tkinter.Menu( menuMainMenu, tearoff=0 ) menuFile.add_command( label='Exit', command=self.__doMenuFileExit ) menuMainMenu.add_cascade( label='File', menu=menuFile ) self.__menuViz = Tkinter.Menu( menuMainMenu, tearoff=0 ) self.__menuViz.add_radiobutton( label='Isosurface', value=self.__vtkViewport.ISO, variable=self.__vizType, command=self.__doSetVizType ) self.__menuViz.add_radiobutton( label='Raycast - Composite', value=self.__vtkViewport.COMP, variable=self.__vizType, command=self.__doSetVizType ) self.__menuViz.add_radiobutton( label='Raycast - MIP', value=self.__vtkViewport.MIP, variable=self.__vizType, command=self.__doSetVizType ) self.__menuViz.add_separator() self.__menuViz.add_radiobutton( label='Head', value=self.__vtkViewport.HEAD, variable=self.__vizDataset, command=self.__doSetVizType ) self.__menuViz.add_radiobutton( label='Feet', value=self.__vtkViewport.FEET, variable=self.__vizDataset, command=self.__doSetVizType ) menuMainMenu.add_cascade( label='Visualization', menu=self.__menuViz ) self.__menuOptions = Tkinter.Menu( menuMainMenu, tearoff=0 ) self.__menuOptions.add_command( label='Dataset Properties', command=self.__doMenuOptionProps ) self.__menuOptions.add_command( label='Global Level of Detail', command=self.__doMenuOptionDetail ) #self.__menuOptions.add_checkbutton( label='Smoothing', # variable=self.__vizSmooth, # command=self.__doSetVizSmooth ) menuMainMenu.add_cascade( label='Options', menu=self.__menuOptions ) def __doSetVizType( self ): dataset = self.__vizDataset.get() viz = self.__vizType.get() if ( dataset == self.__vtkViewport.HEAD ): if ( viz == self.__vtkViewport.ISO ): self.__vtkViewport.showIsosurfaceHead() elif ( viz == self.__vtkViewport.COMP ): self.__vtkViewport.showCompHead() elif ( viz == self.__vtkViewport.MIP ): self.__vtkViewport.showMIPHead() elif ( dataset == self.__vtkViewport.FEET ): if ( viz == self.__vtkViewport.ISO ): self.__vtkViewport.showIsosurfaceFeet() elif ( viz == self.__vtkViewport.COMP ): self.__vtkViewport.showCompFeet() elif ( viz == self.__vtkViewport.MIP ): self.__vtkViewport.showMIPFeet() def __doMenuOptionProps( self ): self.__dialogDatasetProps.show() def __doMenuOptionDetail( self ): self.__dialogGlobalDetail.show() """ def __doSetVizSmooth( self ): smoothFlag = self.__vizSmooth.get() print "smooth flag = ",smoothFlag if ( smoothFlag == I_TRUE ): self.__vtkViewport.renWin.PolygonSmoothingOn() self.__vtkViewport.renWin.Update() else: self.__vtkViewport.renWin.PolygonSmoothingOff() self.__vtkViewport.renWin.Update() """ def __doMenuFileExit( self ): print "Bye" self.__vtkViewport.destroy() self.__rootWindow.destroy() sys.exit( 0 ) print "Done" #------------------------ END OF GUI CLASS ---------------------------------- #### main function #### root = Tkinter.Tk() gui = GUI(root) root.mainloop()