cmtkImagePairAffineRegistrationCommandLine.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: 2530 $
00026 //
00027 //  $LastChangedDate: 2010-11-01 16:16:43 -0700 (Mon, 01 Nov 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkImagePairAffineRegistrationCommandLine.h"
00034 
00035 #include <System/cmtkConsole.h>
00036 #include <System/cmtkThreads.h>
00037 #include <System/cmtkTimers.h>
00038 #include <System/cmtkCommandLine.h>
00039 #include <System/cmtkExitException.h>
00040 #include <System/cmtkCompressedStream.h>
00041 #include <System/cmtkMountPoints.h>
00042 
00043 #include <Base/cmtkTypes.h>
00044 #include <Base/cmtkAnatomicalOrientation.h>
00045 #include <Base/cmtkTransformChangeToSpaceAffine.h>
00046 #include <Base/cmtkTransformChangeFromSpaceAffine.h>
00047 
00048 #include <Registration/cmtkRegistrationCallback.h>
00049 #include <Registration/cmtkProtocolCallback.h>
00050 #include <Registration/cmtkMakeInitialAffineTransformation.h>
00051 
00052 #include <IO/cmtkVolumeIO.h>
00053 #include <IO/cmtkClassStream.h>
00054 #include <IO/cmtkClassStreamAffineXform.h>
00055 #include <IO/cmtkXformIO.h>
00056 #include <IO/cmtkAffineXformITKIO.h>
00057 
00058 #ifdef CMTK_USE_SQLITE
00059 #  include <Registration/cmtkImageXformDB.h>
00060 #endif
00061 
00062 #ifdef HAVE_SYS_TYPES_H
00063 #  include <sys/types.h>
00064 #endif
00065 
00066 #ifdef HAVE_SYS_STAT_H
00067 #  include <sys/stat.h>
00068 #endif
00069 
00070 #ifdef HAVE_SYS_UTSNAME_H
00071 #  include <sys/utsname.h>
00072 #endif
00073 
00074 #ifdef _MSC_VER
00075 #  include <direct.h>
00076 #endif
00077 
00078 #include <stdio.h>
00079 #include <string.h>
00080 #include <iostream>
00081 
00082 namespace 
00083 cmtk
00084 {
00085 
00088 
00089 ImagePairAffineRegistrationCommandLine
00090 ::ImagePairAffineRegistrationCommandLine 
00091 ( const int argc, const char* argv[] ) 
00092   : m_InitialXformPath( NULL ),
00093     m_ReformattedImagePath( NULL ),
00094     m_OutputPathITK( NULL ),
00095 #ifdef CMTK_USE_SQLITE
00096     m_UpdateDB( NULL ),
00097 #endif
00098     m_ProtocolFileName( NULL )
00099 {
00100   this->m_Metric = 0;
00101 
00102   this->m_AutoMultiLevels = 0;
00103   this->m_CoarsestResolution = -1;
00104   this->m_MaxStepSize = 8;
00105   this->m_MinStepSize = 0.1;
00106   this->m_Sampling = 1.0;
00107   OutParametersName = OutMatrixName = Studylist = Time = NULL;
00108 
00109   Verbose = 0;
00110 
00111   bool forceOutsideFlag = false;
00112   Types::DataItem forceOutsideValue = 0;
00113 
00114   const char* inStudylist = NULL;
00115   const char *InitialStudylist = NULL;
00116   Study1 = Study2 = NULL;
00117 
00118   const char* clArg1 = NULL; // input studylist or reference image
00119   const char* clArg2 = NULL; // empty or floating image
00120 
00121   try 
00122     {
00123     CommandLine cl( CommandLine::PROPS_XML );
00124     cl.SetProgramInfo( CommandLine::PRG_TITLE, "Rigid and affine registration" );
00125     cl.SetProgramInfo( CommandLine::PRG_DESCR, "This program performs rigid and affine image registration using multi-resolution optimization of voxel-based image similarity measures." );
00126     cl.SetProgramInfo( CommandLine::PRG_CATEG, "CMTK.Registration.Experimental" );
00127 
00128     typedef CommandLine::Key Key;
00129     cl.AddSwitch( Key( 'v', "verbose" ), &Verbose, true, "Verbose mode" )->SetProperties( CommandLine::PROPS_NOXML );
00130     cl.AddSwitch( Key( 'q', "quiet" ), &Verbose, false, "Quiet mode" )->SetProperties( CommandLine::PROPS_NOXML );
00131 
00132     cl.BeginGroup( "Automation", "Automation Options" );
00133     cl.AddOption( Key( "auto-multi-levels" ), &this->m_AutoMultiLevels, "Automatic optimization and resolution parameter generation for <n> levels" );
00134 
00135     cl.BeginGroup( "Optimization", "Optimization settings" );
00136     cl.AddOption( Key( "max-stepsize" ), &this->m_MaxStepSize, "Maximum optimizer step size, which determines search space exploration." );
00137     cl.AddOption( Key( "min-stepsize" ), &this->m_MinStepSize, "Minimum optimizer step size, which determines precision." );
00138     cl.AddOption( Key( "stepfactor" ), &this->m_OptimizerStepFactor, "Factor for search step size reduction. Must be > 0.0 and < 1.0" );
00139     cl.AddOption( Key( "delta-f-threshold" ), &this->m_DeltaFThreshold, "Optional threshold to terminate optimization (level) if relative change of target function drops below this value." );
00140     cl.EndGroup();
00141 
00142     cl.BeginGroup( "Resolution", "Image resolution parameters" );
00143     cl.AddOption( Key( 's', "sampling" ), &this->m_Sampling, "Image sampling (finest resampled image resolution)" );
00144     cl.AddOption( Key( "coarsest" ), &this->m_CoarsestResolution, "Upper limit for image sampling in multiresolution hierarchy" );
00145 
00146     cl.AddSwitch( Key( "omit-original-data" ), &this->m_UseOriginalData, false, "Do not use original data in full resolution, omit final stage in multiresolution hierarchy, thus reducing computation time." );
00147     cl.EndGroup();
00148 
00149     cl.BeginGroup( "Transformation", "Transformation parameters" );
00150     cl.AddVector( Key( "dofs" ), this->NumberDOFs, "Add number of degrees of freedom. This can be 3 (translation), 6 (rigid: translation and rotation), "
00151                   "7 (rigid plus global scale), 9 (rigid plus anisotropic scales), 12 (rigid plus scales plus shears), or 603 (rigid plus shears, but no scale). "
00152                   "This option can be repeated, in which case DOFs are used for successive optimization runs in the order that they appear." );
00153     cl.AddVector( Key( "dofs-final" ), this->NumberDOFsFinal, "Add number of degrees of freedom for final level only [can be repeated]" );
00154     
00155     CommandLine::EnumGroup<MakeInitialAffineTransformation::Mode>::SmartPtr
00156       initGroup = cl.AddEnum( "init", &this->m_Initializer, "Select initializer for the affine trasnformation." );
00157     initGroup->AddSwitch( Key( "none" ), MakeInitialAffineTransformation::NONE, "Use input transformation, or identity transformation if none was provided ." );
00158     initGroup->AddSwitch( Key( "fov" ), MakeInitialAffineTransformation::FOV, "Align centers of field of view (or crop regions) using a translation." );
00159     initGroup->AddSwitch( Key( "com" ), MakeInitialAffineTransformation::COM, "Align centers of mass using a translation." );
00160     initGroup->AddSwitch( Key( "pax" ), MakeInitialAffineTransformation::PAX, "Align images by rotation using principal axes and translation using centers of mass." );
00161     initGroup->AddSwitch( Key( "physical" ), MakeInitialAffineTransformation::PHYS, "Align images by rotation using direction vectors stored in input images and translation using image origins." );
00162     
00163     cl.AddOption( Key( "initial" ), &InitialStudylist, "Initialize transformation from given path" )->SetProperties( CommandLine::PROPS_XFORM );
00164     cl.AddSwitch( Key( "initial-is-inverse" ), &this->m_InitialXformIsInverse, true, "Invert initial transformation before initializing registration" );
00165     cl.EndGroup();
00166 
00167     cl.BeginGroup( "Image data", "Image data" );
00168     CommandLine::EnumGroup<int>::SmartPtr
00169       metricGroup = cl.AddEnum( "registration-metric", &this->m_Metric, "Registration metric for motion estimation by image-to-image registration." );
00170     metricGroup->AddSwitch( Key( "nmi" ), 0, "Normalized Mutual Information metric" );
00171     metricGroup->AddSwitch( Key( "mi" ), 1, "Standard Mutual Information metric" );
00172     metricGroup->AddSwitch( Key( "cr" ), 2, "Correlation Ratio metric" );
00173     metricGroup->AddSwitch( Key( "rms" ), 3, "Root of Mean Squaresa metric (this is the square root of MSD)" );
00174     metricGroup->AddSwitch( Key( "msd" ), 4, "Mean Squared Difference metric" );
00175     metricGroup->AddSwitch( Key( "ncc" ), 5, "Normalized Cross Correlation metric" );
00176 
00177     cl.BeginGroup( "Interpolation", "Floating Image Interpolation Options" );
00178     cmtk::CommandLine::EnumGroup<Interpolators::InterpolationEnum>::SmartPtr kernelGroup = 
00179       cl.AddEnum( "interpolation", &this->m_FloatingImageInterpolation, "Interpolation method for floating image sampling:" );
00180     kernelGroup->AddSwitch( Key( "nearest-neighbor" ), Interpolators::NEAREST_NEIGHBOR, "Nearest neighbor interpolation (for intensity and label data)" );
00181     kernelGroup->AddSwitch( Key( "linear" ), Interpolators::LINEAR, "Trilinear interpolation" );
00182     kernelGroup->AddSwitch( Key( "cubic" ), Interpolators::CUBIC, "Tricubic interpolation" );
00183     kernelGroup->AddSwitch( Key( "cosine-sinc" ), Interpolators::COSINE_SINC, "Cosine-windowed sinc interpolation (most accurate but slowest)" );
00184     kernelGroup->AddSwitch( Key( "partial-volume" ), Interpolators::PARTIALVOLUME, "Partial volume interpolation (for label data)" );
00185     kernelGroup->AddSwitch( Key( "automatic" ), Interpolators::DEFAULT, "Select interpolation automatically based on data type: linear for grey-level data, nearest neighbor for label data." );
00186 
00187     cl.AddSwitch( Key( "match-histograms" ), &this->m_MatchFltToRefHistogram, true, "Match floating image histogram to reference image histogram." );
00188     cl.AddOption( Key( "force-outside-value" ), &forceOutsideValue, "Force values outside field of view to this value rather than drop incomplete pixel pairs", &forceOutsideFlag );
00189 
00190     this->m_PreprocessorRef.AttachToCommandLine( cl );
00191     this->m_PreprocessorFlt.AttachToCommandLine( cl );
00192 
00193     cl.BeginGroup( "Output", "Output parameters" )->SetProperties( CommandLine::PROPS_NOXML );
00194     cl.AddOption( Key( 'o', "output" ), &this->Studylist, "Output path for final transformation" );
00195     cl.AddOption( Key( "write-matrix" ), &this->OutMatrixName, "Output path for final transformation in matrix format" );
00196     cl.AddOption( Key( "write-parameters" ), &this->OutParametersName, "Output path for final transformation in plain parameter list format" );
00197     cl.AddOption( Key( "write-protocol" ), &this->m_ProtocolFileName, "Optimization protocol output file name" );
00198     cl.AddOption( Key( "write-time" ), &this->Time, "Computation time statistics output file name" );
00199     cl.EndGroup();
00200 
00201     cl.BeginGroup( "SlicerImport", "Import Results into Slicer" );
00202     cl.AddOption( Key( "write-itk" ), &this->m_OutputPathITK, "Output path for final transformation in ITK format" )
00203       ->SetProperties( CommandLine::PROPS_XFORM | CommandLine::PROPS_OUTPUT )
00204       ->SetAttribute( "reference", "FloatingImage" );
00205     cl.AddOption( Key( "write-reformatted" ), &this->m_ReformattedImagePath, "Write reformatted floating image." )->SetProperties( CommandLine::PROPS_IMAGE | CommandLine::PROPS_OUTPUT );
00206     cl.EndGroup();
00207     
00208 #ifdef CMTK_USE_SQLITE
00209     cl.BeginGroup( "Database", "Image/Transformation Database" );
00210     cl.AddOption( Key( "db" ), &this->m_UpdateDB, "Path to image/transformation database that should be updated with the new registration and/or reformatted image." );
00211     cl.EndGroup();
00212 #endif
00213 
00214     cl.AddParameter( &clArg1, "ReferenceImage", "Reference (fixed) image path" )->SetProperties( CommandLine::PROPS_IMAGE );
00215     cl.AddParameter( &clArg2, "FloatingImage", "Floating (moving) image path" )->SetProperties( CommandLine::PROPS_IMAGE | CommandLine::PROPS_OPTIONAL );
00216 
00217     cl.Parse( argc, argv );
00218     }
00219   catch ( const CommandLine::Exception& ex )
00220     {
00221     StdErr << ex << "\n";
00222     throw cmtk::ExitException( 1 );
00223     }
00224   
00225   if ( (this->m_OptimizerStepFactor <= 0) || (this->m_OptimizerStepFactor >= 1) ) 
00226     {
00227     StdErr << "ERROR: step factor value " << this->m_OptimizerStepFactor << " is invalid. Must be in range (0..1)\n";
00228     throw cmtk::ExitException( 1 );
00229     }
00230 
00231   if ( clArg2 ) 
00232     {
00233     Study1 = const_cast<char*>( clArg1 );
00234     Study2 = const_cast<char*>( clArg2 );
00235     } 
00236   else
00237     {
00238     inStudylist = clArg1;
00239     if ( InitialStudylist ) 
00240       {
00241       StdErr << "Transformation will be overriden by '--initial' list.\n";
00242       }
00243     
00244     if ( Verbose )
00245       StdErr << "Reading input studylist " << inStudylist << ".\n";
00246     
00247     ClassStream typedStream( MountPoints::Translate(inStudylist), "registration", ClassStream::READ );
00248     if ( ! typedStream.IsValid() ) 
00249       {
00250       StdErr << "Could not open studylist archive " << inStudylist << ".\n";
00251       throw cmtk::ExitException( 1 );
00252       }
00253 
00254     typedStream.Seek ( "registration" );
00255     Study1 = typedStream.ReadString( "reference_study" );
00256     Study2 = typedStream.ReadString( "floating_study" );
00257     if ( Study2 )
00258       {
00259       AffineXform::SmartPtr affineXform;
00260       typedStream >> affineXform;
00261       this->SetInitialTransformation( affineXform );
00262       }
00263     else
00264       {
00265       // legacy studylists have inverse transformation in them
00266       Study2 = typedStream.ReadString( "model_study" );
00267       AffineXform::SmartPtr affineXform;
00268       typedStream >> affineXform;
00269       this->SetInitialTransformation( affineXform->GetInverse() );
00270       }
00271 
00272     typedStream.Close();
00273     }
00274 
00275   if ( !Study1 )
00276     {
00277     StdErr << "ERROR: reference image path resolved to NULL.\n";
00278     throw cmtk::ExitException( 1 );
00279     }
00280   
00281   if ( !Study2 )
00282     {
00283     StdErr << "ERROR: floating image path resolved to NULL.\n";
00284     throw cmtk::ExitException( 1 );
00285     }
00286   
00287   UniformVolume::SmartPtr volume( VolumeIO::ReadOriented( Study1, Verbose ) );
00288   if ( !volume )
00289     {
00290     StdErr << "ERROR: volume " << this->Study1 << " could not be read\n";
00291     throw cmtk::ExitException( 1 );
00292     }
00293   this->SetVolume_1( UniformVolume::SmartPtr( this->m_PreprocessorRef.GetProcessedImage( volume ) ) );
00294 
00295   volume = UniformVolume::SmartPtr( VolumeIO::ReadOriented( Study2, Verbose ) );
00296   if ( !volume )
00297     {
00298     StdErr << "ERROR: volume " << this->Study2 << " could not be read\n";
00299     throw cmtk::ExitException( 1 );
00300     }
00301   this->SetVolume_2(  UniformVolume::SmartPtr( this->m_PreprocessorFlt.GetProcessedImage( volume ) ) );
00302 
00303   if ( InitialStudylist ) 
00304     {
00305     Xform::SmartPtr xform( XformIO::Read( InitialStudylist, Verbose ) );
00306     if ( ! xform ) 
00307       {
00308       StdErr << "ERROR: could not read transformation from " << InitialStudylist << "\n";
00309       throw cmtk::ExitException( 1 );
00310       }
00311     
00312     AffineXform::SmartPtr affine( AffineXform::SmartPtr::DynamicCastFrom( xform ) );
00313     if ( ! affine )
00314       {
00315       StdErr << "ERROR: transformation " << InitialStudylist << " is not affine.\n";
00316       throw cmtk::ExitException( 1 );
00317       }
00318 
00319     if ( affine->m_MetaInformation[META_SPACE] != AnatomicalOrientation::ORIENTATION_STANDARD )
00320       {
00321       TransformChangeFromSpaceAffine toStandardSpace( *affine, *(this->m_Volume_1), *(this->m_Volume_2) );
00322       *affine = toStandardSpace.GetTransformation();
00323       affine->m_MetaInformation[META_SPACE] = AnatomicalOrientation::ORIENTATION_STANDARD;
00324       }
00325     
00326     this->SetInitialTransformation( affine );
00327     }
00328   
00329   if ( this->m_Initializer != MakeInitialAffineTransformation::NONE ) 
00330     {
00331     if ( inStudylist || InitialStudylist ) 
00332       {
00333       StdErr << "INFO: initial transformation was provided. Selected transformation initializer will be ignored.\n";
00334       } 
00335     }
00336   
00337   if ( this->m_ProtocolFileName ) 
00338     {
00339     RegistrationCallback::SmartPtr callback( new ProtocolCallback( this->m_ProtocolFileName ) );
00340     this->SetCallback( callback );
00341     }
00342 
00343   if ( forceOutsideFlag )
00344     {
00345     this->SetForceOutside( true, forceOutsideValue );
00346     }
00347 }
00348 
00349 CallbackResult
00350 ImagePairAffineRegistrationCommandLine::InitRegistration ()
00351 {
00352   CallbackResult Result = Superclass::InitRegistration();
00353   return Result;
00354 }
00355         
00356 void
00357 ImagePairAffineRegistrationCommandLine::OutputResultMatrix( const char* matrixName ) const
00358 {
00359   Types::Coordinate matrix[4][4];
00360   this->GetTransformation()->GetMatrix( matrix );
00361 
00362   FILE* mfile = fopen( matrixName, "w" );
00363   if ( mfile )
00364     {
00365     for ( int i = 0; i < 4; ++i )
00366       {
00367       fprintf( mfile, "%e\t%e\t%e\t%e\n", matrix[0][i], matrix[1][i], matrix[2][i], matrix[3][i] );
00368       }
00369     fclose( mfile );
00370     }
00371 }
00372 
00373 void
00374 ImagePairAffineRegistrationCommandLine::OutputResultParameters
00375 ( const char* paramsName, const CoordinateVector& v ) const
00376 {
00377   FILE* pfile = fopen( paramsName, "w" );
00378   if ( pfile )
00379     {
00380     for ( unsigned int idx=0; idx < v.Dim; ++idx )
00381       fprintf( pfile, "#%d: %f\n", idx, v.Elements[idx] );
00382     fclose( pfile );
00383     }
00384 }
00385 
00386 void
00387 ImagePairAffineRegistrationCommandLine::OutputResultList( const char* studyList ) const
00388 {
00389   ClassStream classStream( studyList, "studylist", ClassStream::WRITE );
00390   if ( !classStream.IsValid() ) return;
00391   
00392   classStream.Begin( "studylist" );
00393   classStream.WriteInt( "num_sources", 2 );
00394   classStream.End();
00395     
00396   classStream.Begin( "source" );
00397   classStream.WriteString( "studyname", CompressedStream::GetBaseName( Study1 ) );
00398   classStream.End();
00399     
00400   classStream.Begin( "source" );
00401   classStream.WriteString( "studyname", CompressedStream::GetBaseName( Study2 ) );
00402   classStream.End();
00403     
00404   classStream.Close();
00405     
00406   classStream.Open( studyList, "registration", ClassStream::WRITE );
00407     
00408   classStream.Begin( "registration" );
00409   classStream.WriteString( "reference_study", CompressedStream::GetBaseName( Study1 ) );
00410   classStream.WriteString( "floating_study", CompressedStream::GetBaseName( Study2 ) );
00411     
00412   classStream << *(this->GetTransformation());
00413     
00414   classStream.End();
00415   classStream.Close();
00416     
00417   classStream.Open( studyList, "settings", ClassStream::WRITE );
00418   classStream.WriteDouble( "exploration", this->m_MaxStepSize );
00419   classStream.WriteDouble( "accuracy", this->m_MinStepSize );
00420   classStream.WriteDouble( "min_sampling", this->m_Sampling );
00421   classStream.WriteDouble( "coarsest_resolution", this->m_CoarsestResolution );
00422   classStream.WriteInt( "metric", this->m_Metric );
00423   classStream.WriteDouble( "optimizer_step_factor", this->m_OptimizerStepFactor );
00424   classStream.WriteString( "initializer", MakeInitialAffineTransformation::GetModeName( this->m_Initializer ) );
00425 
00426   this->m_PreprocessorRef.WriteSettings( classStream );  
00427   this->m_PreprocessorFlt.WriteSettings( classStream );  
00428 
00429   classStream.Close();
00430     
00431   classStream.Open( studyList, "statistics", ClassStream::WRITE );
00432   classStream.WriteDouble( "time", this->GetTotalElapsedTime() );
00433   classStream.WriteDouble( "walltime", this->GetTotalElapsedWalltime() );
00434 #ifdef CMTK_USE_THREADS
00435   classStream.WriteDouble( "thread_time", this->GetThreadTotalElapsedTime() );
00436 #endif
00437     
00438 #ifndef _MSC_VER
00439   struct utsname name;
00440   if ( uname( &name ) >= 0 ) 
00441     {
00442     classStream.WriteString( "host", name.nodename );
00443     classStream.WriteString( "system", name.sysname );
00444     }
00445 #endif
00446   classStream.Close();
00447 }
00448 
00449 void
00450 ImagePairAffineRegistrationCommandLine::OutputResult ( const CoordinateVector* v )
00451 {
00452   if ( Verbose ) 
00453     {
00454     fprintf( stderr, "\rResulting transformation parameters: \n" );
00455     for ( unsigned int idx=0; idx<v->Dim; ++idx )
00456       fprintf( stderr, "#%d: %f\n", idx, v->Elements[idx] );
00457     }
00458   
00459   if ( this->OutMatrixName )
00460     {
00461     this->OutputResultMatrix( this->OutMatrixName );
00462     }
00463 
00464   if ( this->OutParametersName )
00465     {
00466     this->OutputResultParameters( this->OutParametersName, *v );
00467     }
00468 
00469   if ( this->Studylist ) 
00470     {
00471     this->OutputResultList( this->Studylist );
00472     }
00473 
00474   if ( this->m_OutputPathITK ) 
00475     {
00476     TransformChangeToSpaceAffine toNative( *(this->GetTransformation()), *(this->m_Volume_1), *(this->m_Volume_2), AnatomicalOrientationBase::SPACE_ITK );
00477     AffineXformITKIO::Write( this->m_OutputPathITK, toNative.GetTransformation() );
00478     }
00479 
00480   if ( this->m_ReformattedImagePath )
00481     {
00482     VolumeIO::Write( *(this->GetReformattedFloatingImage()), this->m_ReformattedImagePath, this->Verbose );
00483     }
00484 
00485 #ifdef CMTK_USE_SQLITE
00486   if ( this->m_UpdateDB )
00487     {
00488     try
00489       {
00490       cmtk::ImageXformDB db( this->m_UpdateDB );
00491       
00492       if ( this->m_ReformattedImagePath )
00493         {
00494         db.AddImage( this->m_ReformattedImagePath, this->m_ReferenceVolume->GetMetaInfo( META_FS_PATH ) );
00495         }
00496       
00497       if ( this->Studylist )
00498         {
00499         if ( this->m_InitialXformPath ) 
00500           {
00501           db.AddRefinedXform( this->Studylist, true /*invertible*/, this->m_InitialXformPath, this->m_InitialXformIsInverse );
00502           }
00503         else
00504           {
00505           db.AddImagePairXform( this->Studylist, true /*invertible*/, this->m_ReferenceVolume->GetMetaInfo( META_FS_PATH ), this->m_FloatingVolume->GetMetaInfo( META_FS_PATH ) );
00506           }
00507         }
00508       }
00509     catch ( const cmtk::ImageXformDB::Exception& ex )
00510       {
00511       StdErr << "DB ERROR: " << ex.what() << " on database " << this->m_UpdateDB << "\n";
00512       }
00513     }
00514 #endif
00515 }
00516 
00517 void
00518 ImagePairAffineRegistrationCommandLine::EnterResolution
00519 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f,
00520   const int index, const int total )
00521 {
00522   if ( Verbose )
00523     fprintf( stderr, "\rEntering resolution level %d out of %d...\n", index, total );
00524   this->Superclass::EnterResolution( v, f, index, total );
00525 }
00526 
00527 CallbackResult
00528 ImagePairAffineRegistrationCommandLine::Register ()
00529 {
00530   const double baselineTime = Timers::GetTimeProcess();
00531   CallbackResult Result = Superclass::Register();
00532   const int elapsed = static_cast<int>( Timers::GetTimeProcess() - baselineTime );
00533 
00534   if ( Time ) 
00535     {
00536     FILE *tfp = fopen( Time, "w" );
00537     
00538     if ( tfp ) 
00539       {
00540       fprintf( tfp, "%d\n", elapsed );
00541       fclose( tfp );
00542       } 
00543     else 
00544       {
00545       std::cerr << "Could not open time file " << Time << "\n";
00546       }
00547     }
00548   return Result;
00549 }
00550 
00551 } // namespace cmtk
00552 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines