cmtkGroupwiseRegistrationFunctionalBase.cxx

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: 2509 $
00026 //
00027 //  $LastChangedDate: 2010-10-28 10:56:54 -0700 (Thu, 28 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 // Define this to debug the MPI communication:
00034 //#define DEBUG_COMM
00035 
00036 #include <Registration/cmtkGroupwiseRegistrationFunctionalBase.h>
00037 
00038 #include <Base/cmtkMathUtil.h>
00039 #include <IO/cmtkVolumeIO.h>
00040 #include <System/cmtkConsole.h>
00041 #include <System/cmtkThreadPool.h>
00042 
00043 #include <Base/cmtkAnatomicalOrientation.h>
00044 
00045 #include <Base/cmtkInterpolator.h>
00046 #include <Base/cmtkTypedArrayFunctionHistogramMatching.h>
00047 #include <Base/cmtkUniformVolumeFilter.h>
00048 #include <Registration/cmtkReformatVolume.h>
00049 
00050 #ifdef CMTK_BUILD_MPI
00051 #  include <mpi.h>
00052 #  include <IO/cmtkMPI.h>
00053 #endif
00054 
00055 namespace
00056 cmtk
00057 {
00058 
00061 
00062 GroupwiseRegistrationFunctionalBase
00063 ::GroupwiseRegistrationFunctionalBase() 
00064   : m_FreeAndRereadImages( false ),
00065     m_ForceZeroSum( false ),
00066     m_ForceZeroSumFirstN( 0 ),
00067     m_ActiveImagesFrom( 0 ),
00068     m_ActiveImagesTo( 0 ),
00069     m_ActiveXformsFrom( 0 ),
00070     m_ActiveXformsTo( 0 ),
00071     m_TemplateNumberOfPixels( 0 ), 
00072     m_ProbabilisticSampleDensity( -1.0 ),
00073     m_ProbabilisticSampleUpdatesAfter( 1000000 ),
00074     m_ProbabilisticSampleUpdatesSince( 0 ),
00075     m_GaussianSmoothImagesSigma( -1.0 ),
00076     m_UserBackgroundValue( 0 ),
00077     m_UserBackgroundFlag( false ),
00078     m_ParametersPerXform( 0 ),
00079     m_RepeatIntensityHistogramMatching( false )
00080 {
00081   this->m_NumberOfThreads = ThreadPool::GetGlobalThreadPool().GetNumberOfThreads();
00082   this->m_NumberOfTasks = 4 * this->m_NumberOfThreads - 3;
00083 
00084   this->m_Data.clear();
00085 #ifdef CMTK_BUILD_MPI
00086   this->m_RankMPI = MPI::COMM_WORLD.Get_rank();
00087   this->m_SizeMPI = MPI::COMM_WORLD.Get_size();
00088 #endif
00089 }
00090 
00091 GroupwiseRegistrationFunctionalBase::~GroupwiseRegistrationFunctionalBase()
00092 {
00093   if ( this->m_Data.size() )
00094     {
00095     const size_t numberOfImages = this->m_ImageVector.size();
00096     for ( size_t i = 0; i < numberOfImages; ++i )
00097       {
00098       if ( this->m_Data[i] )
00099         Memory::DeleteArray( this->m_Data[i] );
00100       }
00101     }
00102 }
00103 
00104 void
00105 GroupwiseRegistrationFunctionalBase::CreateTemplateGridFromTargets
00106 ( const std::vector<UniformVolume::SmartPtr>& targets, const int downsample )
00107 {
00108   Types::Coordinate templateSize[3] = {0,0,0};
00109   UniformVolume::IndexType templateDims;
00110   Types::Coordinate templateDelta = 1e10;
00111 
00112   for ( size_t i = 0; i < targets.size(); ++i )
00113     {
00114     for ( int dim = 0; dim < 3; ++dim )
00115       {
00116       templateSize[dim] = std::max( templateSize[dim], targets[i]->Size[dim] );
00117       }
00118     templateDelta = std::min( templateDelta, targets[i]->GetMinDelta() );
00119     }
00120   
00121   for ( int dim = 0; dim < 3; ++dim )
00122     {
00123     templateDims[dim] = 1 + static_cast<int>( templateSize[dim] / templateDelta );
00124     templateSize[dim] = (templateDims[dim]-1) * templateDelta;
00125     }
00126   
00127   UniformVolume::SmartPtr templateGrid( new UniformVolume( templateDims, FixedVector<3,Types::Coordinate>( templateSize ) ) );
00128   this->SetTemplateGrid( templateGrid, downsample );
00129 }
00130 
00131 void
00132 GroupwiseRegistrationFunctionalBase::CreateTemplateGrid
00133 ( const DataGrid::IndexType& dims, const UniformVolume::CoordinateVectorType& deltas )
00134 {
00135   UniformVolume::SmartPtr templateGrid( new UniformVolume( dims, deltas ) );
00136   this->SetTemplateGrid( templateGrid );
00137 }
00138 
00139 void
00140 GroupwiseRegistrationFunctionalBase::SetTemplateGrid
00141 ( UniformVolume::SmartPtr& templateGrid,
00142   const int downsample,
00143   const bool useTemplateData )
00144 { 
00145   this->m_TemplateGrid = templateGrid->Clone();
00146   this->m_UseTemplateData = useTemplateData;
00147   
00148   if ( this->m_UseTemplateData && ! this->m_TemplateGrid->GetData() )
00149     {
00150     UniformVolume::SmartPtr readImage( VolumeIO::ReadOriented( templateGrid->m_MetaInformation[META_FS_PATH].c_str(), false /*verbose*/ ) );
00151     this->m_TemplateGrid->SetData( readImage->GetData() );
00152     }
00153   
00154   if ( ! this->m_TemplateGrid->MetaKeyExists( META_IMAGE_ORIENTATION ) )
00155     {
00156     this->m_TemplateGrid->m_MetaInformation[META_IMAGE_ORIENTATION] = AnatomicalOrientation::ORIENTATION_STANDARD;
00157     }
00158   if ( ! this->m_TemplateGrid->MetaKeyExists( META_IMAGE_ORIENTATION_ORIGINAL ) )
00159     {
00160     this->m_TemplateGrid->m_MetaInformation[META_IMAGE_ORIENTATION_ORIGINAL] = AnatomicalOrientation::ORIENTATION_STANDARD;
00161     }
00162   if ( ! this->m_TemplateGrid->MetaKeyExists( META_SPACE ) )
00163     {
00164     this->m_TemplateGrid->SetMetaInfo( META_SPACE, AnatomicalOrientation::ORIENTATION_STANDARD );
00165     }
00166   if ( ! this->m_TemplateGrid->MetaKeyExists( META_SPACE_ORIGINAL ) )
00167     {
00168     this->m_TemplateGrid->SetMetaInfo( META_SPACE_ORIGINAL, AnatomicalOrientation::ORIENTATION_STANDARD );
00169     }
00170 
00171   if ( this->m_UseTemplateData )
00172     {
00173     this->m_TemplateGrid = UniformVolume::SmartPtr( this->PrepareSingleImage( this->m_TemplateGrid ) );
00174     }
00175   
00176   if ( downsample > 1 )
00177     {
00178     this->m_TemplateGrid = UniformVolume::SmartPtr( this->m_TemplateGrid->GetDownsampledAndAveraged( downsample, true /*approxIsotropic*/ ) );
00179     }
00180   this->m_TemplateNumberOfPixels = this->m_TemplateGrid->GetNumberOfPixels();  
00181   
00182   if ( this->m_UseTemplateData )
00183     {
00184     this->CopyTemplateData();
00185     }
00186   
00187   this->PrepareTargetImages();
00188 }
00189 
00190 
00191 void
00192 GroupwiseRegistrationFunctionalBase
00193 ::AllocateStorage()
00194 {
00195   if ( !this->m_TemplateGrid )
00196     {
00197     StdErr << "FATAL: must set template grid for groupwise registration before allocating storage\n";
00198     exit( 1 );
00199     }
00200 
00201   const size_t numberOfImages = this->m_OriginalImageVector.size();
00202   
00203   if ( this->m_TemplateNumberOfPixels )
00204     {
00205     if ( (this->m_ProbabilisticSampleDensity > 0) && (this->m_ProbabilisticSampleDensity < 1) )
00206       this->m_TemplateNumberOfSamples = static_cast<size_t>( this->m_ProbabilisticSampleDensity * this->m_TemplateNumberOfPixels);
00207     else
00208       this->m_TemplateNumberOfSamples = this->m_TemplateNumberOfPixels;
00209     
00210     if ( this->m_Data.size() )
00211       {
00212       for ( size_t i = 0; i < numberOfImages; ++i )
00213         {
00214         if ( this->m_Data[i] )
00215           Memory::DeleteArray( this->m_Data[i] );
00216         }
00217       }
00218     
00219     this->m_Data.resize( numberOfImages );
00220     for ( size_t i = 0; i < numberOfImages; ++i )
00221       {
00222       this->m_Data[i] = Memory::AllocateArray<byte>( this->m_TemplateNumberOfSamples );
00223       }
00224     
00225     this->m_TempData.resize( this->m_TemplateNumberOfSamples );
00226     }
00227 }
00228 
00229 void
00230 GroupwiseRegistrationFunctionalBase
00231 ::SetTargetImages
00232 ( std::vector<UniformVolume::SmartPtr>& tImages )
00233 {
00234   this->m_OriginalImageVector = tImages;
00235 
00236   this->m_ActiveImagesFrom = 0;
00237   this->m_ActiveImagesTo = tImages.size();
00238 
00239   this->m_ActiveXformsFrom = 0;
00240   this->m_ActiveXformsTo = tImages.size();
00241 
00242   this->m_ProbabilisticSampleUpdatesSince = 0;
00243 }
00244 
00245 UniformVolume::SmartPtr
00246 GroupwiseRegistrationFunctionalBase
00247 ::PrepareSingleImage( UniformVolume::SmartPtr& image )
00248 {
00249   if ( !image->GetData() )
00250     {
00251     UniformVolume::SmartPtr readImage( VolumeIO::ReadOriented( image->m_MetaInformation[META_FS_PATH].c_str(), false /*verbose*/ ) );
00252     image->SetData( readImage->GetData() );
00253     }
00254   
00255   TypedArray::SmartPtr data;
00256   if ( this->m_GaussianSmoothImagesSigma > 0 )
00257     {
00258     data = UniformVolumeFilter( image ).GetDataGaussFiltered( Units::GaussianSigma( this->m_GaussianSmoothImagesSigma * this->m_TemplateGrid->GetMinDelta() ) );
00259     
00260     if ( this->m_FreeAndRereadImages )
00261       {
00262       image->SetData( TypedArray::SmartPtr::Null );
00263       }
00264     }
00265   else
00266     {
00267     if ( this->m_FreeAndRereadImages )
00268       {
00269       data = image->GetData();
00270       image->SetData( TypedArray::SmartPtr::Null );
00271       }
00272     else
00273       {
00274       data = image->GetData()->Clone();
00275       }
00276     }
00277   
00278   UniformVolume::SmartPtr newTargetImage = image->CloneGrid();
00279   newTargetImage->SetData( data );
00280   return newTargetImage;
00281 }
00282 
00283 void
00284 GroupwiseRegistrationFunctionalBase
00285 ::PrepareTargetImages()
00286 {
00287   this->m_ImageVector.resize( this->m_OriginalImageVector.size() );
00288   for ( size_t i = 0; i < this->m_OriginalImageVector.size(); ++i )
00289     {
00290     this->m_ImageVector[i] = this->PrepareSingleImage( this->m_OriginalImageVector[i] );
00291     }
00292 }
00293 
00294 void
00295 GroupwiseRegistrationFunctionalBase::GetParamVector( CoordinateVector& v )
00296 {
00297   v.SetDim( this->ParamVectorDim() );
00298 
00299   for ( size_t idx = 0; idx < this->m_XformVector.size(); ++idx )
00300     {
00301     this->m_XformVector[idx]->GetParamVector( v, idx * this->m_ParametersPerXform );
00302     }
00303 }
00304 
00305 void
00306 GroupwiseRegistrationFunctionalBase::SetParamVector( CoordinateVector& v )
00307 {
00308   size_t offset = 0;
00309   for ( size_t xIdx = 0; xIdx < this->m_XformVector.size(); ++xIdx )
00310     {
00311     CoordinateVector vv( this->m_ParametersPerXform, v.Elements + offset, false /*free*/ );
00312     offset += this->m_ParametersPerXform;
00313     this->m_XformVector[xIdx]->SetParamVector( vv );
00314     }
00315 }
00316 
00317 void
00318 GroupwiseRegistrationFunctionalBase::SetParamVector
00319 ( CoordinateVector& v, const size_t xformIdx )
00320 {
00321   const size_t offset = this->m_ParametersPerXform * xformIdx;
00322   CoordinateVector vv( this->m_ParametersPerXform, v.Elements + offset, false /*free*/ );
00323   this->m_XformVector[xformIdx]->SetParamVector( vv );
00324 }
00325 
00326 void
00327 GroupwiseRegistrationFunctionalBase
00328 ::SetParameter( const size_t param, const Types::Coordinate value )
00329 {
00330   this->m_XformVector[param / this->m_ParametersPerXform]->SetParameter( param % this->m_ParametersPerXform, value );
00331 }
00332 
00333 void
00334 GroupwiseRegistrationFunctionalBase
00335 ::SetParameter( const size_t xform, const size_t param, const Types::Coordinate value )
00336 {
00337   this->m_XformVector[xform]->SetParameter( param, value );
00338 }
00339 
00340 GroupwiseRegistrationFunctionalBase::ReturnType
00341 GroupwiseRegistrationFunctionalBase::EvaluateAt( CoordinateVector& v )
00342 {
00343   if ( (this->m_ProbabilisticSampleDensity > 0) && (this->m_ProbabilisticSampleDensity < 1) )
00344     {
00345     if ( !this->m_ProbabilisticSampleUpdatesSince )
00346       this->UpdateProbabilisticSamples();
00347     (++this->m_ProbabilisticSampleUpdatesSince) %= this->m_ProbabilisticSampleUpdatesAfter;
00348     }
00349 
00350   this->SetParamVector( v );
00351   this->InterpolateAllImages();
00352   
00353   return this->Evaluate();
00354 }
00355 
00356 GroupwiseRegistrationFunctionalBase::ReturnType
00357 GroupwiseRegistrationFunctionalBase::EvaluateWithGradient
00358 ( CoordinateVector& v, CoordinateVector& g, const Types::Coordinate step )
00359 {
00360   const Self::ReturnType baseValue = this->EvaluateAt( v );
00361 
00362   for ( size_t param = 0; param < this->ParamVectorDim(); ++param )
00363     {
00364     g[param] = 0.0;
00365 
00366     const size_t imageIndex = param / this->m_ParametersPerXform;
00367     const size_t paramIndex = param % this->m_ParametersPerXform;
00368 
00369     const Types::Coordinate pStep = this->GetParamStep( param, step );
00370     if ( pStep > 0 )
00371       {
00372       byte* tmp = this->m_Data[imageIndex];
00373       this->m_Data[imageIndex] = &(this->m_TempData[0]);
00374 
00375       const Types::Coordinate p0 = v[param];
00376 
00377       this->SetParameter( imageIndex, paramIndex, p0 + pStep );
00378       this->InterpolateImage( imageIndex, this->m_Data[imageIndex] );
00379       const Self::ReturnType upper = this->Evaluate();
00380 
00381       this->SetParameter( imageIndex, paramIndex, p0 - pStep );
00382       this->InterpolateImage( imageIndex, this->m_Data[imageIndex] );
00383       const Self::ReturnType lower = this->Evaluate();
00384 
00385       this->m_Data[imageIndex] = tmp;
00386       this->SetParameter( imageIndex, paramIndex, p0 );
00387 
00388       if ( (upper > baseValue) || (lower > baseValue) )
00389         {
00390         g[param] = (upper - lower);
00391         }
00392       }
00393     }
00394 
00395   if ( this->m_ForceZeroSum )
00396     {
00397     this->ForceZeroSumGradient( g );
00398     }
00399 
00400   return baseValue;
00401 }
00402 
00403 void
00404 GroupwiseRegistrationFunctionalBase::UpdateProbabilisticSamples()
00405 {
00406 #ifdef CMTK_BUILD_MPI
00407   const size_t samplesPerNode = 1 + (this->m_TemplateNumberOfSamples / this->m_SizeMPI);
00408   std::vector<size_t> nodeSamples( samplesPerNode );
00409   this->m_ProbabilisticSamples.resize( samplesPerNode * this->m_SizeMPI );
00410 #else
00411   this->m_ProbabilisticSamples.resize( this->m_TemplateNumberOfSamples );
00412 #endif
00413   
00414   
00415 #ifdef CMTK_BUILD_MPI
00416   const size_t firstSample = 0;
00417   const size_t lastSample = samplesPerNode;
00418 #else
00419   const size_t firstSample = 0;
00420   const size_t lastSample = this->m_TemplateNumberOfSamples;
00421 #endif
00422 
00423   for ( size_t i = firstSample; i < lastSample; ++i )
00424     {
00425     const size_t sample = static_cast<size_t>( this->m_TemplateNumberOfPixels * MathUtil::UniformRandom() );
00426 #ifdef CMTK_BUILD_MPI
00427     nodeSamples[i] = sample;
00428 #else
00429     this->m_ProbabilisticSamples[i] = sample;
00430 #endif
00431     }
00432   
00433 #ifdef CMTK_BUILD_MPI
00434   MPI::COMM_WORLD.Allgather( &nodeSamples[0], sizeof( nodeSamples[0] ) * samplesPerNode, MPI::CHAR, &this->m_ProbabilisticSamples[0], sizeof( nodeSamples[0] ) * samplesPerNode, MPI::CHAR );
00435 #endif
00436 
00437 #ifdef CMTK_BUILD_MPI
00438   this->m_ProbabilisticSamples.resize( this->m_TemplateNumberOfSamples );
00439 #endif
00440 }
00441 
00442 void
00443 GroupwiseRegistrationFunctionalBase
00444 ::InterpolateAllImages()
00445 {
00446 #ifdef CMTK_BUILD_MPI
00447   // do my share of interpolations
00448   for ( size_t idx = this->m_ActiveImagesFrom + this->m_RankMPI; idx < this->m_ActiveImagesTo; idx += this->m_SizeMPI )
00449     {
00450     this->InterpolateImage( idx, this->m_Data[idx] );
00451     }
00452 
00453   // exchange results with other processes
00454   for ( size_t idx = this->m_ActiveImagesFrom; idx < this->m_ActiveImagesTo; ++idx )
00455     {
00456 #ifdef DEBUG_COMM
00457     fprintf( stderr, "%d\tBroadcasting reformated image %d with root %d\n", (int)this->m_RankMPI, (int)idx, (int)((idx-this->m_ActiveImagesFrom) % this->m_SizeMPI) );
00458 #endif
00459     MPI::COMM_WORLD.Bcast( this->m_Data[idx], this->m_TemplateNumberOfSamples, MPI::CHAR, (idx - this->m_ActiveImagesFrom) % this->m_SizeMPI );
00460     }
00461 #else
00462   for ( size_t idx = this->m_ActiveImagesFrom; idx < this->m_ActiveImagesTo; ++idx )
00463     {
00464     this->InterpolateImage( idx, this->m_Data[idx] );
00465     }
00466 #endif
00467 }
00468 
00469 void
00470 GroupwiseRegistrationFunctionalBase
00471 ::ForceZeroSumGradient( CoordinateVector& g ) const
00472 {
00473   const size_t numberOfXforms = this->m_XformVector.size();
00474   const size_t zeroSumFirstN = this->m_ForceZeroSumFirstN ? this->m_ForceZeroSumFirstN : numberOfXforms;
00475 
00476 #pragma omp parallel for
00477   for ( size_t param = 0; param < this->m_ParametersPerXform; ++param )
00478     {
00479     Types::Coordinate avg = 0;
00480 
00481     size_t pparam = param;
00482     for ( size_t idx = 0; idx < zeroSumFirstN; ++idx, pparam += this->m_ParametersPerXform )
00483       {
00484       avg += g[pparam];
00485       }
00486     
00487     avg *= 1.0 / zeroSumFirstN;
00488     
00489     pparam = param;
00490     for ( size_t idx = 0; idx < numberOfXforms; ++idx, pparam += this->m_ParametersPerXform  )
00491       {
00492       g[pparam] -= avg;
00493       }
00494     }
00495 
00496   // if the remaining vector is smaller than threshold, throw it out.
00497   const Types::Coordinate gMax = g.MaxNorm();
00498   if ( gMax < 1e-3 )
00499     {
00500     g.Clear();
00501     }
00502 }
00503 
00504 bool
00505 GroupwiseRegistrationFunctionalBase
00506 ::Wiggle()
00507 {
00508   bool wiggle = false;
00509 
00510   if ( (this->m_ProbabilisticSampleDensity > 0) && (this->m_ProbabilisticSampleDensity < 1) )
00511     {
00512     this->m_ProbabilisticSampleUpdatesSince = 0;
00513     wiggle = true;
00514     }
00515 
00516   if ( this->m_RepeatIntensityHistogramMatching )
00517     {
00518     TypedArray::SmartPtr referenceData = this->m_TemplateGrid->GetData();
00519     if ( !this->m_UseTemplateData )
00520       referenceData = TypedArray::SmartPtr::Null;
00521     
00522     for ( size_t i = 0; i < this->m_OriginalImageVector.size(); ++i )
00523       {
00524       UniformVolume::SmartPtr scaledImage;
00525       if ( this->m_OriginalImageVector[i]->GetData() )
00526         {
00527         scaledImage = UniformVolume::SmartPtr( this->m_OriginalImageVector[i]->Clone( true /*copyData*/ ) );
00528         }
00529       else
00530         {
00531         scaledImage = UniformVolume::SmartPtr( VolumeIO::ReadOriented( this->m_OriginalImageVector[i]->m_MetaInformation[META_FS_PATH].c_str(), false /*verbose*/ ) );
00532         }
00533 
00534       UniformVolume::SmartPtr reformatImage( this->GetReformattedImage( scaledImage, i ) );
00535       if ( referenceData )
00536         {
00537         scaledImage->GetData()->ApplyFunctionObject( TypedArrayFunctionHistogramMatching( *(reformatImage->GetData()), *referenceData ) );
00538         }
00539       else
00540         {
00541         referenceData = reformatImage->GetData();
00542         }
00543       
00544       this->m_ImageVector[i] = UniformVolume::SmartPtr( this->PrepareSingleImage( scaledImage ) );
00545       }
00546     this->InterpolateAllImages();
00547     wiggle = true;
00548     }
00549 
00550   return wiggle;
00551 }
00552 
00553 void
00554 GroupwiseRegistrationFunctionalBase
00555 ::CopyTemplateData()
00556 {
00557   const TypedArray* dataArray = this->m_TemplateGrid->GetData();
00558 
00559   if ( dataArray )
00560     {
00561     const size_t size = dataArray->GetDataSize();
00562     this->m_TemplateData.resize( size );
00563     
00564     for ( size_t i = 0; i < size; ++i )
00565       {
00566       Types::DataItem value;
00567       if ( dataArray->Get( value, i ) )
00568         this->m_TemplateData[i] = static_cast<byte>( value );
00569       else
00570         this->m_TemplateData[i] = this->m_PaddingValue;
00571       }
00572     }
00573 }
00574 
00575 void
00576 GroupwiseRegistrationFunctionalBase
00577 ::DebugWriteImages()
00578 {
00579   this->InterpolateAllImages();
00580   UniformVolume::SmartPtr writeVolume( this->m_TemplateGrid->CloneGrid() );
00581   writeVolume->CreateDataArray( TYPE_BYTE );
00582 
00583   for ( size_t i = 0; i < this->m_TemplateNumberOfPixels; ++i )
00584     {
00585     writeVolume->SetDataAt( this->m_TemplateData[i], i );
00586     }
00587   VolumeIO::Write( *writeVolume, "template.nii", true );
00588 
00589   for ( size_t n = 0; n < this->m_ImageVector.size(); ++n )
00590     {
00591     for ( size_t i = 0; i < this->m_TemplateNumberOfPixels; ++i )
00592       {
00593       writeVolume->SetDataAt( this->m_Data[n][i], i );
00594       }
00595 
00596     char path[PATH_MAX];
00597     sprintf( path, "target%02d.nii", static_cast<int>( n ) );
00598     VolumeIO::Write( *writeVolume, path, true );
00599     }
00600 }
00601 
00602 const UniformVolume::SmartPtr
00603 GroupwiseRegistrationFunctionalBase
00604 ::GetReformattedImage( const UniformVolume::SmartPtr& targetGrid, const size_t idx ) const
00605 {
00606   ReformatVolume reformat;
00607   reformat.SetInterpolation( Interpolators::LINEAR );
00608   reformat.SetReferenceVolume( targetGrid );
00609   reformat.SetFloatingVolume( this->m_OriginalImageVector[idx] );
00610   
00611   reformat.SetWarpXform( WarpXform::SmartPtr::DynamicCastFrom( this->m_XformVector[idx] ) );
00612   reformat.SetAffineXform( AffineXform::SmartPtr::DynamicCastFrom( this->m_XformVector[idx] ) );
00613   
00614   if ( this->m_UserBackgroundFlag )
00615     {
00616     reformat.SetPaddingValue( this->m_UserBackgroundValue );
00617     }
00618   
00619   UniformVolume::SmartPtr result = reformat.PlainReformat();
00620 
00621   if ( this->m_UserBackgroundFlag )
00622     {
00623     result->GetData()->ClearPaddingFlag();
00624     }
00625   return result;
00626 }
00627 
00628 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines