cmtkImagePairAffineRegistrationFunctionalTemplate.txx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2578 $
00026 //
00027 //  $LastChangedDate: 2010-12-01 14:27:46 -0800 (Wed, 01 Dec 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <Base/cmtkTransformedVolumeAxes.h>
00034 
00035 namespace
00036 cmtk
00037 {
00038 
00039 template<class VM>
00040 typename ImagePairAffineRegistrationFunctionalTemplate<VM>::ReturnType 
00041 ImagePairAffineRegistrationFunctionalTemplate<VM>
00042 ::Evaluate() 
00043 {
00044   const TransformedVolumeAxes axesHash( *this->m_ReferenceGrid, this->m_AffineXform, this->m_FloatingGrid->Deltas().begin(), this->m_FloatingGrid->m_Offset.begin() );
00045   const Vector3D *axesHashX = axesHash[0], *axesHashY = axesHash[1], *axesHashZ = axesHash[2];
00046   
00047   this->m_Metric->Reset();
00048   
00049   const DataGrid::IndexType& Dims = this->m_ReferenceGrid->GetDims();
00050   const int DimsX = Dims[0], DimsY = Dims[1], DimsZ = Dims[2];
00051   
00052   this->Clipper.SetDeltaX( axesHashX[DimsX-1] - axesHashX[0] );
00053   this->Clipper.SetDeltaY( axesHashY[DimsY-1] - axesHashY[0] );
00054   this->Clipper.SetDeltaZ( axesHashZ[DimsZ-1] - axesHashZ[0] );
00055   this->Clipper.SetClippingBoundaries( this->m_FloatingCropRegionFractIndex );
00056   
00057   DataGrid::IndexType::ValueType startZ, endZ;
00058   if ( this->ClipZ( this->Clipper, axesHashZ[0], startZ, endZ ) ) 
00059     {
00060     startZ = std::max<DataGrid::IndexType::ValueType>( startZ, this->m_ReferenceCropRegion.From()[2] );
00061     endZ = std::min<DataGrid::IndexType::ValueType>( endZ, this->m_ReferenceCropRegion.To()[2] + 1 );
00062     
00063     const int numberOfTasks = std::min<size_t>( 4 * this->m_NumberOfThreads - 3, endZ - startZ + 1 );
00064     this->m_EvaluateTaskInfo.resize( numberOfTasks );
00065     
00066     for ( int taskIdx = 0; taskIdx < numberOfTasks; ++taskIdx ) 
00067       {
00068       this->m_EvaluateTaskInfo[taskIdx].thisObject = this;
00069       this->m_EvaluateTaskInfo[taskIdx].AxesHash = &axesHash;
00070       this->m_EvaluateTaskInfo[taskIdx].StartZ = startZ;
00071       this->m_EvaluateTaskInfo[taskIdx].EndZ = endZ;
00072       }
00073     
00074     ThreadPool::GetGlobalThreadPool().Run( EvaluateThread, this->m_EvaluateTaskInfo );
00075     }
00076   return this->m_Metric->Get();
00077 }
00078 
00079 template<class VM>
00080 void 
00081 ImagePairAffineRegistrationFunctionalTemplate<VM>
00082 ::EvaluateThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t ) 
00083 {
00084   typename Self::EvaluateTaskInfo *info = static_cast<typename Self::EvaluateTaskInfo*>( args );
00085   
00086   Self *me = info->thisObject;
00087   VM& metric = dynamic_cast<VM&>( *(me->m_Metric) );
00088   
00089   VM& threadMetric = me->m_ThreadMetric[threadIdx];
00090   threadMetric.Reset();
00091   
00092   const Vector3D *hashX = (*info->AxesHash)[0], *hashY = (*info->AxesHash)[1], *hashZ = (*info->AxesHash)[2];
00093   Vector3D pFloating;
00094   
00095   const DataGrid::IndexType& Dims = me->m_ReferenceGrid->GetDims();
00096   const int DimsX = Dims[0], DimsY = Dims[1];
00097   
00098   int fltIdx[3];
00099   Types::Coordinate fltFrac[3];
00100   
00101   Vector3D rowStart;
00102   Vector3D planeStart;
00103   
00104   DataGrid::IndexType::ValueType pX, pY, pZ;
00105   // Loop over all remaining planes
00106   for ( pZ = info->StartZ + taskIdx; pZ < info->EndZ; pZ += taskCnt ) 
00107     {
00108     // Offset of current reference voxel
00109     int r = pZ * DimsX * DimsY;
00110     
00111     planeStart = hashZ[pZ];
00112     
00113     DataGrid::IndexType::ValueType startY, endY;
00114     if ( me->ClipY( me->Clipper, planeStart, startY, endY ) ) 
00115       { 
00116       startY = std::max<DataGrid::IndexType::ValueType>( startY, me->m_ReferenceCropRegion.From()[1] );
00117       endY = std::min<DataGrid::IndexType::ValueType>( endY, me->m_ReferenceCropRegion.To()[1] + 1 );
00118       r += startY * DimsX;
00119       
00120       // Loop over all remaining rows
00121       for ( pY = startY; pY<endY; ++pY ) 
00122         {
00123         (rowStart = planeStart) += hashY[pY];
00124         
00125         DataGrid::IndexType::ValueType startX, endX;
00126         if ( me->ClipX( me->Clipper, rowStart, startX, endX ) ) 
00127           {         
00128           startX = std::max<DataGrid::IndexType::ValueType>( startX, me->m_ReferenceCropRegion.From()[0] );
00129           endX = std::min<DataGrid::IndexType::ValueType>( endX, me->m_ReferenceCropRegion.To()[0] + 1 );
00130           
00131           r += startX;
00132           // Loop over all remaining voxels in current row
00133           for ( pX = startX; pX<endX; ++pX, ++r ) 
00134             {
00135             // Continue metric computation.
00136             Types::DataItem sampleX;
00137             if ( metric.GetSampleX( sampleX, r ) )
00138               {
00139               (pFloating = rowStart) += hashX[pX];
00140               
00141               // probe volume and get the respective voxel
00142               if ( me->m_FloatingGrid->FindVoxelByIndex( pFloating, fltIdx, fltFrac ) )
00143                 {
00144                 threadMetric.Increment( sampleX, metric.GetSampleY( fltIdx, fltFrac ) );
00145                 }
00146               else
00147                 { 
00148                 if ( me->m_ForceOutsideFlag ) 
00149                   {
00150                   threadMetric.Increment( sampleX, me->m_ForceOutsideValueRescaled );           
00151                   }
00152                 }
00153               }
00154             }
00155           r += (DimsX-endX);
00156           } 
00157         else
00158           {
00159           r += DimsX;
00160           }
00161         }
00162       
00163       r += (DimsY-endY) * DimsX;
00164       } 
00165     else
00166       {
00167       r += DimsY * DimsX;
00168       }
00169     }
00170   
00171   me->m_MetricMutex.Lock();
00172   metric.Add( threadMetric );
00173   me->m_MetricMutex.Unlock();
00174 }
00175 
00176 } // namnespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines