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 "cmtkWarpXform.h"
00034
00035 #include <Base/cmtkMathUtil.h>
00036 #include <Base/cmtkUniformVolume.h>
00037
00038 #include <string.h>
00039 #include <algorithm>
00040
00041 namespace
00042 cmtk
00043 {
00044
00047
00048 void
00049 WarpXform::InitGrid
00050 ( const FixedVector<3,Types::Coordinate>& domain, const Self::IndexType& dims )
00051 {
00052 this->Domain = domain;
00053 this->m_Dims = dims;
00054 std::fill( this->m_Offset.begin(), this->m_Offset.end(), 0 );
00055
00056 NumberOfControlPoints = this->m_Dims[0] * this->m_Dims[1] * this->m_Dims[2];
00057 this->AllocateParameterVector( 3 * NumberOfControlPoints );
00058 this->Update();
00059 }
00060
00061 void
00062 WarpXform::Update( const bool )
00063 {
00064 nextI = 3;
00065 nextJ = nextI * this->m_Dims[0];
00066 nextK = nextJ * this->m_Dims[1];
00067 nextIJ = nextJ + nextI;
00068 nextIK = nextK + nextI;
00069 nextJK = nextK + nextJ;
00070 nextIJK = nextJK + nextI;
00071 }
00072
00073 void
00074 WarpXform::GetDerivativeLandmarksMSD
00075 ( double& lowerMSD, double& upperMSD, const MatchedLandmarkList* ll,
00076 const unsigned int idx, const Types::Coordinate step )
00077 {
00078 upperMSD = lowerMSD = 0;
00079
00080 Types::Coordinate pOld = this->m_Parameters[idx];
00081
00082 this->m_Parameters[idx] += step;
00083 MatchedLandmarkList::const_iterator it = ll->begin();
00084 while ( it != ll->end() )
00085 {
00086 Self::SpaceVectorType source( (*it)->GetLocation() );
00087 Self::SpaceVectorType target( (*it)->GetTargetLocation() );
00088 this->ApplyInPlace( source );
00089 upperMSD += (source - target).SumOfSquares();
00090 ++it;
00091 }
00092
00093 this->m_Parameters[idx] = pOld - step;
00094 it = ll->begin();
00095 while ( it != ll->end() )
00096 {
00097 Self::SpaceVectorType source( (*it)->GetLocation() );
00098 Self::SpaceVectorType target( (*it)->GetTargetLocation() );
00099 this->ApplyInPlace( source );
00100 lowerMSD += (source - target).SumOfSquares();
00101 ++it;
00102 }
00103 this->m_Parameters[idx] = pOld;
00104
00105 upperMSD /= ll->size();
00106 lowerMSD /= ll->size();
00107 }
00108
00109 Types::Coordinate
00110 WarpXform::GetInverseConsistencyError
00111 ( const Self* inverse, const UniformVolume* volume, const UniformVolume::RegionType* voi ) const
00112 {
00113 Self::SpaceVectorType v, vv;
00114 Types::Coordinate result = 0.0;
00115 int count = 0;
00116
00117 DataGrid::RegionType myVoi;
00118 const DataGrid::RegionType *pVoi = &myVoi;
00119 if ( voi )
00120 {
00121 pVoi = voi;
00122 }
00123 else
00124 {
00125 myVoi = volume->GetWholeImageRegion();
00126 }
00127
00128 for ( int z = pVoi->From()[2]; z < pVoi->To()[2]; ++z )
00129 for ( int y = pVoi->From()[1]; y < pVoi->To()[1]; ++y )
00130 for ( int x = pVoi->From()[0]; x < pVoi->To()[0]; ++x )
00131 {
00132 v = volume->GetGridLocation( x, y, z );
00133 vv = v;
00134 this->ApplyInPlace( vv );
00135 if ( inverse->InDomain( vv ) )
00136 {
00137 inverse->ApplyInPlace( vv );
00138 v -= vv;
00139 result += v.RootSumOfSquares();
00140 ++count;
00141 }
00142 }
00143
00144 return count ? result / count : 0.0;
00145 }
00146
00147 void
00148 WarpXform::GetDerivativeInverseConsistencyError
00149 ( double& lower, double& upper, const Self* inverse,
00150 const UniformVolume* volume, const UniformVolume::RegionType* voi,
00151 const unsigned int idx, const Types::Coordinate step )
00152 {
00153 const Types::Coordinate pOld = this->m_Parameters[idx];
00154 upper = lower = (-this->GetInverseConsistencyError( inverse, volume, voi ));
00155
00156 this->m_Parameters[idx] += step;
00157 upper += this->GetInverseConsistencyError( inverse, volume, voi );
00158
00159 this->m_Parameters[idx] = pOld - step;
00160 lower+= this->GetInverseConsistencyError( inverse, volume, voi );
00161
00162 this->m_Parameters[idx] = pOld;
00163 }
00164
00165 Types::Coordinate
00166 WarpXform::GetParamStep
00167 ( const size_t idx, const Self::SpaceVectorType&, const Types::Coordinate mmStep ) const
00168 {
00169 if ( this->m_ActiveFlags && ! (*this->m_ActiveFlags)[idx] ) return 0;
00170
00171 int controlPointIdx = idx / 3;
00172 unsigned short x = ( controlPointIdx % this->m_Dims[0] );
00173 unsigned short y = ( (controlPointIdx / this->m_Dims[0]) % this->m_Dims[1] );
00174 unsigned short z = ( (controlPointIdx / this->m_Dims[0]) / this->m_Dims[1] );
00175
00176 if ( (x>=this->m_IgnoreEdge) && (x<(this->m_Dims[0]-this->m_IgnoreEdge)) &&
00177 (y>=this->m_IgnoreEdge) && (y<(this->m_Dims[1]-this->m_IgnoreEdge)) &&
00178 (z>=this->m_IgnoreEdge) && (z<(this->m_Dims[2]-this->m_IgnoreEdge)) )
00179 {
00180 return mmStep;
00181 }
00182 else
00183 {
00184 return 0;
00185 }
00186 }
00187
00188 void
00189 WarpXform::SetParametersActive()
00190 {
00191 if ( !this->m_ActiveFlags )
00192 {
00193 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00194 }
00195 this->m_ActiveFlags->Set();
00196 }
00197
00198 void
00199 WarpXform::SetParameterActive
00200 ( const size_t index, const bool active )
00201 {
00202 if ( !this->m_ActiveFlags )
00203 {
00204 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00205 }
00206 this->m_ActiveFlags->Set( index, active );
00207 }
00208
00209 void
00210 WarpXform::SetParametersActive( const DataGrid::RegionType& )
00211 {
00212 if ( !this->m_ActiveFlags )
00213 {
00214 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00215 }
00216 }
00217
00218 void
00219 WarpXform::SetParametersActive
00220 ( const int axis, const bool active )
00221 {
00222 if ( !this->m_ActiveFlags )
00223 {
00224 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00225 }
00226 for ( unsigned int idx = (unsigned int)axis; idx < this->m_NumberOfParameters; idx += 3 )
00227 this->m_ActiveFlags->Set( idx, active );
00228 }
00229
00230 void
00231 WarpXform::SetParametersActive( const char* axes )
00232 {
00233 if ( !this->m_ActiveFlags )
00234 {
00235 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, false ) );
00236 }
00237 if ( axes )
00238 {
00239 if ( strchr( axes, 'x' ) || strchr( axes, 'X' ) )
00240 this->SetParametersActive( AXIS_X );
00241 if ( strchr( axes, 'y' ) || strchr( axes, 'Y' ) )
00242 this->SetParametersActive( AXIS_Y );
00243 if ( strchr( axes, 'z' ) || strchr( axes, 'Z' ) )
00244 this->SetParametersActive( AXIS_Z );
00245 }
00246 }
00247
00248 void
00249 WarpXform::SetParameterInactive( const size_t index )
00250 {
00251 if ( !this->m_ActiveFlags )
00252 {
00253 this->m_ActiveFlags = BitVector::SmartPtr( new BitVector( this->m_NumberOfParameters, true ) );
00254 }
00255 this->m_ActiveFlags->Reset( index );
00256 }
00257
00258 int
00259 WarpXform::GetParameterActive( const size_t index ) const
00260 {
00261 if ( this->m_ActiveFlags )
00262 return (*this->m_ActiveFlags)[index];
00263 else
00264 return 1;
00265 }
00266
00267 void
00268 WarpXform::DeleteParameterActiveFlags()
00269 {
00270 this->m_ActiveFlags = BitVector::SmartPtr::Null;
00271 }
00272
00273 void
00274 WarpXform::ReplaceInitialAffine( const AffineXform* newAffineXform )
00275 {
00276 AffineXform change;
00277
00278
00279 if ( this->m_InitialAffineXform )
00280 {
00281 change = *(this->m_InitialAffineXform->GetInverse());
00282 }
00283
00284
00285 if ( newAffineXform )
00286 change.Concat( *newAffineXform );
00287
00288
00289 Types::Coordinate *coeff = this->m_Parameters;
00290 for ( unsigned int idx = 0; idx < NumberOfControlPoints; ++idx, coeff+=3 )
00291 {
00292 Self::SpaceVectorType p( coeff );
00293 change.ApplyInPlace( p );
00294 coeff[0] = p[0];
00295 coeff[1] = p[1];
00296 coeff[2] = p[2];
00297 }
00298
00299
00300
00301 if ( newAffineXform )
00302 {
00303 this->m_InitialAffineXform = AffineXform::SmartPtr::DynamicCastFrom( newAffineXform->Clone() );
00304 }
00305 else
00306 {
00307 this->m_InitialAffineXform = AffineXform::SmartPtr( new AffineXform );
00308 }
00309 this->m_InitialAffineXform->m_MetaInformation[META_XFORM_FIXED_IMAGE_PATH] = this->m_MetaInformation[META_XFORM_FIXED_IMAGE_PATH];
00310 this->m_InitialAffineXform->m_MetaInformation[META_XFORM_MOVING_IMAGE_PATH] = this->m_MetaInformation[META_XFORM_MOVING_IMAGE_PATH];
00311 }
00312
00313 void
00314 WarpXform::ConcatAffine( const AffineXform* affineXform )
00315 {
00316
00317 Types::Coordinate *coeff = this->m_Parameters;
00318 for ( unsigned int idx = 0; idx < NumberOfControlPoints; ++idx, coeff+=3 )
00319 {
00320 Self::SpaceVectorType p( coeff );
00321 affineXform->ApplyInPlace( p );
00322 coeff[0] = p[0];
00323 coeff[1] = p[1];
00324 coeff[2] = p[2];
00325 }
00326
00327
00328
00329 if ( this->m_InitialAffineXform.GetReferenceCount() != 1 )
00330 this->m_InitialAffineXform = this->m_InitialAffineXform->Clone();
00331 this->m_InitialAffineXform->Concat( *affineXform );
00332 }
00333
00334 }