Shapeworks Studio  2.1
Shape analysis software suite
itkPSMEntropyModelFilter.h
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef __itkPSMEntropyModelFilter_h
19 #define __itkPSMEntropyModelFilter_h
20 
21 #include "itkInPlaceImageFilter.h"
22 #include "itkPSMParticleSystem.h"
23 #include "itkPSMImplicitSurfaceDomain.h"
24 #include "itkPSMShapeEntropyFunction.h"
25 #include "itkPSMParticleEntropyFunction.h"
26 #include "itkPSMGradientDescentOptimizer.h"
27 #include "itkPSMContainerArrayAttribute.h"
28 //#include "itkPSMMeanCurvatureAttribute.h"
29 #include "itkPSMSurfaceNeighborhood.h"
30 #include "itkPSMTwoCostFunction.h"
31 #include "itkCommand.h"
32 
33 namespace itk
34 {
35 
77 template <class TImage, class TShapeMatrix = PSMShapeMatrixAttribute<double, TImage::ImageDimension> >
78 class ITK_EXPORT PSMEntropyModelFilter
79  : public InPlaceImageFilter<TImage,TImage>
80 {
81  public:
84  typedef InPlaceImageFilter<TImage,TImage> Superclass;
85  typedef SmartPointer<Self> Pointer;
86  typedef SmartPointer<const Self> ConstPointer;
87 
89  itkStaticConstMacro(Dimension, unsigned int, TImage::ImageDimension);
90 
93 
95  typedef TShapeMatrix ShapeMatrixType;
96  typedef typename ShapeMatrixType::Pointer ShapeMatrixPointerType;
97 
99  itkNewMacro(Self);
100 
102  itkTypeMacro(PSMEntropyModelFilter, InPlaceImageFilter);
103 
105  typedef TImage ImageType;
106 
108  typedef typename ImageType::PointType PointType;
109 
112 
115  {
116  vnl_vector_fixed<double,Dimension> x;
117  vnl_vector_fixed<double,Dimension> y;
118  vnl_vector_fixed<double,Dimension> z;
119  bool valid;
120 
122  { valid = false; }
123 
124  };
125 
132  void SetInput(const std::string& s, itk::DataObject *o)
133  {
134  Superclass::SetInput(s,o);
135  }
136  void SetInput(const TImage *image)
137  {
138  this->SetInput(0, image);
139  }
140  void SetInput( unsigned int index, const TImage * image )
141  {
142  if (this->GetNumberOfInputs() < index+1)
143  {
144  this->SetNumberOfRequiredInputs(index+1);
145  }
146 
147  this->ProcessObject::SetNthInput(index, const_cast< TImage *>( image ) );
148  }
149 
166  void SetNumberOfScales(unsigned int n)
167  {
168  m_NumberOfScales = n;
169  if (m_Tolerances.size() < n)
170  {
171  m_Tolerances.resize(n);
172  }
173  if (m_MaximumNumberOfIterations.size() < n)
174  {
175  m_MaximumNumberOfIterations.resize(n);
176  }
177  if (m_RegularizationInitial.size() < n)
178  {
179  m_RegularizationInitial.resize(n);
180  }
181  if (m_RegularizationFinal.size() < n)
182  {
183  m_RegularizationFinal.resize(n);
184  }
185  if (m_RegularizationDecaySpan.size() < n)
186  {
187  m_RegularizationDecaySpan.resize(n);
188  }
189 
190  }
191  itkGetMacro(NumberOfScales, unsigned int);
192  itkSetMacro(CurrentScale, unsigned int);
193  itkGetMacro(CurrentScale, unsigned int);
194 
197  // void SetInputModel(const ParticleModel &model);
198 
202  void SetInputCorrespondencePoints(unsigned int index, const std::vector<PointType> &corr)
203  {
204  if (m_InputCorrespondencePoints.size() < (index+1))
205  {
206  m_InputCorrespondencePoints.resize(index+1);
207  }
208  m_InputCorrespondencePoints[index] = corr;
209  }
210 
212  itkGetObjectMacro(ParticleSystem, ParticleSystemType);
213  itkGetConstObjectMacro(ParticleSystem, ParticleSystemType);
214 
221  {
222  return m_ParticleEntropyFunction;
223  }
224 
230  {
231  return m_ShapeEntropyFunction;
232  }
233 
235  itkGetObjectMacro(Optimizer, OptimizerType);
236  itkGetConstObjectMacro(Optimizer, OptimizerType);
237 
243  void SetMaximumNumberOfIterations(const std::vector<unsigned int> &n)
244  {
245  m_MaximumNumberOfIterations = n;
246  }
247  void SetMaximumNumberOfIterations(unsigned int n, unsigned int i = 0)
248  {
249  // Resize the tolerances list if necessary
250  if (m_MaximumNumberOfIterations.size() < i+1)
251  {
252  itkExceptionMacro("Specified scale does not exist. Call SetNumberOfScales before SetMaximumNumberOfIterations");
253  }
254  m_MaximumNumberOfIterations[i] = n;
255 
256  if (m_CurrentScale == i)
257  {
258  m_Optimizer->SetMaximumNumberOfIterations(n);
259  }
260 
261  }
262  unsigned int GetMaximumNumberOfIterations(unsigned int i = 0) const
263  {
264  if (m_MaximumNumberOfIterations.size() < i+1)
265  {
266  itkExceptionMacro("Specified scale does not exist.");
267  }
268  return m_MaximumNumberOfIterations[i];
269  }
270 
274  unsigned int GetNumberOfElapsedIterations() const
275  {
276  return m_Optimizer->GetNumberOfIterations();
277  }
278 
282  itkGetMacro(Initialized, bool);
283 
289  itkGetMacro(Initializing, bool);
290  itkSetMacro(Initializing, bool);
291 
299  void SetShapeEntropyWeighting(double w)
300  {
301  m_CostFunction->SetRelativeGradientScaling(w);
302  }
303  double GetShapeEntropyWeighting() const
304  {
305  return m_CostFunction->GetRelativeGradientScaling();
306  }
307 
308  /* /\** This method simply calls the appropriate method in */
309  /* PSMParticleEntropyFunction. It is exposed here for */
310  /* convenience. The minimum radius of the neighborhood of points */
311  /* that are considered in the entropy calculation. The neighborhood */
312  /* is a spherical radius in 3D space. The actual radius used in a */
313  /* calculation may exceed this value, but will not exceed the */
314  /* MaximumNeighborhoodRadius. This parameter should ALWAYS be set by */
315  /* an application, because it must be scaled according to the */
316  /* spacing in the image. A good value is typically 5x the spacing */
317  /* of the highest-resolution dimension (the dimension with the */
318  /* smallest spacing. *\/ */
319  /* void SetMinimumNeighborhoodRadius( double s) */
320  /* { this->m_ParticleEntropyFunction->SetMinimumNeighborhoodRadius(s); } */
321  /* double GetMinimumNeighborhoodRadius() const */
322  /* { return this->m_ParticleEntropyFunction->GetMinimumNeighborhoodRadius(); } */
323 
324  /* /\** Maximum radius of the neighborhood of points that are considered */
325  /* in the calculation. The neighborhood is a spherical radius in 3D */
326  /* space. MaximumNeighborhoodRadius should be set to a value */
327  /* equal-to or less-than the length of the largest dimension of the */
328  /* image. This parameter should ALWAYS be set by an application, */
329  /* since this class cannot know by default the size of input */
330  /* images. The radius value should be specified in real-world */
331  /* coordinates. *\/ */
332  /* void SetMaximumNeighborhoodRadius( double s) */
333  /* { this->m_ParticleEntropyFunction->SetMaximumNeighborhoodRadius(s); } */
334  /* double GetMaximumNeighborhoodRadius() const */
335  /* { return this->m_ParticleEntropyFunction->GetMaximumNeighborhoodRadius(); } */
336 
342  const std::vector<double> &GetShapePCAVariances() const
343  {
344  return m_ShapeEntropyFunction->GetShapePCAVariances();
345  }
346 
367  void SetRegularizationInitial(const std::vector<double> &v)
368  {
369  if (v.size() != m_RegularizationInitial.size())
370  {
371  itkExceptionMacro("Number of variables does not match number of scales. Call SetNumberOfScales first.");
372  }
373  m_RegularizationInitial = v;
374  }
375  void SetRegularizationInitial(double t, unsigned int i=0)
376  {
377  // Resize the tolerances list if necessary
378  if (m_RegularizationInitial.size() < i+1)
379  {
380  itkExceptionMacro("Specified scale does not exist. Call SetNumberOfScales before SetTolerance");
381  }
382  m_RegularizationInitial[i] = t;
383 
384  if (m_CurrentScale == i)
385  {
386  m_Optimizer->SetTolerance(t);
387  }
388  }
389  double GetRegularizationInitial(unsigned int i=0) const
390  {
391  if (m_RegularizationInitial.size() < i+1)
392  {
393  itkExceptionMacro("Specified scale does not exist");
394  }
395  else return m_RegularizationInitial[i];
396  }
397  void SetRegularizationFinal(const std::vector<double> &v)
398  {
399  if (v.size() != m_RegularizationFinal.size())
400  {
401  itkExceptionMacro("Number of variables does not match number of scales. Call SetNumberOfScales first.");
402  }
403  m_RegularizationFinal = v;
404  }
405  void SetRegularizationFinal(double t, unsigned int i=0)
406  {
407  // Resize the tolerances list if necessary
408  if (m_RegularizationFinal.size() < i+1)
409  {
410  itkExceptionMacro("Specified scale does not exist. Call SetNumberOfScales before SetTolerance");
411  }
412  m_RegularizationFinal[i] = t;
413 
414  if (m_CurrentScale == i)
415  {
416  m_Optimizer->SetTolerance(t);
417  }
418  }
419  double GetRegularizationFinal(unsigned int i=0) const
420  {
421  if (m_RegularizationFinal.size() < i+1)
422  {
423  itkExceptionMacro("Specified scale does not exist");
424  }
425  else return m_RegularizationFinal[i];
426  }
427  void SetRegularizationDecaySpan(const std::vector<double> &v)
428  {
429  if (v.size() != m_RegularizationDecaySpan.size())
430  {
431  itkExceptionMacro("Number of variables does not match number of scales. Call SetNumberOfScales first.");
432  }
433  m_RegularizationDecaySpan = v;
434  }
435  void SetRegularizationDecaySpan(double t, unsigned int i=0)
436  {
437  // Resize the tolerances list if necessary
438  if (m_RegularizationDecaySpan.size() < i+1)
439  {
440  itkExceptionMacro("Specified scale does not exist. Call SetNumberOfScales before SetTolerance");
441  }
442  m_RegularizationDecaySpan[i] = t;
443 
444  if (m_CurrentScale == i)
445  {
446  m_Optimizer->SetTolerance(t);
447  }
448  }
449  double GetRegularizationDecaySpan(unsigned int i=0) const
450  {
451  if (m_RegularizationDecaySpan.size() < i+1)
452  {
453  itkExceptionMacro("Specified scale does not exist");
454  }
455  else return m_RegularizationDecaySpan[i];
456  }
457 
462  {
463  m_ShapeEntropyFunction->SetMinimumVariance(r);
464  }
465  void SetMinimumVariance(double r)
466  {
467  m_ShapeEntropyFunction->SetMinimumVariance(r);
468  }
469  double GetRegularizationConstant() const
470  {
471  return m_ShapeEntropyFunction->GetMinimumVariance();
472  }
473  double GetMinimumVariance() const
474  {
475  return m_ShapeEntropyFunction->GetMinimumVariance();
476  }
477 
486  void SetTolerance(const std::vector<double> &v)
487  {
488  if (v.size() != m_Tolerances.size())
489  {
490  itkExceptionMacro("Number of variables does not match number of scales. Call SetNumberOfScales first.");
491  }
492  m_Tolerances = v;
493  }
494  void SetTolerance(double t, unsigned int i = 0)
495  {
496  // Resize the tolerances list if necessary
497  if (m_Tolerances.size() < i+1)
498  {
499  itkExceptionMacro("Specified scale does not exist. Call SetNumberOfScales before SetTolerance");
500  }
501  m_Tolerances[i] = t;
502 
503  if (m_CurrentScale == i)
504  {
505  m_Optimizer->SetTolerance(t);
506  }
507  }
508  double GetTolerance(unsigned int i = 0) const
509  {
510  if (m_Tolerances.size() > i)
511  {
512  return m_Tolerances[i];
513  }
514  else
515  {
516  itkExceptionMacro("Specified scale does not exist.");
517  }
518  }
519 
525  itkGetMacro(ShapeMatrix, ShapeMatrixPointerType);
526  const ShapeMatrixType *GetShapeMatrix() const
527  {
528  return m_ShapeMatrix;
529  }
530 
534  bool CreateSingleCorrespondence();
535 
539  void SetDomainName(const std::string &s, unsigned int i);
540 
544  unsigned int GetDomainIndexByName(const std::string &name);
545 
548  void AddCuttingPlane(const vnl_vector_fixed<double,3> &x,
549  const vnl_vector_fixed<double,3> &y,
550  const vnl_vector_fixed<double,3> &z,
551  unsigned int domain);
552  void AddCuttingPlane(const vnl_vector_fixed<double,3> &x,
553  const vnl_vector_fixed<double,3> &y,
554  const vnl_vector_fixed<double,3> &z,
555  const std::string &s)
556  {
557  this->AddCuttingPlane(x,y,z,this->GetDomainIndexByName(s));
558  }
559 
560  protected:
562  virtual ~PSMEntropyModelFilter() {};
563 
564  void PrintSelf(std::ostream& os, Indent indent) const
565  {
566  Superclass::PrintSelf(os, indent);
567  }
568 
570  void GenerateData();
571 
575  virtual void AllocateDataCaches();
576 
580  virtual void AllocateWorkingImages();
581 
585  virtual void AllocateDomainsAndNeighborhoods();
586 
590  void InitializeCorrespondences();
591 
595  itkSetMacro(Initialized, bool);
596 
599  void OptimizerIterateCallback(Object *, const EventObject &);
600 
603  typename PSMImplicitSurfaceDomain<
604  typename ImageType::PixelType, Dimension>::Pointer
605  &GetDomainByName(const std::string &name)
606  {
607  return this->GetDomain(this->GetDomainIndexByName(name));
608  }
609 
611  typename PSMImplicitSurfaceDomain<
612  typename ImageType::PixelType, Dimension>::Pointer
613  &GetDomain(unsigned int i)
614  {
615  if (i >= m_DomainList.size())
616  { itkExceptionMacro("Requested domain not available"); }
617  return m_DomainList[i];
618  }
619 
620  private:
621  PSMEntropyModelFilter(const Self&); //purposely not implemented
622  void operator=(const Self&); //purposely not implemented
623 
624  std::vector<typename TImage::Pointer> m_WorkingImages;
625  typename OptimizerType::Pointer m_Optimizer;
626 
628  std::vector<unsigned int> m_MaximumNumberOfIterations;
629 
634  std::vector<double> m_RegularizationInitial;
635  std::vector<double> m_RegularizationFinal;
636  std::vector<double> m_RegularizationDecaySpan;
637 
643  bool m_Initializing;
644 
648  bool m_Initialized;
649 
653  virtual void InitializeOptimizationFunctions();
654 
658  // typename PSMMeanCurvatureAttribute<typename ImageType::PixelType, Dimension>
659  // ::Pointer m_MeanCurvatureCache;
660 
662  typename PSMShapeEntropyFunction<Dimension>::Pointer m_ShapeEntropyFunction;
663 
666  m_ParticleEntropyFunction;
667 
670  typename PSMTwoCostFunction<Dimension>::Pointer m_CostFunction;
671 
674  ShapeMatrixPointerType m_ShapeMatrix;
675 
678  typename itk::MemberCommand< PSMEntropyModelFilter<TImage,TShapeMatrix> >
679  ::Pointer m_IterateCallback;
680 
682  typename ParticleSystemType::Pointer m_ParticleSystem;
683 
687  std::vector<std::vector<PointType> > m_InputCorrespondencePoints;
688 
691  std::vector<std::string> m_DomainListNames;
692 
694  std::vector<typename PSMImplicitSurfaceDomain<
695  typename ImageType::PixelType, Dimension>::Pointer> m_DomainList;
696 
699  std::vector<typename PSMSurfaceNeighborhood<ImageType>::Pointer> m_NeighborhoodList;
700 
703  unsigned int m_NumberOfScales;
704 
708  unsigned int m_CurrentScale;
709 
712  std::vector<double> m_Tolerances;
713 
715  std::vector<CuttingPlaneType> m_CuttingPlanes;
716 };
717 
718 } // end namespace itk
719 
720 #ifndef ITK_MANUAL_INSTANTIATION
721 #include "itkPSMEntropyModelFilter.hxx"
722 #endif
723 
724 #endif
725 
PSMImplicitSurfaceDomain< typename ImageType::PixelType, Dimension >::Pointer & GetDomain(unsigned int i)
PSMShapeEntropyFunction< Dimension > * ShapeEntropyFunction()
void SetMaximumNumberOfIterations(const std::vector< unsigned int > &n)
void SetNumberOfScales(unsigned int n)
unsigned int GetNumberOfElapsedIterations() const
PSMParticleSystem< Dimension > ParticleSystemType
PSMGradientDescentOptimizer< typename ImageType::PixelType, Dimension > OptimizerType
void SetInputCorrespondencePoints(unsigned int index, const std::vector< PointType > &corr)
PSMImplicitSurfaceDomain< typename ImageType::PixelType, Dimension >::Pointer & GetDomainByName(const std::string &name)
const std::vector< double > & GetShapePCAVariances() const
void SetRegularizationInitial(const std::vector< double > &v)
A facade class that manages interactions with a particle system.
void SetInput(const std::string &s, itk::DataObject *o)
This the most basic of all PSM model optimization filters. This filter assembles all of the necessary...
PSMParticleEntropyFunction< typename ImageType::PixelType, Dimension > * GetParticleEntropyFunction()
void SetTolerance(const std::vector< double > &v)