freAccuracySOMetricThread.txx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   F.R.E.E. - flexible registration evaluation engine
00004   Version:   v.1.0.0
00005   Date:      $Date: 2006/09/01 12:00:00 $
00006   Module:    $RCSfile: freAccuracySOMetricThread.txx,v $
00007   Language:  C++
00008 
00009 
00010 
00011   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00012   Institute for Medical Biometry and Informatics, University of Heidelberg,
00013   Germany). All rights reserved.
00014   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00015   for details.
00016 
00017      This software is distributed WITHOUT ANY WARRANTY; without even 
00018      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00019      PURPOSE.  See the above copyright notices for more information.
00020 
00021 =========================================================================*/
00022 #ifndef __freAccuracySOMetricThread_txx
00023 #define __freAccuracySOMetricThread_txx
00024 
00025 #include "freAccuracySOMetricThread.h"
00026 
00027 #include "freVectorToNormImageFilter.h"
00028 #include "freImageSampleCharacteristicsCalculator.h"
00029 #include "freSessionProcessor.h"
00030 
00031 #include "itkNumericTraits.h"
00032 #include "itkSubtractImageFilter.h"
00033 #include "itkImageAdaptor.h"
00034 #include "itkPointSet.h"
00035 #include "itkListSample.h"
00036 
00037 namespace FREE
00038 {
00039 
00040 template <unsigned int VImageDimension>
00041 void
00042 AccuracySOMetricThread<VImageDimension>:: 
00043 SetResultFieldPath(const IDPath& path)
00044 {
00045   this->LockExecutionMutex();
00046     this->m_ResultFieldPath = path;
00047   this->UnlockExecutionMutex();
00048 };
00049 
00050 template <unsigned int VImageDimension>
00051 const IDPath&
00052 AccuracySOMetricThread<VImageDimension>:: 
00053 GetResultFieldPath() const {return m_ResultFieldPath;};
00054 
00055 template <unsigned int VImageDimension>
00056 void
00057 AccuracySOMetricThread<VImageDimension>:: 
00058 SetReferenceFieldPath(const IDPath& path)
00059 {
00060   this->LockExecutionMutex();
00061     this->m_ReferenceFieldPath = path;
00062   this->UnlockExecutionMutex();
00063 };
00064 
00065 template <unsigned int VImageDimension>
00066 const IDPath&
00067 AccuracySOMetricThread<VImageDimension>:: 
00068 GetReferenceFieldPath() const {return m_ReferenceFieldPath;};
00069 
00070 template <unsigned int VImageDimension>
00071 void
00072 AccuracySOMetricThread<VImageDimension>:: 
00073 SetReferencePointsPath(const IDPath& path)
00074 {
00075   this->LockExecutionMutex();
00076     this->m_ReferencePointsPath = path;
00077   this->UnlockExecutionMutex();
00078 };
00079 
00080 template <unsigned int VImageDimension>
00081 const IDPath&
00082 AccuracySOMetricThread<VImageDimension>:: 
00083 GetReferencePointsPath() const {return m_ReferencePointsPath;};
00084 
00085 template <unsigned int VImageDimension>
00086 void
00087 AccuracySOMetricThread<VImageDimension>:: 
00088 SetMovingPointsPath(const IDPath& path)
00089 {
00090   this->LockExecutionMutex();
00091     this->m_MovingPointsPath = path;
00092   this->UnlockExecutionMutex();
00093 };
00094 
00095 template <unsigned int VImageDimension>
00096 const IDPath&
00097 AccuracySOMetricThread<VImageDimension>:: 
00098 GetMovingPointsPath() const {return m_MovingPointsPath;};
00099 
00100 template <unsigned int VImageDimension>
00101 void
00102 AccuracySOMetricThread<VImageDimension>:: 
00103 SetUseField(const bool& bUseField)
00104 {
00105   this->LockExecutionMutex();
00106     this->m_UseField = bUseField;
00107   this->UnlockExecutionMutex();
00108 };
00109 
00110 template <unsigned int VImageDimension>
00111 bool
00112 AccuracySOMetricThread<VImageDimension>:: 
00113 GetUseField() const {return m_UseField;};
00114 
00115 template <unsigned int VImageDimension>
00116 AccuracySOMetricThread<VImageDimension>:: 
00117 AccuracySOMetricThread()
00118 {
00119   m_UseField = true;
00120   m_ReferenceFieldPath.Reset();
00121   m_ReferencePointsPath.Reset();
00122   m_MovingPointsPath.Reset();
00123   m_ResultFieldPath.Reset();
00124 };
00125 
00126 template <unsigned int VImageDimension>
00127 AccuracySOMetricThread<VImageDimension>:: 
00128 ~AccuracySOMetricThread() {};
00129 
00130 template <unsigned int VImageDimension>
00131 bool
00132 AccuracySOMetricThread<VImageDimension>:: 
00133 ProcessSetup(Setup* pAdaptationSetup) throw()
00134 {
00135   bool result = false;
00136 
00137   ControllerCentral::AddOnProgressEvent(this->m_EvaluatedSessionProgressEvent);
00138 
00139   try
00140         {
00141     SessionProcessor processor;
00142 
00143     processor.SetSetup(pAdaptationSetup);
00144     processor.DefineOutput("resultField", this->m_ResultFieldPath);
00145 
00146     processor.InitializeSession();
00147         
00148     this->m_EvaluatedSessionProgressEvent->SetACR(processor.GetSessionInfo()->GetSessionCache());
00149 
00150     clock_t start = clock();
00151 
00152     typename TransformationFieldType::Pointer smpResult = processor.GetCastedOutput<TransformationFieldType>("resultField");
00153                 
00154     clock_t stop = clock();
00155     double dDuration = (stop-start) / (CLOCKS_PER_SEC/10); //convert clocks to thenth second
00156 
00157     //evaluating registration result
00158                 if (m_UseField)
00159                 {
00160       EvaluateField(smpResult, processor.GetSessionInfo());
00161                 }
00162                 else
00163                 {
00164                         EvaluatePoints(smpResult, processor.GetSessionInfo());
00165                 }
00166 
00167                 m_Results.SetDuration((unsigned long)dDuration);
00168 
00169     result = true;
00170         }
00171         catch( FREE::ExceptionBase & err ) 
00172         { 
00173                 this->m_FailureComment = std::string(err.what());
00174         } 
00175         catch(...)
00176         {
00177                 this->m_FailureComment = "unkown error";
00178         }
00179 
00180   ControllerCentral::RemoveOnProgressEvent(m_EvaluatedSessionProgressEvent);
00181 
00182   return result;
00183 };
00184 
00185 template <unsigned int VImageDimension>
00186 void
00187 AccuracySOMetricThread<VImageDimension>:: 
00188 EvaluateField(TransformationFieldType* pResultField, SessionInfo* pSessionInfo)
00189 {
00190   typename TransformationFieldType::Pointer smpRefField = NULL;
00191 
00192   if (m_ReferenceFieldPath.IsEmpty()) throwExceptionMacro("Error: Reference field path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00193 
00194   try
00195   {
00196     SessionAccessor::GenericMediaPointer smpFieldReference = SessionAccessor::GetMedia(m_ReferenceFieldPath,pSessionInfo);
00197     smpRefField = dynamic_cast<TransformationFieldType*>(smpFieldReference.GetPointer());
00198   }
00199   catchAllNPassMacro("Error: cannot retrieve reference field. Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00200   if (smpRefField.IsNull()) throwExceptionMacro("Error: Reference field is of wrong type. Ensure correct initialisation of the metric. Field class name: "<<smpRefField->GetNameOfClass());
00201 
00202   //calculating difference between reference field and final field
00203         typedef itk::SubtractImageFilter< TransformationFieldType, TransformationFieldType, TransformationFieldType > SubtractFilterType;
00204         typename SubtractFilterType::Pointer smpSubFilter = SubtractFilterType::New();
00205                 
00206         //computing mean and variance of the field difference
00207         typedef itk::Image<double,VImageDimension> NormImageType;
00208         typedef VectorToNormImageFilter<TransformationFieldType, NormImageType > NormImageFilterType;
00209         typedef ImageSampleCharacteristicsCalculator<NormImageType> CharCalculator;
00210         typename NormImageFilterType::Pointer smpNormFilter = NormImageFilterType::New();
00211 
00212   smpSubFilter->SetInput1(pResultField);
00213         smpSubFilter->SetInput2(smpRefField);
00214         smpNormFilter->SetInput(smpSubFilter->GetOutput());
00215         smpNormFilter->Update();
00216         typename NormImageType::Pointer smpNormImage = smpNormFilter->GetOutput();
00217 
00218         CharCalculator calculator;
00219         calculator.SetImage(smpNormImage);
00220         calculator.Compute();
00221 
00222         this->m_Results.SetError(calculator.GetMean());
00223         this->m_Results.SetVariance(calculator.GetVariance());
00224         this->m_Results.SetSamplesize(pResultField->GetLargestPossibleRegion().GetNumberOfPixels());
00225 
00226         //checking for minimum or maximum
00227         typedef itk::ImageRegionConstIterator<NormImageType> NormIterator;
00228 
00229   double dMin = itk::NumericTraits< double >::max();
00230   double dMax = 0.0;
00231 
00232         NormIterator it(smpNormImage,pResultField->GetBufferedRegion());
00233         for ( it.GoToBegin(); !it.IsAtEnd(); ++it )
00234         {
00235                 if (it.Get()<dMin) dMin = it.Get();
00236                 if (it.Get()>dMax) dMax = it.Get();
00237         }
00238 
00239   this->m_Results.SetMinError(dMin);
00240   this->m_Results.SetMaxError(dMax);
00241 };
00242 
00243 template <unsigned int VImageDimension>
00244 void
00245 AccuracySOMetricThread<VImageDimension>:: 
00246 EvaluatePoints(TransformationFieldType* pResultField, SessionInfo* pSessionInfo)
00247 {
00248   typedef TransformationFieldType FieldType;
00249   typedef typename TransformationFieldType::Pointer FieldPointer;
00250 
00251         typedef typename ImageTypes<VImageDimension>::PointSetType PointSetType;
00252         typedef typename PointSetType::Pointer PointSetPointer;
00253 
00254   PointSetPointer smpRefPoints = 0;
00255   PointSetPointer smpMovingPoints = 0;
00256 
00257   if (m_ReferencePointsPath.IsEmpty()) throwExceptionMacro("Error: Reference points path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00258   try
00259   {
00260     typename SessionAccessor::GenericMediaPointer genPoints = SessionAccessor::GetMedia(m_ReferencePointsPath,pSessionInfo);
00261     smpRefPoints = dynamic_cast<PointSetType*>(genPoints.GetPointer());
00262   }
00263   catchAllNPassMacro("Error: cannot retrieve reference point set Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00264 
00265   if (m_MovingPointsPath.IsEmpty()) throwExceptionMacro("Error: Reference points path is null, but should be used to measure registration. Ensure correct initialisation of the metric.");
00266   try
00267   {
00268     SessionAccessor::GenericMediaPointer genPoints = SessionAccessor::GetMedia(m_MovingPointsPath,pSessionInfo);
00269     smpMovingPoints = dynamic_cast<PointSetType*>(genPoints.GetPointer());
00270   }
00271   catchAllNPassMacro("Error: cannot retrieve reference point set Ensure correct IDPath. Used path: "<<m_ReferenceFieldPath.ToStr());
00272 
00273   if (smpRefPoints->GetNumberOfPoints() != smpMovingPoints->GetNumberOfPoints()) throwExceptionMacro("Error: reference point set and moving point set must have same number of points. Reference count: " << smpRefPoints->GetNumberOfPoints() << "; moving count: " << smpMovingPoints->GetNumberOfPoints());
00274   
00275   //map each reference point into the moving domaime and calculate difference
00276 
00277         typename PointSetType::PointsContainer::Iterator refIter = smpRefPoints->GetPoints()->Begin();
00278   typename PointSetType::PointsContainer::Iterator movingIter = smpMovingPoints->GetPoints()->Begin();
00279 
00280   typename PointSetType::PointsContainer::Iterator endOfPoints = smpRefPoints->GetPoints()->End();
00281 
00282         const unsigned int iMeasurementVectorSize = 1;
00283   typedef itk::Vector<double,iMeasurementVectorSize> MeasurementVectorType;
00284   typedef itk::Statistics::ListSample< MeasurementVectorType > SampleType;
00285 
00286         typename SampleType::Pointer smpSample = SampleType::New();
00287         smpSample->SetMeasurementVectorSize(iMeasurementVectorSize);
00288 
00289   double dMin = itk::NumericTraits< double >::max();
00290   double dMax = 0.0;
00291 
00292   while (refIter != endOfPoints)
00293   {
00294     typename PointSetType::PointType refPoint = refIter.Value();
00295     typename PointSetType::PointType movingPoint = movingIter.Value();
00296 
00297     typename FieldType::PixelType translation;
00298     translation.Fill(0.0);
00299 
00300     typename FieldType::IndexType index;
00301                 bool bInField =  pResultField->TransformPhysicalPointToIndex(refPoint, index);
00302 
00303                 if (bInField)
00304     { //referencepoint is within the transformation field
00305       translation = pResultField->GetPixel(index);
00306             refPoint += translation;
00307 
00308       MeasurementVectorType mv;
00309 
00310                   typename PointSetType::PointType::VectorType difVector = movingPoint - refPoint;
00311       mv[0] = difVector.GetNorm();
00312 
00313                         this->m_Results.GetPointErrors().push_back(mv[0]);
00314       smpSample->PushBack(mv);
00315 
00316                   if (mv[0]<dMin) dMin = mv[0];
00317                   if (mv[0]>dMax) dMax = mv[0];
00318                 }
00319                 else
00320                 {
00321                         this->m_Results.GetUnevaluatedPoints()++;
00322                 }
00323                 ++refIter;
00324                 ++movingIter;
00325   }
00326 
00327         // Calculate mean and variance
00328         typedef itk::Statistics::CovarianceCalculator< SampleType > CovarianceAlgorithmType;
00329 
00330         typename CovarianceAlgorithmType::Pointer covarianceAlgorithm = CovarianceAlgorithmType::New();
00331         covarianceAlgorithm->SetInputSample( smpSample );
00332         covarianceAlgorithm->SetMean( 0 );
00333         covarianceAlgorithm->Update();
00334 
00335         double mean = covarianceAlgorithm->GetMean()->GetElement(0);
00336         double var = (*(covarianceAlgorithm->GetOutput()))(0,0);
00337 
00338         this->m_Results.SetError(mean);
00339         this->m_Results.SetVariance(var);
00340   this->m_Results.SetMinError(dMin);
00341   this->m_Results.SetMaxError(dMax);
00342 };
00343 
00344 
00345 
00346 } // end namespace FREE
00347 
00348 #endif

Generated at Sat Oct 13 15:18:04 2007 for f.r.e.e. - Flexible Registration and Evaluation Engine by doxygen 1.5.3 written by Dimitri van Heesch, © 1997-2000