1
/*=========================================================================
3
Program: Image Guided Surgery Software Toolkit
4
Module: $RCSfile: NeedleBiopsy.cxx,v $
6
Date: $Date: 2009-06-12 15:23:31 $
7
Version: $Revision: 1.3 $
9
Copyright (c) ISC Insight Software Consortium. All rights reserved.
10
See IGSTKCopyright.txt or http://www.igstk.org/copyright.htm for details.
12
This software is distributed WITHOUT ANY WARRANTY; without even
13
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14
PURPOSE. See the above copyright notices for more information.
16
=========================================================================*/
18
#include "NeedleBiopsy.h"
20
#include "FL/Fl_File_Chooser.H"
21
#include "FL/Fl_Input.H"
22
#include "igstkEvents.h"
23
#include "itksys/SystemTools.hxx"
24
#include "itksys/Directory.hxx"
25
#include "igstkTransformObserver.h"
27
#include "PolarisTrackerConfigurationGUI.h"
28
#include "AuroraTrackerConfigurationGUI.h"
29
#include "MicronTrackerConfigurationGUI.h"
31
/** -----------------------------------------------------------------
33
* -----------------------------------------------------------------
35
NeedleBiopsy::NeedleBiopsy() : m_LogFile()
38
/** Setup logger, for all igstk components. */
39
m_Logger = LoggerType::New();
40
this->GetLogger()->SetTimeStampFormat( itk::LoggerBase::HUMANREADABLE );
41
this->GetLogger()->SetHumanReadableFormat("%Y %b %d, %H:%M:%S");
42
this->GetLogger()->SetPriorityLevel( LoggerType::INFO );
44
/** Direct the application log message to the std::cout */
45
itk::StdStreamLogOutput::Pointer m_LogCoutOutput
46
= itk::StdStreamLogOutput::New();
47
m_LogCoutOutput->SetStream( std::cout );
48
this->GetLogger()->AddLogOutput( m_LogCoutOutput );
50
/** Direct the igstk components log message to the file. */
51
itk::StdStreamLogOutput::Pointer m_LogFileOutput
52
= itk::StdStreamLogOutput::New();
53
std::string logFileName;
54
logFileName = "logNeedleBiopsy"
55
+ itksys::SystemTools::GetCurrentDateTime( "_%Y_%m_%d_%H_%M_%S" ) + ".txt";
56
m_LogFile.open( logFileName.c_str() );
57
if( !m_LogFile.fail() )
59
m_LogFileOutput->SetStream( m_LogFile );
60
this->GetLogger()->AddLogOutput( m_LogFileOutput );
64
//Return if fail to open the log file
65
igstkLogMacro( DEBUG, "Problem opening Log file:"
66
<< logFileName << "\n" );
70
/** Initialize all member variables */
72
m_ImageReader = ImageReaderType::New();
73
m_LandmarkRegistration = RegistrationType::New();
74
m_Annotation = igstk::Annotation2D::New();
75
m_WorldReference = igstk::AxesObject::New();
76
m_TrackerInitializerList.clear();
77
m_Plan = new igstk::TreatmentPlan;
79
/** Setting up spatial objects and their representations */
80
m_NeedleTip = EllipsoidType::New();
81
m_NeedleTipRepresentation = EllipsoidRepresentationType::New();
82
m_NeedleTip->SetRadius( 5, 5, 5 );
83
m_NeedleTipRepresentation->RequestSetEllipsoidObject( m_NeedleTip );
84
m_NeedleTipRepresentation->SetColor(1.0,0.0,0.0);
85
m_NeedleTipRepresentation->SetOpacity(1.0);
87
m_Needle = CylinderType::New();
88
m_NeedleRepresentation = CylinderRepresentationType::New();
89
m_Needle->SetRadius( 1.5 );
90
m_Needle->SetHeight( 100 );
91
m_NeedleRepresentation->RequestSetCylinderObject( m_Needle );
92
m_NeedleRepresentation->SetColor(0.0,1.0,0.0);
93
m_NeedleRepresentation->SetOpacity(1.0);
95
m_TargetPoint = EllipsoidType::New();
96
m_TargetRepresentation = EllipsoidRepresentationType::New();
97
m_TargetPoint->SetRadius( 6, 6, 6 );
98
m_TargetRepresentation->RequestSetEllipsoidObject( m_TargetPoint );
99
m_TargetRepresentation->SetColor( 1.0, 0.0, 0.0);
100
m_TargetRepresentation->SetOpacity( 0.6 );
102
m_EntryPoint = EllipsoidType::New();
103
m_EntryRepresentation = EllipsoidRepresentationType::New();
104
m_EntryPoint->SetRadius( 6, 6, 6 );
105
m_EntryRepresentation->RequestSetEllipsoidObject( m_EntryPoint );
106
m_EntryRepresentation->SetColor( 0.0, 0.0, 1.0);
107
m_EntryRepresentation->SetOpacity( 0.6 );
109
m_FiducialPoint = EllipsoidType::New();
110
m_FiducialRepresentation = EllipsoidRepresentationType::New();
111
m_FiducialPoint->SetRadius( 6, 6, 6 );
112
m_FiducialRepresentation->RequestSetEllipsoidObject( m_FiducialPoint );
113
m_FiducialRepresentation->SetColor( 0.0, 1.0, 0.0);
114
m_FiducialRepresentation->SetOpacity( 0.6 );
117
m_Path = PathType::New();
119
point.SetPosition( 0, 0, 0);
120
point.SetRadius( 2 );
121
m_Path->AddPoint( point );
122
m_Path->AddPoint( point );
124
m_PathRepresentation.clear();
125
for( int i=0; i<4; i++ )
127
PathRepresentationType::Pointer rep = PathRepresentationType::New();
128
rep->RequestSetTubeObject( m_Path );
129
rep->SetColor( 0.0, 1.0, 0.0);
130
rep->SetOpacity( 0.4 );
131
m_PathRepresentation.push_back( rep );
134
/** Creating observers and their call back functions */
136
/** This observes picking event from view */
137
m_ViewPickerObserver = LoadedObserverType::New();
138
m_ViewPickerObserver->SetCallbackFunction( this, &NeedleBiopsy::Picking );
140
/** This observes reslicing events from FourQuadrantView class */
141
m_ViewResliceObserver = LoadedObserverType::New();
142
m_ViewResliceObserver->SetCallbackFunction( this,
143
&NeedleBiopsy::ResliceImage);
146
* This observer catches the tracker configuration sent out by
147
* TrackerConfiguration GUI
149
m_TrackerConfigurationObserver = LoadedObserverType::New();
150
m_TrackerConfigurationObserver->SetCallbackFunction( this,
151
&NeedleBiopsy::RequestInitializeTracker);
154
* This observer listens to the TrackerToolTransformUpdateEvent from
155
* TrackerTool class, notice this event doesn't carry any payload, it
156
* only functions as a ticker here to trigger image representation class
157
* to do image reslicing according to the current tooltip location.
159
* NeedleBiopsy::Tracking()
161
m_TrackerToolUpdateObserver = LoadedObserverType::New();
162
m_TrackerToolUpdateObserver->SetCallbackFunction( this,
163
&NeedleBiopsy::Tracking);
165
/** Create image slice representations */
166
m_ImageRepresentation.clear();
167
for (int i=0; i<6; i++)
169
ImageRepresentationType::Pointer rep = ImageRepresentationType::New();
170
m_ImageRepresentation.push_back( rep );
175
/** -----------------------------------------------------------------
177
* -----------------------------------------------------------------
179
NeedleBiopsy::~NeedleBiopsy()
181
m_TrackerInitializerList.clear();
182
m_TrackerToolList.clear();
187
/** -----------------------------------------------------------------
189
* This methods asks for folder directory contains a single dicom
190
* series. If it loads the image successfully, it will try loading
191
* the previously saved treatment plan, in the same parent directory
192
* which should be named "folderName_TreatmentPlan.igstk".
195
* ReadTreatmentPlan()
196
* WriteTreatmentPlan()
199
* igstkTreatmentPlanIO
200
* -----------------------------------------------------------------
202
int NeedleBiopsy::RequestLoadImage()
204
const char * directoryname = fl_dir_chooser("DICOM Volume directory","");
205
if ( directoryname != NULL )
207
igstkLogMacro( DEBUG,
208
"Set ImageReader directory: " << directoryname << "\n" )
209
m_ImageDir = directoryname;
210
m_ImageReader->RequestSetDirectory( directoryname );
212
igstkLogMacro( DEBUG, "ImageReader loading images... \n" )
213
m_ImageReader->RequestReadImage();
217
* IGSTK uses event for inter-components communication.
218
* Event/observer model is used to replace the normal Get() method.
219
* CTImageObserver here is defined by Macro in header file:
220
* igstkObserverObjectMacro( CTImage,
221
* igstk::CTImageReader::ImageModifiedEvent,
222
* igstk::CTImageSpatialObject);
223
* Refer to igstkMacros.h for more detail about this macro.
225
CTImageObserver::Pointer m_CTImageObserver = CTImageObserver::New();
226
m_ImageReader->AddObserver(igstk::CTImageReader::ImageModifiedEvent(),
229
m_ImageReader->RequestGetImage(); // This will invoke the event
231
if(m_CTImageObserver->GotCTImage())
233
igstkLogMacro( DEBUG, "Image loaded...\n" )
234
m_ImageSpatialObject = m_CTImageObserver->GetCTImage();
235
this->ConnectImageRepresentation();
236
this->ReadTreatmentPlan();
241
igstkLogMacro( DEBUG, "Reading image failure...\n" )
247
igstkLogMacro( DEBUG, "No directory is selected\n" )
253
/** -----------------------------------------------------------------
254
* This method should be invoked only when the Image has been loaded
255
* -----------------------------------------------------------------
257
void NeedleBiopsy::ConnectImageRepresentation()
259
/** Setting up annotation and added to four views */
260
m_Annotation->RequestSetAnnotationText( 2, "Georgetown ISIS Center" );
261
for( int i=0; i<4; i++)
263
ViewerGroup->m_Views[i]->RequestAddAnnotation2D( m_Annotation );
267
* Pass image spatial object to image slice representation and set
268
* the desired slice orientation for each representations, and then
269
* add them to the views
271
for( int i=0; i<6; i++)
273
m_ImageRepresentation[i]->RequestSetImageSpatialObject(
274
m_ImageSpatialObject );
277
m_ImageRepresentation[0]->RequestSetOrientation(
278
ImageRepresentationType::Axial );
279
m_ImageRepresentation[1]->RequestSetOrientation(
280
ImageRepresentationType::Sagittal );
281
m_ImageRepresentation[2]->RequestSetOrientation(
282
ImageRepresentationType::Coronal );
284
m_ImageRepresentation[3]->RequestSetOrientation(
285
ImageRepresentationType::Axial );
286
m_ImageRepresentation[4]->RequestSetOrientation(
287
ImageRepresentationType::Sagittal );
288
m_ImageRepresentation[5]->RequestSetOrientation(
289
ImageRepresentationType::Coronal );
291
for ( int i=0; i<3; i++)
293
ViewerGroup->m_Views[i]->RequestRemoveObject( m_ImageRepresentation[i] );
294
ViewerGroup->m_Views[3]->RequestRemoveObject( m_ImageRepresentation[i+3] );
295
ViewerGroup->m_Views[i]->RequestAddObject( m_ImageRepresentation[i] );
296
ViewerGroup->m_Views[3]->RequestAddObject( m_ImageRepresentation[i+3] );
300
* Add all the spatial object to the views
301
* Notice the Copy() method is used for most of the representation
302
* classes but not the path. This is because the underlying geometry
303
* is fixed for those spatial object once it's created.But the path
304
* will change it's shape, so we need to keep seperate pointer for
305
* path representation in each view
307
for ( int i=0; i<4; i++)
309
igstk::View::Pointer view = ViewerGroup->m_Views[i];
310
view->RequestAddObject( m_NeedleTipRepresentation->Copy() );
311
view->RequestAddObject( m_NeedleRepresentation->Copy() );
312
view->RequestAddObject( m_TargetRepresentation->Copy() );
313
view->RequestAddObject( m_EntryRepresentation->Copy() );
314
view->RequestAddObject( m_FiducialRepresentation->Copy() );
315
view->RequestAddObject( m_PathRepresentation[i] );
319
* Here we connect the scene graph
320
* Here we created a virtual world reference system(as the root) and
321
* attached all the objects as its children.
322
* This is for the convenience in the following implementation. You
323
* use any spatial object, view, tracker, or tracker tool as a
324
* reference system in IGSTK. And you can create your own class to
325
* use the coordinate system API by using this macro:
326
* igstkCoordinateSystemClassInterfaceMacro()
328
* igstkCoordinateSystemInterfaceMacros.h
330
* igstkCoordinateSystem
331
* igstkCoordinateSystemDelegator
333
igstk::Transform transform;
334
transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
335
for( int i=0; i<4; i++)
337
ViewerGroup->m_Views[i]->RequestSetTransformAndParent(
338
transform, m_WorldReference );
341
m_ImageSpatialObject->RequestSetTransformAndParent(
342
transform, m_WorldReference );
344
m_EntryPoint->RequestSetTransformAndParent( transform, m_WorldReference );
345
m_TargetPoint->RequestSetTransformAndParent( transform, m_WorldReference );
346
m_FiducialPoint->RequestSetTransformAndParent( transform, m_WorldReference );
347
m_Path->RequestSetTransformAndParent( transform, m_WorldReference );
349
m_Needle->RequestSetTransformAndParent( transform, m_WorldReference );
350
m_NeedleTip->RequestSetTransformAndParent( transform, m_WorldReference );
352
/** Reset and enable the view */
353
for( int i=0; i<4; i++)
355
ViewerGroup->m_Views[i]->RequestResetCamera();
356
ViewerGroup->m_Views[i]->SetRefreshRate( 30 );
357
ViewerGroup->m_Views[i]->RequestStart();
358
ViewerGroup->m_Displays[i]->RequestEnableInteractions();
362
* Request information about the slice bounds. The answers will be
363
* received in the form of events. This will be used to initialize
364
* the reslicing sliders and initial slice position
366
SliceBoundsObserver::Pointer boundsObs = SliceBoundsObserver::New();
367
for ( int i=0; i<3; i++)
369
m_ImageRepresentation[i]->AddObserver(
370
igstk::IntegerBoundsEvent(), boundsObs);
372
m_ImageRepresentation[i]->RequestGetSliceNumberBounds();
374
if( boundsObs->GotSliceBounds() )
376
const unsigned int min = boundsObs->GetSliceBounds().minimum;
377
const unsigned int max = boundsObs->GetSliceBounds().maximum;
378
const unsigned int slice =
379
static_cast< unsigned int > ( (min + max) / 2.0 );
380
m_ImageRepresentation[i]->RequestSetSliceNumber( slice );
381
m_ImageRepresentation[i+3]->RequestSetSliceNumber( slice );
382
ViewerGroup->m_Sliders[i]->minimum( min );
383
ViewerGroup->m_Sliders[i]->maximum( max );
384
ViewerGroup->m_Sliders[i]->value( slice );
385
ViewerGroup->m_Sliders[i]->activate();
390
/** Adding observer for picking event */
391
for ( int i=0; i<3; i++)
393
ViewerGroup->m_Views[i]->AddObserver(
394
igstk::CoordinateSystemTransformToEvent(),
395
m_ViewPickerObserver );
398
/** Adding observer for slider bar reslicing event*/
399
ViewerGroup->AddObserver( igstk::QuadrantViews::ReslicingEvent(),
400
m_ViewResliceObserver );
403
/** -----------------------------------------------------------------
404
* Here we read the treatment plan. In this simple example
405
* we assume there is one entry point, one target point, and at least
406
* 3 fiducial points. Here is a sample format
407
---------------------------------------------------------------------
409
0.820425 -143.635 -186
413
98.4887 -152.976 -181
414
-1.89214 -148.996 -191
415
-59.2006 -190.563 -191
416
--------------------------------------------------------------------
419
* igstkTreatmentPlanIO
420
* -----------------------------------------------------------------
422
void NeedleBiopsy::ReadTreatmentPlan()
424
igstk::TreatmentPlanIO * reader = new igstk::TreatmentPlanIO;
426
m_PlanFilename = m_ImageDir + "_TreatmentPlan.igstk";
428
m_Plan = new igstk::TreatmentPlan;
430
if (itksys::SystemTools::FileExists( m_PlanFilename.c_str()))
432
reader->SetFileName( m_PlanFilename );
433
if ( reader->RequestRead( ) )
435
m_Plan = reader->GetTreatmentPlan();
439
/** Populate the choice box */
440
TPlanPointList->clear();
441
TPlanPointList->add( "Entry" );
442
TPlanPointList->add( "Target" );
444
m_TrackerLandmarksContainer.clear();
446
for( unsigned int i = 0; i < m_Plan->m_FiducialPoints.size(); i++ )
448
sprintf( buf, "Fiducial%i", i+1 );
449
TPlanPointList->add( buf );
450
RegistrationType::LandmarkTrackerPointType p;
451
m_TrackerLandmarksContainer.push_back(p);
454
// Setting object position according to treatment plan
455
m_EntryPoint->RequestSetTransformAndParent(
456
PointToTransform( m_Plan->m_EntryPoint ), m_WorldReference);
458
m_TargetPoint->RequestSetTransformAndParent(
459
PointToTransform( m_Plan->m_TargetPoint ), m_WorldReference);
463
TPlanPointList->value(0);
464
ChangeSelectedTPlanPoint();
467
/** -----------------------------------------------------------------
468
* Overwrite the current treatment plan to the file
471
* igstkTreatmentPlanIO
472
*---------------------------------------------------------------------
474
void NeedleBiopsy::WriteTreatmentPlan()
476
igstk::TreatmentPlanIO * writer = new igstk::TreatmentPlanIO;
477
writer->SetFileName( m_PlanFilename );
478
writer->SetTreatmentPlan( m_Plan );
479
writer->RequestWrite();
482
/** -----------------------------------------------------------------
483
* When changing the selection in the choice box, this function
484
* reslices images to the current point location, and also show the
485
* position in the annotation in blue. Whenever a point is selected
486
* in the choice box, the picking event will update this point's location
488
* NeedleBiopsy::Picking
489
*---------------------------------------------------------------------
491
void NeedleBiopsy::ChangeSelectedTPlanPoint()
493
if ( TPlanPointList->size() == 0)
499
* Check which point is selected, the first two are entry and target
502
ImageSpatialObjectType::PointType point;
503
int choice = TPlanPointList->value();
506
point = m_Plan->m_EntryPoint;
508
else if ( choice == 1 )
510
point = m_Plan->m_TargetPoint;
514
point = m_Plan->m_FiducialPoints[ choice-2];
515
m_FiducialPoint->RequestSetTransformAndParent(
516
PointToTransform(point), m_WorldReference );
519
/** Display point position as annotation */
521
sprintf( buf, "[%.2f, %.2f, %.2f]", point[0], point[1], point[2]);
522
m_Annotation->RequestSetAnnotationText(0, buf);
523
m_Annotation->RequestSetFontColor(0, 0, 0, 1.0);
524
m_Annotation->RequestSetFontSize(0, 12);
526
/** Reslice image to the selected point position */
527
if( m_ImageSpatialObject->IsInside( point ) )
529
ImageSpatialObjectType::IndexType index;
530
m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
531
igstkLogMacro( DEBUG, index <<"\n");
532
ResliceImage( index );
536
igstkLogMacro( DEBUG, "This point is not defined in the image...\n" )
541
/** -----------------------------------------------------------------
542
* Choose to connect to a tracker
543
* A tracker specific GUI is initialized, and the observer is hooked
544
* to it to catch the configuration. When the "confirm" button is
545
* pressed, an event loaded with tracker configuration will be sent out.
546
* And it will trigger the RequestInitializeTracker(), which does the
547
* actual tracker initialization
548
*---------------------------------------------------------------------
550
void NeedleBiopsy::RequestConnectToTracker()
552
RequestStopTracking();
554
switch( ConnectToTrackerBtn->value() )
558
igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
559
config.SetTrackerType( igstk::TrackerConfiguration::Polaris );
560
PolarisTrackerConfigurationGUI * gui;
561
m_TrackerConfigurationGUI = gui = new PolarisTrackerConfigurationGUI();
562
m_TrackerConfigurationGUI->SetConfiguration( config );
563
m_TrackerConfigurationGUI->RemoveAllObservers();
564
m_TrackerConfigurationGUI->AddObserver(
565
igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
566
m_TrackerConfigurationObserver);
571
igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
572
config.SetTrackerType( igstk::TrackerConfiguration::Aurora );
573
AuroraTrackerConfigurationGUI * gui;
574
m_TrackerConfigurationGUI = gui = new AuroraTrackerConfigurationGUI();
575
m_TrackerConfigurationGUI->SetConfiguration( config );
576
m_TrackerConfigurationGUI->RemoveAllObservers();
577
m_TrackerConfigurationGUI->AddObserver(
578
igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
579
m_TrackerConfigurationObserver);
584
igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
585
config.SetTrackerType( igstk::TrackerConfiguration::Micron );
586
MicronTrackerConfigurationGUI * gui;
587
m_TrackerConfigurationGUI = gui = new MicronTrackerConfigurationGUI();
588
m_TrackerConfigurationGUI->SetConfiguration( config );
589
m_TrackerConfigurationGUI->RemoveAllObservers();
590
m_TrackerConfigurationGUI->AddObserver(
591
igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
592
m_TrackerConfigurationObserver);
598
/** -----------------------------------------------------------------
599
* Call back function for ConfigurationEvent observer
600
*---------------------------------------------------------------------
602
void NeedleBiopsy::RequestInitializeTracker(const itk::EventObject & event)
604
typedef igstk::TrackerConfigurationGUIBase GUIType;
605
if ( GUIType::ConfigurationEvent().CheckEvent( &event ) )
607
GUIType::ConfigurationEvent *confEvent =
608
( GUIType::ConfigurationEvent *) & event;
610
igstk::TrackerConfiguration tc = confEvent->Get();
612
m_TrackerInitializer = new igstk::TrackerInitializer;
613
m_TrackerInitializer->SetTrackerConfiguration( & tc );
615
if ( m_TrackerInitializer->RequestInitializeTracker() )
617
igstk::Tracker::Pointer tracker = m_TrackerInitializer->GetTracker();
618
igstk::TrackerTool::Pointer tool =
619
m_TrackerInitializer->GetNonReferenceToolList()[0];
620
igstk::TrackerTool::Pointer refTool =
621
m_TrackerInitializer->GetReferenceTool();
623
/** Connect the scene graph with an identity transform first */
624
igstk::Transform transform;
625
transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
626
if ( m_TrackerInitializer->HasReferenceTool() )
628
refTool->RequestSetTransformAndParent(transform, m_WorldReference);
632
tracker->RequestSetTransformAndParent(transform, m_WorldReference);
635
/** Now who the registration window and initialize it */
636
RegistrationWindow->show();
637
FiducialNumber->clear();
638
m_TrackerLandmarksContainer.clear();
640
for ( unsigned int i=0; i<m_Plan->m_FiducialPoints.size(); i++)
642
sprintf( buf, "%d", i+1 );
643
FiducialNumber->add(buf);
644
RegistrationType::LandmarkTrackerPointType p;
645
m_TrackerLandmarksContainer.push_back(p);
649
* Set the tracker and image fiducial landmark to the first point
650
* and reslice the image to show this fiducial point
652
FiducialNumber->value(0);
653
TPlanPointList->value(2);
654
ChangeSelectedTPlanPoint();
659
/** -----------------------------------------------------------------
660
* Call this method every time we successfully connect or disconnect to
661
* a tracker. This updates the available tracker and tracker tool
662
* in the GUI list as well as internal pointer list.
663
*---------------------------------------------------------------------
665
void NeedleBiopsy::UpdateTrackerAndTrackerToolList()
667
TrackerList->clear();
668
TrackerToolList->clear();
669
m_TrackerToolList.clear();
672
for ( unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
675
sprintf(buf, "%d", i+1);
678
m_TrackerInitializerList[i]->GetTrackerTypeAsString() + "]";
679
TrackerList->add( s.c_str() );
680
std::vector< igstk::TrackerTool::Pointer > toolList =
681
m_TrackerInitializerList[i]->GetNonReferenceToolList();
682
for ( unsigned int j=0; j< toolList.size(); j++)
685
sprintf(buf,"%d", ++n);
688
m_TrackerInitializerList[i]->GetTrackerTypeAsString() + "]";
689
TrackerToolList->add( s.c_str() );
690
m_TrackerToolList.push_back( toolList[j] );
696
/** -----------------------------------------------------------------
697
* Disconnect a tracker. After disconnecting it, set the active tool
698
* to the first available tool
699
*---------------------------------------------------------------------
701
void NeedleBiopsy::RequestDisconnetTracker()
703
RequestStopTracking();
704
unsigned int n = TrackerList->value();
705
if ( n < m_TrackerInitializerList.size() )
707
m_TrackerInitializerList[n]->StopAndCloseTracker();
708
m_TrackerInitializerList.erase( m_TrackerInitializerList.begin() + n );
709
UpdateTrackerAndTrackerToolList();
710
if (m_TrackerInitializerList.size()>0)
712
TrackerList->value(0);
713
TrackerToolList->value(0);
715
ChangeActiveTrackerTool();
719
/** -----------------------------------------------------------------
720
* Hot switch the active tool, the one that drives the reslicing and
721
* needle display. The reslicing is done by using an observer listening
722
* to the TrackerToolTransformUpdateEvent, and the call back function
723
* will get the tool tip position in the image space and reslice image
724
* to that point. Refer to:
725
* NeedleBiopsy::Tracking
726
* First, we stop the tracking and disconnect the observer from other tools
727
* Second, we connect observer to the selected tool
728
* Finally, we attach spatial objects representing the needle to this tool
729
* and restart the tracking again
730
*---------------------------------------------------------------------
732
void NeedleBiopsy::ChangeActiveTrackerTool()
734
RequestStopTracking();
735
itksys::SystemTools::Delay( 500 );
737
if (m_TrackerToolList.size() != 0)
739
for (unsigned int i=0; i<m_TrackerToolList.size(); i++)
741
m_TrackerToolList[i]->RemoveAllObservers();
743
m_ActiveTool = m_TrackerToolList[ TrackerToolList->value()];
745
m_ActiveTool->AddObserver(
746
igstk::TrackerToolTransformUpdateEvent(), m_TrackerToolUpdateObserver);
748
igstk::Transform transform;
749
transform.SetToIdentity(igstk::TimeStamp::GetLongestPossibleTime());
750
m_Needle->RequestDetachFromParent();
751
m_NeedleTip->RequestDetachFromParent();
752
m_Needle->RequestSetTransformAndParent( transform, m_ActiveTool);
753
m_NeedleTip->RequestSetTransformAndParent( transform, m_ActiveTool);
755
RequestStartTracking();
758
/** -----------------------------------------------------------------
759
* Call back functions for registration window. Every time user clicks
760
* on the set fiducial point button, it will read from the recently
761
* initialized tracker's first non-reference tool. The reading will
762
* serve as a tracker landmark point for registration.
763
* This will automatic jump to the next fiducial point for user to set
764
*---------------------------------------------------------------------
766
void NeedleBiopsy::SetTrackerFiducialPoint()
768
igstk::TrackerTool::Pointer tool =
769
m_TrackerInitializer->GetNonReferenceToolList()[0];
771
typedef igstk::TransformObserver ObserverType;
772
ObserverType::Pointer transformObserver = ObserverType::New();
773
transformObserver->ObserveTransformEventsFrom( tool );
774
transformObserver->Clear();
775
tool->RequestComputeTransformTo( m_WorldReference );
776
if ( transformObserver->GotTransform() )
778
int n = FiducialNumber->value();
779
int m = FiducialNumber->size();
780
m_TrackerLandmarksContainer[n] =
781
TransformToPoint( transformObserver->GetTransform() );
782
std::cout << m_TrackerLandmarksContainer[n] <<"\n";
785
FiducialNumber->value(n+1);
786
TPlanPointList->value(n+3);
787
ChangeSelectedTPlanPoint();
792
/** -----------------------------------------------------------------
793
* Pair points 3D landmark registration
794
* Image landmarks are from treatment plan. Refer to:
797
* tracker landmarks are set in the registration window. Refer to:
798
* SetTrackerFiducialPoint
799
*---------------------------------------------------------------------
801
void NeedleBiopsy::RequestRegistration()
803
m_LandmarkRegistration->RequestResetRegistration();
804
for( unsigned int i=0; i< m_TrackerLandmarksContainer.size(); i++)
806
m_LandmarkRegistration->RequestAddImageLandmarkPoint(
807
m_Plan->m_FiducialPoints[i] );
808
m_LandmarkRegistration->RequestAddTrackerLandmarkPoint(
809
m_TrackerLandmarksContainer[i] );
812
m_LandmarkRegistration->RequestComputeTransform();
814
igstk::TransformObserver::Pointer lrtcb = igstk::TransformObserver::New();
815
lrtcb->ObserveTransformEventsFrom( m_LandmarkRegistration );
818
m_LandmarkRegistration->RequestGetTransformFromTrackerToImage();
820
if( lrtcb->GotTransform() )
822
RegistrationErrorObserver::Pointer lRmscb =
823
RegistrationErrorObserver::New();
824
m_LandmarkRegistration->AddObserver( igstk::DoubleTypeEvent(), lRmscb );
825
m_LandmarkRegistration->RequestGetRMSError();
826
if( lRmscb->GotRegistrationError() )
828
std::cout << "\nRegistration Error" <<
829
lRmscb->GetRegistrationError() << "\n";
832
igstk::Transform transform = lrtcb->GetTransform();
833
std::cout << transform << "\n";
834
if ( m_TrackerInitializer->HasReferenceTool() )
836
m_TrackerInitializer->GetReferenceTool()
837
->RequestSetTransformAndParent(transform, m_WorldReference);
841
m_TrackerInitializer->GetTracker()
842
->RequestSetTransformAndParent(transform, m_WorldReference);
846
* Only when a tracker is registered with the image, it will show up
847
* on the gui as available. Otherwise it will be disconnected
849
m_TrackerInitializerList.push_back( m_TrackerInitializer );
850
UpdateTrackerAndTrackerToolList();
851
TrackerList->value(m_TrackerInitializerList.size()-1);
852
TrackerToolList->value(m_TrackerInitializerList.size()-1);
853
ChangeActiveTrackerTool();
854
RequestStartTracking();
858
m_TrackerInitializer->StopAndCloseTracker();
863
/** -----------------------------------------------------------------
864
* Start tracking of all the connected trackers
865
*---------------------------------------------------------------------
867
void NeedleBiopsy::RequestStartTracking()
869
for (unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
871
m_TrackerInitializerList[i]->GetTracker()->RequestStartTracking();
874
TrackingBtn->label("Stop");
875
TrackingBtn->value(1);
876
ControlGroup->redraw();
879
/** -----------------------------------------------------------------
880
* Stop tracking of all the connected trackers
881
*---------------------------------------------------------------------
883
void NeedleBiopsy::RequestStopTracking()
885
for (unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
887
m_TrackerInitializerList[i]->GetTracker()->RequestStopTracking();
890
TrackingBtn->label("Tracking");
891
TrackingBtn->value(0);
892
ControlGroup->redraw();
895
/** -----------------------------------------------------------------
896
* Callback function for observer listening to the slider bar
898
*---------------------------------------------------------------------
900
void NeedleBiopsy::ResliceImage( const itk::EventObject & event )
903
if ( igstk::QuadrantViews::ReslicingEvent().CheckEvent( &event ) )
905
igstk::QuadrantViews::ReslicingEvent *resliceEvent =
906
( igstk::QuadrantViews::ReslicingEvent *) & event;
907
this->ResliceImage( resliceEvent->Get() );
912
/** -----------------------------------------------------------------
913
* Methods for reslicing images given an index number
914
*---------------------------------------------------------------------
916
void NeedleBiopsy::ResliceImage ( IndexType index )
918
m_ImageRepresentation[0]->RequestSetSliceNumber( index[2] );
919
m_ImageRepresentation[1]->RequestSetSliceNumber( index[0] );
920
m_ImageRepresentation[2]->RequestSetSliceNumber( index[1] );
922
m_ImageRepresentation[3]->RequestSetSliceNumber( index[2] );
923
m_ImageRepresentation[4]->RequestSetSliceNumber( index[0] );
924
m_ImageRepresentation[5]->RequestSetSliceNumber( index[1] );
926
ViewerGroup->m_AxialSlider->value( index[2] );
927
ViewerGroup->m_SagittalSlider->value( index[0] );
928
ViewerGroup->m_CoronalSlider->value( index[1] );
930
this->ViewerGroup->redraw();
935
/** -----------------------------------------------------------------
936
* Callback function for picking event.
937
* Upon receiving a valid picking event, this method will change the
938
* value of currently selected treatment plan point, reslice the image
939
* to that location, update the annotation with the new point position,
940
* and write the modified treatment plan to the file.
941
*---------------------------------------------------------------------
943
void NeedleBiopsy::Picking( const itk::EventObject & event)
945
if ( igstk::CoordinateSystemTransformToEvent().CheckEvent( &event ) )
947
typedef igstk::CoordinateSystemTransformToEvent TransformEventType;
948
const TransformEventType * tmevent =
949
dynamic_cast< const TransformEventType *>( & event );
951
igstk::CoordinateSystemTransformToResult transformCarrier = tmevent->Get();
952
igstk::Transform transform = transformCarrier.GetTransform();
953
ImageSpatialObjectType::PointType point = TransformToPoint( transform );
955
if( m_ImageSpatialObject->IsInside( point ) )
957
int choice = TPlanPointList->value();
961
m_EntryPoint->RequestSetTransformAndParent(
962
transform , m_WorldReference );
963
m_Plan->m_EntryPoint = point;
966
else if ( choice == 1 )
968
m_TargetPoint->RequestSetTransformAndParent(
969
transform, m_WorldReference );
970
m_Plan->m_TargetPoint = point;
975
m_FiducialPoint->RequestSetTransformAndParent(
976
transform, m_WorldReference );
977
m_Plan->m_FiducialPoints[ choice-2] = point;
980
/** Update annotation */
982
sprintf( buf, "[%.2f, %.2f, %.2f]", point[0], point[1], point[2]);
983
m_Annotation->RequestSetAnnotationText(0, buf);
984
m_Annotation->RequestSetFontColor(0, 1.0, 0, 0);
985
m_Annotation->RequestSetFontSize(0, 12);
987
/** Wirte the updated plan to file */
988
this->WriteTreatmentPlan();
991
ImageSpatialObjectType::IndexType index;
992
m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
993
igstkLogMacro( DEBUG, index <<"\n")
994
ResliceImage( index );
998
igstkLogMacro( DEBUG, "Picked point outside image...\n" )
1003
/** -----------------------------------------------------------------
1004
* Every time we modify the entry point or target point, we need to
1005
* rebuild the geometry of the path, and add them to the View again
1006
*---------------------------------------------------------------------
1008
void NeedleBiopsy::UpdatePath()
1012
TubePointType point;
1013
igstk::Transform::VectorType v;
1015
v = ( PointToTransform( m_Plan->m_EntryPoint) ).GetTranslation();
1016
point.SetPosition( v[0], v[1], v[2]);
1017
point.SetRadius( 2 );
1018
m_Path->AddPoint( point );
1020
v = ( PointToTransform( m_Plan->m_TargetPoint) ).GetTranslation();
1021
point.SetPosition( v[0], v[1], v[2]);
1022
point.SetRadius( 2.1 );
1023
m_Path->AddPoint( point );
1026
for (int i=0; i<4; i++)
1028
ViewerGroup->m_Views[i]->RequestRemoveObject( m_PathRepresentation[i] );
1029
m_PathRepresentation[i]->RequestSetTubeObject( NULL );
1030
m_PathRepresentation[i]->RequestSetTubeObject( m_Path );
1031
m_PathRepresentation[i]->SetColor( 0.0, 1.0, 0.0 );
1032
m_PathRepresentation[i]->SetOpacity( 0.5 );
1033
ViewerGroup->m_Views[i]->RequestAddObject( m_PathRepresentation[i] );
1038
/** -----------------------------------------------------------------
1039
* Callback function for TrackerToolTransformUpdateEvent
1040
* This function computes the transform of the tooltip location in
1041
* the image space (WorldReference is essential image coordinate system
1042
* since image is attached to WorldReference using an identity transform),
1043
* and reslice image to that tip location
1044
*---------------------------------------------------------------------
1047
void NeedleBiopsy::Tracking(const itk::EventObject & event )
1049
if ( igstk::TrackerToolTransformUpdateEvent().CheckEvent( &event ) )
1051
typedef igstk::TransformObserver ObserverType;
1052
ObserverType::Pointer transformObserver = ObserverType::New();
1053
transformObserver->ObserveTransformEventsFrom( m_ActiveTool );
1054
transformObserver->Clear();
1055
m_ActiveTool->RequestComputeTransformTo( m_WorldReference );
1056
if ( transformObserver->GotTransform() )
1058
ImageSpatialObjectType::PointType point =
1059
TransformToPoint( transformObserver->GetTransform() );
1061
if( m_ImageSpatialObject->IsInside( point ) )
1063
ImageSpatialObjectType::IndexType index;
1064
m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
1065
ResliceImage( index );