cmtkReformatVolumeMPI.txx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 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: 1858 $
00026 //
00027 //  $LastChangedDate: 2010-06-18 15:50:56 -0700 (Fri, 18 Jun 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <mpi.h>
00034 
00035 #include <algorithm>
00036 
00037 namespace
00038 cmtk
00039 {
00040 
00043 
00044 UniformVolume* 
00045 ReformatVolume::GetTransformedReference
00046 ( const std::vector<SplineWarpXform::SmartPtr>* xformList,
00047   std::vector<UniformVolume::SmartPtr>* volumeList,
00048   Types::Coordinate *const volumeOffset,
00049   const bool includeReferenceData )
00050 {
00051   const int mpiRank = MPI::COMM_WORLD.Get_rank();
00052   const int mpiSize = MPI::COMM_WORLD.Get_size();
00053 
00054   UniformVolume* result = NULL;
00055   unsigned int numberOfImages = 0;
00056   std::vector<UniformVolumeInterpolatorBase::SmartConstPtr> interpolatorList;
00057   interpolatorList.push_back( this->CreateInterpolator( this->ReferenceVolume ) );
00058   if ( volumeList )
00059     {
00060     numberOfImages = 1 + volumeList->size();
00061     for ( unsigned int img = 0; img < numberOfImages-1; ++img ) 
00062       {
00063       interpolatorList.push_back( this->CreateInterpolator( (*volumeList)[img] ) );
00064       }
00065     }
00066   
00067   const SplineWarpXform* splineXform = dynamic_cast<const SplineWarpXform*>( this->m_WarpXform.GetConstPtr() );
00068   if ( ! splineXform ) 
00069     {
00070     StdErr << "ERROR: ReformatVolume::GetTransformedReference supports spline warp only.\n";
00071     return NULL;
00072     }
00073   
00074   DataClass dataClass = ReferenceVolume->GetData()->GetDataClass();
00075   int maxLabel = 0;
00076   if ( dataClass == DATACLASS_LABEL ) 
00077     {
00078     maxLabel = static_cast<int>( ReferenceVolume->GetData()->GetRange().m_UpperBound );
00079     
00080     for ( unsigned int img = 0; img < numberOfImages-1; ++img ) 
00081       {
00082       maxLabel = std::max( maxLabel, static_cast<int>( (*volumeList)[img]->GetData()->GetRange().m_UpperBound ) );
00083       }
00084     }
00085   
00086   // bounding box for reformatted volume.
00087   Types::Coordinate bbFrom[3], delta[3];
00088   result = this->CreateTransformedReference( bbFrom, delta, volumeOffset );
00089 
00090   const size_t mpiBlockSize = (result->GetNumberOfPixels() + mpiSize - 1) / mpiSize;
00091 
00092   ScalarDataType dtype = ReferenceVolume->GetData()->GetType();
00093   TypedArray::SmartPtr dataArray( TypedArray::Create( dtype, mpiBlockSize  ) );
00094 
00095   if ( this->m_UsePaddingValue )
00096     dataArray->SetPaddingValue( this->m_PaddingValue );
00097 
00098   const size_t numberOfThreads = Threads::GetNumberOfThreads();
00099   std::vector<GetTransformedReferenceTP> params( numberOfThreads );
00100 
00101   for ( size_t thr = 0; thr < numberOfThreads; ++thr ) 
00102     {
00103     params[thr].thisObject = this;
00104     params[thr].ThisThreadIndex = thr;
00105     params[thr].NumberOfThreads = numberOfThreads;
00106     params[thr].dims = result->GetDims();
00107     params[thr].m_Offset = mpiRank;
00108     params[thr].m_Stride = mpiSize;
00109     params[thr].bbFrom = bbFrom;
00110     params[thr].delta = delta;
00111     params[thr].splineXform = splineXform;
00112     params[thr].numberOfImages = numberOfImages;
00113     params[thr].xformList = xformList;
00114     params[thr].interpolatorList = &interpolatorList;
00115     params[thr].dataArray = dataArray;
00116     params[thr].maxLabel = maxLabel;
00117     params[thr].IncludeReferenceData = includeReferenceData;
00118     }
00119   
00120   if ( mpiRank == 0 ) 
00121     Progress::Begin( 0, result->GetNumberOfPixels(), result->GetNumberOfPixels() / 1e5 );
00122 
00123   switch ( dataClass ) 
00124     {
00125     default:
00126     case DATACLASS_GREY: 
00127     {
00128     if ( xformList && !xformList->empty() )
00129       Threads::RunThreads( GetTransformedReferenceGreyAvg, numberOfThreads, &params[0] );
00130     else
00131       Threads::RunThreads( GetTransformedReferenceGrey, numberOfThreads, &params[0] );
00132     }
00133     break;
00134     case DATACLASS_LABEL: 
00135     {
00136     Threads::RunThreads( GetTransformedReferenceLabel, numberOfThreads, &params[0] );
00137     }
00138     break;
00139     }
00140 
00141   if ( mpiRank == 0 )
00142     {
00143     Progress::Done();  
00144     }
00145 
00146   TypedArray::SmartPtr resultDataArray( TypedArray::Create( dtype, mpiBlockSize * mpiSize ) );
00147   
00148   MPI::Datatype sendtype = MPI::BYTE.Create_vector( mpiBlockSize, dataArray->GetItemSize(), dataArray->GetItemSize() );
00149   sendtype.Commit();
00150 
00151   MPI::Datatype temptype = MPI::BYTE.Create_vector( mpiBlockSize, dataArray->GetItemSize(), mpiSize * dataArray->GetItemSize() );
00152   MPI::Datatype recvtype = temptype.Create_resized( 0, dataArray->GetItemSize() );
00153   recvtype.Commit();
00154 
00155   MPI::COMM_WORLD.Gather( dataArray->GetDataPtr(), 1, sendtype, resultDataArray->GetDataPtr(), 1, recvtype, 0 /*root*/ );
00156 
00157   result->SetData( resultDataArray );
00158   
00159   return result;
00160 }
00161 
00162 CMTK_THREAD_RETURN_TYPE
00163 ReformatVolume::GetTransformedReferenceGreyAvg( void *const arg )
00164 {
00165   GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00166 
00167   const ReformatVolume* thisObject = params->thisObject;
00168   TypedArray::SmartPtr dataArray = params->dataArray;
00169   const SplineWarpXform* splineXform = params->splineXform;
00170   const Types::Coordinate* delta = params->delta;
00171   const Types::Coordinate* bbFrom = params->bbFrom;
00172   const DataGrid::IndexType& dims = params->dims;
00173 
00174   const std::vector<SplineWarpXform::SmartPtr>* xformList = params->xformList;
00175   const std::vector<UniformVolumeInterpolatorBase::SmartConstPtr>* interpolatorList = params->interpolatorList;
00176 
00177   Types::Coordinate minDelta = std::min( delta[0], std::min( delta[1], delta[2] ) );
00178   
00179   std::vector<Types::DataItem> value( params->numberOfImages );
00180   
00181   std::vector<const UniformVolume*> volumes( params->numberOfImages-1 );
00182   std::vector<const SplineWarpXform*> xforms( params->numberOfImages-1 );
00183 
00184   for ( unsigned int img = 0; img < params->numberOfImages-1; ++img ) 
00185     {
00186     xforms[img] = (*xformList)[img];
00187     }
00188 
00189   const UniformVolume* referenceVolume = thisObject->ReferenceVolume;
00190 
00191   const size_t numberOfPixels = dims[0] * dims[1] * dims[2];
00192   const size_t statusUpdateIncrement = std::max<size_t>( 1, numberOfPixels / 100 );
00193 
00194   const size_t firstOffset = params->m_Offset + params->ThisThreadIndex * params->m_Stride;
00195   const size_t incrOffset = params->NumberOfThreads * params->m_Stride;
00196 
00197   size_t toOffset = params->ThisThreadIndex;
00198 
00199   int cx = firstOffset % dims[0];
00200   int cy = (firstOffset / dims[0]) % dims[1];
00201   int cz = firstOffset / (dims[0] * dims[1]) ;
00202 
00203   Types::Coordinate xyz[3] = { bbFrom[0] + cx * delta[0], bbFrom[1] + cy * delta[1], bbFrom[2] + cz * delta[2] };
00204   
00205   for ( size_t offset = firstOffset; offset < numberOfPixels; offset += incrOffset, toOffset += params->NumberOfThreads ) 
00206     {
00207     if ( ! firstOffset && ! (offset % statusUpdateIncrement) ) 
00208       Progress::SetProgress( offset );
00209     
00210     UniformVolume::CoordinateVectorType v( xyz );
00211     const bool success = splineXform->ApplyInverseInPlace( v, 0.1 * minDelta );
00212     UniformVolume::CoordinateVectorType u = v;
00213     
00214     unsigned int toIdx = 0;
00215     if ( success ) 
00216       {
00217       if ( (*interpolatorList)[0]->GetDataAt( v, value[toIdx] ) )
00218         ++toIdx;
00219       
00220       for ( unsigned int img = 0; img < params->numberOfImages-1; ++img ) 
00221         {
00222         v = u;
00223         xforms[img]->ApplyInPlace( v );
00224         
00225         if ( (*interpolatorList)[img+1]->GetDataAt( v, value[toIdx] ) )
00226           ++toIdx;          
00227         }
00228       }
00229     
00230     if ( toIdx && success ) 
00231       {
00232       Types::DataItem avg = value[0];
00233       for ( unsigned int idx = 1; idx < toIdx; ++idx )
00234         avg += value[idx];
00235       dataArray->Set( avg / toIdx, toOffset );
00236       } 
00237     else
00238       {
00239       dataArray->SetPaddingAt( toOffset );
00240       }
00241 
00242     cx += incrOffset;
00243     if ( cx >= dims[0] )
00244       {
00245       cy += cx / dims[0];
00246       cx %= dims[0];
00247 
00248       if ( cy >= dims[1] )
00249         {
00250         cz += cy / dims[1];
00251         cy %= dims[1];
00252         xyz[3] = bbFrom[2] + cz * delta[2];
00253         }
00254       xyz[1] = bbFrom[1] + cy * delta[1];
00255       }
00256     xyz[0] = bbFrom[0] + cx * delta[0];
00257     }
00258 
00259   return CMTK_THREAD_RETURN_VALUE;
00260 }
00261 
00262 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines