cmtkVoxelMatchingAffineFunctionalTemplate.h

Go to the documentation of this file.
00001 /*
00002 //  Copyright 1997-2009 Torsten Rohlfing
00003 //
00004 //  Copyright 2004-2010 SRI International
00005 //
00006 //  This file is part of the Computational Morphometry Toolkit.
00007 //
00008 //  http://www.nitrc.org/projects/cmtk/
00009 //
00010 //  The Computational Morphometry Toolkit is free software: you can
00011 //  redistribute it and/or modify it under the terms of the GNU General Public
00012 //  License as published by the Free Software Foundation, either version 3 of
00013 //  the License, or (at your option) any later version.
00014 //
00015 //  The Computational Morphometry Toolkit is distributed in the hope that it
00016 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00017 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 //  GNU General Public License for more details.
00019 //
00020 //  You should have received a copy of the GNU General Public License along
00021 //  with the Computational Morphometry Toolkit.  If not, see
00022 //  <http://www.gnu.org/licenses/>.
00023 //
00024 //  $Revision: 2752 $
00025 //
00026 //  $LastChangedDate: 2011-01-17 11:33:31 -0800 (Mon, 17 Jan 2011) $
00027 //
00028 //  $LastChangedBy: torstenrohlfing $
00029 //
00030 */
00031 
00032 #ifndef __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_
00033 #define __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_
00034 
00035 #include <cmtkconfig.h>
00036 
00037 #include <Registration/cmtkVoxelMatchingAffineFunctional.h>
00038 #include <Registration/cmtkVoxelMatchingFunctional.h>
00039 
00040 #include <Base/cmtkTransformedVolumeAxes.h>
00041 
00042 namespace
00043 cmtk
00044 {
00045 
00048 
00058 template<class VM>
00059 class VoxelMatchingAffineFunctionalTemplate :
00061   public VoxelMatchingAffineFunctional, 
00063   public VoxelMatchingFunctional_Template<VM> 
00064 {
00065 public:
00067   typedef VoxelMatchingAffineFunctionalTemplate<VM> Self;
00068 
00070   typedef SmartPointer<Self> SmartPtr;
00071 
00073   typedef VoxelMatchingAffineFunctional Superclass;
00074 
00076   typedef Functional::ReturnType ReturnType;
00077 
00085   VoxelMatchingAffineFunctionalTemplate( UniformVolume::SmartPtr& reference, UniformVolume::SmartPtr& floating, AffineXform::SmartPtr& affineXform )
00086     : VoxelMatchingAffineFunctional( reference, floating, affineXform ),
00087       VoxelMatchingFunctional_Template<VM>( reference, floating ),
00088       m_NumberOfThreads( ThreadPool::GetGlobalThreadPool().GetNumberOfThreads() )    
00089   {
00090     this->m_ThreadMetric.resize( m_NumberOfThreads, dynamic_cast<const VM&>( *(this->Metric) ) );
00091   }
00092 
00094   virtual ~VoxelMatchingAffineFunctionalTemplate() {}
00095 
00097   virtual typename Self::ReturnType EvaluateAt ( CoordinateVector& v ) 
00098   {
00099     this->m_AffineXform->SetParamVector( v );
00100     return this->Evaluate();
00101   }
00102 
00115   virtual typename Self::ReturnType Evaluate() 
00116   {
00117     const TransformedVolumeAxes axesHash( *this->ReferenceGrid, this->m_AffineXform, this->FloatingGrid->Deltas().begin(), this->FloatingGrid->m_Offset.begin() );
00118     const Vector3D *axesHashX = axesHash[0], *axesHashY = axesHash[1], *axesHashZ = axesHash[2];
00119     
00120     this->Metric->Reset();
00121 
00122     const DataGrid::IndexType& Dims = this->ReferenceGrid->GetDims();
00123     const int DimsX = Dims[0], DimsY = Dims[1], DimsZ = Dims[2];
00124 
00125     this->Clipper.SetDeltaX( axesHashX[DimsX-1] - axesHashX[0] );
00126     this->Clipper.SetDeltaY( axesHashY[DimsY-1] - axesHashY[0] );
00127     this->Clipper.SetDeltaZ( axesHashZ[DimsZ-1] - axesHashZ[0] );
00128     this->Clipper.SetClippingBoundaries( this->m_FloatingCropRegionFractional );
00129     
00130     DataGrid::IndexType::ValueType startZ, endZ;
00131     if ( this->ClipZ( this->Clipper, axesHashZ[0], startZ, endZ ) ) 
00132       {
00133       startZ = std::max<DataGrid::IndexType::ValueType>( startZ, this->m_ReferenceCropRegion.From()[2] );
00134       endZ = std::min<DataGrid::IndexType::ValueType>( endZ, this->m_ReferenceCropRegion.To()[2] + 1 );
00135       
00136       const int numberOfTasks = std::min<size_t>( 4 * this->m_NumberOfThreads - 3, endZ - startZ + 1 );
00137       this->m_EvaluateTaskInfo.resize( numberOfTasks );
00138       
00139       for ( int taskIdx = 0; taskIdx < numberOfTasks; ++taskIdx ) 
00140         {
00141         this->m_EvaluateTaskInfo[taskIdx].thisObject = this;
00142         this->m_EvaluateTaskInfo[taskIdx].AxesHash = &axesHash;
00143         this->m_EvaluateTaskInfo[taskIdx].StartZ = startZ;
00144         this->m_EvaluateTaskInfo[taskIdx].EndZ = endZ;
00145         }
00146 
00147       ThreadPool::GetGlobalThreadPool().Run( EvaluateThread, this->m_EvaluateTaskInfo );
00148       }
00149     return this->Metric->Get();
00150   }
00151   
00159   size_t m_NumberOfThreads;
00160 
00162   std::vector<VM> m_ThreadMetric;
00163 
00165   MutexLock m_MetricMutex;
00166 
00172   typedef struct 
00173   {
00175     Self *thisObject;
00177     const TransformedVolumeAxes* AxesHash;
00179     DataGrid::IndexType::ValueType StartZ;
00181     DataGrid::IndexType::ValueType EndZ;
00182   } EvaluateTaskInfo;
00183  
00185   std::vector<typename Self::EvaluateTaskInfo> m_EvaluateTaskInfo;
00186 
00195   static void EvaluateThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t ) 
00196   {
00197   typename Self::EvaluateTaskInfo *info = static_cast<typename Self::EvaluateTaskInfo*>( args );
00198 
00199     Self *me = info->thisObject;
00200     const VM* Metric = me->Metric;
00201 
00202     VM& threadMetric = me->m_ThreadMetric[threadIdx];
00203     threadMetric.Reset();
00204 
00205     const Vector3D *hashX = (*info->AxesHash)[0], *hashY = (*info->AxesHash)[1], *hashZ = (*info->AxesHash)[2];
00206     Vector3D pFloating;
00207 
00208     const DataGrid::IndexType& Dims = me->ReferenceGrid->GetDims();
00209     const int DimsX = Dims[0], DimsY = Dims[1];
00210 
00211     int fltIdx[3];
00212     Types::Coordinate fltFrac[3];
00213 
00214     const int FltDimsX = me->FloatingDims[0], FltDimsY = me->FloatingDims[1];
00215 
00216     Vector3D rowStart;
00217     Vector3D planeStart;
00218 
00219     int offset;
00220     DataGrid::IndexType::ValueType pX, pY, pZ;
00221     // Loop over all remaining planes
00222     for ( pZ = info->StartZ + taskIdx; pZ < info->EndZ; pZ += taskCnt ) 
00223       {
00224       // Offset of current reference voxel
00225       int r = pZ * DimsX * DimsY;
00226       
00227       planeStart = hashZ[pZ];
00228       
00229       DataGrid::IndexType::ValueType startY, endY;
00230       if ( me->ClipY( me->Clipper, planeStart, startY, endY ) ) 
00231         {       
00232         startY = std::max<DataGrid::IndexType::ValueType>( startY, me->m_ReferenceCropRegion.From()[1] );
00233         endY = std::min<DataGrid::IndexType::ValueType>( endY, me->m_ReferenceCropRegion.To()[1] + 1 );
00234         r += startY * DimsX;
00235         
00236         // Loop over all remaining rows
00237         for ( pY = startY; pY<endY; ++pY ) 
00238           {
00239           (rowStart = planeStart) += hashY[pY];
00240           
00241           DataGrid::IndexType::ValueType startX, endX;
00242           if ( me->ClipX( me->Clipper, rowStart, startX, endX ) ) 
00243             {       
00244             startX = std::max<DataGrid::IndexType::ValueType>( startX, me->m_ReferenceCropRegion.From()[0] );
00245             endX = std::min<DataGrid::IndexType::ValueType>( endX, me->m_ReferenceCropRegion.To()[0] + 1 );
00246             
00247             r += startX;
00248             // Loop over all remaining voxels in current row
00249             for ( pX = startX; pX<endX; ++pX, ++r ) 
00250               {
00251               (pFloating = rowStart) += hashX[pX];
00252               
00253               // probe volume and get the respective voxel
00254               if ( me->FloatingGrid->FindVoxelByIndex( pFloating, fltIdx, fltFrac ) )
00255                 {
00256                 // Compute data index of the floating voxel in the floating 
00257                 // volume.
00258                 offset = fltIdx[0]+FltDimsX*(fltIdx[1]+FltDimsY*fltIdx[2]);
00259                 
00260                 // Continue metric computation.
00261                 threadMetric.Increment( Metric->GetSampleX( r ), Metric->GetSampleY( offset, fltFrac ) );
00262                 }
00263               }
00264             r += (DimsX-endX);
00265             } 
00266           else
00267             {
00268             r += DimsX;
00269             }
00270           }
00271         
00272         r += (DimsY-endY) * DimsX;
00273         } 
00274       else
00275         {
00276         r += DimsY * DimsX;
00277         }
00278       }
00279 
00280     me->m_MetricMutex.Lock();
00281     me->Metric->AddMetric( threadMetric );
00282     me->m_MetricMutex.Unlock();
00283   }
00284 };
00285 
00287 
00288 } // namespace cmtk
00289 
00290 #endif // #ifndef __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines