Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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, ¶ms[0] );
00130 else
00131 Threads::RunThreads( GetTransformedReferenceGrey, numberOfThreads, ¶ms[0] );
00132 }
00133 break;
00134 case DATACLASS_LABEL:
00135 {
00136 Threads::RunThreads( GetTransformedReferenceLabel, numberOfThreads, ¶ms[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 );
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 }