[IGSTK-Developers] Tracker, slicer, etc

Frank Lindseth Frank.Lindseth at sintef.no
Mon Jun 18 18:02:46 EDT 2007


Hi David,

Tracker:
I just went trough your "tracker interface changes" page: It looks  
very good, I will send our comments after speaking to the rest of the  
trondheim developers.
But I was hoping that it would be possible to incorporate the  
"coordinate system changes" that we basically agrees on (both in  
terms of the necessity for doing so as well as how it should be done)  
at the same time:
http://public.kitware.com/IGSTKWIKI/index.php/ 
DesignChallenges#Coordinate_systems_.2F_Transforms_.2F_Registration
http://public.kitware.com/IGSTKWIKI/index.php/ 
Talk:DesignChallenges#Coordinate_systems_.2F_Transforms_.2F_Registration
http://public.kitware.com/IGSTKWIKI/index.php/ 
Minutes_052407#DesignChallenges
I.e.
- The Tracker comp. supplies the (Image)SpatialObj with tool (tip)  
positions and orientations (i.e. calibration included) in tracker  
(reference frame) coordinates.
- Each ImageSpatialObject is associated with A) a accumulated Image/ 
VolumeTransform that tells where the volume is relative to the  
tracker ref. frame and B) a list of all the UpdateTransforms that a  
volume has gone trough (for a pre.op. volume the list of  
updateTransf. could be 1)DICOM transf. 2) MR-MR or CT-CT or CT-MR  
transf. 3) Patient reg. transf. (Tracker-Image transf.) 4) MR to  
US-01 update, 5) US-01 to US-02 update, etc.).
- Using the position of the tool tip in tracker coords. and  
accumulated Image/VolumeTransform the ImageSpatialObj can supply the  
ImageSliceRep. with the information needed to extract the right  
slices from the volume.

Slicer:
As pointed out by Patrick, it's time to start the practical work with  
the new Slicer comp.
much have been said already:
http://public.kitware.com/IGSTKWIKI/index.php/ImageSliceRepresentation
http://public.kitware.com/IGSTKWIKI/index.php/ 
Talk:ImageSliceRepresentation
http://public.kitware.com/IGSTKWIKI/index.php/DesignChallenges#Slicing
http://public.kitware.com/IGSTKWIKI/index.php/ 
Talk:DesignChallenges#Slicing

As you know, a slice can be displayed in both a "2D window" and (on a  
2D plane) in a "3D scene".
IGSTK needs both. You have previously told me that you will submit  a  
C++ OrthoPlaneWidget class (based on the "atamai python classes") to  
VTK:
>>>> Yes, we have an OrthoPlaneWidget C++ class that can be used for  
>>>> displaying
>>>> three (or just two or one) slices in a 3D scene. This class will  
>>>> be committed
>>>> to VTK cvs, probably around the middle of June.
>>>>
Do you think that it would be possible/wise to make IGSTK Slicer  
comp. based on such a Ortho/ObliquePlane/SliceWidget?

--------------
Just to illustrate it's intended use of the slicer comp. I have  
included the miniasp.py atamai example below
Of course, writing an application in C++ usually requires more lines  
of code than the equivalent application in python,
but this is actually a "full blown viewer app." (easily extendable to  
a navigation/tracker app.), and it shows how "easy" it could
be to put together an application with the right functionality using  
high-level components. I loved it during my PhD work several years ago,
and I love it today... Wouldn't it be nice if it was just as easy to  
use IGSTK some time in the future, at the same time as it was safe. I  
believe this
is possible if we focus functionality, anybody else???

miniasp.py:
----
#!/usr/local/bin/python

# Basic image viewer example that doesn't rely on any GUI toolkits
# outside of VTK

# here are a few variables to change the behaviour:

# initial size of the window
windowWidth = 852
windowHeight = 640

# interpolation of images
interpolation = 1

# width of border around the frames
borderwidth = 1

# arrange the panes in a 1 + 3 griding
viewports = [(0.00, 0.00, 0.67, 1.00),
              (0.67, 0.67, 1.00, 1.00),
              (0.67, 0.33, 1.00, 0.67),
              (0.67, 0.00, 1.00, 0.33)]

# or arrange the planes in 2 * 2 gridding
#viewports = [(0.00, 0.00, 0.50, 0.50),
#             (0.00, 0.50, 0.50, 1.00),
#             (0.50, 0.00, 1.00, 0.50),
#             (0.50, 0.50, 1.00, 1.00)]

# check for correct usage
import os, sys

if not sys.argv[1:]:
     filename = "phantom.mnc"
else:
     filename = sys.argv[1]

# first, load a script that sets the paths for the modules we load
import paths

# then load all of the classes we use
from PaneFrame import *
from RenderPane import *
from RenderPane2D import *
from WindowLevelInteractionMode import *

from OrthoPlanesFactory import *
from AnatomicalLabelsFactory import *
from OutlineFactory import *
from CrossCursorFactory import *

from ModePalette import *

# load the 'vtk widget set'
import Widgets

# load the file reader
from vtkMINCReader import *

# put everything together

# create the ortho-planes, to display 3 slices through data set
planes = OrthoPlanesFactory()
planes.SetSliceInterpolate(interpolation)
planes.SetTextureInterpolate(interpolation)
planes.ActivatePlaneGuides()
# this reader can be replaced by a reader for other file types
reader = vtkMINCReader()
reader.SetFileName(filename)

# get the data range for the lookup table,
# also get the shift/scale to convert the data into intensity
# values: intensity = data*scale + shift
(minval,maxval) = reader.GetDataRange()
intensityShift = reader.GetShift()
intensityScale = reader.GetScale()

# for convenience
imageData = reader.GetOutput()

# create a greyscale lookup table to use
table = vtkLookupTable()
table.SetTableRange(minval,maxval)
table.SetSaturationRange(0,0)
table.SetHueRange(0,0)
table.SetValueRange(0,1)
table.Build()

# add these to the orthoplanes
planes.SetInput(imageData)
planes.SetLookupTable(table)

# generate a frame around the volume
frame = OutlineFactory()
frame.SetInput(imageData)
frame.SetColor(1.0000, 0.8431, 0.0000)

# generate axes labels
labels = AnatomicalLabelsFactory()
labels.SetInput(imageData)

# make a cursor to display in all the frames
cursor = CrossCursorFactory()

# create window/level interaction for the rendering pane, attach
# the lookup table here too
windowlevel = WindowLevelInteractionMode()
windowlevel.SetLookupTable(table)

# create the rendering panes, add the actors
paneframe = PaneFrame(width=windowWidth, height=windowHeight)
paneframe.SetTitle("Atamai MiniAsp ["+filename+"]")

# the height of the control panel at the bottom,
# and the width of the borders around the panes
panelheight = 27

# figure out what the offsets on the viewports will have to
# be to make room for the control panel
viewportOffsets = []

for viewport in viewports:
   viewportOffsets.append(
     (0, int(panelheight*(1.0-viewport[1])),
      0, int(panelheight*(1.0-viewport[3]))))

# create the primary rendering pane with a nice border around it
pane = RenderPane(paneframe)
pane.SetViewport(viewports[0])
pane.SetViewportOffsets(viewportOffsets[0])
pane.SetBackground(1,1,1)
pane.SetBorderWidth(borderwidth)
pane.ConnectActorFactory(planes)
pane.ConnectActorFactory(frame)
pane.ConnectActorFactory(labels)
pane.ConnectCursor(cursor)
pane.BindModeToButton(windowlevel,3,"Shift")

# set up another pane for the single image
pane2 = RenderPane2D(paneframe)
pane2.SetViewport(viewports[1])
pane2.SetViewportOffsets(viewportOffsets[1])
pane2.SetBackground(0.5,0.5,0.5)
pane2.SetBorderWidth(borderwidth)
pane2.ConnectPlane(planes.GetAxialPlane())
pane2.ConnectCursor(cursor)
pane2.BindModeToButton(windowlevel,3,"Shift")

# set up another pane for the single image
pane3 = RenderPane2D(paneframe)
pane3.SetViewport(viewports[2])
pane3.SetViewportOffsets(viewportOffsets[2])
pane3.SetBackground(0.5,0.5,0.5)
pane3.SetBorderWidth(borderwidth)
pane3.ConnectPlane(planes.GetCoronalPlane())
pane3.ConnectCursor(cursor)
pane3.BindModeToButton(windowlevel,3,"Shift")

# set up another pane for the single image
pane4 = RenderPane2D(paneframe)
pane4.SetViewport(viewports[3])
pane4.SetViewportOffsets(viewportOffsets[3])
pane4.SetBackground(0.5,0.5,0.5)
pane4.SetBorderWidth(borderwidth)
pane4.ConnectPlane(planes.GetSagittalPlane())
pane4.ConnectCursor(cursor)
pane4.BindModeToButton(windowlevel,3,"Shift")

# set up a final pane just for the control panel
pane5 = RenderPane2D(paneframe)
pane5.SetViewport(0.0,0.0,1.0,0.0)
pane5.SetViewportOffsets(0,0,0,panelheight)
pane5.SetBackground(0.75,0.75,0.75)

# create a label for cursor coordinate readout, set the text to black
coordlabel = Widgets.CoordinateLabel(pane5,x=-280,y=0,
                                      foreground=(0.0,0.0,0.0))
coordlabel.SetCursor(cursor)

# create a label for intensity readout, set the text to red
intensitylabel = Widgets.IntensityLabel(pane5,x=-380,y=0,
                                         foreground=(1.0,0.0,0.0))
intensitylabel.SetInput(imageData)
intensitylabel.SetCursor(cursor)
intensitylabel.SetShift(intensityShift)
intensitylabel.SetScale(intensityScale)
intensitylabel.SetInterpolate(interpolation)

# create a logo bitmap
bitmapReader = vtkImageReader()
bitmapReader.SetFileName(os.path.join(paths.prefix,"classes/ 
Atamai.rgba"))
bitmapReader.SetDataScalarTypeToUnsignedChar()
bitmapReader.SetNumberOfScalarComponents(4)
bitmapReader.SetDataExtent(0,199,0,57,0,0)
logolabel = Widgets.Label(pane5,x=0,y=0,width=100,height=27,
                           bitmap=bitmapReader.GetOutput())

# create a palette of mouse mode interaction choices
modePalette = ModePalette(pane5,x=105,y=0)
modePalette.AddPane(pane)
modePalette.AddPane(pane2)
modePalette.AddPane(pane3)
modePalette.AddPane(pane4)
modePalette.SetLookupTable(table)

paneframe.Render()
pane.GetRenderer().GetActiveCamera().SetEyeAngle(5.0)

# start 'er up
paneframe.Start()



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/igstk-developers/attachments/20070619/a55d7f75/attachment.html>


More information about the IGSTK-Developers mailing list