cmtkGroupwiseRegistrationOutput.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: 2464 $
00026 //
00027 //  $LastChangedDate: 2010-10-19 09:54:33 -0700 (Tue, 19 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torsten_at_home $
00030 //
00031 */
00032 
00033 #include "cmtkGroupwiseRegistrationOutput.h"
00034 
00035 #include <IO/cmtkGroupwiseRegistrationFunctionalIO.h>
00036 #include <IO/cmtkClassStream.h>
00037 #include <IO/cmtkStudyList.h>
00038 #include <IO/cmtkClassStreamStudyList.h>
00039 #include <IO/cmtkVolumeIO.h>
00040 
00041 #include <limits.h>
00042 #include <vector>
00043 
00044 namespace
00045 cmtk
00046 {
00047 
00050 
00051 bool
00052 GroupwiseRegistrationOutput::WriteGroupwiseArchive( const char* path ) const
00053 {
00054 #ifdef CMTK_BUILD_MPI    
00055   // only root process needs to write outputs
00056   if ( MPI::COMM_WORLD.Get_rank() == 0 )
00057 #endif
00058     {
00059     // create class stream archive.
00060     if ( path )
00061       {
00062       ClassStream stream;
00063 
00064       if ( this->m_OutputRootDirectory )
00065         {
00066         char completePath[PATH_MAX];
00067         snprintf( completePath, sizeof( completePath ), "%s/%s", this->m_OutputRootDirectory, path );
00068         stream.Open( completePath, ClassStream::WRITE );
00069         }
00070       else
00071         stream.Open( path, ClassStream::WRITE );
00072       
00073       if ( ! stream.IsValid() ) return false;
00074       stream << *this->m_Functional;
00075       stream.Close();
00076       }
00077     }
00078   return true;
00079 }
00080 
00081 bool 
00082 GroupwiseRegistrationOutput::WriteXformsSeparateArchives
00083 ( const char* path, const char* templatePath )
00084 { 
00085 #ifdef CMTK_BUILD_MPI    
00086   // only root process needs to write outputs
00087   if ( MPI::COMM_WORLD.Get_rank() == 0 )
00088 #endif
00089     {
00090     if ( path )
00091       {
00092       char fullPath[PATH_MAX];
00093       
00094       for ( size_t img = 0; img < this->m_Functional->GetNumberOfTargetImages(); ++img )
00095         {
00096         StudyList slist;
00097         Study::SmartPtr refstudy;
00098         if ( this->m_OutputRootDirectory  && ! this->m_ExistingTemplatePath )
00099           {
00100           snprintf( fullPath, sizeof( fullPath ), "%s/%s", this->m_OutputRootDirectory, templatePath );
00101           refstudy = slist.AddStudy( fullPath );
00102           }
00103         else
00104           {
00105           refstudy = slist.AddStudy( templatePath );
00106           }
00107         
00108         const UniformVolume* image = this->m_Functional->GetOriginalTargetImage( img );
00109         Study::SmartPtr imgstudy = slist.AddStudy( image->m_MetaInformation[META_FS_PATH].c_str() );
00110         
00111         WarpXform::SmartPtr warpXform = WarpXform::SmartPtr::DynamicCastFrom( this->m_Functional->GetGenericXformByIndex( img ) );
00112         if ( warpXform )
00113           {
00114           AffineXform::SmartPtr affineXform( warpXform->GetInitialAffineXform() );
00115           slist.AddXform( refstudy, imgstudy, affineXform, warpXform );
00116           }
00117         else
00118           {
00119           AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Functional->GetGenericXformByIndex( img ) );
00120           slist.AddXform( refstudy, imgstudy, affineXform );
00121           }
00122         
00123         if ( this->m_OutputRootDirectory )
00124           {
00125           snprintf( fullPath, sizeof( fullPath ), "%s/%s/target-%03d.list", this->m_OutputRootDirectory, path, (int)img );
00126           }
00127         else
00128           {
00129           snprintf( fullPath, sizeof( fullPath ), "%s/target-%03d.list", path, (int)img );
00130           }
00131         ClassStreamStudyList::Write( fullPath, &slist );
00132         }
00133       }
00134     }
00135   return true;
00136 }
00137 
00138 bool
00139 GroupwiseRegistrationOutput::WriteAverageImage( const char* path, const cmtk::Interpolators::InterpolationEnum interp, const bool useTemplateData )
00140 {
00141   // reformat output and generate average images
00142   if ( path )
00143     {
00144     UniformVolume::SmartPtr templateGrid = this->m_Functional->GetTemplateGrid();
00145     const size_t numberOfPixels = templateGrid->GetNumberOfPixels();
00146 
00147     TypedArray::SmartPtr average( TypedArray::Create( TYPE_FLOAT, numberOfPixels ) );
00148     float* averagePtr = static_cast<float*>( average->GetDataPtr() );
00149 
00150     TypedArray::SmartPtr count( TypedArray::Create( TYPE_USHORT, numberOfPixels ) );
00151     unsigned short* countPtr = static_cast<unsigned short*>( count->GetDataPtr() );
00152     
00153     if ( useTemplateData )
00154       {
00155       if ( ! templateGrid->GetData() )
00156         {
00157         UniformVolume::SmartPtr readImage( VolumeIO::ReadOriented( templateGrid->m_MetaInformation[META_FS_PATH].c_str(), false /*verbose*/ ) );
00158         templateGrid->SetData( readImage->GetData() );
00159         }
00160 
00161       for ( size_t px = 0; px < numberOfPixels; ++px )
00162         {
00163         averagePtr[px] = static_cast<float>( templateGrid->GetDataAt( px ) );
00164         }
00165       count->Fill( 1 );
00166       }  
00167     else
00168       {
00169       average->Fill( 0 );
00170       count->Fill( 0 );
00171       }
00172 
00173     if ( this->m_Verbose )
00174       {
00175       StdErr << "Reformating output images ";
00176       }
00177 #ifdef CMTK_BUILD_MPI
00178     const size_t idxFrom = MPI::COMM_WORLD.Get_rank();
00179     const size_t idxSkip = MPI::COMM_WORLD.Get_size();
00180 #else
00181     const size_t idxFrom = 0;
00182     const size_t idxSkip = 1;
00183 #endif
00184     for ( size_t idx = idxFrom; idx < this->m_Functional->GetNumberOfTargetImages(); idx += idxSkip )
00185       {
00186       UniformVolume::SmartPtr floatingVolume = this->m_Functional->GetOriginalTargetImage( idx );
00187       if ( !floatingVolume->GetData() )
00188         floatingVolume = UniformVolume::SmartPtr( VolumeIO::ReadOriented( floatingVolume->m_MetaInformation[META_FS_PATH].c_str(), false /*verbose*/ ) );
00189       
00190       cmtk::ReformatVolume reformat;
00191       reformat.SetReferenceVolume( templateGrid );
00192       reformat.SetFloatingVolume( floatingVolume );
00193       reformat.SetInterpolation( interp );
00194       
00195       AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Functional->GetGenericXformByIndex( idx ) );
00196       if ( affineXform )
00197         {
00198         reformat.SetAffineXform( affineXform );
00199         }
00200 
00201       WarpXform::SmartPtr warpXform = WarpXform::SmartPtr::DynamicCastFrom( this->m_Functional->GetGenericXformByIndex( idx ) );
00202       if ( warpXform )
00203         reformat.SetWarpXform( warpXform );
00204       
00205       UniformVolume::SmartPtr ref( reformat.PlainReformat() );
00206       if ( this->m_Verbose )
00207         {
00208         StdErr << ".";
00209         }
00210       const TypedArray* data = ref->GetData();
00211 #pragma omp parallel for
00212       for ( size_t i = 0; i < numberOfPixels; ++i )
00213         {
00214         Types::DataItem v;
00215         if ( data->Get( v, i ) )
00216           {
00217           averagePtr[i] += static_cast<float>( v );
00218           ++countPtr[i];
00219           }
00220         }
00221       }
00222     if ( this->m_Verbose )
00223       {
00224       StdErr << " done\n";
00225       }
00226 
00227 #ifdef CMTK_BUILD_MPI
00228     float* averagePtrMPI = Memory::AllocateArray<float>( numberOfPixels );
00229     MPI::COMM_WORLD.Reduce( averagePtr, averagePtrMPI, numberOfPixels, MPI::FLOAT, MPI::SUM, 0 );
00230     memcpy( averagePtr, averagePtrMPI, numberOfPixels * sizeof( *averagePtr ) );
00231     Memory::DeleteArray( averagePtrMPI );
00232 
00233     unsigned short* countPtrMPI = Memory::AllocateArray<unsigned short>( numberOfPixels );
00234     MPI::COMM_WORLD.Reduce( countPtr, countPtrMPI, numberOfPixels, MPI::UNSIGNED_SHORT, MPI::SUM, 0 );
00235     memcpy( countPtr, countPtrMPI, numberOfPixels * sizeof( *countPtr ) );
00236     Memory::DeleteArray( countPtrMPI );
00237 #endif
00238 
00239 #ifdef CMTK_BUILD_MPI
00240     if ( MPI::COMM_WORLD.Get_rank() == 0 )
00241 #endif
00242       {
00243 #pragma omp parallel for
00244       for ( size_t i = 0; i < numberOfPixels; ++i )
00245         {
00246         if ( countPtr[i] )
00247           averagePtr[i] /= countPtr[i];
00248         else
00249           average->SetPaddingAt( i );
00250         }
00251       templateGrid->SetData( average );
00252 
00253       if ( this->m_OutputRootDirectory )
00254         {
00255         char fullPath[PATH_MAX];
00256         snprintf( fullPath, sizeof( fullPath ), "%s/%s", this->m_OutputRootDirectory, path );
00257         VolumeIO::Write( *templateGrid, fullPath, this->m_Verbose );
00258         }
00259       else
00260         {
00261         VolumeIO::Write( *templateGrid, path, this->m_Verbose );
00262         }
00263       }
00264     }
00265   
00266   return 0;
00267 }
00268 
00269 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines