Needle Biopsy

From IGSTK

Jump to: navigation, search

Contents

Introduction

This example application shows how to program a simple IGT application using IGSTK.

How to build

  1. This application builds automatically when IGSTK_USE_FLTK and IGSTK_BUILD_EXAMPLES is turned ON.

If you want to use Micron tracker with this application, make sure you have configured the with IGSTK_USE_MicronTracker ON.

If you follow this process and successfully build the IGSTK, the final binary file should be in your “IGSTK-Bin/bin/” or sub directory

Requirements to run the application

  1. You should have a Polaris, Aurora, or Micron Tracker connected to your system, with necessary drivers installed and additional files for setting up the tracker (such as SROMs, markers, and camera calibration file)
  2. Have an image volume with fiducial markers in it. Image should be DICOM format with CT or MR as modality, and should be stored in a directory with only one series. You should also have the object scanned available with the fiducial stay intact. You need to use it for landmark registration
  3. Some pointer tool that can be tracked and has known coordinate system definition and tooltip offset. In IGSTK, the cylinder object assumes the principle axis (the longest axis) to be Z. To have the needle displayed correctly in the image overlay. You might have to calibrate the axis. For instance, for Aurora tool, depending on the wiring of the sensor, some times, you might have to flip the Z axis. In the example, for Micron tracker, we assume the needle axis is the X axis in the marker coordinate system (The longer xline), so we need to switch X and Z to have the needle displayed correctly.
  4. This application also assume you might use some kind of reference tool, but that’s optional.

How to run the application

  1. Run the executable
  2. Load the image series from disk
  3. The application will automatically look for the corresponding treatment plan for this image series (DirName_TreatmentPlan.igstk). If the plan file doesn’t exist, it will create a default plan of 5 points (entry, target, and 3 fiducials). A example plan file is showing below. For more details, please refer to classes igstkTreatmentPlan and igstkTreatmentPlanIO in the example source code directory.
  4. You can change the values for these points by selecting them from the drop-down choice box and then click on the image. Annotation should show the updated value in red. Meanwhile the values will also be save to the disk, next time you load the same image, it will read these values back
  5. You can then choose to connect to tracker, after setting all the parameters, you can click “confirm”, if success, the registration window will show up.
  6. You need to use the tracker tool to touch the fiducial on the object, in the same sequence as in the planning part, and then click on set tracker fiducal button. It will also jump to the next fiducial for user to set.
  7. After setting all the fiducials, you can click on “Registration” this will do the landmark registration between image space and tracker space. If it returns successfully, a new tracker and tracker tool will be added to the list box. The view windows should also start tracking the tool location.
  8. If you have multiple tracker, or tracker tool connected. You can change the active tool from the choice box, which will switch the tool that the View window is following.

Example treatment plan file format:

# Entry point
0.820425  -143.635  -186
# Target point
54.268    -108.513  -191
# Fiducial points
98.4887   -152.976  -181
-1.89214  -148.996  -191
-59.2006  -190.563  -191

How to connect the scene graph

1. Choose a world coordinate system as the initial point of reference, you can use any class that has a coordinate system API, such as SpatialObject, Tracker, TrackerTool, and View. In this case we made up a virtual "WorldReference" using an AxesSpatialObject.

m_WorldReference        = igstk::AxesObject::New();

2. Now we need to add object to the scene by connecting them to the WorldReference. At this stage we are just going to stack everything in the world reference system using identity transform. Notice that we use the igstk::TimeStamp::GetLongestPossibleTime() as the valid period of the transform. This transform is essentially a constant transform. Don't forget to connect View, only when the View is connected to the scene graph will it be able to render the scene!!

igstk::Transform transform;
transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
ViewerGroup->m_Views[i]->RequestSetTransformAndParent( transform, m_WorldReference );
m_ImageSpatialObject->RequestSetTransformAndParent( transform, m_WorldReference );
m_Needle->RequestSetTransformAndParent( transform, m_WorldReference );
m_NeedleTip->RequestSetTransformAndParent( transform, m_WorldReference );

3. It's a little bit tricky for the case of Tracker and TrackerTool. If you are using a reference tool, you should connect the reference TrackerTool to the world reference system, and if you don't use a reference tool, you should connect Tracker to the world reference directly. There is no need to connect Tracker and TrackerTool for scene graph purpose. They are internally wired when you request attaching a TrackerTool to Tracker, and the parent-child relationship will change automatically if you decide to set one of the TrackerTool as a reference.

     /** Connect the scene graph with an identity transform first */
     igstk::Transform transform;
     transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
     if ( m_TrackerInitializer->HasReferenceTool() )
       {
       refTool->RequestSetTransformAndParent(transform, m_WorldReference);
       }
     else
       {
       tracker->RequestSetTransformAndParent(transform, m_WorldReference);
       }

Now we also want our needle to move with TrackerTool1, so we attached those spatial object as the child of the TrackerTool1. To avoid circular connection, we designed the scene graph so that it refuses to connect to a parent, when a circular connection is detected. If you want to change the scene graph tree structure, it is safer to detach it from its parents and then do the re-attaching.

     igstk::Transform transform;
     transform.SetToIdentity(igstk::TimeStamp::GetLongestPossibleTime());
     m_Needle->RequestDetachFromParent();
     m_NeedleTip->RequestDetachFromParent();
     m_Needle->RequestSetTransformAndParent( transform, m_ActiveTool);
     m_NeedleTip->RequestSetTransformAndParent( transform, m_ActiveTool);



4. When you have registered the Tracker and Image, you can substitute the Transform in the previous code with the LandmarkRegistrationTransform. When doing the registration, be careful about which two frames you are registering with. In the case of using TrackerTool2 as the reference tool, image landmark points are in the WorldReference, and tracker landmark points are in TrackerTool2's frame. Meaning, when you are acquiring tracker landmark points using TrackerTool1, you should call the following:

trackerTool1->RequestComputeTransformTo( TrackerTool2 ); 


5. After start tracking, if you want to get the overlaid position of TrackerTool in the Image space. You can do either of the following. They have the same effects, since ImageSpatialObject is attached to WorldReference suing an identity transform.

trackerTool1->RequestComputeTransformTo( m_ImageSpatialObject ); 
trackerTool1->RequestComputeTransformTo( m_WorldReference ); 

You need to connect an observer to the trackerTool1 to listening to the returned transform.

// Connect observer
typedef igstk::TransformObserver ObserverType;
ObserverType::Pointer transformObserver = ObserverType::New();
transformObserver->ObserveTransformEventsFrom( m_ActiveTool );
transformObserver->Clear();
// Request for transform
m_ActiveTool->RequestComputeTransformTo( m_WorldReference );
// Check the recipient
if ( transformObserver->GotTransform() )
{
  // Retreive the transform
  igstk::Transform transform = transformObserver->GetTransform() ;
}

6. As we said, we can use any class that has a coordinate system API as the world coordinate reference. For example, we can use ImageSpatialObject as the world coordinate system, so the above example is equivalent to:

7. The flexible scene graph design not only allows you to compute the transform between any two connected points in the scene graph tree but also allows you to see the world from different perspective. For example, if you want to observe the scene from a NeedTip's point of view as it's moving in the patient anatomy, just attach the View to the NeedleTip.


If you have any question, please send your email to igstk-users@public.kitware.com.

Personal tools
TOOLBOX
LANGUAGES