cmtkReformatVolume.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: 1852 $
00026 //
00027 //  $LastChangedDate: 2010-06-18 13:17:53 -0700 (Fri, 18 Jun 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 namespace
00034 cmtk
00035 {
00036 
00039 
00040 UniformVolume* 
00041 ReformatVolume::GetTransformedReference
00042 ( const std::vector<SplineWarpXform::SmartPtr>* xformList,
00043   std::vector<UniformVolume::SmartPtr>* volumeList,
00044   Types::Coordinate *const volumeOffset,
00045   const bool includeReferenceData )
00046 {
00047   UniformVolume* result = NULL;
00048   unsigned int numberOfImages = 0;
00049 
00050   std::vector<UniformVolumeInterpolatorBase::SmartConstPtr> interpolatorList;
00051   interpolatorList.push_back( this->CreateInterpolator( this->ReferenceVolume ) );
00052   if ( volumeList )
00053     {
00054     numberOfImages = 1 + volumeList->size();
00055     for ( unsigned int img = 0; img < numberOfImages-1; ++img ) 
00056       {
00057       interpolatorList.push_back( this->CreateInterpolator( (*volumeList)[img] ) );
00058       }
00059     }
00060   
00061   const SplineWarpXform* splineXform = dynamic_cast<const SplineWarpXform*>( this->m_WarpXform.GetConstPtr() );
00062   if ( ! splineXform ) 
00063     {
00064     StdErr << "ERROR: ReformatVolume::GetTransformedReference supports spline warp only.\n";
00065     return NULL;
00066     }
00067   
00068   DataClass dataClass = ReferenceVolume->GetData()->GetDataClass();
00069   int maxLabel = 0;
00070   if ( dataClass == DATACLASS_LABEL ) 
00071     {
00072     const Types::DataItemRange rangeRef = ReferenceVolume->GetData()->GetRange();
00073     maxLabel = static_cast<int>( rangeRef.m_UpperBound );
00074     
00075     for ( unsigned int img = 0; img < numberOfImages-1; ++img ) 
00076       {
00077       const Types::DataItemRange rangeFlt = (*volumeList)[img]->GetData()->GetRange();
00078       maxLabel = std::max( maxLabel, static_cast<int>( rangeFlt.m_UpperBound ) );
00079       }
00080     }
00081   
00082   // bounding box for reformatted volume.
00083   Types::Coordinate bbFrom[3], delta[3];
00084   result = this->CreateTransformedReference( bbFrom, delta, volumeOffset );
00085 
00086   const ScalarDataType dtype = (this->m_UserDataType != TYPE_NONE) ? this->m_UserDataType : ReferenceVolume->GetData()->GetType();
00087   TypedArray::SmartPtr dataArray( TypedArray::Create( dtype, result->GetNumberOfPixels() ) );
00088   if ( this->m_UsePaddingValue )
00089     dataArray->SetPaddingValue( this->m_PaddingValue );
00090   result->SetData( dataArray );
00091 
00092   const size_t numberOfThreads = Threads::GetNumberOfThreads();
00093   std::vector<GetTransformedReferenceTP> params( numberOfThreads );
00094 
00095   for ( size_t thr = 0; thr < numberOfThreads; ++thr ) 
00096     {
00097     params[thr].thisObject = this;
00098     params[thr].ThisThreadIndex = thr;
00099     params[thr].NumberOfThreads = numberOfThreads;
00100     params[thr].dims = result->GetDims();
00101     params[thr].bbFrom = bbFrom;
00102     params[thr].delta = delta;
00103     params[thr].splineXform = splineXform;
00104     params[thr].numberOfImages = numberOfImages;
00105     params[thr].xformList = xformList;
00106     params[thr].volumeList = volumeList;
00107     params[thr].interpolatorList = &interpolatorList;
00108     params[thr].dataArray = dataArray;
00109     params[thr].maxLabel = maxLabel;
00110     params[thr].IncludeReferenceData = includeReferenceData;
00111     }
00112   
00113   switch ( dataClass ) 
00114     {
00115     default:
00116     case DATACLASS_GREY: 
00117     {
00118     if ( xformList && !xformList->empty() )
00119       Threads::RunThreads( GetTransformedReferenceGreyAvg, numberOfThreads, &params[0] );
00120     else
00121       Threads::RunThreads( GetTransformedReferenceGrey, numberOfThreads, &params[0] );
00122     }
00123     break;
00124     case DATACLASS_LABEL: 
00125     {
00126     Threads::RunThreads( GetTransformedReferenceLabel, numberOfThreads, &params[0] );
00127     }
00128     break;
00129     }
00130 
00131   return result;
00132 }
00133 
00134 CMTK_THREAD_RETURN_TYPE
00135 ReformatVolume::GetTransformedReferenceGreyAvg( void *const arg )
00136 {
00137   GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00138 
00139   TypedArray::SmartPtr dataArray = params->dataArray;
00140   const SplineWarpXform* splineXform = params->splineXform;
00141   const Types::Coordinate* delta = params->delta;
00142   const Types::Coordinate* bbFrom = params->bbFrom;
00143   const DataGrid::IndexType& dims = params->dims;
00144 
00145   const std::vector<SplineWarpXform::SmartPtr>* xformList = params->xformList;
00146   const std::vector<UniformVolumeInterpolatorBase::SmartConstPtr>* interpolatorList = params->interpolatorList;
00147 
00148   Types::Coordinate minDelta = std::min( delta[0], std::min( delta[1], delta[2] ) );
00149   
00150   std::vector<Types::DataItem> value( params->numberOfImages );
00151   
00152   std::vector<const SplineWarpXform*> xforms( params->numberOfImages-1 );
00153 
00154   for ( unsigned int img = 0; img < params->numberOfImages-1; ++img ) 
00155     {
00156     xforms[img] = (*xformList)[img];
00157     }
00158 
00159   int cx = params->ThisThreadIndex % dims[0];
00160   int cy = (params->ThisThreadIndex / dims[0]) % dims[1];
00161   int cz = params->ThisThreadIndex / (dims[0] * dims[1]) ;
00162 
00163   UniformVolume::CoordinateVectorType xyz;
00164   xyz[0] = bbFrom[0] + cx * delta[0];
00165   xyz[1] = bbFrom[1] + cy * delta[1];
00166   xyz[2] = bbFrom[2] + cz * delta[2];
00167   
00168   const size_t numberOfPixels = dims[0] * dims[1] * dims[2];
00169   const size_t statusUpdateIncrement = std::max<size_t>( 1, numberOfPixels / 100 );
00170 
00171   UniformVolume::CoordinateVectorType u, v;
00172   for ( size_t offset = params->ThisThreadIndex; offset < numberOfPixels; offset += params->NumberOfThreads ) 
00173     {
00174     if ( ! params->ThisThreadIndex && ! (offset % statusUpdateIncrement) ) 
00175       Progress::SetProgress( offset );
00176 
00177     v = xyz;
00178     const bool success = splineXform->ApplyInverseInPlace( v, 0.1 * minDelta );
00179     u = v;
00180     
00181     unsigned int toIdx = 0;
00182     if ( success ) 
00183       {
00184       if ( params->IncludeReferenceData ) 
00185         {
00186         if ( (*interpolatorList)[0]->GetDataAt( v, value[toIdx] ) )
00187           ++toIdx;
00188         }
00189       
00190       for ( unsigned int img = 0; img < params->numberOfImages-1; ++img ) 
00191         {
00192         v = u;
00193         xforms[img]->ApplyInPlace( v );
00194         
00195         if ( (*interpolatorList)[img+1]->GetDataAt( v, value[toIdx] ) )
00196           ++toIdx;
00197         }
00198       }
00199     if ( toIdx && success ) 
00200       {
00201       Types::DataItem avg = value[0];
00202       for ( unsigned int idx = 1; idx < toIdx; ++idx )
00203         avg += value[idx];
00204       dataArray->Set( avg / toIdx, offset );
00205       } 
00206     else
00207       dataArray->SetPaddingAt( offset );
00208 
00209     cx += params->NumberOfThreads;
00210     if ( cx >= dims[0] )
00211       {
00212       cy += cx / dims[0];
00213       cx %= dims[0];
00214 
00215       if ( cy >= dims[1] )
00216         {
00217         cz += cy / dims[1];
00218         cy %= dims[1];
00219         xyz[2] = bbFrom[2] + cz * delta[2];
00220         }
00221       xyz[1] = bbFrom[1] + cy * delta[1];
00222       }
00223     xyz[0] = bbFrom[0] + cx * delta[0];
00224     }
00225 
00226   return CMTK_THREAD_RETURN_VALUE;
00227 }
00228 
00229 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines