00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef __itkDiffusionQballReconstructionImageFilter_txx
00017 #define __itkDiffusionQballReconstructionImageFilter_txx
00018
00019 #include "itkDiffusionQballReconstructionImageFilter.h"
00020 #include "itkImageRegionConstIterator.h"
00021 #include "itkImageRegionConstIteratorWithIndex.h"
00022 #include "itkImageRegionIterator.h"
00023 #include "itkArray.h"
00024 #include "vnl/vnl_vector.h"
00025 #include "itkPointShell.h"
00026
00027 namespace itk {
00028
00029 #define QBALL_RECON_PI 3.14159265358979323846
00030
00031 template< class TReferenceImagePixelType,
00032 class TGradientImagePixelType,
00033 class TOdfPixelType,
00034 int NrOdfDirections,
00035 int NrBasisFunctionCenters>
00036 DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00037 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00038 NrBasisFunctionCenters>
00039 ::DiffusionQballReconstructionImageFilter() :
00040 m_GradientDirectionContainer(NULL),
00041 m_NumberOfGradientDirections(0),
00042 m_NumberOfEquatorSamplingPoints(0),
00043 m_NumberOfBaselineImages(1),
00044 m_Threshold(NumericTraits< ReferencePixelType >::NonpositiveMin()),
00045 m_BValue(1.0),
00046 m_GradientImageTypeEnumeration(Else),
00047 m_DirectionsDuplicated(false)
00048 {
00049
00050
00051 this->SetNumberOfRequiredInputs( 1 );
00052 }
00053
00054 template< class TReferenceImagePixelType,
00055 class TGradientImagePixelType,
00056 class TOdfPixelType,
00057 int NrOdfDirections,
00058 int NrBasisFunctionCenters>
00059 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00060 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00061 NrBasisFunctionCenters>
00062 ::BeforeThreadedGenerateData()
00063 {
00064
00065
00066
00067 const unsigned int numberOfInputs = this->GetNumberOfInputs();
00068
00069
00070
00071 if( m_NumberOfGradientDirections < 6 )
00072 {
00073 itkExceptionMacro( << "At least 6 gradient directions are required" );
00074 }
00075
00076
00077
00078 if ( numberOfInputs == 1
00079 && m_GradientImageTypeEnumeration != GradientIsInASingleImage )
00080 {
00081 std::string gradientImageClassName(
00082 this->ProcessObject::GetInput(0)->GetNameOfClass());
00083 if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 )
00084 {
00085 itkExceptionMacro( <<
00086 "There is only one Gradient image. I expect that to be a VectorImage. "
00087 << "But its of type: " << gradientImageClassName );
00088 }
00089 }
00090
00091
00092
00093 this->ComputeReconstructionMatrix();
00094
00095
00096 m_BZeroImage = BZeroImageType::New();
00097 if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
00098 {
00099 typename ReferenceImageType::Pointer img = static_cast< ReferenceImageType * >(this->ProcessObject::GetInput(0));
00100 m_BZeroImage->SetSpacing( img->GetSpacing() );
00101 m_BZeroImage->SetOrigin( img->GetOrigin() );
00102 m_BZeroImage->SetDirection( img->GetDirection() );
00103 m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
00104 m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
00105 }
00106
00107 else if( m_GradientImageTypeEnumeration == GradientIsInASingleImage )
00108 {
00109 typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >(
00110 this->ProcessObject::GetInput(0) );
00111 m_BZeroImage->SetSpacing( img->GetSpacing() );
00112 m_BZeroImage->SetOrigin( img->GetOrigin() );
00113 m_BZeroImage->SetDirection( img->GetDirection() );
00114 m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
00115 m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
00116 }
00117
00118 m_BZeroImage->Allocate();
00119
00120 }
00121
00122 template< class TReferenceImagePixelType,
00123 class TGradientImagePixelType,
00124 class TOdfPixelType,
00125 int NrOdfDirections,
00126 int NrBasisFunctionCenters>
00127 typename itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::OdfPixelType
00128 itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::Normalize( OdfPixelType odf, typename NumericTraits<ReferencePixelType>::AccumulateType b0 )
00129 {
00130 switch( m_NormalizationMethod )
00131 {
00132
00133
00134 case QBR_STANDARD:
00135 {
00136 odf.Normalize();
00137 return odf;
00138 break;
00139 }
00140
00141 case QBR_B_ZERO_B_VALUE:
00142 {
00143 for(int i=0; i<NrOdfDirections; i++)
00144 {
00145 odf[i] = ((TOdfPixelType)log((TOdfPixelType)b0)-odf[i])/m_BValue;
00146 }
00147 return odf;
00148 break;
00149 }
00150
00151 case QBR_B_ZERO:
00152 {
00153 odf *= 1.0/b0;
00154 return odf;
00155 break;
00156 }
00157
00158 case QBR_NONE:
00159 {
00160 return odf;
00161 break;
00162 }
00163 }
00164
00165 return odf;
00166 }
00167
00168
00169 template< class TReferenceImagePixelType,
00170 class TGradientImagePixelType,
00171 class TOdfPixelType,
00172 int NrOdfDirections,
00173 int NrBasisFunctionCenters >
00174 vnl_vector<TOdfPixelType> itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::PreNormalize( vnl_vector<TOdfPixelType> vec )
00175 {
00176 switch( m_NormalizationMethod )
00177 {
00178
00179 case QBR_STANDARD:
00180 {
00181 return vec;
00182 break;
00183 }
00184
00185 case QBR_B_ZERO_B_VALUE:
00186 {
00187 int n = vec.size();
00188 for(int i=0; i<n; i++)
00189 {
00190 vec[i] = log(vec[i]);
00191 }
00192 return vec;
00193 break;
00194 }
00195
00196 case QBR_B_ZERO:
00197 {
00198 return vec;
00199 break;
00200 }
00201
00202 case QBR_NONE:
00203 {
00204 return vec;
00205 break;
00206 }
00207 }
00208
00209 return vec;
00210 }
00211
00212 template< class TReferenceImagePixelType,
00213 class TGradientImagePixelType,
00214 class TOdfPixelType,
00215 int NrOdfDirections,
00216 int NrBasisFunctionCenters>
00217 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00218 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00219 NrBasisFunctionCenters>
00220 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
00221 int )
00222 {
00223
00224 typename OutputImageType::Pointer outputImage =
00225 static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
00226 ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
00227 oit.GoToBegin();
00228 ImageRegionIterator< BZeroImageType > oit2(m_BZeroImage, outputRegionForThread);
00229 oit2.GoToBegin();
00230 vnl_vector<TOdfPixelType> B(m_NumberOfGradientDirections);
00231
00232
00233
00234
00235
00236
00237
00238 if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
00239 {
00240
00241 ImageRegionConstIterator< ReferenceImageType >
00242 it(static_cast< ReferenceImageType * >(this->ProcessObject::GetInput(0)),
00243 outputRegionForThread);
00244 it.GoToBegin();
00245
00246
00247 typedef ImageRegionConstIterator< GradientImageType > GradientIteratorType;
00248 std::vector< GradientIteratorType * > gradientItContainer;
00249 for( unsigned int i = 1; i<= m_NumberOfGradientDirections; i++ )
00250 {
00251
00252 int index = i;
00253 if(m_DirectionsDuplicated)
00254 index = i % (m_NumberOfGradientDirections/2);
00255
00256
00257 typename GradientImageType::Pointer gradientImagePointer = NULL;
00258
00259 gradientImagePointer = static_cast< GradientImageType * >(
00260 this->ProcessObject::GetInput(index) );
00261 GradientIteratorType *git = new GradientIteratorType(
00262 gradientImagePointer, outputRegionForThread );
00263 git->GoToBegin();
00264 gradientItContainer.push_back(git);
00265 }
00266
00267
00268
00269 while( !it.IsAtEnd() )
00270 {
00271
00272
00273 ReferencePixelType b0 = it.Get();
00274
00275
00276 OdfPixelType odf(0.0);
00277
00278
00279 if( (b0 != 0) && (b0 >= m_Threshold) )
00280 {
00281
00282
00283 for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
00284 {
00285 GradientPixelType b = gradientItContainer[i]->Get();
00286 B[i] = static_cast<TOdfPixelType>(b);
00287 ++(*gradientItContainer[i]);
00288 }
00289
00290
00291 B = PreNormalize(B);
00292
00293
00294 odf = ( (*m_ReconstructionMatrix) * B ).data_block();
00295
00296
00297 odf.Normalize();
00298
00299 }
00300 else
00301 {
00302
00303 for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
00304 {
00305 ++(*gradientItContainer[i]);
00306 }
00307 }
00308
00309
00310 oit.Set( odf );
00311 ++oit;
00312 oit2.Set( b0 );
00313 ++oit2;
00314 ++it;
00315 }
00316
00317
00318 for( unsigned int i = 0; i< gradientItContainer.size(); i++ )
00319 {
00320 delete gradientItContainer[i];
00321 }
00322 }
00323
00324 else if( m_GradientImageTypeEnumeration == GradientIsInASingleImage )
00325 {
00326
00327
00328 typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType;
00329 typedef typename GradientImagesType::PixelType GradientVectorType;
00330 typename GradientImagesType::Pointer gradientImagePointer = NULL;
00331
00332 gradientImagePointer = static_cast< GradientImagesType * >(
00333 this->ProcessObject::GetInput(0) );
00334 GradientIteratorType git(gradientImagePointer, outputRegionForThread );
00335 git.GoToBegin();
00336
00337
00338 std::vector<unsigned int> baselineind;
00339 std::vector<unsigned int> gradientind;
00340 for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
00341 gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
00342 {
00343 if(gdcit.Value().one_norm() <= 0.0)
00344 {
00345 baselineind.push_back(gdcit.Index());
00346 }
00347 else
00348 {
00349 gradientind.push_back(gdcit.Index());
00350 }
00351 }
00352
00353
00354 if( m_DirectionsDuplicated )
00355 {
00356 int gradIndSize = gradientind.size();
00357 for(int i=0; i<gradIndSize; i++)
00358 gradientind.push_back(gradientind[i]);
00359 }
00360
00361
00362
00363 while( !git.IsAtEnd() )
00364 {
00365
00366 GradientVectorType b = git.Get();
00367
00368
00369 typename NumericTraits<ReferencePixelType>::AccumulateType b0 = NumericTraits<ReferencePixelType>::Zero;
00370 for(unsigned int i = 0; i < baselineind.size(); ++i)
00371 {
00372 b0 += b[baselineind[i]];
00373 }
00374 b0 /= this->m_NumberOfBaselineImages;
00375
00376
00377 OdfPixelType odf(0.0);
00378
00379
00380 if( (b0 != 0) && (b0 >= m_Threshold) )
00381 {
00382 for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
00383 {
00384 B[i] = static_cast<TOdfPixelType>(b[gradientind[i]]);
00385 }
00386
00387
00388 B = PreNormalize(B);
00389
00390
00391 odf = ( (*m_ReconstructionMatrix) * B ).data_block();
00392
00393
00394 odf = Normalize(odf, b0);
00395
00396 }
00397
00398
00399 oit.Set( odf );
00400 ++oit;
00401 oit2.Set( b0 );
00402 ++oit2;
00403 ++git;
00404 }
00405 }
00406
00407 std::cout << "One Thread finished reconstruction" << std::endl;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 template< class TReferenceImagePixelType,
00430 class TGradientImagePixelType,
00431 class TOdfPixelType,
00432 int NrOdfDirections,
00433 int NrBasisFunctionCenters>
00434 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00435 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00436 NrBasisFunctionCenters>
00437 ::ComputeReconstructionMatrix()
00438 {
00439
00440 if( m_NumberOfGradientDirections < 6 )
00441 {
00442 itkExceptionMacro( << "Not enough gradient directions supplied. Need to supply at least 6" );
00443 }
00444
00445 {
00446
00447 bool warning = false;
00448 for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
00449 gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
00450 {
00451 for(GradientDirectionContainerType::ConstIterator gdcit2 = this->m_GradientDirectionContainer->Begin();
00452 gdcit2 != this->m_GradientDirectionContainer->End(); ++gdcit2)
00453 {
00454 if(gdcit1.Value() == gdcit2.Value() && gdcit1.Index() != gdcit2.Index())
00455 {
00456 itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." );
00457 warning = true;
00458 break;
00459 }
00460 }
00461 if (warning) break;
00462 }
00463
00464
00465
00466
00467 vnl_vector<double> centerMass(3);
00468 centerMass.fill(0.0);
00469 int count = 0;
00470 for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
00471 gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
00472 {
00473 if(gdcit1.Value().one_norm() > 0.0)
00474 {
00475 centerMass += gdcit1.Value();
00476 count ++;
00477 }
00478 }
00479 centerMass /= count;
00480 if(centerMass.two_norm() > 0.1)
00481 {
00482 m_DirectionsDuplicated = true;
00483 m_NumberOfGradientDirections *= 2;
00484 }
00485 }
00486
00487
00488 if(!this->m_NumberOfEquatorSamplingPoints)
00489 this->m_NumberOfEquatorSamplingPoints
00490 = (int) ceil((double)sqrt(8*QBALL_RECON_PI*this->m_NumberOfGradientDirections));
00491
00492 vnl_matrix<double>* Q =
00493 new vnl_matrix<double>(3, m_NumberOfGradientDirections);
00494
00495 {
00496
00497 int i = 0;
00498 for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
00499 gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
00500 {
00501 if(gdcit.Value().one_norm() > 0.0)
00502 {
00503 (*Q)(0,i) = gdcit.Value().get(0);
00504 (*Q)(1,i) = gdcit.Value().get(1);
00505 (*Q)(2,i++) = gdcit.Value().get(2);
00506 }
00507 }
00508 if(m_DirectionsDuplicated)
00509 {
00510 for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
00511 gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
00512 {
00513 if(gdcit.Value().one_norm() > 0.0)
00514 {
00515 (*Q)(0,i) = -gdcit.Value().get(0);
00516 (*Q)(1,i) = -gdcit.Value().get(1);
00517 (*Q)(2,i++) = -gdcit.Value().get(2);
00518 }
00519 }
00520 }
00521
00522 }
00523
00524 vnl_matrix_fixed<double, 3, NOdfDirections>* U =
00525 itk::PointShell<NOdfDirections, vnl_matrix_fixed<double, 3, NOdfDirections> >::DistributePointShell();
00526
00527 vnl_matrix_fixed<double, 3, NBasisFunctionCenters>* V =
00528 itk::PointShell<NBasisFunctionCenters, vnl_matrix_fixed<double, 3, NBasisFunctionCenters> >::DistributePointShell();
00529
00530
00531 vnl_matrix<double> *C
00532 = new vnl_matrix<double>(3, m_NumberOfEquatorSamplingPoints);
00533 for(unsigned int i=0; i<m_NumberOfEquatorSamplingPoints; i++)
00534 {
00535 double theta = i * (2*QBALL_RECON_PI / m_NumberOfEquatorSamplingPoints);
00536 (*C)(0,i) = cos(theta);
00537 (*C)(1,i) = sin(theta);
00538 (*C)(2,i) = NumericTraits<double>::Zero;
00539 }
00540
00541
00542 vnl_matrix<double> *S
00543 = new vnl_matrix<double>(3,m_NumberOfEquatorSamplingPoints*NOdfDirections);
00544
00545 {
00546 vnl_vector_fixed<double,3> z(NumericTraits<double>::Zero);
00547 z.put(2,NumericTraits<double>::One);
00548 vnl_matrix_fixed<double,3,3> eye(NumericTraits<double>::Zero);
00549 eye.fill_diagonal(NumericTraits<double>::One);
00550 for(int i=0; i<NOdfDirections; i++)
00551 {
00552 vnl_vector_fixed<double,3> ui = (*U).get_column(i);
00553 vnl_matrix<double> *RC
00554 = new vnl_matrix<double>(3,m_NumberOfEquatorSamplingPoints);
00555
00556 if( (z(0)*ui(0)+z(1)*ui(1)+z(2)*ui(2)+1) != 0 )
00557 {
00558 vnl_matrix_fixed<double,3,3> R;
00559 R.set_column(0, (z+ui)*(z(0)+ui(0)));
00560 R.set_column(1, (z+ui)*(z(1)+ui(1)));
00561 R.set_column(2, (z+ui)*(z(2)+ui(2)));
00562 R /= (z(0)*ui(0)+z(1)*ui(1)+z(2)*ui(2)+1);
00563 R -= eye;
00564 (*RC) = R*(*C);
00565 }
00566 else
00567 {
00568 RC = C;
00569 }
00570 (*S).set_columns(i*m_NumberOfEquatorSamplingPoints, *RC);
00571 }
00572 }
00573
00574
00575
00576 vnl_matrix<double> *H_plus
00577 = new vnl_matrix<double>(NBasisFunctionCenters,m_NumberOfGradientDirections);
00578
00579 double maxSigma = QBALL_RECON_PI/6;
00580 double bestSigma = maxSigma;
00581
00582 {
00583 double stepsize = 0.01;
00584 double start = 0.01;
00585 double minCondition = NumericTraits<double>::max();
00586
00587 vnl_matrix<double> *H
00588 = new vnl_matrix<double>(m_NumberOfGradientDirections,NBasisFunctionCenters,(double)0);
00589
00590 {
00591
00592 int increasing = 0;
00593 for( double sigma=start; sigma<maxSigma; sigma+=stepsize)
00594 {
00595 vnl_matrix<double> *tmpH
00596 = new vnl_matrix<double>(m_NumberOfGradientDirections,NBasisFunctionCenters);
00597
00598 for(unsigned int r=0; r<m_NumberOfGradientDirections; r++)
00599 {
00600 for(int c=0; c<NBasisFunctionCenters; c++)
00601 {
00602 double qtv = (*Q)(0,r)*(*V)(0,c)
00603 + (*Q)(1,r)*(*V)(1,c)
00604 + (*Q)(2,r)*(*V)(2,c);
00605 qtv = (qtv<-1.0) ? -1.0 : ( (qtv>1.0) ? 1.0 : qtv);
00606 double x = acos(qtv);
00607 (*tmpH)(r,c) = (1.0/(sigma*sqrt(2.0*QBALL_RECON_PI)))
00608 *exp((-x*x)/(2*sigma*sigma));
00609 }
00610 }
00611
00612 vnl_svd<double> *solver;
00613 if(m_NumberOfGradientDirections>NBasisFunctionCenters)
00614 {
00615 solver = new vnl_svd<double>(*tmpH);
00616 }
00617 else
00618 {
00619 solver = new vnl_svd<double>(tmpH->transpose());
00620 }
00621 double condition = solver->sigma_max() / solver->sigma_min();
00622
00623 std::cout << sigma << ": " << condition << std::endl;
00624
00625 if( condition < minCondition )
00626 {
00627 minCondition = condition;
00628 bestSigma = sigma;
00629 H->update(*tmpH);
00630 }
00631 else
00632 {
00633
00634 if (++increasing>3) break;
00635 }
00636 }
00637 }
00638
00639
00640 vnl_matrix_inverse<double> *pseudoInverse
00641 = new vnl_matrix_inverse<double>(*H);
00642 (*H_plus) = pseudoInverse->pinverse();
00643
00644 std::cout << "choosing sigma = " << bestSigma << std::endl;
00645
00646 }
00647
00648
00649
00650 vnl_matrix<double> *G
00651 = new vnl_matrix<double>(m_NumberOfEquatorSamplingPoints*NOdfDirections,NBasisFunctionCenters);
00652
00653 {
00654 for(unsigned int r=0; r<m_NumberOfEquatorSamplingPoints*NOdfDirections; r++)
00655 {
00656 for(int c=0; c<NBasisFunctionCenters; c++)
00657 {
00658 double stv = (*S)(0,r)*(*V)(0,c)
00659 + (*S)(1,r)*(*V)(1,c)
00660 + (*S)(2,r)*(*V)(2,c);
00661 stv = (stv<-1.0) ? -1.0 : ( (stv>1.0) ? 1.0 : stv);
00662 double x = acos(stv);
00663 (*G)(r,c) = (1.0/(bestSigma*sqrt(2.0*QBALL_RECON_PI)))
00664 *exp((-x*x)/(2*bestSigma*bestSigma));
00665 }
00666 }
00667 }
00668
00669 vnl_matrix<double> *GH_plus =
00670 new vnl_matrix<double>(m_NumberOfEquatorSamplingPoints*NOdfDirections,m_NumberOfGradientDirections);
00671
00672
00673 for (unsigned i = 0; i < m_NumberOfEquatorSamplingPoints*NOdfDirections; ++i)
00674 for (unsigned j = 0; j < m_NumberOfGradientDirections; ++j)
00675 {
00676 double accum = (*G)(i,0) * (*H_plus)(0,j);
00677 for (unsigned k = 1; k < NOdfDirections; ++k)
00678 accum += (*G)(i,k) * (*H_plus)(k,j);
00679 (*GH_plus)(i,j) = accum;
00680 }
00681
00682 typename vnl_matrix<double>::iterator it3;
00683 for( it3 = (*GH_plus).begin(); it3 != (*GH_plus).end(); it3++)
00684 {
00685 if(*it3<0.0)
00686 *it3 = 0;
00687 }
00688
00689
00690 for(unsigned int i=0; i<NOdfDirections*m_NumberOfEquatorSamplingPoints; i++)
00691 {
00692 vnl_vector< double > r = GH_plus->get_row(i);
00693 r /= r.sum();
00694 GH_plus->set_row(i,r);
00695 }
00696
00697
00698
00699
00700
00701 m_ReconstructionMatrix
00702 = new vnl_matrix<TOdfPixelType>(NOdfDirections,m_NumberOfGradientDirections,0.0);
00703 for(int i=0; i<NOdfDirections; i++)
00704 {
00705 for(unsigned int j=0; j<m_NumberOfGradientDirections; j++)
00706 {
00707 for(unsigned int k=0; k<m_NumberOfEquatorSamplingPoints; k++)
00708 {
00709 (*m_ReconstructionMatrix)(i,j) += (TOdfPixelType)(*GH_plus)(m_NumberOfEquatorSamplingPoints*i+k,j);
00710 }
00711 }
00712 }
00713
00714
00715 for(int i=0; i<NOdfDirections; i++)
00716 {
00717 vnl_vector< TOdfPixelType > r = m_ReconstructionMatrix->get_row(i);
00718 r /= r.sum();
00719 m_ReconstructionMatrix->set_row(i,r);
00720 }
00721 std::cout << "Reconstruction Matrix computed." << std::endl;
00722
00723 }
00724
00725 template< class TReferenceImagePixelType,
00726 class TGradientImagePixelType,
00727 class TOdfPixelType,
00728 int NrOdfDirections,
00729 int NrBasisFunctionCenters>
00730 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00731 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00732 NrBasisFunctionCenters>
00733 ::AddGradientImage( const GradientDirectionType &gradientDirection,
00734 const GradientImageType *gradientImage )
00735 {
00736
00737
00738 if( m_GradientImageTypeEnumeration == GradientIsInASingleImage)
00739 {
00740 itkExceptionMacro( << "Cannot call both methods:"
00741 << "AddGradientImage and SetGradientImage. Please call only one of them.");
00742 }
00743
00744
00745
00746 if( !this->m_GradientDirectionContainer )
00747 {
00748 this->m_GradientDirectionContainer = GradientDirectionContainerType::New();
00749 }
00750
00751 this->m_NumberOfGradientDirections = m_GradientDirectionContainer->Size();
00752
00753 m_GradientDirectionContainer->InsertElement( this->m_NumberOfGradientDirections,
00754 gradientDirection / gradientDirection.two_norm() );
00755
00756 this->ProcessObject::SetNthInput( this->m_NumberOfGradientDirections,
00757 const_cast< GradientImageType* >(gradientImage) );
00758
00759 m_GradientImageTypeEnumeration = GradientIsInManyImages;
00760 }
00761
00762 template< class TReferenceImagePixelType,
00763 class TGradientImagePixelType,
00764 class TOdfPixelType,
00765 int NrOdfDirections,
00766 int NrBasisFunctionCenters>
00767 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00768 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00769 NrBasisFunctionCenters>
00770 ::SetGradientImage( GradientDirectionContainerType *gradientDirection,
00771 const GradientImagesType *gradientImage )
00772 {
00773
00774
00775 if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
00776 {
00777 itkExceptionMacro( << "Cannot call both methods:"
00778 << "AddGradientImage and SetGradientImage. Please call only one of them.");
00779 }
00780
00781 this->m_GradientDirectionContainer = gradientDirection;
00782
00783 unsigned int numImages = gradientDirection->Size();
00784 this->m_NumberOfBaselineImages = 0;
00785 for(GradientDirectionContainerType::Iterator it = this->m_GradientDirectionContainer->Begin();
00786 it != this->m_GradientDirectionContainer->End(); it++)
00787 {
00788 if(it.Value().one_norm() <= 0.0)
00789 {
00790 this->m_NumberOfBaselineImages++;
00791 }
00792 else
00793 {
00794 it.Value() = it.Value() / it.Value().two_norm();
00795 }
00796 }
00797
00798 this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages;
00799
00800
00801
00802 if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections )
00803 {
00804 itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages
00805 << "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages
00806 << " directions specified but image has " << gradientImage->GetVectorLength()
00807 << " components.");
00808 }
00809
00810 this->ProcessObject::SetNthInput( 0,
00811 const_cast< GradientImagesType* >(gradientImage) );
00812 m_GradientImageTypeEnumeration = GradientIsInASingleImage;
00813 }
00814
00815
00816 template< class TReferenceImagePixelType,
00817 class TGradientImagePixelType,
00818 class TOdfPixelType,
00819 int NrOdfDirections,
00820 int NrBasisFunctionCenters>
00821 void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
00822 TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
00823 NrBasisFunctionCenters>
00824 ::PrintSelf(std::ostream& os, Indent indent) const
00825 {
00826 Superclass::PrintSelf(os,indent);
00827
00828 os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl;
00829 if ( m_GradientDirectionContainer )
00830 {
00831 os << indent << "GradientDirectionContainer: "
00832 << m_GradientDirectionContainer << std::endl;
00833 }
00834 else
00835 {
00836 os << indent <<
00837 "GradientDirectionContainer: (Gradient directions not set)" << std::endl;
00838 }
00839 os << indent << "NumberOfGradientDirections: " <<
00840 m_NumberOfGradientDirections << std::endl;
00841 os << indent << "NumberOfBaselineImages: " <<
00842 m_NumberOfBaselineImages << std::endl;
00843 os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl;
00844 os << indent << "BValue: " << m_BValue << std::endl;
00845 if ( this->m_GradientImageTypeEnumeration == GradientIsInManyImages )
00846 {
00847 os << indent << "Gradient images haven been supplied " << std::endl;
00848 }
00849 else if ( this->m_GradientImageTypeEnumeration == GradientIsInManyImages )
00850 {
00851 os << indent << "A multicomponent gradient image has been supplied" << std::endl;
00852 }
00853 }
00854
00855 }
00856
00857 #endif // __itkDiffusionQballReconstructionImageFilter_txx