Orfeo Toolbox  3.16
itkFEMRegistrationFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkFEMRegistrationFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-04-01 22:17:59 $
7  Version: $Revision: 1.60 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkFEMRegistrationFilter_txx
18 #define __itkFEMRegistrationFilter_txx
19 
20 // disable debug warnings in MS compiler
21 #ifdef _MSC_VER
22 #pragma warning(disable: 4786)
23 #endif
24 
26 #include "itkFEMElements.h"
27 #include "itkFEMLoadBC.h"
28 
29 
30 #include "itkImageFileWriter.h"
31 #include "itkImageFileReader.h"
32 #include "itkCastImageFilter.h"
41 
42 #include "vnl/algo/vnl_determinant.h"
43 
44 namespace itk {
45 namespace fem {
46 
47 
48 template<class TMovingImage,class TFixedImage>
50 {
51 }
52 
53 
54 template<class TMovingImage,class TFixedImage>
56 {
57  m_FileCount=0;
58 
59  m_MinE=0;
60  m_MinE=vnl_huge_val(m_MinE);
61 
62  m_CurrentLevel=0;
63  m_DescentDirection=positive;
64  m_E.set_size(1);
65  m_Gamma.set_size(1);
66  m_Gamma[m_CurrentLevel]=1;
67  m_Rho.set_size(1);
68  m_E[0]=1.;
69  m_Rho[0]=1.;
70  m_Maxiters.set_size(1);
71  m_Maxiters[m_CurrentLevel]=1;
72  m_Dt=1;
73  m_Alpha=1.0;
74  m_Temp=0.0;
75  m_MeshPixelsPerElementAtEachResolution.set_size(1);
76  m_NumberOfIntegrationPoints.set_size(1);
77  m_NumberOfIntegrationPoints[m_CurrentLevel]=4;
78  m_MetricWidth.set_size(1);
79  m_MetricWidth[m_CurrentLevel]=3;
80  m_DoLineSearchOnImageEnergy=1;
81  m_LineSearchMaximumIterations=100;
82  m_UseMassMatrix=true;
83 
84  m_NumLevels=1;
85  m_MaxLevel=1;
86  m_MeshStep=2;
87  m_MeshLevels=1;
88  m_DoMultiRes=false;
89  m_UseLandmarks=false;
90  m_MinJacobian=1.0;
91 
92  m_TotalIterations=0;
93 
94  m_ReadMeshFile=false;
95 
96  for (unsigned int i=0; i < ImageDimension; i++)
97  {
98  m_ImageScaling[i]=1;
99  m_CurrentImageScaling[i]=1;
100  m_FullImageSize[i]=0;
101  m_ImageOrigin[i]=0;
102  }
103  m_FloatImage=NULL;
104  m_Field=NULL;
105  m_TotalField=NULL;
106  m_WarpedImage=NULL;
107 
108  // Setup the default interpolator
109  typename DefaultInterpolatorType::Pointer interp =
110  DefaultInterpolatorType::New();
111 
112  m_Interpolator =
113  static_cast<InterpolatorType*>( interp.GetPointer() );
114  m_Interpolator->SetInputImage(m_Field);
115 
116  m_Load = 0;
117 
118 }
119 
120 
121 template<class TMovingImage,class TFixedImage>
123 {
124  // Solve the system in time
125  if (!m_DoMultiRes && m_Maxiters[m_CurrentLevel] > 0)
126  {
127  SolverType mySolver;
128  mySolver.SetDeltatT(m_Dt);
129  mySolver.SetRho(m_Rho[m_CurrentLevel]);
130  mySolver.SetAlpha(m_Alpha);
131  CreateMesh(static_cast<double>(m_MeshPixelsPerElementAtEachResolution[m_CurrentLevel]),
132  mySolver,m_FullImageSize);
133  ApplyLoads(mySolver,m_FullImageSize);
134 
135  const unsigned int ndofpernode=(m_Element)->GetNumberOfDegreesOfFreedomPerNode();
136  const unsigned int numnodesperelt=(m_Element)->GetNumberOfNodes()+1;
137  const unsigned int ndof=mySolver.GetNumberOfDegreesOfFreedom();
138  unsigned int nzelts;
139  if (!m_ReadMeshFile)
140  {
141  nzelts=numnodesperelt*ndofpernode*ndof;
142  }
143  else
144  {
145  nzelts=((2*numnodesperelt*ndofpernode*ndof > 25*ndof) ? 2*numnodesperelt*ndofpernode*ndof : 25*ndof);
146  }
147  LinearSystemWrapperItpack itpackWrapper;
148  itpackWrapper.SetMaximumNonZeroValuesInMatrix(nzelts);
149  itpackWrapper.SetMaximumNumberIterations(2*mySolver.GetNumberOfDegreesOfFreedom());
150  itpackWrapper.SetTolerance(1.e-1);
151  // itpackWrapper.JacobianSemiIterative();
152  itpackWrapper.JacobianConjugateGradient();
153  mySolver.SetLinearSystemWrapper(&itpackWrapper);
154 
155  if( m_UseMassMatrix )
156  {
157  mySolver.AssembleKandM();
158  }
159  else
160  {
161  mySolver.InitializeForSolution();
162  mySolver.AssembleK();
163  }
164  IterativeSolve(mySolver);
165  // InterpolateVectorField(&mySolver);
166  }
167  else //if (m_Maxiters[m_CurrentLevel] > 0)
168  {
169  MultiResSolve();
170  }
171 
172  if (m_Field)
173  {
174  if (m_TotalField) m_Field=m_TotalField;
175  this->ComputeJacobian(1.,m_Field,2.5);
176  WarpImage(m_OriginalMovingImage);
177  }
178  return;
179 }
180 
181 template<class TMovingImage,class TFixedImage>
183 {
184  m_MovingImage=R;
185  if (m_TotalIterations == 0)
186  {
187  m_OriginalMovingImage=R;
188  }
189 }
190 
191 template<class TMovingImage,class TFixedImage>
193 {
194  m_FixedImage=T;
195  m_FullImageSize = m_FixedImage->GetLargestPossibleRegion().GetSize();
196 
197  VectorType disp;
198  for (unsigned int i=0; i < ImageDimension; i++)
199  {
200  disp[i]=0.0;
201  m_ImageOrigin[i]=0;
202 
203  }
204 
205  m_CurrentLevelImageSize=m_FullImageSize;
206 
207 }
208 
209 
210 template<class TMovingImage,class TFixedImage>
212 {
213  // Choose the similarity metric
214 
215 
216 // for using the imagetoimagemetricloads
217 #ifdef USEIMAGEMETRIC
220  typedef itk::PatternIntensityImageToImageMetric<FixedImageType,MovingImageType> MetricType2;
223 // typedef itk::DemonsImageToImageMetric<FixedImageType,MovingImageType> MetricType5;
224 
226 
227  float m_Temp=1.0;
228 
229  MetricType3::Pointer m=MetricType3::New();
230  MetricType4::Pointer ma=MetricType4::New();
231 
232  unsigned int whichmetric=(unsigned int) which;
233 
234  m_WhichMetric=which;
235  unsigned int nsp=1;
236  for (int i=0; i<ImageDimension; i++)
237  {
238  nsp *= m_MetricWidth[m_CurrentLevel];
239  }
240  if (whichmetric == 3 )
241  {
242  m->SetNumberOfSpatialSamples(nsp/2);
243  m->SetFixedImageStandardDeviation(0.4);
244  m->SetMovingImageStandardDeviation(0.4);
245  }
246  else if (whichmetric == 4 )
247  {
248  ma->SetNumberOfHistogramBins( 10 );
249  ma->SetNumberOfSpatialSamples( nsp/2 );
250  }
251 
252  switch (whichmetric)
253  {
254  case 0:
255  m_Metric=MetricType0::New();
256  m_Metric->SetScaleGradient(m_Temp); // this is the default(?)
257  //p=MetricType0::New();
258  //m_Function->SetInverseMetric(p);
259  break;
260  case 1:
261  m_Metric=MetricType1::New();
262  m_Metric->SetScaleGradient(m_Temp);
263  break;
264  case 2:
265  m_Metric=MetricType2::New();
266  m_Metric->SetScaleGradient(m_Temp);
267  break;
268  case 3:
269  m_Metric=m;
270  m_Metric->SetScaleGradient(m_Temp);
271  break;
272  case 4:
273  m_Metric=ma;
274  m_Metric->SetScaleGradient(m_Temp);
275  break;
276  case 5:
277  m_Metric=MetricType5::New();
278  m_Metric->SetScaleGradient(m_Temp);
279  break;
280  default:
281  m_Metric=MetricType0::New();
282  m_Metric->SetScaleGradient(m_Temp);
283 
284  }
285 #else
286 
293 
294  typename MetricType3::Pointer m=MetricType3::New();
295  typename MetricType4::Pointer ma=MetricType4::New();
296 
297  unsigned int whichmetric=(unsigned int) which;
298  m_WhichMetric=(unsigned int)which;
299 
300  switch (whichmetric)
301  {
302  case 0:
303  m_Metric=MetricType0::New();
304  break;
305  case 1:
306  m_Metric=MetricType1::New();
307  break;
308  case 2:
309  m_Metric=MetricType2::New();
310  break;
311  case 3:
312  m_Metric=m;
313  break;
314  case 4:
315  m_Metric=ma;
316  break;
317  case 5:
318  m_Metric=MetricType5::New();
319  break;
320  default:
321  m_Metric=MetricType0::New();
322  }
323 
324 
325  m_Metric->SetGradientStep( m_Gamma[m_CurrentLevel] );
326  if ( m_Temp == 1.0 ) m_Metric->SetNormalizeGradient(true);
327  else m_Metric->SetNormalizeGradient(false);
328 #endif
329 }
330 
331 template<class TMovingImage,class TFixedImage>
333 // Reads the parameters necessary to configure the example & returns
334 // false if no configuration file is found
335 {
336  std::ifstream f;
337  char buffer[4096] = {'\0'};
338  Float fbuf = 0.0;
339  unsigned int ibuf = 0;
340  unsigned int jj;
341 
342  std::cout << "Reading config file..." << fname << std::endl;
343  f.open(fname);
344  if (f)
345  {
346 
347  this->DoMultiRes(true);
348 
350  f >> ibuf;
351  this->m_NumLevels = (unsigned int) ibuf;
352 
354  f >> ibuf;
355  this->m_MaxLevel = ibuf;
356 
357  // get the initial scales for the pyramid
359  for (jj=0; jj<ImageDimension; jj++)
360  {
361  f >> ibuf;
362  m_ImageScaling[jj] = ibuf;
363  }
364 
365  this->m_MeshPixelsPerElementAtEachResolution.set_size(m_NumLevels);
367  for (jj=0; jj<this->m_NumLevels; jj++)
368  {
369  f >> ibuf;
370  this->m_MeshPixelsPerElementAtEachResolution(jj) = ibuf;
371  }
372 
374  this->m_E.set_size(m_NumLevels);
375  for (jj=0; jj<this->m_NumLevels; jj++)
376  {
377  f >> fbuf;
378  this->SetElasticity(fbuf,jj);
379  }
380 
382  this->m_Rho.set_size(m_NumLevels);
383  for (jj=0; jj<this->m_NumLevels; jj++)
384  {
385  f >> fbuf;
386  this->SetRho(fbuf,jj);
387  }
388 
390  this->m_Gamma.set_size(m_NumLevels);
391  for (jj=0; jj<this->m_NumLevels; jj++)
392  {
393  f >> fbuf;
394  this->SetGamma(fbuf,jj);
395  }
396 
398  this->m_NumberOfIntegrationPoints.set_size(m_NumLevels);
399  for(jj=0; jj< m_NumLevels; jj++)
400  {
401  f >> ibuf;
402  this->SetNumberOfIntegrationPoints(ibuf,jj);
403  }
404 
406  this->m_MetricWidth.set_size(m_NumLevels);
407  for(jj=0; jj< m_NumLevels; jj++)
408  {
409  f >> ibuf;
410  this->SetWidthOfMetricRegion(ibuf,jj);
411  }
412 
414  this->m_Maxiters.set_size(m_NumLevels);
415  for (jj=0; jj<this->m_NumLevels; jj++)
416  {
417  f >> ibuf;
418  this->SetMaximumIterations(ibuf,jj);
419  }
420 
422  float fbuf2=1.0;
423  f >> fbuf;
424  f >> fbuf2;
425  m_Temp=fbuf2;
426  this->ChooseMetric(fbuf);
427 
429  f >> fbuf;
430  this->m_Alpha=fbuf;
431 
433  f >> ibuf;
434  if (ibuf == 0)
435  {
436  this->SetDescentDirectionMinimize();
437  }
438  else
439  {
440  this->SetDescentDirectionMaximize();
441  }
442 
444  f >> ibuf;
445  this->DoLineSearch(ibuf);
446 
448  f >> fbuf;
449  this->SetTimeStep(fbuf);
450 
452  f >> fbuf;
453  this->SetEnergyReductionFactor(fbuf);
454 
456  f >> ibuf;
457  m_EmployRegridding = (unsigned int) ibuf;
458 
460  f >> ibuf;
461  this->m_FullImageSize[0] = ibuf;
462 
464  f >> ibuf;
465  this->m_FullImageSize[1] = ibuf;
466 
468  f >> ibuf;
469  unsigned int dim=2;
470  if (ibuf > 0) dim=3;
471  if (dim == 3) this->m_FullImageSize[2] = ibuf;
472 
474  f >> buffer;
475  this->SetMovingFile(buffer);
476 
478  f >> buffer;
479  this->SetFixedFile(buffer);
480 
482  f >> ibuf;
484  f >> buffer;
485 
486  if (ibuf == 1)
487  {
488  this->UseLandmarks(true);
489  this->SetLandmarkFile(buffer);
490  }
491  else
492  {
493  this->UseLandmarks(false);
494  }
495 
497  f >> buffer;
498  this->SetResultsFile(buffer);
499 
501  f >> ibuf;
503  f >> buffer;
504 
505  if (ibuf == 1)
506  {
507  this->SetWriteDisplacements(true);
508  this->SetDisplacementsFile(buffer);
509  }
510  else
511  {
512  this->SetWriteDisplacements(false);
513  }
514 
516  f >> ibuf;
518  f >> buffer;
519 
520  if (ibuf == 1)
521  {
522  this->m_ReadMeshFile=true;
523  this->m_MeshFileName=buffer;
524  }
525  else
526  {
527  this->m_ReadMeshFile=false;
528  }
529 
530  f.close();
531  std::cout << "Example configured. E " << m_E << " rho " << m_Rho << std::endl;
532  return true;
533  }
534  else
535  {
536  std::cout << "No configuration file specified...quitting.\n";
537  return false;
538  }
539 }
540 
541 template<class TMovingImage,class TFixedImage>
543 // Outputs the displacement field as a multicomponent image XYZXYZXYZ...
544 {
545 
546  std::cout << "Writing multi-component displacement vector field...";
547 
548  typedef itk::ImageFileWriter< FieldType > FieldWriterType;
549  typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
550 
551  fieldWriter->SetInput( m_Field );
552  fieldWriter->SetFileName("VectorDeformationField.mhd");
553  try
554  {
555  fieldWriter->Update();
556  }
557  catch( itk::ExceptionObject & excp )
558  {
559  std::cerr << "Error while saving the displacement vector field" << std::endl;
560  std::cerr << excp << std::endl;
561  }
562 
563  std::cout << "done" << std::endl;
564  return 0;
565 }
566 
567 template<class TMovingImage,class TFixedImage>
569 // Outputs the displacement field for the index provided (0=x,1=y,2=z)
570 {
571  // Initialize the Moving to the displacement field
572  typename IndexSelectCasterType::Pointer fieldCaster = IndexSelectCasterType::New();
573  fieldCaster->SetInput( m_Field );
574  fieldCaster->SetIndex( index );
575 
576  // Define the output of the Moving
577  typename FloatImageType::Pointer fieldImage = FloatImageType::New();
578  fieldCaster->Update();
579  fieldImage = fieldCaster->GetOutput();
580 
581  // Set up the output filename
582  std::string outfile=m_DisplacementsFileName+static_cast<char>('x'+index)+std::string("vec.mhd");
583  std::cout << "Writing displacements to " << outfile;
584 
585  typedef typename FloatImageType::PixelType FType;
586 
587  typedef ImageFileWriter<FloatImageType> WriterType;
588  typename WriterType::Pointer writer = WriterType::New();
589  writer->SetInput(fieldImage);
590  writer->SetFileName(outfile.c_str());
591  writer->Write();
592 
593  std::cout << " ...done" << std::endl;
594  return 0;
595 }
596 
597 template<class TMovingImage,class TFixedImage>
599 {
600  // -------------------------------------------------------
601  std::cout << "Warping image" << std::endl;
602 
603  {
604  typename WarperType::Pointer warper = WarperType::New();
605 
606  typedef typename WarperType::CoordRepType WarperCoordRepType;
608  InterpolatorType0;
610  InterpolatorType1;
612  InterpolatorType2;
613  typename InterpolatorType1::Pointer interpolator = InterpolatorType1::New();
614 
615  warper = WarperType::New();
616  warper->SetInput( ImageToWarp );
617  warper->SetDeformationField( m_Field );
618  warper->SetInterpolator( interpolator );
619  warper->SetOutputOrigin( m_FixedImage->GetOrigin() );
620  warper->SetOutputSpacing( m_FixedImage->GetSpacing() );
621  warper->SetOutputDirection( m_FixedImage->GetDirection() );
622  typename FixedImageType::PixelType padValue = 0;
623  warper->SetEdgePaddingValue( padValue );
624  warper->Update();
625 
626  m_WarpedImage=warper->GetOutput();
627  }
628 
629 }
630 
631 template<class TMovingImage,class TFixedImage>
633  Solver& mySolver, ImageSizeType imagesize)
634 {
635 
636  vnl_vector<double> MeshOriginV; MeshOriginV.set_size(ImageDimension);
637  vnl_vector<double> MeshSizeV; MeshSizeV.set_size(ImageDimension);
638  vnl_vector<double> ImageSizeV; ImageSizeV.set_size(ImageDimension);
639  vnl_vector<double> ElementsPerDim; ElementsPerDim.set_size(ImageDimension);
640  for (unsigned int i=0; i<ImageDimension; i++)
641  {
642  MeshSizeV[i]=(double)imagesize[i]; // FIX ME make more general
643 
644  MeshOriginV[i]=(double)m_ImageOrigin[i];// FIX ME make more general
645  ImageSizeV[i]=(double) imagesize[i]+1;//to make sure all elts are inside the interpolation mesh
646  ElementsPerDim[i]=MeshSizeV[i]/PixelsPerElement;
647 
648  }
649 
650  std::cout << " ElementsPerDim " << ElementsPerDim << std::endl;
651 
652  if (m_ReadMeshFile)
653  {
654  std::ifstream meshstream;
655  meshstream.open(m_MeshFileName.c_str());
656  if (!meshstream)
657  {
658  std::cout<<"File "<<m_MeshFileName<<" not found!\n";
659  return;
660  }
661 
662  mySolver.Read(meshstream);
663  mySolver.GenerateGFN();
665 
666  if (m)
667  {
668  m->E=this->GetElasticity(m_CurrentLevel); // Young modulus -- used in the membrane ///
669  }
670  // now scale the mesh to the current scale
671  Element::VectorType coord;
672  Node::ArrayType* nodes = &(mySolver.node);
673  Node::ArrayType::iterator node=nodes->begin();
674  m_Element=( *((*node)->m_elements.begin()));
675  for(node=nodes->begin(); node != nodes->end(); node++)
676  {
677  coord = (*node)->GetCoordinates();
678  for (unsigned int ii = 0; ii < ImageDimension; ii++)
679  {
680  coord[ii] = coord[ii]/(float)m_CurrentImageScaling[ii];
681  }
682  (*node)->SetCoordinates(coord);
683  }
684  }
685  else if (ImageDimension == 2 && dynamic_cast<Element2DC0LinearQuadrilateral*>(m_Element) != NULL)
686  {
687  m_Material->E = this->GetElasticity(m_CurrentLevel);
688  Generate2DRectilinearMesh(m_Element,mySolver,MeshOriginV,MeshSizeV,ElementsPerDim);
689  mySolver.GenerateGFN();
690 
691  std::cout << " init interpolation grid : im sz " << ImageSizeV << " MeshSize " << MeshSizeV << std::endl;
692  mySolver.InitializeInterpolationGrid(ImageSizeV,MeshOriginV,MeshSizeV);
693  std::cout << " done initializing interpolation grid " << std::endl;
694  }
695  else if ( ImageDimension == 3 && dynamic_cast<Element3DC0LinearHexahedron*>(m_Element) != NULL)
696  {
697  m_Material->E = this->GetElasticity(m_CurrentLevel);
698 
699  std::cout << " generating regular mesh " << std::endl;
700  Generate3DRectilinearMesh(m_Element,mySolver,MeshOriginV,MeshSizeV,ElementsPerDim);
701  mySolver.GenerateGFN();
702  std::cout << " generating regular mesh done " << std::endl;
703 // the global to local transf is too slow so don't do it.
704  std::cout << " DO NOT init interpolation grid : im sz " << ImageSizeV << " MeshSize " << MeshSizeV << std::endl;
705  //mySolver.InitializeInterpolationGrid(ImageSizeV,MeshOriginV,MeshSizeV);
706  //std::cout << " done initializing interpolation grid " << std::endl;
707  }
708  else
709  {
710  FEMException e(__FILE__, __LINE__);
711  e.SetDescription("CreateMesh - wrong image or element type");
712  e.SetLocation(ITK_LOCATION);
713  throw e;
714  }
715 
716 }
717 
718 
719 template<class TMovingImage,class TFixedImage>
721 ::ApplyImageLoads(SolverType& mySolver, TMovingImage* movingimg, TFixedImage* fixedimg )
722 {
724  m_Load->SetMovingImage(movingimg);
725  m_Load->SetFixedImage(fixedimg);
726  if (!m_Field) this->InitializeField();
727 #ifndef USEIMAGEMETRIC
728  m_Load->SetDeformationField(this->GetDeformationField());
729 #endif
730  m_Load->SetMetric(m_Metric);
731  m_Load->InitializeMetric();
732  m_Load->SetTemp(m_Temp);
733  m_Load->SetGamma(m_Gamma[m_CurrentLevel]);
734  ImageSizeType r;
735  for (unsigned int dd = 0; dd < ImageDimension; dd++)
736  {
737  r[dd] = m_MetricWidth[m_CurrentLevel];
738  }
739  m_Load->SetMetricRadius(r);
740  m_Load->SetNumberOfIntegrationPoints(m_NumberOfIntegrationPoints[m_CurrentLevel]);
741  m_Load->GN = mySolver.load.size()+1; //NOTE SETTING GN FOR FIND LATER
742  m_Load->SetSign((Float)m_DescentDirection);
743  mySolver.load.push_back( FEMP<Load>(&*m_Load) );
745  (&*mySolver.load.Find(mySolver.load.size()));
746 }
747 
748 template<class TMovingImage,class TFixedImage>
750 {
751  //
752  // Apply the boundary conditions. We pin the image corners.
753  // First compute which elements these will be.
755  std::cout << " applying loads " << std::endl;
756 
757  vnl_vector<Float> pd; pd.set_size(ImageDimension);
758  vnl_vector<Float> pu; pu.set_size(ImageDimension);
759 
760  if (m_UseLandmarks)
761  {
762 
763  LoadArray::iterator loaditerator;
765 
766  if ( this->m_LandmarkArray.empty() )
767  {
768  // Landmark loads
769  std::ifstream f;
770  std::cout << m_LandmarkFileName << std::endl;
771  f.open(m_LandmarkFileName.c_str());
772  if (f)
773  {
774 
775  std::cout << "Try loading landmarks..." << std::endl;
776  std::cout << "Try loading landmarks..." << std::endl;
777  try
778  {
779  mySolver.load.clear(); // NOTE: CLEARING ALL LOADS - LMS MUST BE APPLIED FIRST
780  mySolver.Read(f);
781  }
782  catch (itk::ExceptionObject &err)
783  {
784  std::cerr << "Exception: cannot read load landmark FEMRegistrationFilter.txx " << err;
785  }
786  f.close();
787 
788  m_LandmarkArray.resize(mySolver.load.size());
789  unsigned int ct = 0;
790  for(loaditerator = mySolver.load.begin(); loaditerator != mySolver.load.end(); loaditerator++)
791  {
792  if ((l3 = dynamic_cast<LoadLandmark*>( &(*(*loaditerator)) )) != 0 )
793  {
794  LoadLandmark::Pointer l4 = dynamic_cast<LoadLandmark*>(l3->Clone());
795  m_LandmarkArray[ct] = l4;
796  ct++;
797  }
798  }
799 
800  mySolver.load.clear(); // NOTE: CLEARING ALL LOADS - LMS MUST BE APPLIED FIRST
801  }
802  else
803  {
804  std::cout << "no landmark file specified." << std::endl;
805  }
806 
807  }
808 
809 
810 // now scale the landmarks
811 
812  std::cout << " num of LM loads " << m_LandmarkArray.size() << std::endl;
813  /*
814  * Step over all the loads again to scale them by the global landmark weight.
815  */
816  if ( !m_LandmarkArray.empty())
817  {
818  for(unsigned int lmind = 0; lmind<m_LandmarkArray.size(); lmind++)
819  {
820 
821  m_LandmarkArray[lmind]->el[0] = NULL;
822  bool isFound = false;
823  std::cout << " prescale Pt " << m_LandmarkArray[lmind]->GetTarget() << std::endl;
824  if (scaling)
825  {
826  m_LandmarkArray[lmind]->ScalePointAndForce(scaling,m_EnergyReductionFactor);
827  std::cout << " postscale Pt " << m_LandmarkArray[lmind]->GetTarget() << " scale " << scaling[0] << std::endl;
828  }
829 
830  pu = m_LandmarkArray[lmind]->GetSource();
831  pd = m_LandmarkArray[lmind]->GetPoint();
832 
833  for (Element::ArrayType::const_iterator n = mySolver.el.begin();
834  n != mySolver.el.end() && !isFound; n++)
835  {
836  if ( (*n)->GetLocalFromGlobalCoordinates(pu, pd ) )
837  {
838  isFound = true;
839  m_LandmarkArray[lmind]->SetPoint(pd);
840  m_LandmarkArray[lmind]->el[0] = ( ( &**n ) );
841  }
842  }
843 
844  m_LandmarkArray[lmind]->GN = lmind;
845  LoadLandmark::Pointer l5 = (dynamic_cast<LoadLandmark::Pointer>(m_LandmarkArray[lmind]->Clone()));
846  mySolver.load.push_back(FEMP<Load>(l5));
847  }
848  }
849  std::cout << " landmarks done" << std::endl;
850  }
851 
852  // now apply the BC loads
853  LoadBC::Pointer l1;
854 
855  //Pin one corner of image
856  unsigned int CornerCounter,ii,EdgeCounter = 0;
857  Node::ArrayType* nodes = &(mySolver.node);
858  Element::VectorType coord;
859  Node::ArrayType::iterator node = nodes->begin();
860  bool EdgeFound;
861  unsigned int nodect = 0;
862  while(node != nodes->end() && EdgeCounter < ImageDimension )
863  {
864  coord = (*node)->GetCoordinates();
865  CornerCounter = 0;
866  for (ii = 0; ii < ImageDimension; ii++)
867  {
868  if (coord[ii] == m_ImageOrigin[ii] || coord[ii] == ImgSz[ii]-1 ) CornerCounter++;
869  }
870  if (CornerCounter == ImageDimension) // the node is located at a true corner
871  {
872  unsigned int ndofpernode=(*((*node)->m_elements.begin()))->GetNumberOfDegreesOfFreedomPerNode();
873  unsigned int numnodesperelt=(*((*node)->m_elements.begin()))->GetNumberOfNodes();
874  unsigned int whichnode;
875 
876  unsigned int maxnode=numnodesperelt-1;
877 
878  typedef typename Node::SetOfElements NodeEltSetType;
879  for( NodeEltSetType::iterator elt = (*node)->m_elements.begin();
880  elt != (*node)->m_elements.end(); elt++)
881  {
882  for (whichnode=0; whichnode<=maxnode; whichnode++)
883  {
884  coord=(*elt)->GetNode(whichnode)->GetCoordinates();
885  CornerCounter=0;
886 
887  for (ii=0; ii < ImageDimension; ii++)
888  {
889  if (coord[ii] == m_ImageOrigin[ii] || coord[ii] == ImgSz[ii]-1 )
890  {
891  CornerCounter++;
892  }
893  }
894  if (CornerCounter == ImageDimension - 1)
895  {
896  EdgeFound=true;
897  }
898  else
899  {
900  EdgeFound=false;
901  }
902  if (EdgeFound)
903  {
904  for (unsigned int jj=0; jj<ndofpernode; jj++)
905  {
906  std::cout << " which node " << whichnode << std::endl;
907  std::cout << " edge coord " << coord << std::endl;
908 
909  l1=LoadBC::New();
910  // now we get the element from the node -- we assume we need fix the dof only once
911  // even if more than one element shares it.
912  l1->m_element= (*elt); // Fixed bug TS 1/17/03 ( *((*node)->m_elements.begin()));
913  //l1->m_element= ( *((*node)->m_elements[ect-1]));
914  unsigned int localdof=whichnode*ndofpernode+jj;
915  l1->m_dof=localdof;
916  l1->m_value=vnl_vector<double>(1,0.0);
917  mySolver.load.push_back( FEMP<Load>(&*l1) );
918  }
919  EdgeCounter++;
920  }
921  }
922  }//end elt loop
923  }
924  node++;
925  nodect++;
926  std::cout << " node " << nodect << std::endl;
927  }//
928 
929  return;
930 }
931 
932 template<class TMovingImage,class TFixedImage>
934 {
935  if (!m_Load)
936  {
937  std::cout << " m_Load not initialized " << std::endl;
938  return;
939  }
940 
941  bool Done=false;
942  unsigned int iters=0;
943  m_MinE=10.e99;
944  Float deltE=0;
945  while ( !Done && iters < m_Maxiters[m_CurrentLevel] )
946  {
947  const Float lastdeltE=deltE;
948  const unsigned int DLS=m_DoLineSearchOnImageEnergy;
949  // Reset the variational similarity term to zero.
950 
951  Float LastE=m_Load->GetCurrentEnergy();
952  m_Load->SetCurrentEnergy(0.0);
953  m_Load->InitializeMetric();
954 
955  if (!m_Field)
956  {
957  std::cout << " Big Error -- Field is NULL ";
958  }
959  // Assemble the master force vector (from the applied loads)
960  // if (iters == 1) // for testing
961 
962  if( m_UseMassMatrix )
963  {
964  mySolver.AssembleFforTimeStep();
965  }
966  else
967  {
968  mySolver.AssembleF();
969  }
970 
971  m_Load->PrintCurrentEnergy();
972 
973 
974  // Solve the system of equations for displacements (u=K^-1*F)
975  mySolver.Solve();
976 
977  //mySolver.PrintDisplacements(0);
978  // Float ImageSimilarity=0.0;
979 
980  //#ifdef USEIMAGEMETRIC
981  //LastE=EvaluateResidual(*mySolver,mint);
982  //#endif
983 
984 #ifndef USEIMAGEMETRIC
985  if (m_DescentDirection == 1)
986  {
987  deltE=(LastE - m_Load->GetCurrentEnergy());
988  }
989  else
990  {
991  deltE=(m_Load->GetCurrentEnergy() - LastE );
992  }
993 #else
994  if (m_DescentDirection == 1)
995  {
996  deltE=(m_Load->GetCurrentEnergy() - LastE );
997  }
998  else
999  {
1000  deltE=(LastE - m_Load->GetCurrentEnergy());
1001  }
1002 #endif
1003 
1004  if ( DLS==2 && deltE < 0.0 )
1005  {
1006  std::cout << " line search ";
1007  const float tol = 1.0;//((0.01 < LastE) ? 0.01 : LastE/10.);
1008  LastE=this->GoldenSection(mySolver,tol,m_LineSearchMaximumIterations);
1009  deltE=(m_MinE-LastE);
1010  std::cout << " line search done " << std::endl;
1011  }
1012 
1013  iters++;
1014 
1015  if (deltE == 0.0)
1016  {
1017  std::cout << " no change in energy " << std::endl;
1018  Done=true;
1019  }
1020  if ( (DLS == 0) && ( iters >= m_Maxiters[m_CurrentLevel] ) )
1021  {
1022  Done=true;
1023  }
1024  else if ((DLS > 0) &&
1025  ( iters >= m_Maxiters[m_CurrentLevel] || (deltE < 0.0 && iters > 5 && lastdeltE < 0.0)))
1026  {
1027  Done=true;
1028  }
1029  float curmaxsol=mySolver.GetCurrentMaxSolution();
1030  if (curmaxsol == 0)
1031  {
1032  curmaxsol=1.0;
1033  }
1034  Float mint= m_Gamma[m_CurrentLevel]/curmaxsol;
1035  if (mint > 1)
1036  {
1037  mint = 1.0;
1038  }
1039 
1040  if (mySolver.GetCurrentMaxSolution() < 0.01 && iters > 2)
1041  {
1042  Done=true;
1043  }
1044  mySolver.AddToDisplacements(mint);
1045  m_MinE=LastE;
1046 
1047  InterpolateVectorField(mySolver);
1048 
1049 
1050  if (m_EmployRegridding != 0)
1051  {
1052  if ( iters % m_EmployRegridding == 0 )
1053  {
1054  this->EnforceDiffeomorphism(1.0, mySolver, true);
1055  // std::string rfn="warpedimage";
1056  // WriteWarpedImage(rfn.c_str());
1057  }
1058  }
1059  // uncomment to write out every deformation SLOW due to interpolating vector field everywhere.
1060  //else if ( (iters % 5) == 0 || Done ) {
1061  //WarpImage(m_MovingImage);
1062  //WriteWarpedImage(m_ResultsFileName.c_str());
1063  //}
1064  std::cout << " min E " << m_MinE << " delt E " << deltE << " iter " << iters << std::endl;
1065  m_TotalIterations++;
1066  }
1067 }
1068 
1069 template<class TMovingImage,class TFixedImage>
1072 {
1073 
1074  std::cout << " allocating deformation field " << std::endl;
1075 
1076  m_Field = FieldType::New();
1077 
1078  m_FieldRegion.SetSize(m_CurrentLevelImageSize );
1079  m_Field->SetOrigin( m_FixedImage->GetOrigin() );
1080  m_Field->SetSpacing( m_FixedImage->GetSpacing() );
1081  m_Field->SetDirection( m_FixedImage->GetDirection() );
1082  m_Field->SetLargestPossibleRegion( m_FieldRegion );
1083  m_Field->SetBufferedRegion( m_FieldRegion );
1084  m_Field->SetLargestPossibleRegion( m_FieldRegion );
1085  m_Field->Allocate();
1086 
1087  VectorType disp;
1088  for (unsigned int t=0; t<ImageDimension; t++)
1089  {
1090  disp[t]=0.0;
1091  }
1092  FieldIterator fieldIter( m_Field, m_FieldRegion );
1093  fieldIter.GoToBegin();
1094  for(; !fieldIter.IsAtEnd(); ++fieldIter )
1095  {
1096  fieldIter.Set(disp);
1097  }
1098 }
1099 
1100 template<class TMovingImage,class TFixedImage>
1101 void
1103 {
1104 
1105  typename FieldType::Pointer field=m_Field;
1106 
1107  if (!field)
1108  {
1109  this->InitializeField();
1110  }
1111  m_FieldSize=field->GetLargestPossibleRegion().GetSize();
1112 
1113  std::cout << " interpolating vector field of size " << m_FieldSize;
1114 
1115  Float rstep,sstep,tstep;
1116 
1117  vnl_vector<double> Pos; // solution at the point
1118  vnl_vector<double> Sol; // solution at the local point
1119  vnl_vector<double> Gpt; // global position given by local point
1120 
1121 
1122  VectorType disp;
1123  for (unsigned int t=0; t<ImageDimension; t++)
1124  {
1125  disp[t]=0.0;
1126  }
1127  FieldIterator fieldIter( field, field->GetLargestPossibleRegion() );
1128 
1129  fieldIter.GoToBegin();
1130  typename FixedImageType::IndexType rindex = fieldIter.GetIndex();
1131 
1132  Sol.set_size(ImageDimension);
1133  Gpt.set_size(ImageDimension);
1134 
1135  if (ImageDimension == 2)
1136  {
1137  Element::ConstPointer eltp;
1138 
1139  for(; !fieldIter.IsAtEnd(); ++fieldIter )
1140  {
1141  // get element pointer from the solver elt pointer image
1142  rindex = fieldIter.GetIndex();
1143  for(unsigned int d=0; d<ImageDimension; d++)
1144  {
1145  Gpt[d]=(double)rindex[d];
1146  }
1147  eltp=mySolver.GetElementAtPoint(Gpt);
1148  if (eltp)
1149  {
1150  eltp->GetLocalFromGlobalCoordinates(Gpt, Pos);
1151 
1152  unsigned int Nnodes= eltp->GetNumberOfNodes();
1153  typename Element::VectorType shapef(Nnodes);
1154  shapef = eltp->ShapeFunctions(Pos);
1155  Float solval;
1156  for(unsigned int f=0; f<ImageDimension; f++)
1157  {
1158  solval=0.0;
1159  for(unsigned int n=0; n<Nnodes; n++)
1160  {
1161  solval += shapef[n] * mySolver.GetLS()->GetSolutionValue(
1162  eltp->GetNode(n)->GetDegreeOfFreedom(f) , mySolver.TotalSolutionIndex);
1163  }
1164  Sol[f]=solval;
1165  disp[f] =(Float) 1.0*Sol[f];
1166  }
1167  field->SetPixel(rindex, disp );
1168  }
1169  }
1170  }
1171 
1172  if (ImageDimension==3)
1173  {
1174  // FIXME SHOULD BE 2.0 over meshpixperelt
1175  rstep=1.25/((double)m_MeshPixelsPerElementAtEachResolution[m_CurrentLevel]);//
1176  sstep=1.25/((double)m_MeshPixelsPerElementAtEachResolution[m_CurrentLevel]);//
1177  tstep=1.25/((double)m_MeshPixelsPerElementAtEachResolution[m_CurrentLevel]);//
1178 // std::cout << " r s t steps " << rstep << " " << sstep << " "<< tstep << std::endl;
1179 
1180  Pos.set_size(ImageDimension);
1181  for( Element::ArrayType::iterator elt=mySolver.el.begin(); elt != mySolver.el.end(); elt++)
1182  {
1183  for (double r=-1.0; r <= 1.0; r=r+rstep )
1184  {
1185  for (double s=-1.0; s <= 1.0; s=s+sstep )
1186  {
1187  for (double t=-1.0; t <= 1.0; t=t+tstep )
1188  {
1189  Pos[0]=r;
1190  Pos[1]=s;
1191  Pos[2]=t;
1192 
1193  unsigned int Nnodes= (*elt)->GetNumberOfNodes();
1194  typename Element::VectorType shapef(Nnodes);
1195 
1196 #define FASTHEX
1197 #ifdef FASTHEX
1198 //FIXME temporarily using hexahedron shape f for speed
1199  shapef[0] = (1 - r) * (1 - s) * (1 - t) * 0.125;
1200  shapef[1] = (1 + r) * (1 - s) * (1 - t) * 0.125;
1201  shapef[2] = (1 + r) * (1 + s) * (1 - t) * 0.125;
1202  shapef[3] = (1 - r) * (1 + s) * (1 - t) * 0.125;
1203  shapef[4] = (1 - r) * (1 - s) * (1 + t) * 0.125;
1204  shapef[5] = (1 + r) * (1 - s) * (1 + t) * 0.125;
1205  shapef[6] = (1 + r) * (1 + s) * (1 + t) * 0.125;
1206  shapef[7] = (1 - r) * (1 + s) * (1 + t) * 0.125;
1207 #else
1208  shapef = (*elt)->ShapeFunctions(Pos);
1209 #endif
1210 
1211  Float solval,posval;
1212  bool inimage=true;
1213 
1214 // float interperror=0.0;
1215 
1216  for(unsigned int f=0; f<ImageDimension; f++)
1217  {
1218  solval=0.0;
1219  posval=0.0;
1220  for(unsigned int n=0; n<Nnodes; n++)
1221  {
1222  posval += shapef[n]*(((*elt)->GetNodeCoordinates(n))[f]);
1223  solval += shapef[n] * mySolver.GetLS()->GetSolutionValue(
1224  (*elt)->GetNode(n)->GetDegreeOfFreedom(f) , mySolver.TotalSolutionIndex);
1225  }
1226  Sol[f]=solval;
1227  Gpt[f]=posval;
1228 
1229  Float x=Gpt[f];
1230  long int temp;
1231  if (x != 0) temp=(long int) ((x)+0.5); else temp=0;// round
1232  rindex[f]=temp;
1233  disp[f] =(Float) 1.0*Sol[f];
1234  if ( temp < 0 || temp > (long int) m_FieldSize[f]-1) inimage=false;
1235 
1236  }
1237  if (inimage) field->SetPixel(rindex, disp );
1238  }
1239  }
1240  }//end of for loops
1241 
1242  } // end of elt array loop
1243 
1244  }/* */ // end if imagedimension==3
1245 
1246  // Insure that the values are exact at the nodes. They won't necessarily be unless we use this code.
1247  std::cout << " interpolation done " << std::endl;
1248 }
1249 
1250 template<class TMovingImage,class TFixedImage>
1252  FieldType* field, float smooth)
1253 {
1254  unsigned int row;
1255  unsigned int col;
1256  bool jproduct=true;
1257 
1258  m_MinJacobian=1.0;
1259 
1260  if (!field)
1261  {
1262  field=m_Field;
1263  jproduct=false;
1264  }
1265 
1266  if ( !m_FloatImage && jproduct)
1267  {
1268  std::cout << " allocating m_FloatImage " << std::endl;
1269  m_FloatImage = FloatImageType::New();
1270  m_FloatImage->SetLargestPossibleRegion( field->GetLargestPossibleRegion() );
1271  m_FloatImage->SetBufferedRegion( field->GetLargestPossibleRegion().GetSize() );
1272  m_FloatImage->Allocate();
1273 
1274  ImageRegionIteratorWithIndex<FloatImageType> wimIter( m_FloatImage, m_FloatImage->GetLargestPossibleRegion() );
1275  wimIter.GoToBegin();
1276  for(; !wimIter.IsAtEnd(); ++wimIter )
1277  {
1278  wimIter.Set(1.0);
1279  }
1280  }
1281 
1282  typename Element::MatrixType jMatrix,idMatrix;
1283  jMatrix.set_size(ImageDimension,ImageDimension);
1284 
1285  FieldIterator fieldIter( field, field->GetLargestPossibleRegion() );
1286  typename FixedImageType::IndexType rindex;
1287  typename FixedImageType::IndexType ddrindex;
1288  typename FixedImageType::IndexType ddlindex;
1289 
1290  typename FixedImageType::IndexType difIndex[ImageDimension][2];
1291 
1292  std:: cout << " get jacobian " << std::endl;
1293 
1294  float det;
1295  unsigned int posoff=1;
1296 
1297  float space=1.0;
1298 
1299  typename FieldType::PixelType dPix;
1300  typename FieldType::PixelType lpix;
1301  typename FieldType::PixelType llpix;
1302  typename FieldType::PixelType rpix;
1303  typename FieldType::PixelType rrpix;
1304  typename FieldType::PixelType cpix;
1305 
1306  for( fieldIter.GoToBegin(); !fieldIter.IsAtEnd(); ++fieldIter )
1307  {
1308  rindex=fieldIter.GetIndex();
1309 
1310  bool oktosample=true;
1311 
1312  cpix=field->GetPixel(rindex);
1313  for(row=0; row< ImageDimension;row++)
1314  {
1315  difIndex[row][0]=rindex;
1316  difIndex[row][1]=rindex;
1317  ddrindex=rindex;
1318  ddlindex=rindex;
1319  if (rindex[row] <
1320  static_cast<typename FixedImageType::IndexType::IndexValueType>(m_FieldSize[row]-2) )
1321  {
1322  difIndex[row][0][row]=rindex[row]+posoff;
1323  ddrindex[row]=rindex[row]+posoff*2;
1324  } else oktosample=false;
1325  if (rindex[row] > 1 )
1326  {
1327  difIndex[row][1][row]=rindex[row]-1;
1328  ddlindex[row]=rindex[row]-2;
1329  } else oktosample=false;
1330 
1331  float h=1.0;
1332  space=1.0; // should use image spacing here?
1333 
1334  rpix = field->GetPixel(difIndex[row][1]);
1335  rpix = rpix*h+cpix*(1.-h);
1336  lpix = field->GetPixel(difIndex[row][0]);
1337  lpix = lpix*h+cpix*(1.-h);
1338  dPix = ( rpix - lpix)*sign*space/(2.0);
1339  for(col=0; col< ImageDimension;col++)
1340  {
1341  Float val;
1342  if (row == col) val=dPix[col]+1.0;
1343  else val = dPix[col];
1344  jMatrix.put(row,col,val);
1345  }
1346  }
1347 
1348  //the determinant of the jacobian matrix
1349  det = (float) vnl_determinant(jMatrix);
1350  if (det < 0.) det=0.0;
1351  if ( jproduct && oktosample ) // FIXME - NEED TO COMPOSE THE FULL FIELD
1352  m_FloatImage->SetPixel(rindex, m_FloatImage->GetPixel(rindex)*det );
1353  if ( oktosample)
1354  {
1355  if (det < m_MinJacobian) m_MinJacobian=det;
1356  }
1357  }
1358  std::cout << " min Jacobian " << m_MinJacobian << std::endl;
1359 
1360  if (jproduct && m_FloatImage && smooth > 0)
1361  {
1363 
1364  typename DGF::Pointer filter = DGF::New();
1365  filter->SetVariance(smooth);
1366  filter->SetMaximumError(.01f);
1367  filter->SetInput(m_FloatImage);
1368  filter->Update();
1369  m_FloatImage=filter->GetOutput();
1370  }
1371 
1372 }
1373 
1374 template<class TMovingImage,class TFixedImage>
1376  SolverType& mySolver , bool onlywriteimages )
1377 {
1378 
1379  // FIX ME - WE NEED TO STORE THE PRODUCTS OF THE JACOBIANS
1380  // s.t. WE TRACK THE JACOBIAN OF THE O.D.E. FLOW.
1381  std::cout << " Checking Jacobian ";
1382  this->ComputeJacobian(1.,NULL);
1383  if (m_MinJacobian < thresh) //FIXME
1384  {
1385  std::cout << " Enforcing diffeomorphism " << std::endl;
1386  // resize the vector field to full size
1387  typename FieldType::Pointer fullField=NULL;
1388  ExpandFactorsType expandFactors[ImageDimension];
1389  bool resize=false;
1390  for (unsigned int ef=0; ef<ImageDimension; ef++)
1391  {
1393  ((float) m_FullImageSize[ef]/(float)m_CurrentLevelImageSize[ef]);
1394  expandFactors[ef]=factor;
1395  if (factor != 1.) resize=true;
1396  }
1397  if (resize)
1398  fullField=ExpandVectorField(expandFactors,m_Field); // this works - linear interp and expansion of vf
1399  else fullField=m_Field;
1400 
1401  // FIXME : SHOULD COMPUTE THE JACOBIAN AGAIN AND EXIT THE FUNCTION
1402  // IF IT'S NOT BELOW THE THRESH. ALSO, WE SHOULD STORE THE FULL TIME
1403  // INTEGRATED JACOBIAN FIELD AND MULTIPLY IT BY THE INCREMENTAL.
1404 
1405  // here's where we warp the image
1406 
1407  typename WarperType::Pointer warper = WarperType::New();
1408  typedef typename WarperType::CoordRepType WarperCoordRepType;
1410  InterpolatorType0;
1412  InterpolatorType1;
1413  typename InterpolatorType1::Pointer interpolator = InterpolatorType1::New();
1414 
1415  // if using landmarks, warp them
1416 
1417  if (m_UseLandmarks)
1418  {
1419  std::cout << " warping landmarks " << m_LandmarkArray.size() << std::endl;
1420 
1421  if(!m_LandmarkArray.empty())
1422  {
1423  for(unsigned int lmind=0; lmind<m_LandmarkArray.size(); lmind++)
1424  {
1425  std::cout << " old source " << m_LandmarkArray[lmind]->GetSource() << " target " << m_LandmarkArray[lmind]->GetTarget() << std::endl;
1426 
1427  // Convert the source to warped coords.
1428  m_LandmarkArray[lmind]->GetSource()=m_LandmarkArray[lmind]->GetSource()+
1429  (dynamic_cast<LoadLandmark*>( &*mySolver.load.Find(lmind) )->GetForce() );
1430  std::cout << " new source " << m_LandmarkArray[lmind]->GetSource() << " target " << m_LandmarkArray[lmind]->GetTarget() << std::endl;
1431 
1432  LoadLandmark::Pointer l5=(dynamic_cast<LoadLandmark::Pointer>(m_LandmarkArray[lmind]->Clone()));
1433  mySolver.load.push_back(FEMP<Load>(l5));
1434 
1435  }
1436  std::cout << " warping landmarks done " << std::endl;
1437  } else std::cout << " landmark array empty " << std::endl;
1438  }
1439 
1440  // store the total deformation by composing with the full field
1441  if (!m_TotalField && !onlywriteimages)
1442  {
1443  std::cout << " allocating total deformation field " << std::endl;
1444 
1445  m_TotalField = FieldType::New();
1446 
1447  m_FieldRegion.SetSize(fullField->GetLargestPossibleRegion().GetSize() );
1448  m_TotalField->SetLargestPossibleRegion( m_FieldRegion );
1449  m_TotalField->SetBufferedRegion( m_FieldRegion );
1450  m_TotalField->SetLargestPossibleRegion( m_FieldRegion );
1451  m_TotalField->Allocate();
1452 
1453  VectorType disp;
1454  for (unsigned int t=0; t<ImageDimension; t++)
1455  {
1456  disp[t]=0.0;
1457  }
1458  FieldIterator fieldIter( m_TotalField, m_FieldRegion );
1459  fieldIter.GoToBegin();
1460  for(; !fieldIter.IsAtEnd(); ++fieldIter )
1461  {
1462  fieldIter.Set(disp);
1463  }
1464  }
1465 
1466  if (onlywriteimages)
1467  {
1468  warper = WarperType::New();
1469  warper->SetInput( m_OriginalMovingImage );
1470  warper->SetDeformationField( fullField );
1471  warper->SetInterpolator( interpolator );
1472  warper->SetOutputOrigin( m_FixedImage->GetOrigin() );
1473  warper->SetOutputSpacing( m_FixedImage->GetSpacing() );
1474  warper->SetOutputDirection( m_FixedImage->GetDirection() );
1475  typename MovingImageType::PixelType padValue = 0;
1476  warper->SetEdgePaddingValue( padValue );
1477  warper->Update();
1478  m_WarpedImage=warper->GetOutput();
1479  }
1480  else if (m_TotalField)
1481  {
1482 
1483  typename InterpolatorType::ContinuousIndexType inputIndex;
1484 
1485  typedef typename InterpolatorType::OutputType InterpolatedType;
1486 
1487  InterpolatedType interpolatedValue;
1488 
1489  m_Interpolator->SetInputImage(fullField);
1490 
1491  typename FixedImageType::IndexType index;
1492  FieldIterator totalFieldIter( m_TotalField, m_TotalField->GetLargestPossibleRegion() );
1493  totalFieldIter.GoToBegin();
1494  unsigned int jj;
1495  float pathsteplength=0;
1496  while( !totalFieldIter.IsAtEnd() )
1497  {
1498  index=totalFieldIter.GetIndex();
1499  for (jj=0; jj<ImageDimension; jj++)
1500  {
1501  inputIndex[jj]=(WarperCoordRepType) index[jj];
1502  interpolatedValue[jj]=0.0;
1503  }
1504  if( m_Interpolator->IsInsideBuffer( inputIndex ) )
1505  {
1506 
1507  interpolatedValue =
1508  m_Interpolator->EvaluateAtContinuousIndex( inputIndex );
1509 
1510  }
1511  VectorType interped;
1512  float temp=0.0;
1513  for (jj = 0; jj < ImageDimension; jj++)
1514  {
1515  interped[jj] = interpolatedValue[jj];
1516  temp += interped[jj]*interped[jj];
1517  }
1518  pathsteplength += vcl_sqrt(temp);
1519  m_TotalField->SetPixel(index,m_TotalField->GetPixel(index)+interped);
1520  ++totalFieldIter;
1521  }
1522  std::cout << " incremental path length " << pathsteplength << std::endl;
1523 
1524 
1525  // then we set the field to zero
1526 
1527  {
1528  FieldIterator fieldIter( m_Field, m_Field->GetLargestPossibleRegion() );
1529  fieldIter.GoToBegin();
1530  while( !fieldIter.IsAtEnd() )
1531  {
1532  VectorType disp;
1533  disp.Fill(0.0);
1534  fieldIter.Set(disp);
1535  ++fieldIter;
1536  }
1537  }
1538  // now do the same for the solver
1539  unsigned int ii;
1540  Node::ArrayType* nodes = &(mySolver.node);
1541  for( Node::ArrayType::iterator node=nodes->begin(); node != nodes->end(); node++)
1542  {
1543  // Now put it into the solution!
1544  for (ii=0; ii < ImageDimension; ii++)
1545  {
1546  mySolver.GetLinearSystemWrapper()->
1547  SetSolutionValue((*node)->GetDegreeOfFreedom(ii),0.0,mySolver.TotalSolutionIndex);
1548  mySolver.GetLinearSystemWrapper()->
1549  SetSolutionValue((*node)->GetDegreeOfFreedom(ii),0.0,mySolver.SolutionTMinus1Index);
1550  }
1551  }
1552 
1553 
1554  warper = WarperType::New();
1555  warper->SetInput( m_OriginalMovingImage );
1556  warper->SetDeformationField( m_TotalField );
1557  warper->SetInterpolator( interpolator );
1558  warper->SetOutputOrigin( m_FixedImage->GetOrigin() );
1559  warper->SetOutputSpacing( m_FixedImage->GetSpacing() );
1560  warper->SetOutputDirection( m_FixedImage->GetDirection() );
1561  typename FixedImageType::PixelType padValue = 0;
1562  warper->SetEdgePaddingValue( padValue );
1563  warper->Update();
1564 
1565  // set it as the new moving image
1566 
1567  this->SetMovingImage( warper->GetOutput() );
1568 
1569  m_WarpedImage=m_MovingImage;
1570 
1571 
1572  // now repeat the pyramid if necessary
1573 
1574  if ( resize )
1575  {
1576  std::cout << " re-doing pyramid " << std::endl;
1577  typename FixedPyramidType::Pointer m_MovingPyramid;
1578  m_MovingPyramid = NULL;
1579  m_MovingPyramid = FixedPyramidType::New();
1580  m_MovingPyramid->SetInput( m_MovingImage);
1581  m_MovingPyramid->SetNumberOfLevels( 1 );
1582  typedef typename FixedPyramidType::ScheduleType ScheduleType;
1583  ScheduleType SizeReductionMoving=m_MovingPyramid->GetSchedule();
1584 
1585  ii=m_CurrentLevel;
1586  for (jj=0; jj<ImageDimension; jj++)
1587  {
1588  unsigned int scale=m_ImageScaling[jj]/(unsigned int)vcl_pow(2.0,(double)ii);
1589  if (scale < 1) scale=1;
1590  SizeReductionMoving[0][jj]=scale;
1591  }
1592 
1593  m_MovingPyramid->SetSchedule(SizeReductionMoving);
1594  m_MovingPyramid->GetOutput( 0 )->Update();
1595  m_Load->SetMovingImage(m_MovingPyramid->GetOutput(0));
1596 
1597  std::cout << " re-doing pyramid done " << std::endl;
1598  }
1599  else
1600  {
1601  m_Load->SetMovingImage(this->GetMovingImage( ));
1602  }
1603  }
1604  std::cout << " Enforcing diffeomorphism done " << std::endl;
1605  }
1606 }
1607 
1608 template<class TMovingImage,class TFixedImage>
1610 {
1611 
1612  // for image output
1613  std::ofstream fbin;
1614  std::string exte=".mhd";
1615  std::string fnum;
1616 
1617  OStringStream buf;
1618  buf<<(m_FileCount+10);
1619  fnum=std::string(buf.str().c_str());
1620 
1621  std::string fullfname=(fname+fnum+exte);
1622 
1623  if (!m_WarpedImage) return;
1624 
1625  typedef MinimumMaximumImageFilter<MovingImageType> MinMaxFilterType;
1626  typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New();
1627  minMaxFilter->SetInput( m_WarpedImage );
1628  minMaxFilter->Update();
1629  float min = minMaxFilter->GetMinimum();
1630  double shift = -1.0 * static_cast<double>( min );
1631  double scale = static_cast<double>( minMaxFilter->GetMaximum() );
1632  scale += shift;
1633  scale = 255.0 / scale;
1635  typename FilterType::Pointer filter = FilterType::New();
1636  filter->SetInput( m_WarpedImage );
1637  filter->SetShift( shift );
1638  filter->SetScale( scale );
1639  filter->Update();
1640 
1641 
1642  typedef unsigned char PIX;
1643  typedef itk::Image<PIX,ImageDimension> WriteImageType;
1645  typename CasterType1::Pointer caster1 = CasterType1::New();
1646  caster1->SetInput(filter->GetOutput());
1647  caster1->Update();
1650  writer->SetFileName(fullfname.c_str());
1651  writer->SetInput(caster1->GetOutput() );
1652  writer->Write();
1653 
1654  m_FileCount++;
1655 
1656 }
1657 
1658 template<class TMovingImage,class TFixedImage>
1661 {
1662  // re-size the vector field
1663  if (!field) field=m_Field;
1664 
1665  std::cout << " input field size " << m_Field->GetLargestPossibleRegion().GetSize()
1666  << " expand factors ";
1667  VectorType pad;
1668  for (unsigned int i=0; i< ImageDimension; i++)
1669  {
1670  pad[i]=0.0;
1671  std::cout << expandFactors[i] << " ";
1672  }
1673  std::cout << std::endl;
1674  typename ExpanderType::Pointer m_FieldExpander = ExpanderType::New();
1675  m_FieldExpander->SetInput(field);
1676  m_FieldExpander->SetExpandFactors( expandFactors );
1677  // use default
1678  m_FieldExpander->SetEdgePaddingValue( pad );
1679  m_FieldExpander->UpdateLargestPossibleRegion();
1680 
1681  m_FieldSize=m_FieldExpander->GetOutput()->GetLargestPossibleRegion().GetSize();
1682 
1683  return m_FieldExpander->GetOutput();
1684 }
1685 
1686 template<class TMovingImage,class TFixedImage>
1688 {
1689 
1690  // Here, we need to iterate through the nodes, get the nodal coordinates,
1691  // sample the VF at the node and place the values in the SolutionVector.
1692  unsigned int ii;
1693  Node::ArrayType* nodes = &(mySolver.node);
1694  Element::VectorType coord;
1695  VectorType SolutionAtNode;
1696 
1697  m_Interpolator->SetInputImage(m_Field);
1698 
1699  for( Node::ArrayType::iterator node=nodes->begin(); node != nodes->end(); node++)
1700  {
1701  coord=(*node)->GetCoordinates();
1702  typename InterpolatorType::ContinuousIndexType inputIndex;
1703  typedef typename InterpolatorType::OutputType InterpolatedType;
1704  InterpolatedType interpolatedValue;
1705 
1706 
1707  for (unsigned int jj=0; jj<ImageDimension; jj++)
1708  {
1709  inputIndex[jj]=(CoordRepType) coord[jj];
1710  interpolatedValue[jj]=0.0;
1711  }
1712  if( m_Interpolator->IsInsideBuffer( inputIndex ) )
1713  {
1714  interpolatedValue =
1715  m_Interpolator->EvaluateAtContinuousIndex( inputIndex );
1716  }
1717 
1718  for (unsigned int jj=0; jj<ImageDimension; jj++)
1719  {
1720  SolutionAtNode[jj]=interpolatedValue[jj];
1721  }
1722 
1723  // Now put it into the solution!
1724  for (ii=0; ii < ImageDimension; ii++)
1725  {
1726  Float Sol=SolutionAtNode[ii];
1727  mySolver.GetLinearSystemWrapper()->
1728  SetSolutionValue((*node)->GetDegreeOfFreedom(ii),Sol,mySolver.TotalSolutionIndex);
1729  mySolver.GetLinearSystemWrapper()->
1730  SetSolutionValue((*node)->GetDegreeOfFreedom(ii),Sol,mySolver.SolutionTMinus1Index);
1731  }
1732  }
1733 
1734 }
1735 
1736 template<class TMovingImage,class TFixedImage>
1738 {
1739  FieldIterator fieldIter( m_Field, m_Field->GetLargestPossibleRegion() );
1740  fieldIter.GoToBegin();
1741  unsigned int ct=0;
1742 
1743  float max=0;
1744  while( !fieldIter.IsAtEnd() )
1745  {
1746  VectorType disp=fieldIter.Get();
1747  if ((ct % modnum) == 0) std::cout << " field pix " << fieldIter.Get() << std::endl;
1748  for (unsigned int i=0; i<ImageDimension;i++)
1749  {
1750  if (vcl_fabs(disp[i]) > max )
1751  {
1752  max=vcl_fabs(disp[i]);
1753  }
1754  }
1755  ++fieldIter;
1756  ct++;
1757 
1758  }
1759  std::cout << " max vec " << max << std::endl;
1760 }
1761 
1762 template<class TMovingImage,class TFixedImage>
1764 {
1765 
1766  vnl_vector<Float> LastResolutionSolution;
1767 
1768  // Setup a multi-resolution pyramid
1769  typedef typename FixedPyramidType::ScheduleType ScheduleType;
1770 
1771  for (m_CurrentLevel=0; m_CurrentLevel<m_MaxLevel; m_CurrentLevel++)
1772  {
1773  std::cout << " beginning level " << m_CurrentLevel << std::endl;
1774  // Setup a multi-resolution pyramid
1775 
1776  SolverType SSS;
1777  typename FixedImageType::SizeType nextLevelSize;
1778  nextLevelSize.Fill( 0 );
1779  typename FixedImageType::SizeType lastLevelSize;
1780 
1781  if (m_Maxiters[m_CurrentLevel] > 0)
1782  {
1783  {
1784  typename FixedPyramidType::Pointer m_MovingPyramid;
1785  typename FixedPyramidType::Pointer m_FixedPyramid;
1786  m_MovingPyramid = FixedPyramidType::New();
1787  m_FixedPyramid = FixedPyramidType::New();
1788 
1789  m_MovingPyramid->SetInput( m_MovingImage);
1790  m_FixedPyramid->SetInput( m_FixedImage);
1791 
1792  // set schedule by specifying the number of levels;
1793  m_MovingPyramid->SetNumberOfLevels( 1 );
1794  m_FixedPyramid->SetNumberOfLevels( 1 );
1795 
1796  ScheduleType SizeReductionMoving=m_MovingPyramid->GetSchedule();
1797  ScheduleType SizeReductionFixed=m_FixedPyramid->GetSchedule();
1798 
1799  unsigned int ii=m_CurrentLevel;
1800  for (unsigned int jj=0; jj<ImageDimension; jj++)
1801  {
1802  unsigned int scale=m_ImageScaling[jj]/(unsigned int)vcl_pow(2.0,(double)ii);
1803  unsigned int nextscale = m_ImageScaling[jj]/(unsigned int)vcl_pow(2.0,(double)(ii+1));
1804  if (scale < 1) scale=1;
1805  if (nextscale < 1) nextscale=1;
1806  SizeReductionMoving[0][jj]=scale;
1807  SizeReductionFixed[0][jj]=scale;
1808  nextLevelSize[jj]=(long int) ( (float) m_FullImageSize[jj] / (float) nextscale );
1809  }
1810 
1811  m_MovingPyramid->SetSchedule(SizeReductionMoving);
1812  m_FixedPyramid->SetSchedule(SizeReductionFixed);
1813  m_MovingPyramid->GetOutput( 0 )->Update();
1814  m_FixedPyramid->GetOutput( 0 )->Update();
1815 
1816  lastLevelSize=m_CurrentLevelImageSize;
1817  m_CurrentLevelImageSize=m_FixedPyramid->GetOutput( 0 )->GetLargestPossibleRegion().GetSize();
1818  if (m_CurrentLevel == m_MaxLevel-1) nextLevelSize=m_CurrentLevelImageSize;
1819 
1820  double scaling[ImageDimension];
1821  for (unsigned int d=0; d < ImageDimension; d++)
1822  {
1823  m_CurrentImageScaling[d]=SizeReductionMoving[0][d];
1824  if (m_CurrentLevel == 0) scaling[d]=(double)SizeReductionMoving[0][d];
1825  else scaling[d]=(double) lastLevelSize[d]/(double) m_CurrentLevelImageSize[d];
1826  std::cout << " scaling " << scaling[d] << std::endl;
1827  }
1828  double MeshResolution=(double)this->m_MeshPixelsPerElementAtEachResolution(m_CurrentLevel);
1829 
1830  SSS.SetDeltatT(m_Dt);
1831  SSS.SetRho(m_Rho[m_CurrentLevel]);
1832  SSS.SetAlpha(m_Alpha);
1833 
1834  CreateMesh(MeshResolution,SSS,m_CurrentLevelImageSize);
1835  ApplyLoads(SSS,m_CurrentLevelImageSize,scaling);
1836  ApplyImageLoads(SSS,m_MovingPyramid->GetOutput(0),
1837  m_FixedPyramid->GetOutput(0));
1838 
1839  m_MovingPyramid = FixedPyramidType::New();
1840  m_FixedPyramid = FixedPyramidType::New();
1841 
1842  }
1843 
1844  unsigned int ndofpernode=(m_Element)->GetNumberOfDegreesOfFreedomPerNode();
1845  unsigned int numnodesperelt=(m_Element)->GetNumberOfNodes()+1;
1846  unsigned int ndof=SSS.GetNumberOfDegreesOfFreedom();
1847  unsigned int nzelts;
1848  if (!m_ReadMeshFile) nzelts=numnodesperelt*ndofpernode*ndof;
1849  else nzelts=((2*numnodesperelt*ndofpernode*ndof > 25*ndof) ? 2*numnodesperelt*ndofpernode*ndof : 25*ndof);
1850 
1851  LinearSystemWrapperItpack itpackWrapper;
1852  unsigned int maxits=2*SSS.GetNumberOfDegreesOfFreedom();
1853  itpackWrapper.SetMaximumNumberIterations(maxits);
1854  itpackWrapper.SetTolerance(1.e-1);
1855  itpackWrapper.JacobianConjugateGradient();
1856  itpackWrapper.SetMaximumNonZeroValuesInMatrix(nzelts);
1857  SSS.SetLinearSystemWrapper(&itpackWrapper);
1858 
1859  if( m_UseMassMatrix )
1860  {
1861  SSS.AssembleKandM();
1862  }
1863  else
1864  {
1865  SSS.InitializeForSolution();
1866  SSS.AssembleK();
1867  }
1868  if (m_CurrentLevel > 0)
1869  {
1870  this->SampleVectorFieldAtNodes(SSS);
1871  }
1872  this->IterativeSolve(SSS);
1873  }
1874 
1875  // now expand the field for the next level, if necessary.
1876  if ( m_CurrentLevel == m_MaxLevel-1 && m_Field)
1877  {
1878  PrintVectorField(900000);
1879  std:: cout << " field size " << m_Field->GetLargestPossibleRegion().GetSize() << std::endl;
1880 
1881  }
1882  else if (m_CurrentLevel < m_MaxLevel-1 && m_Field)
1883  {
1884  ExpandFactorsType expandFactors[ImageDimension];
1885  for (unsigned int ef=0; ef<ImageDimension; ef++)
1886  {
1887  expandFactors[ef]=(ExpandFactorsType)
1888  ((float) nextLevelSize[ef]/(float)m_CurrentLevelImageSize[ef]);
1889  }
1890  m_Field=ExpandVectorField(expandFactors,m_Field);
1891  // this works - linear interp and expansion of vf
1892  PrintVectorField(900000);
1893  std:: cout << " field size " << m_Field->GetLargestPossibleRegion().GetSize() << std::endl;
1894 
1895  }
1896 
1897  std::cout << " end level " << m_CurrentLevel;
1898 
1899 
1900  }// end image resolution loop
1901 
1902  if (m_TotalField)
1903  {
1904  std::cout << " copy field " << m_TotalField->GetLargestPossibleRegion().GetSize()
1905  << " to " << m_Field->GetLargestPossibleRegion().GetSize() << std::endl;
1906  FieldIterator fieldIter( m_TotalField, m_TotalField->GetLargestPossibleRegion() );
1907  fieldIter.GoToBegin();
1908  for(; !fieldIter.IsAtEnd(); ++fieldIter )
1909  {
1910  typename FixedImageType::IndexType index = fieldIter.GetIndex();
1911  m_TotalField->SetPixel(index,m_TotalField->GetPixel(index)
1912  + m_Field->GetPixel(index));
1913  }
1914  }
1915  return;
1916 }
1917 
1918 template<class TMovingImage,class TFixedImage>
1920 {
1921  Float SimE=m_Load->EvaluateMetricGivenSolution(&(mySolver.el),t);
1922 
1923  Float maxsim=1.0;
1924  for (unsigned int i=0; i< ImageDimension; i++)
1925  {
1926  maxsim *= (Float)m_FullImageSize[i];
1927  }
1928  if ( m_WhichMetric != 0)
1929  {
1930  SimE=maxsim-SimE;
1931  }
1932  return vcl_fabs(static_cast<double>(SimE)); //+defe;
1933 }
1934 
1935 template<class TMovingImage,class TFixedImage>
1937 {
1938  // see Numerical Recipes
1939 
1940  const Float Gold=1.618034;
1941  const Float Glimit=100.0;
1942  const Float Tiny=1.e-20;
1943  Float ax=0.0;
1944  Float bx=1.0;
1945  Float fa=vcl_fabs(EvaluateResidual(mySolver, ax));
1946  Float fb=vcl_fabs(EvaluateResidual(mySolver, bx));
1947 
1948  Float dum;
1949  if ( fb > fa )
1950  {
1951  dum=ax; ax=bx; bx=dum;
1952  dum=fb; fb=fa; fa=dum;
1953  }
1954 
1955  Float cx=bx+Gold*(bx-ax); // first guess for c - the 3rd pt needed to bracket the min
1956  Float fc=vcl_fabs(EvaluateResidual(mySolver, cx));
1957 
1958  Float ulim,u,r,q,fu;
1959  while (fb > fc )
1960  // && vcl_fabs(ax) < 3. && vcl_fabs(bx) < 3. && vcl_fabs(cx) < 3.)
1961  {
1962  r=(bx-ax)*(fb-fc);
1963  q=(bx-cx)*(fb-fa);
1964  Float denom=(2.0*mySolver.GSSign(mySolver.GSMax(vcl_fabs(q-r),Tiny),q-r));
1965  u=(bx)-((bx-cx)*q-(bx-ax)*r)/denom;
1966  ulim=bx + Glimit*(cx-bx);
1967  if ((bx-u)*(u-cx) > 0.0)
1968  {
1969  fu=vcl_fabs(EvaluateResidual(mySolver, u));
1970  if (fu < fc)
1971  {
1972  ax=bx;
1973  bx=u;
1974  *a=ax; *b=bx; *c=cx;
1975  return;
1976  }
1977  else if (fu > fb)
1978  {
1979  cx=u;
1980  *a=ax; *b=bx; *c=cx;
1981  return;
1982  }
1983 
1984  u=cx+Gold*(cx-bx);
1985  fu=vcl_fabs(EvaluateResidual(mySolver, u));
1986 
1987  }
1988  else if ( (cx-u)*(u-ulim) > 0.0)
1989  {
1990  fu=vcl_fabs(EvaluateResidual(mySolver, u));
1991  if (fu < fc)
1992  {
1993  bx=cx; cx=u; u=cx+Gold*(cx-bx);
1994  fb=fc; fc=fu; fu=vcl_fabs(EvaluateResidual(mySolver, u));
1995  }
1996 
1997  }
1998  else if ( (u-ulim)*(ulim-cx) >= 0.0)
1999  {
2000  u=ulim;
2001  fu=vcl_fabs(EvaluateResidual(mySolver, u));
2002  }
2003  else
2004  {
2005  u=cx+Gold*(cx-bx);
2006  fu=vcl_fabs(EvaluateResidual(mySolver, u));
2007  }
2008 
2009  ax=bx; bx=cx; cx=u;
2010  fa=fb; fb=fc; fc=fu;
2011 
2012  }
2013 
2014  if ( vcl_fabs(ax) > 1.e3 || vcl_fabs(bx) > 1.e3 || vcl_fabs(cx) > 1.e3)
2015  {
2016  ax=-2.0; bx=1.0; cx=2.0;
2017  } // to avoid crazy numbers caused by bad bracket (u goes nuts)
2018 
2019  *a=ax; *b=bx; *c=cx;
2020  return;
2021 }
2022 
2023 
2024 template<class TMovingImage,class TFixedImage>
2026 {
2027  // We should now have a, b and c, as well as f(a), f(b), f(c),
2028  // where b gives the minimum energy position;
2029  Float ax, bx, cx;
2030  FindBracketingTriplet(mySolver,&ax, &bx, &cx);
2031 
2032  const Float R=0.6180339;
2033  const Float C=(1.0-R);
2034 
2035  Float x0=ax;
2036  Float x1;
2037  Float x2;
2038  Float x3=cx;
2039  if (vcl_fabs(cx-bx) > vcl_fabs(bx-ax))
2040  {
2041  x1=bx;
2042  x2=bx+C*(cx-bx);
2043  }
2044  else
2045  {
2046  x2=bx;
2047  x1=bx-C*(bx-ax);
2048  }
2049 
2050  Float f1=vcl_fabs(EvaluateResidual(mySolver, x1));
2051  Float f2=vcl_fabs(EvaluateResidual(mySolver, x2));
2052  unsigned int iters=0;
2053  while (vcl_fabs(x3-x0) > tol*(vcl_fabs(x1)+vcl_fabs(x2)) && iters < MaxIters)
2054  {
2055  iters++;
2056  if (f2 < f1)
2057  {
2058  x0=x1; x1=x2; x2=R*x1+C*x3;
2059  f1=f2; f2=vcl_fabs(EvaluateResidual(mySolver, x2));
2060  }
2061  else
2062  {
2063  x3=x2; x2=x1; x1=R*x2+C*x0;
2064  f2=f1; f1=vcl_fabs(EvaluateResidual(mySolver, x1));
2065  }
2066  }
2067  Float xmin,fmin;
2068  if (f1<f2)
2069  {
2070  xmin=x1;
2071  fmin=f1;
2072  }
2073  else
2074  {
2075  xmin=x2;
2076  fmin=f2;
2077  }
2078 
2079  mySolver.SetEnergyToMin(xmin);
2080  std:: cout << " emin " << fmin << " at xmin " << xmin << std::endl;
2081  return vcl_fabs(static_cast<double>(fmin));
2082 }
2083 
2084 template<class TMovingImage,class TFixedImage>
2086 PrintSelf(std::ostream& os, Indent indent) const
2087 {
2088  Superclass::PrintSelf( os, indent );
2089 
2090  if (m_Load)
2091  {
2092  os << indent << "Load = " << m_Load;
2093  }
2094  else
2095  {
2096  os << indent << "Load = " << "(None)" << std::endl;
2097  }
2098  if (m_Interpolator)
2099  {
2100  os << indent << "Interpolator = " << m_Interpolator;
2101  }
2102  else
2103  {
2104  os << indent << "Interpolator = " << "(None)" << std::endl;
2105  }
2106 }
2107 
2108 }} // end namespace itk::fem
2109 
2110 #endif

Generated at Sat Feb 2 2013 23:37:08 for Orfeo Toolbox with doxygen 1.8.1.1