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 "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
00056 if ( MPI::COMM_WORLD.Get_rank() == 0 )
00057 #endif
00058 {
00059
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
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
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 ) );
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 ) );
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 }