]> Creatis software - clitk.git/commitdiff
Merge branch 'master' of /home/dsarrut/clitk3.server
authorSimon Rit <simon.rit@creatis.insa-lyon.fr>
Fri, 4 Nov 2011 09:44:56 +0000 (10:44 +0100)
committerSimon Rit <simon.rit@creatis.insa-lyon.fr>
Fri, 4 Nov 2011 09:44:56 +0000 (10:44 +0100)
90 files changed:
.gitignore [deleted file]
common/clitkCommon.h
common/clitkCommon.txx
common/clitkFilterBase.h
common/clitkImageToImageGenericFilter.h
itk/clitkAddRelativePositionConstraintToLabelImageFilter.h
itk/clitkAddRelativePositionConstraintToLabelImageFilter.txx
itk/clitkBooleanOperatorLabelImageFilter.txx
itk/clitkBoundingBoxUtils.h [new file with mode: 0644]
itk/clitkBoundingBoxUtils.txx [new file with mode: 0644]
itk/clitkCropLikeImageFilter.h
itk/clitkCropLikeImageFilter.txx
itk/clitkLabelImageOverlapMeasureFilter.h [new file with mode: 0644]
itk/clitkLabelImageOverlapMeasureFilter.txx [new file with mode: 0644]
itk/clitkRelativePositionAnalyzerFilter.h [new file with mode: 0644]
itk/clitkRelativePositionAnalyzerFilter.txx [new file with mode: 0644]
itk/clitkRelativePositionDataBase.cxx [new file with mode: 0644]
itk/clitkRelativePositionDataBase.h [new file with mode: 0644]
itk/clitkRelativePositionDataBaseAnalyzerFilter.h [new file with mode: 0644]
itk/clitkRelativePositionDataBaseAnalyzerFilter.txx [new file with mode: 0644]
itk/clitkRelativePositionDataBaseBuilderFilter.h [new file with mode: 0644]
itk/clitkRelativePositionDataBaseBuilderFilter.txx [new file with mode: 0644]
itk/clitkSegmentationUtils.h
itk/clitkSegmentationUtils.txx
itk/clitkSliceBySliceRelativePositionFilter.h
itk/clitkSliceBySliceRelativePositionFilter.txx
itk/itkLabelOverlapMeasuresImageFilter.h [new file with mode: 0644]
itk/itkLabelOverlapMeasuresImageFilter.txx [new file with mode: 0644]
scripts/create_midP-2.0.sh
scripts/create_midP_masks-2.0.sh
scripts/midp_common.sh
scripts/registration.sh
segmentation/clitkAnatomicalFeatureDatabase.cxx
segmentation/clitkAnatomicalFeatureDatabase.h
segmentation/clitkAnatomicalFeatureDatabase.txx
segmentation/clitkExtractBones.cxx
segmentation/clitkExtractLung.cxx
segmentation/clitkExtractLung.ggo
segmentation/clitkExtractLungFilter.h
segmentation/clitkExtractLungFilter.txx
segmentation/clitkExtractLungGenericFilter.txx
segmentation/clitkExtractLymphStation_3A.txx
segmentation/clitkExtractLymphStation_4RL.txx
segmentation/clitkExtractLymphStation_Supports.txx
segmentation/clitkExtractLymphStations.cxx
segmentation/clitkExtractLymphStations.ggo
segmentation/clitkExtractLymphStationsFilter.h
segmentation/clitkExtractLymphStationsFilter.old.h [deleted file]
segmentation/clitkExtractLymphStationsFilter.old.txx [deleted file]
segmentation/clitkExtractLymphStationsFilter.txx
segmentation/clitkExtractLymphStationsFilter.txx.save [deleted file]
segmentation/clitkExtractLymphStationsGenericFilter.txx
segmentation/clitkExtractMediastinumFilter.txx
segmentation/clitkExtractPatient.cxx
segmentation/clitkExtractPatientGenericFilter.cxx
segmentation/clitkFilterWithAnatomicalFeatureDatabaseManagement.cxx
segmentation/clitkFilterWithAnatomicalFeatureDatabaseManagement.h
segmentation/clitkMorphoMath.cxx
segmentation/clitkMotionMask.cxx
segmentation/clitkRelativePositionList.txx
tools/CMakeLists.txt
tools/clitkAverageTemporalDimension.cxx
tools/clitkBinarizeImage.cxx
tools/clitkCombineImage.cxx
tools/clitkComposeVF.cxx
tools/clitkGetSpacingGenericFilter.cxx
tools/clitkImageArithm.cxx
tools/clitkImageConvert.cxx
tools/clitkInvertVF.cxx
tools/clitkLabelImageOverlapMeasure.cxx [new file with mode: 0644]
tools/clitkLabelImageOverlapMeasure.ggo [new file with mode: 0644]
tools/clitkLabelImageOverlapMeasureGenericFilter.h [new file with mode: 0644]
tools/clitkLabelImageOverlapMeasureGenericFilter.txx [new file with mode: 0644]
tools/clitkMedianTemporalDimension.cxx
tools/clitkRelativePositionAnalyzer.cxx [new file with mode: 0644]
tools/clitkRelativePositionAnalyzer.ggo [new file with mode: 0644]
tools/clitkRelativePositionAnalyzerGenericFilter.h [new file with mode: 0644]
tools/clitkRelativePositionAnalyzerGenericFilter.txx [new file with mode: 0644]
tools/clitkRelativePositionDataBaseAnalyzer.cxx [new file with mode: 0644]
tools/clitkRelativePositionDataBaseAnalyzer.ggo [new file with mode: 0644]
tools/clitkRelativePositionDataBaseBuilder.cxx [new file with mode: 0644]
tools/clitkRelativePositionDataBaseBuilder.ggo [new file with mode: 0644]
tools/clitkRelativePositionDataBaseBuilderGenericFilter.h [new file with mode: 0644]
tools/clitkRelativePositionDataBaseBuilderGenericFilter.txx [new file with mode: 0644]
tools/clitkRelativePositionGenericFilter.h
tools/clitkRelativePositionGenericFilter.txx
tools/clitkResampleImage.cxx
tools/clitkSetBackground.cxx
tools/clitkWarpImage.cxx
tools/clitkZeroVF.cxx

diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index d5a1572..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-*.swp
-build
index 31f28dc40637bd95e91dfec7974f23183edd43ac..769ca63f0bf4400cbb783cf53d3bd7b44b3fc293 100644 (file)
@@ -48,6 +48,24 @@ namespace clitk {
   typedef unsigned char uchar;
   typedef unsigned short ushort;
   typedef unsigned int uint;
+  
+#define CLITK_TRY_CATCH_EXIT(func) \
+  try { \
+    func; \
+  } \
+  catch (const itk::ExceptionObject& e) { \
+    e.Print(std::cout); \
+    exit(-1);\
+  } \
+  catch (const std::exception& e) { \
+    std::cout << e.what() << std::endl; \
+    exit(-2);\
+  } \
+  catch (...) { \
+    std::cout << "Unknown excpetion" << std::endl; \
+    exit(-3); \
+  }
+    
 
   //--------------------------------------------------------------------
   // when everything goes wrong
@@ -209,6 +227,13 @@ namespace clitk {
   //--------------------------------------------------------------------
   void PrintMemoryUsed();
 
+  //--------------------------------------------------------------------
+  // Convert a map to a vector
+  template <typename M, typename V> 
+  void MapToVecFirst(const M & m, V & v);
+  template <typename M, typename V> 
+  void MapToVecSecond(const M & m, V & v);
+
 #include "clitkCommon.txx"
 
 } // end namespace
index dc7f1653c45d5d9e3538043297ca89408c64b80e..5ee83bdca8f4f3efc23ae2aa8dc12ad28a2fe36e 100644 (file)
@@ -195,6 +195,7 @@ std::string GetTypeAsString()
 }
 //--------------------------------------------------------------------
 
+
 //--------------------------------------------------------------------
 template<class ImageType>
 void CloneImage(const typename ImageType::Pointer & input, typename ImageType::Pointer & output)
@@ -217,5 +218,22 @@ void CloneImage(const typename ImageType::Pointer & input, typename ImageType::P
 }
 //--------------------------------------------------------------------
 
+
+//--------------------------------------------------------------------
+// http://stackoverflow.com/questions/771453/copy-map-values-to-vector-in-stl
+template <typename M, typename V> 
+void MapToVecFirst(const  M & m, V & v) {
+  for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) {
+    v.push_back( it->first );
+  }
+}
+template <typename M, typename V> 
+void MapToVecSecond(const  M & m, V & v) {
+  for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) {
+    v.push_back( it->second );
+  }
+}
+//--------------------------------------------------------------------
+
 #endif /* end #define CLITKCOMMON_TXX */
 
index 29caaf08d94fccb6fbe5d6c46410f7c6fb231d9c..b05f64d24b81b97be443fd0f4e2ee1686b4978c4 100644 (file)
@@ -31,7 +31,7 @@ namespace clitk {
   
   //--------------------------------------------------------------------
   /*
-    Convenient class to manage options from GGO (gengetopt) to filter
+    Convenient class to manage frequent options
   */
   //--------------------------------------------------------------------
   class FilterBase
index 5fe21192b3d5a698b92c9c1c403b517844694ef6..07ba4928cc7121ceab7173301f0e5eacbd149004 100644 (file)
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ===========================================================================**/
+
 #ifndef CLITKIMAGETOIMAGEGENERICFILTER_H
 #define CLITKIMAGETOIMAGEGENERICFILTER_H
+
 #include "clitkImageToImageGenericFilterBase.h"
 
 namespace clitk {
index fa5e95b1c39eb3bc90bc8488ca1feaad320c689a..00edd718b167f5d980dacd6941eeb7a587b951d2 100644 (file)
@@ -21,6 +21,7 @@
 
 // clitk
 #include "clitkFilterBase.h"
+#include "clitkCropLikeImageFilter.h"
 
 // itk
 #include <itkPasteImageFilter.h>
@@ -91,7 +92,10 @@ namespace clitk {
     void AddOrientationType(OrientationTypeEnumeration orientation);
     void AddOrientationTypeString(std::string s);
     void ClearOrientationType();
-    void AddAngles(double a, double b);
+    void AddAnglesInRad(double a, double b);
+    void AddAnglesInDeg(double a, double b);
+    double GetAngle1InRad(int i) { return m_Angle1[i]; }
+    double GetAngle2InRad(int i) { return m_Angle2[i]; }
     int GetNumberOfAngles();
     std::string GetOrientationTypeString(int i) { return m_OrientationTypeString[i]; }
     std::vector<std::string> & GetOrientationTypeString() { return m_OrientationTypeString; }
@@ -128,6 +132,12 @@ namespace clitk {
     itkSetMacro(CombineWithOrFlag, bool);
     itkBooleanMacro(CombineWithOrFlag);
 
+    itkGetConstMacro(FuzzyMapOnlyFlag, bool);
+    itkSetMacro(FuzzyMapOnlyFlag, bool);
+    itkBooleanMacro(FuzzyMapOnlyFlag);
+
+    typename FloatImageType::Pointer GetFuzzyMap() { return m_FuzzyMap; }
+
     // I dont want to verify inputs information
     virtual void VerifyInputInformation() { }
     
@@ -151,6 +161,7 @@ namespace clitk {
     bool m_InverseOrientationFlag;
     bool m_RemoveObjectFlag;
     bool m_CombineWithOrFlag;
+    bool m_FuzzyMapOnlyFlag;
 
     virtual void GenerateOutputInformation();
     virtual void GenerateInputRequestedRegion();
@@ -160,6 +171,7 @@ namespace clitk {
     typename ImageType::Pointer working_image;
     typename ImageType::Pointer object_resampled;
     typename FloatImageType::Pointer relPos;
+    typename FloatImageType::Pointer m_FuzzyMap;
     ImagePointer input;
     ImagePointer object;
 
index 694910c6490434280661bbbba1d51dfbc96a3bbc..e25f98b829fa3c65ed497f5fb5ffd73de863a066 100644 (file)
@@ -22,6 +22,7 @@
 #include "clitkAutoCropFilter.h"
 #include "clitkResampleImageWithOptionsFilter.h"
 #include "clitkBooleanOperatorLabelImageFilter.h"
+#include "clitkCropLikeImageFilter.h"
 
 // itk
 #include <deque>
@@ -61,6 +62,7 @@ AddRelativePositionConstraintToLabelImageFilter():
   CombineWithOrFlagOff();
   VerboseStepFlagOff();
   WriteStepFlagOff();
+  FuzzyMapOnlyFlagOff();
 }
 //--------------------------------------------------------------------
 
@@ -136,6 +138,8 @@ AddOrientationTypeString(std::string t)
   if (t == "NotSupTo") { AddOrientationType(SupTo); InverseOrientationFlagOn(); return; }
   if (t == "NotInfTo") { AddOrientationType(InfTo); InverseOrientationFlagOn(); return; }
 
+  if (t == "Angle") return;
+
   clitkExceptionMacro("Error, you must provide LeftTo,RightTo or AntTo,PostTo or SupTo,InfTo (or NotLeftTo, NotRightTo etc) but you give " << t);
 }
 //--------------------------------------------------------------------
@@ -175,15 +179,27 @@ GenerateInputRequestedRegion()
 template <class ImageType>
 void 
 clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::
-AddAngles(double a, double b) 
+AddAnglesInRad(double a, double b) 
 {
-  AddOrientationTypeString("Angle");
+  m_OrientationTypeString.push_back("Angle");
+  m_OrientationType.push_back(Angle);
   m_Angle1.push_back(a);
   m_Angle2.push_back(b);
 }
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::
+AddAnglesInDeg(double a, double b) 
+{
+  AddAnglesInRad(clitk::deg2rad(a), clitk::deg2rad(b));
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 template <class ImageType>
 void 
@@ -361,7 +377,6 @@ GenerateData()
   typedef itk::RelativePositionPropImageFilter<ImageType, FloatImageType> RelPosFilterType;
   typename RelPosFilterType::Pointer relPosFilter;
 
-  typename FloatImageType::Pointer m_FuzzyMap;
   for(int i=0; i<GetNumberOfAngles(); i++) {
     // Compute fuzzy map
     relPosFilter = RelPosFilterType::New();
@@ -411,6 +426,7 @@ GenerateData()
 
   relPos = m_FuzzyMap;
   StopCurrentStep<FloatImageType>(relPos);
+  if (GetFuzzyMapOnlyFlag()) return;
                
   //--------------------------------------------------------------------
   //--------------------------------------------------------------------
index 86b464538d176e3c579084e89bda2c2c072eb2ea..ff0f5748063503d5b7c5656c714943740020c18c 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "clitkCommon.h"
 #include "clitkBooleanOperatorLabelImageFilter.h"
-#include "clitkSegmentationUtils.h"
+#include "clitkBoundingBoxUtils.h"
 
 namespace clitk {
 
diff --git a/itk/clitkBoundingBoxUtils.h b/itk/clitkBoundingBoxUtils.h
new file mode 100644 (file)
index 0000000..311e67d
--- /dev/null
@@ -0,0 +1,60 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKBOUNDINGBOXUTILS_H
+#define CLITKBOUNDINGBOXUTILS_H
+
+// clitk
+#include "clitkCommon.h"
+
+// itk
+#include <itkBoundingBox.h>
+
+namespace clitk {
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void ComputeBBFromImageRegion(const ImageType * image, 
+                                typename ImageType::RegionType region,
+                                typename itk::BoundingBox<unsigned long, 
+                                                          ImageType::ImageDimension>::Pointer bb);
+  
+  //--------------------------------------------------------------------
+  template<int Dimension>
+  void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
+                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
+                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2);
+
+  //--------------------------------------------------------------------
+  template<int Dimension>
+  void ComputeBBUnion(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
+                      typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
+                      typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2);
+  
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void ComputeRegionFromBB(const ImageType * image, 
+                           const typename itk::BoundingBox<unsigned long, 
+                                                           ImageType::ImageDimension>::Pointer bb, 
+                           typename ImageType::RegionType & region);
+
+} // end clitk namespace
+
+#include "clitkBoundingBoxUtils.txx"
+
+#endif
diff --git a/itk/clitkBoundingBoxUtils.txx b/itk/clitkBoundingBoxUtils.txx
new file mode 100644 (file)
index 0000000..d6fbc24
--- /dev/null
@@ -0,0 +1,120 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+namespace clitk {
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void ComputeBBFromImageRegion(const ImageType * image, 
+                                typename ImageType::RegionType region,
+                                typename itk::BoundingBox<unsigned long, 
+                                ImageType::ImageDimension>::Pointer bb) {
+    typedef typename ImageType::IndexType IndexType;
+    IndexType firstIndex;
+    IndexType lastIndex;
+    for(unsigned int i=0; i<image->GetImageDimension(); i++) {
+      firstIndex[i] = region.GetIndex()[i];
+      lastIndex[i] = firstIndex[i]+region.GetSize()[i];
+    }
+
+    typedef itk::BoundingBox<unsigned long, 
+                             ImageType::ImageDimension> BBType;
+    typedef typename BBType::PointType PointType;
+    PointType lastPoint;
+    PointType firstPoint;
+    image->TransformIndexToPhysicalPoint(firstIndex, firstPoint);
+    image->TransformIndexToPhysicalPoint(lastIndex, lastPoint);
+
+    bb->SetMaximum(lastPoint);
+    bb->SetMinimum(firstPoint);
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<int Dimension>
+  void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
+                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
+                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
+    typedef itk::BoundingBox<unsigned long, Dimension> BBType;
+    typedef typename BBType::PointType PointType;
+    PointType lastPoint;
+    PointType firstPoint;
+    for(unsigned int i=0; i<Dimension; i++) {
+      firstPoint[i] = std::max(bbi1->GetMinimum()[i], bbi2->GetMinimum()[i]);
+      lastPoint[i] = std::min(bbi1->GetMaximum()[i], bbi2->GetMaximum()[i]);
+    }
+    bbo->SetMaximum(lastPoint);
+    bbo->SetMinimum(firstPoint);
+  }
+  //--------------------------------------------------------------------
+
+
+  ///--------------------------------------------------------------------
+  template<int Dimension>
+  void ComputeBBUnion(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
+                      typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
+                      typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
+    typedef itk::BoundingBox<unsigned long, Dimension> BBType;
+    typedef typename BBType::PointType PointType;
+    PointType lastPoint;
+    PointType firstPoint;
+    for(unsigned int i=0; i<Dimension; i++) {
+      firstPoint[i] = std::min(bbi1->GetMinimum()[i], bbi2->GetMinimum()[i]);
+      lastPoint[i] = std::max(bbi1->GetMaximum()[i], bbi2->GetMaximum()[i]);
+    }
+    bbo->SetMaximum(lastPoint);
+    bbo->SetMinimum(firstPoint);
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void ComputeRegionFromBB(const ImageType * image, 
+                           const typename itk::BoundingBox<unsigned long, 
+                                                           ImageType::ImageDimension>::Pointer bb, 
+                           typename ImageType::RegionType & region) {
+    // Types
+    typedef typename ImageType::IndexType  IndexType;
+    typedef typename ImageType::PointType  PointType;
+    typedef typename ImageType::RegionType RegionType;
+    typedef typename ImageType::SizeType   SizeType;
+
+    // Region starting point
+    IndexType regionStart;
+    PointType start = bb->GetMinimum();
+    image->TransformPhysicalPointToIndex(start, regionStart);
+    
+    // Region size
+    SizeType regionSize;
+    PointType maxs = bb->GetMaximum();
+    PointType mins = bb->GetMinimum();
+    for(unsigned int i=0; i<ImageType::ImageDimension; i++) {
+      regionSize[i] = lrint((maxs[i] - mins[i])/image->GetSpacing()[i]);
+    }
+   
+    // Create region
+    region.SetIndex(regionStart);
+    region.SetSize(regionSize);
+  }
+  //--------------------------------------------------------------------
+
+
+} // end of namespace
+
index 9281fcad71fc7ec7ce2c7cd5a049a76078670861..c8fae32891eef1c3a7b1f305fcf4e3fbb716cb06 100644 (file)
 #ifndef CLITKCROPLIKEIMAGEFILTER_H
 #define CLITKCROPLIKEIMAGEFILTER_H
 
+// clitk
+#include "clitkBoundingBoxUtils.h"
+
+// itk
 #include <itkImageToImageFilter.h>
 
 namespace clitk {
@@ -100,6 +104,28 @@ namespace clitk {
   }; // end class
   //--------------------------------------------------------------------
 
+
+  //--------------------------------------------------------------------
+  // Convenient function 
+  template<class ImageType>
+  typename ImageType::Pointer
+  ResizeImageLike(const ImageType * input,
+                  const itk::ImageBase<ImageType::ImageDimension> * like, 
+                  typename ImageType::PixelType BG);
+
+  template<class ImageType>
+  typename ImageType::Pointer
+  ResizeImageLike(const ImageType * input,
+                  typename itk::ImageBase<ImageType::ImageDimension>::RegionType * like, 
+                  typename ImageType::PixelType BG);
+
+  template<class ImageType>
+  typename ImageType::Pointer
+  ResizeImageLike(const ImageType * input, 
+                  typename itk::BoundingBox<unsigned long, ImageType::ImageDimension>::Pointer bb, 
+                  typename ImageType::PixelType BG);
+
+
 } // end namespace clitk
 //--------------------------------------------------------------------
 
index 73dd7a7d1532f0f885d1a35f71296145b9691f9f..93644a57c57f9a4a664de713aaab5524b603b06d 100644 (file)
@@ -23,9 +23,6 @@
 #include "clitkCommon.h"
 #include "clitkPasteImageFilter.h"
 
-// itk
-//#include "itkPasteImageFilter.h"
-
 //--------------------------------------------------------------------
 template <class ImageType>
 clitk::CropLikeImageFilter<ImageType>::
@@ -244,5 +241,56 @@ GenerateData() {
 }
 //--------------------------------------------------------------------
    
-#endif //#define CLITKAUTOCROPFILTER
+
+//--------------------------------------------------------------------
+template<class ImageType>
+typename ImageType::Pointer
+clitk::ResizeImageLike(const ImageType * input,                       
+                       const itk::ImageBase<ImageType::ImageDimension> * like, 
+                       typename ImageType::PixelType backgroundValue) 
+{
+  typedef clitk::CropLikeImageFilter<ImageType> CropFilterType;
+  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  cropFilter->SetInput(input);
+  cropFilter->SetCropLikeImage(like);
+  cropFilter->SetBackgroundValue(backgroundValue);
+  cropFilter->Update();
+  return cropFilter->GetOutput();  
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ImageType>
+typename ImageType::Pointer
+clitk::ResizeImageLike(const ImageType * input,                       
+                       typename itk::ImageBase<ImageType::ImageDimension>::RegionType * region, 
+                       typename ImageType::PixelType backgroundValue) 
+{
+  typename ImageType::Pointer output = ImageType::New();
+  output->CopyInformation(input);
+  output->SetRegions(region);
+  output->Allocate();
+  return clitk::ResizeImageLike<ImageType>(input, output, backgroundValue);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ImageType>
+typename ImageType::Pointer
+clitk::ResizeImageLike(const ImageType * input, 
+                       typename itk::BoundingBox<unsigned long, ImageType::ImageDimension>::Pointer bb, 
+                       typename ImageType::PixelType BG)
+{
+  typename ImageType::RegionType region;
+  clitk::ComputeRegionFromBB<ImageType>(input, bb, region);
+  typename ImageType::Pointer output = ImageType::New();
+  output->CopyInformation(input);
+  output->SetRegions(region);
+  output->Allocate();
+  return clitk::ResizeImageLike<ImageType>(input, output, BG);   
+}
+//--------------------------------------------------------------------
+
+#endif //#define CLITKCROPLIKEIMAGEFILTER_TXX
diff --git a/itk/clitkLabelImageOverlapMeasureFilter.h b/itk/clitkLabelImageOverlapMeasureFilter.h
new file mode 100644 (file)
index 0000000..9b4a458
--- /dev/null
@@ -0,0 +1,114 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKLABELIMAGEOVERLAPMEASUREFILTER_H
+#define CLITKRELATIVEPOSITIONANALYZERFILTER_H
+
+// clitk
+#include "clitkFilterBase.h"
+#include "clitkCropLikeImageFilter.h"
+#include "clitkSegmentationUtils.h"
+// #include "itkLabelOverlapMeasuresImageFilter.h"
+
+// itk
+#include <itkImageToImageFilter.h>
+#include <itkLabelStatisticsImageFilter.h>
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Analyze the relative position of a Target (mask image) according
+    to some Object, in a given Support. Indicate the main important
+    position of this Target according the Object. 
+  */
+  //--------------------------------------------------------------------
+  
+  template <class ImageType>
+  class LabelImageOverlapMeasureFilter:
+    public virtual FilterBase,
+    public itk::ImageToImageFilter<ImageType, ImageType>
+  {
+
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<ImageType, ImageType>      Superclass;
+    typedef LabelImageOverlapMeasureFilter<ImageType>          Self;
+    typedef itk::SmartPointer<Self>                            Pointer;
+    typedef itk::SmartPointer<const Self>                      ConstPointer;
+       
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(LabelImageOverlapMeasureFilter, ImageToImageFilter);
+
+    /** Some convenient typedefs. */
+    typedef typename ImageType::ConstPointer ImageConstPointer;
+    typedef typename ImageType::Pointer      ImagePointer;
+    typedef typename ImageType::RegionType   RegionType; 
+    typedef typename ImageType::PixelType    PixelType;
+    typedef typename ImageType::SpacingType  SpacingType;
+    typedef typename ImageType::SizeType     SizeType;
+    typedef typename ImageType::IndexType    IndexType;
+    typedef typename ImageType::PointType    PointType;
+    
+    /** ImageDimension constants */
+    itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+    FILTERBASE_INIT;
+    // Options
+    itkGetConstMacro(BackgroundValue, PixelType);
+    itkSetMacro(BackgroundValue, PixelType);
+
+    itkGetConstMacro(Label1, PixelType);
+    itkSetMacro(Label1, PixelType);
+
+    itkGetConstMacro(Label2, PixelType);
+    itkSetMacro(Label2, PixelType);
+
+    // I dont want to verify inputs information
+    virtual void VerifyInputInformation() { }
+    
+   protected:
+    LabelImageOverlapMeasureFilter();
+    virtual ~LabelImageOverlapMeasureFilter() {}
+    
+    PixelType m_BackgroundValue;
+    PixelType m_Label1;
+    PixelType m_Label2;
+    ImagePointer m_Input1;
+    ImagePointer m_Input2;
+
+    virtual void GenerateOutputInformation();
+    virtual void GenerateInputRequestedRegion();
+    virtual void GenerateData();
+
+  private:
+    LabelImageOverlapMeasureFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#include "clitkLabelImageOverlapMeasureFilter.txx"
+
+#endif
diff --git a/itk/clitkLabelImageOverlapMeasureFilter.txx b/itk/clitkLabelImageOverlapMeasureFilter.txx
new file mode 100644 (file)
index 0000000..11c1e42
--- /dev/null
@@ -0,0 +1,126 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template <class ImageType>
+clitk::LabelImageOverlapMeasureFilter<ImageType>::
+LabelImageOverlapMeasureFilter():
+  clitk::FilterBase(),
+  itk::ImageToImageFilter<ImageType, ImageType>()
+{
+  this->SetNumberOfRequiredInputs(2);
+  SetLabel1(1);
+  SetLabel2(1);
+  SetBackgroundValue(0);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::LabelImageOverlapMeasureFilter<ImageType>::
+GenerateOutputInformation() 
+{ 
+  // DD("GenerateOutputInformation");
+  //ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  // ImagePointer outputImage = this->GetOutput(0);
+  // outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::LabelImageOverlapMeasureFilter<ImageType>::
+GenerateInputRequestedRegion() 
+{
+  // DD("GenerateInputRequestedRegion");
+  // Call default
+  itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
+  // Get input pointers and set requested region to common region
+  ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer input2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
+  input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
+  input2->SetRequestedRegion(input2->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::LabelImageOverlapMeasureFilter<ImageType>::
+GenerateData() 
+{
+  // DD("GenerateData");
+
+  // Get input pointer
+  m_Input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  m_Input2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
+  static const unsigned int dim = ImageType::ImageDimension;
+
+  // Compute union of bounding boxes
+  typedef itk::BoundingBox<unsigned long, dim> BBType;
+  typename BBType::Pointer bb1 = BBType::New();
+  ComputeBBFromImageRegion<ImageType>(m_Input1, m_Input1->GetLargestPossibleRegion(), bb1);
+  typename BBType::Pointer bb2 = BBType::New();
+  ComputeBBFromImageRegion<ImageType>(m_Input2, m_Input2->GetLargestPossibleRegion(), bb2);
+  typename BBType::Pointer bbo = BBType::New();
+  ComputeBBUnion<dim>(bbo, bb1, bb2);
+
+  // Resize like the union
+  ImagePointer input1 = clitk::ResizeImageLike<ImageType>(m_Input1, bbo, GetBackgroundValue());
+  ImagePointer input2 = clitk::ResizeImageLike<ImageType>(m_Input2, bbo, GetBackgroundValue());
+
+  // Compute overlap image
+  ImagePointer image_union = clitk::Clone<ImageType>(input1);
+  ImagePointer image_intersection = clitk::Clone<ImageType>(input1);
+  clitk::Or<ImageType>(image_union, input2, GetBackgroundValue());
+  clitk::And<ImageType>(image_intersection, input2, GetBackgroundValue());
+  
+  writeImage<ImageType>(image_union, "union.mha");
+  writeImage<ImageType>(image_intersection, "intersection.mha");
+  
+  // Compute size
+  typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatFilterType;
+  typename StatFilterType::Pointer statFilter = StatFilterType::New();
+  statFilter->SetInput(image_union);
+  statFilter->SetLabelInput(image_union);
+  statFilter->Update();
+  int u = statFilter->GetCount(GetLabel1());
+
+  statFilter->SetInput(image_intersection);
+  statFilter->SetLabelInput(image_intersection);
+  statFilter->Update();
+  int inter = statFilter->GetCount(GetLabel1());
+  
+  statFilter->SetInput(m_Input1);
+  statFilter->SetLabelInput(m_Input1);
+  statFilter->Update();
+  int in1 = statFilter->GetCount(GetLabel1());
+
+  statFilter->SetInput(m_Input2);
+  statFilter->SetLabelInput(m_Input2);
+  statFilter->Update();
+  int in2 = statFilter->GetCount(GetLabel1());
+
+  std::cout << in1 << " " << in2 << " " << inter << " " << u << " " << (double)inter/(double)u << std::endl;
+}
+//--------------------------------------------------------------------
+
diff --git a/itk/clitkRelativePositionAnalyzerFilter.h b/itk/clitkRelativePositionAnalyzerFilter.h
new file mode 100644 (file)
index 0000000..a41df8b
--- /dev/null
@@ -0,0 +1,163 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKRELATIVEPOSITIONANALYZERFILTER_H
+#define CLITKRELATIVEPOSITIONANALYZERFILTER_H
+
+// clitk
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
+#include "clitkFilterBase.h"
+#include "clitkSliceBySliceRelativePositionFilter.h"
+#include "clitkRelativePositionDataBase.h"
+
+// itk
+#include <itkImageToImageFilter.h>
+#include <itkLabelStatisticsImageFilter.h>
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Analyze the relative position of a Target (mask image) according
+    to some Object (mask image), in a given Support (mask
+    image). Compute the optimal threshold allowing to remove the
+    maximal area from the Support without removing area belonging to
+    the Target.
+  */
+  //--------------------------------------------------------------------
+  
+  template <class ImageType>
+  class RelativePositionAnalyzerFilter:
+    public itk::ImageToImageFilter<ImageType, ImageType>
+  {
+
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<ImageType, ImageType>      Superclass;
+    typedef RelativePositionAnalyzerFilter<ImageType>          Self;
+    typedef itk::SmartPointer<Self>                            Pointer;
+    typedef itk::SmartPointer<const Self>                      ConstPointer;
+       
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(RelativePositionAnalyzerFilter, ImageToImageFilter);
+
+    /** Some convenient typedefs. */
+    typedef typename ImageType::ConstPointer ImageConstPointer;
+    typedef typename ImageType::Pointer      ImagePointer;
+    typedef typename ImageType::RegionType   RegionType; 
+    typedef typename ImageType::PixelType    PixelType;
+    typedef typename ImageType::SpacingType  SpacingType;
+    typedef typename ImageType::SizeType     SizeType;
+    typedef typename ImageType::IndexType    IndexType;
+    typedef typename ImageType::PointType    PointType;
+    
+    /** ImageDimension constants */
+    itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+    FILTERBASE_INIT;
+    typedef itk::Image<float, ImageDimension> FloatImageType;
+
+     /** Input : initial image and object */
+    void SetInputSupport(const ImageType * image);
+    void SetInputObject(const ImageType * image);
+    void SetInputTarget(const ImageType * image);
+    
+    // Input
+    // supportname, objectname multiple targetname
+    
+    // Options
+    itkGetConstMacro(BackgroundValue, PixelType);
+    itkSetMacro(BackgroundValue, PixelType);
+
+    itkGetConstMacro(ForegroundValue, PixelType);
+    itkSetMacro(ForegroundValue, PixelType);
+
+    clitk::RelativePositionDirectionType & GetDirection() { return m_Direction; }
+    void SetDirection(clitk::RelativePositionDirectionType & d) { m_Direction = d; }
+
+    itkGetConstMacro(NumberOfBins, int);
+    itkSetMacro(NumberOfBins, int);
+
+    itkGetConstMacro(AreaLossTolerance, double);
+    itkSetMacro(AreaLossTolerance, double);
+
+    itkGetConstMacro(SupportSize, int);
+    itkGetConstMacro(TargetSize, int);
+    itkGetConstMacro(SizeWithThreshold, int);
+    itkGetConstMacro(SizeWithReverseThreshold, int);
+
+    itkGetConstMacro(Info, clitk::RelativePositionInformationType);
+    itkGetConstMacro(InfoReverse, clitk::RelativePositionInformationType);
+
+    // For debug
+    void PrintOptions();
+    
+    // Print output
+    void Print(std::ostream & os=std::cout);
+
+    // I dont want to verify inputs information
+    virtual void VerifyInputInformation() { }
+    
+   protected:
+    RelativePositionAnalyzerFilter();
+    virtual ~RelativePositionAnalyzerFilter() {}
+    
+    itkSetMacro(SupportSize, int);
+    itkSetMacro(TargetSize, int);
+    itkSetMacro(SizeWithThreshold, int);
+    itkSetMacro(SizeWithReverseThreshold, int);
+
+    PixelType m_BackgroundValue;
+    PixelType m_ForegroundValue;
+    ImagePointer m_Support;
+    ImagePointer m_Object;
+    ImagePointer m_Target;
+    int m_NumberOfBins;
+    double m_AreaLossTolerance;
+    int m_SupportSize;
+    int m_TargetSize;
+    int m_SizeWithReverseThreshold;
+    int m_SizeWithThreshold;
+    clitk::RelativePositionDirectionType m_Direction;
+    clitk::RelativePositionInformationType m_Info;
+    clitk::RelativePositionInformationType m_InfoReverse;
+    
+    virtual void GenerateOutputInformation();
+    virtual void GenerateData();
+
+    typename FloatImageType::Pointer
+    ComputeFuzzyMap(ImageType * object, ImageType * target, ImageType * support, double angle);
+    
+    void
+    ComputeOptimalThresholds(FloatImageType * map, ImageType * target, int bins, double tolerance, 
+                             double & threshold, double & reverseThreshold);
+  private:
+    RelativePositionAnalyzerFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#include "clitkRelativePositionAnalyzerFilter.txx"
+
+#endif
diff --git a/itk/clitkRelativePositionAnalyzerFilter.txx b/itk/clitkRelativePositionAnalyzerFilter.txx
new file mode 100644 (file)
index 0000000..8313766
--- /dev/null
@@ -0,0 +1,287 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template <class ImageType>
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+RelativePositionAnalyzerFilter():
+  itk::ImageToImageFilter<ImageType, ImageType>()
+{
+  this->SetNumberOfRequiredInputs(3); // Input : support, object, target
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+  SetNumberOfBins(100);
+  SetAreaLossTolerance(0.01);
+  SetSupportSize(0);
+  SetTargetSize(0);
+  SetSizeWithThreshold(0);
+  SetSizeWithReverseThreshold(0);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+SetInputSupport(const ImageType * image) 
+{
+  // Process object is not const-correct so the const casting is required.
+  this->SetNthInput(0, const_cast<ImageType *>(image));
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+SetInputObject(const ImageType * image) 
+{
+  // Process object is not const-correct so the const casting is required.
+  this->SetNthInput(1, const_cast<ImageType *>(image));
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+SetInputTarget(const ImageType * image) 
+{
+  // Process object is not const-correct so the const casting is required.
+  this->SetNthInput(2, const_cast<ImageType *>(image));
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+PrintOptions() 
+{
+  DD("TODO");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+GenerateOutputInformation() 
+{ 
+  ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  ImagePointer outputImage = this->GetOutput(0);
+  outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+GenerateData() 
+{
+  static const unsigned int dim = ImageType::ImageDimension;
+  
+  ImagePointer temp = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  m_Object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
+  m_Target = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
+
+  // Remove object from support (keep initial image)
+  m_Support = clitk::Clone<ImageType>(temp);
+  clitk::AndNot<ImageType>(m_Support, m_Object, GetBackgroundValue());
+  
+  // Define filter to compute statics on mask image
+  typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatFilterType;
+  typename StatFilterType::Pointer statFilter = StatFilterType::New();
+
+  // Compute the initial support size
+  statFilter->SetInput(m_Support);
+  statFilter->SetLabelInput(m_Support);
+  statFilter->Update();
+  SetSupportSize(statFilter->GetCount(GetForegroundValue()));
+  // DD(GetSupportSize());
+  
+  // Compute the initial target size
+  ImagePointer s = clitk::ResizeImageLike<ImageType>(m_Support, m_Target, GetBackgroundValue());
+  statFilter->SetInput(s);
+  statFilter->SetLabelInput(m_Target);
+  statFilter->Update();
+  SetTargetSize(statFilter->GetCount(GetForegroundValue()));
+  // DD(GetTargetSize());
+
+  //
+  int bins = GetNumberOfBins();
+  double tolerance = GetAreaLossTolerance();
+
+  // Compute Fuzzy map
+  double angle = GetDirection().angle1;
+  typename FloatImageType::Pointer map = ComputeFuzzyMap(m_Object, m_Target, m_Support, angle);
+  writeImage<FloatImageType>(map, "fuzzy_"+toString(clitk::rad2deg(angle))+".mha");
+
+  // Compute the optimal thresholds (direct and inverse)
+  double mThreshold=0.0;
+  double mReverseThreshold=1.0;
+  ComputeOptimalThresholds(map, m_Target, bins, tolerance, mThreshold, mReverseThreshold);
+
+  // Use the threshold to compute new support
+  int s1 = GetSupportSize();
+  if (mThreshold > 0.0) {
+    ImagePointer support1 = 
+      clitk::SliceBySliceRelativePosition<ImageType>(m_Support, m_Object, 2, 
+                                                     mThreshold,
+                                                     angle,false, // inverseFlag
+                                                     false,  // uniqueConnectedComponent
+                                                     -1, true, 
+                                                     false);//singleObjectCCL
+    // Compute the new support size
+    statFilter->SetInput(support1);
+    statFilter->SetLabelInput(support1);
+    statFilter->Update();
+    s1 = statFilter->GetCount(GetForegroundValue());
+  }
+  
+  int s2 = GetSupportSize();
+  if (mReverseThreshold < 1.0) {
+    ImagePointer support2 = 
+      clitk::SliceBySliceRelativePosition<ImageType>(m_Support, m_Object, 2, 
+                                                     mReverseThreshold, 
+                                                     angle,true,// inverseFlag
+                                                     false, // uniqueConnectedComponent
+                                                     -1, true, 
+                                                     false); //singleObjectCCL
+    // Compute the new support size
+    statFilter = StatFilterType::New();
+    statFilter->SetInput(support2);
+    statFilter->SetLabelInput(support2);
+    statFilter->Update();
+    s2 = statFilter->GetCount(GetForegroundValue());
+  }
+  
+  // Set results values
+  m_Info.threshold = mThreshold;
+  m_Info.sizeAfterThreshold = s1;
+  m_Info.sizeBeforeThreshold = GetSupportSize();
+  m_Info.sizeReference = GetTargetSize();
+  m_InfoReverse.threshold = mReverseThreshold;
+  m_InfoReverse.sizeAfterThreshold = s2;
+  m_InfoReverse.sizeBeforeThreshold = GetSupportSize();
+  m_InfoReverse.sizeReference = GetTargetSize();  
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+typename clitk::RelativePositionAnalyzerFilter<ImageType>::FloatImageType::Pointer
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+ComputeFuzzyMap(ImageType * object, ImageType * target, ImageType * support, double angle)
+{
+  typedef clitk::SliceBySliceRelativePositionFilter<ImageType> SliceRelPosFilterType;
+  typedef typename SliceRelPosFilterType::FloatImageType FloatImageType;
+  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+  sliceRelPosFilter->VerboseStepFlagOff();
+  sliceRelPosFilter->WriteStepFlagOff();
+  sliceRelPosFilter->SetInput(support);
+  sliceRelPosFilter->SetInputObject(object);
+  sliceRelPosFilter->SetDirection(2);
+  sliceRelPosFilter->SetIntermediateSpacingFlag(false);
+  //sliceRelPosFilter->AddOrientationTypeString(orientation);
+  sliceRelPosFilter->AddAnglesInRad(angle, 0.0);
+  sliceRelPosFilter->FuzzyMapOnlyFlagOn(); // do not threshold, only compute the fuzzy map
+  // sliceRelPosFilter->PrintOptions();
+  sliceRelPosFilter->Update();
+  typename FloatImageType::Pointer map = sliceRelPosFilter->GetFuzzyMap();
+
+  // Resize map like object to allow SetBackground
+  map = clitk::ResizeImageLike<FloatImageType>(map, object, GetBackgroundValue());
+  
+  // Remove initial object from the fuzzy map
+  map = clitk::SetBackground<FloatImageType, ImageType>(map, object, GetForegroundValue(), 0.0, true);
+  
+  // Resize the fuzzy map like the target, put 2.0 when outside
+  map = clitk::ResizeImageLike<FloatImageType>(map, target, 2.0);  // Put 2.0 when out of initial map
+  
+  // end
+  return map;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::RelativePositionAnalyzerFilter<ImageType>::
+ComputeOptimalThresholds(FloatImageType * map, ImageType * target, int bins, double tolerance, 
+                         double & threshold, double & reverseThreshold)
+{
+  // Get the histogram of fuzzy values inside the target image
+  typedef itk::LabelStatisticsImageFilter<FloatImageType, ImageType> FloatStatFilterType;
+  typename FloatStatFilterType::Pointer f = FloatStatFilterType::New();
+  f->SetInput(map);
+  f->SetLabelInput(target);
+  f->UseHistogramsOn();
+  f->SetHistogramParameters(bins, 0.0, 1.1);
+  f->Update();
+  int count = f->GetCount(GetForegroundValue());
+  typename FloatStatFilterType::HistogramPointer h = f->GetHistogram(GetForegroundValue());
+
+  // Debug : dump histogram
+  static int i=0;
+  std::ofstream histogramFile(std::string("fuzzy_histo_"+toString(i)+".txt").c_str());
+  for(int j=0; j<bins; j++) {
+    histogramFile << h->GetMeasurement(j,0) 
+                  << "\t" << h->GetFrequency(j) 
+                  << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
+  }
+  histogramFile.close();  
+  i++;
+
+  // Analyze the histogram (direct)
+  double sum = 0.0;
+  bool found = false;
+  threshold = 0.0;
+  for(int j=0; j<bins; j++) {
+    sum += ((double)h->GetFrequency(j)/(double)count);
+    if ((!found) && (sum > tolerance)) {
+      if (j==0) threshold = h->GetBinMin(0,j);
+      else threshold = h->GetBinMin(0,j-1); // the last before reaching the threshold
+      found = true;
+    }
+  }
+
+  // Analyze the histogram (reverse)
+  sum = 0.0;
+  found = false;
+  reverseThreshold = 1.0;
+  for(int j=bins-1; j>=0; j--) {
+    sum += ((double)h->GetFrequency(j)/(double)count);
+    if ((!found) && (sum > tolerance)) {
+      if (j==bins-1) reverseThreshold = h->GetBinMax(0,j);
+      else reverseThreshold = h->GetBinMax(0,j+1);
+      found = true;
+    }
+  }
+}
+//--------------------------------------------------------------------
+
diff --git a/itk/clitkRelativePositionDataBase.cxx b/itk/clitkRelativePositionDataBase.cxx
new file mode 100644 (file)
index 0000000..a9b7327
--- /dev/null
@@ -0,0 +1,239 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKRELATIVEPOSITIONDATABASE_CXX
+#define CLITKRELATIVEPOSITIONDATABASE_CXX
+
+// clitk
+#include "clitkRelativePositionDataBase.h"
+
+namespace clitk {
+
+  //--------------------------------------------------------------------
+  void RelativePositionDataBase::ReadIndex(std::istream & is, IndexType & index)
+  {
+    is >> index.patient; 
+    is >> index.station;
+    is >> index.object;
+    is >> index.direction.angle1; 
+    index.direction.angle1 = clitk::deg2rad(index.direction.angle1);
+    is >> index.direction.angle2;
+    index.direction.angle2 = clitk::deg2rad(index.direction.angle2);
+    std::string s;
+    is >> s;
+    if (s=="true") index.direction.notFlag = true;
+    else index.direction.notFlag = false;
+  }
+  //--------------------------------------------------------------------
+
+  //--------------------------------------------------------------------
+  void RelativePositionDataBase::ReadInformation(std::istream & is, RelativePositionInformationType & v)
+  {
+    is >> v.threshold;
+    is >> v.sizeBeforeThreshold;
+    is >> v.sizeAfterThreshold;
+    is >> v.sizeReference;
+  }
+  //--------------------------------------------------------------------
+  
+  //--------------------------------------------------------------------
+  void RelativePositionDataBase::Read(const std::string & filename)
+  {
+    std::ifstream is;
+    openFileForReading(is, filename);
+
+    std::string s;
+    IndexType index;
+    RelativePositionInformationType v;
+    while (is) {
+      skipComment(is); /* FIXME Read Index etc */ 
+      ReadIndex(is, index);
+      ReadInformation(is, v);      
+
+      if (is) {// FIXME INSERT
+        // Set in station
+        if (m_DB.find(index.station) == m_DB.end()) {
+          MapByObjectType s;
+          m_DB[index.station] = s;
+        }
+        MapByObjectType & s = m_DB[index.station];
+        
+        // Get Direction map from Object
+        if (s.find(index.object) == s.end()) {
+          MapByDirectionType r;
+          s[index.object] = r;
+        }
+        MapByDirectionType & r = s[index.object];
+        
+        // Get Patient map from Direction
+        if (r.find(index.direction) == r.end()) {
+          MapByPatientType q;
+          r[index.direction] = q;
+        }
+        MapByPatientType & q = r[index.direction];
+
+        // Set value by patient
+        q[index.patient] = v;
+        
+        // Debug
+        // index.Println(); 
+        // GetMapByPatient(index).find(index.patient)->second.Println();
+        
+      } // End insertion
+    } // end loop reading
+  }
+  //--------------------------------------------------------------------
+
+  
+  //--------------------------------------------------------------------
+  const RelativePositionDataBase::MapByDirectionType & 
+  RelativePositionDataBase::GetMapByDirection(const IndexType & index) const
+  {
+    const MapByObjectType & a = GetMapByObject(index.station);
+    if (a.find(index.object) == a.end()) {
+      clitkExceptionMacro("Could not find index in DB (object= '" << index.object << "' not found).");
+    }
+    return a.find(index.object)->second;    
+  }
+  //--------------------------------------------------------------------
+  
+
+  //--------------------------------------------------------------------
+  const RelativePositionDataBase::MapByObjectType & 
+  RelativePositionDataBase::GetMapByObject(const std::string & station) const
+  {
+    if (m_DB.find(station) == m_DB.end()) {
+      clitkExceptionMacro("Could not find index in DB (station= '" << station << "' not found).");
+    }
+    return m_DB.find(station)->second;    
+  }
+  //--------------------------------------------------------------------
+  
+
+  //--------------------------------------------------------------------
+  const RelativePositionDataBase::MapByPatientType & 
+  RelativePositionDataBase::GetMapByPatient(const IndexType & index) const
+  {
+    const MapByDirectionType & a = GetMapByDirection(index);
+    if (a.find(index.direction) == a.end()) {
+      std::ostringstream s;
+      index.direction.Print(s);
+      clitkExceptionMacro("Could not find index in DB (direction= '" << s.str() << "' not found).");
+    }
+    return a.find(index.direction)->second;
+  }
+  //--------------------------------------------------------------------
+  
+
+  //--------------------------------------------------------------------
+  const RelativePositionInformationType & 
+  RelativePositionDataBase::GetInformation(const IndexType & index) const
+  {
+    const RelativePositionDataBase::MapByPatientType & a = GetMapByPatient(index);
+    if (a.find(index.patient) == a.end()) {
+      clitkExceptionMacro("Could not find index in DB (patient= '" << index.patient << "' not found).");
+    }
+    return a.find(index.patient)->second;
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  int RelativePositionDataBase::GetNumberOfPatient(const IndexType & index) const
+  {
+    const MapByPatientType & o = GetMapByPatient(index);
+    return o.size();
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  std::vector<std::string> & RelativePositionDataBase::GetListOfPatients(const IndexType & index) const
+  {
+    const MapByPatientType & o = GetMapByPatient(index);
+    MapByPatientType::const_iterator iter = o.begin();
+    std::vector<std::string> * v = new std::vector<std::string>; 
+    MapToVecFirst(o, *v);
+    return *v;
+  }
+  //--------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------
+  double RelativePositionDataBase::GetAreaGain(const IndexType & index) const
+  {
+    // FIXME change name
+    const RelativePositionInformationType & v = GetInformation(index);
+    return v.sizeAfterThreshold/v.sizeBeforeThreshold;
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  double RelativePositionDataBase::GetThreshold(const IndexType & index) const
+  {
+    const RelativePositionInformationType & v = GetInformation(index);
+    return v.threshold;
+  }
+  //--------------------------------------------------------------------
+    
+
+  //--------------------------------------------------------------------
+  void
+  RelativePositionDataBase::GetListOfObjects(const std::string & station, std::vector<std::string> & objects) const
+  {
+    const MapByObjectType & a = GetMapByObject(station);
+    MapToVecFirst(a, objects);
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  void
+  RelativePositionDataBase::GetListOfDirections(const std::string & station, 
+                                                  const std::string & object, 
+                                                  std::vector<RelativePositionDirectionType> & directions) const
+  {
+    IndexType i;
+    i.station = station;
+    i.object = object;
+    const MapByDirectionType & n = GetMapByDirection(i);
+    MapToVecFirst(n, directions);    
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  bool RelativePositionDataBase::CheckIndex(const IndexType & index) const
+  {
+    try {
+      const RelativePositionInformationType & m =  GetInformation(index);
+    } catch (clitk::ExceptionObject e) {
+      // std::cout << e.what() << std::endl;      
+      return false;
+    }
+    return true;
+  }
+  //--------------------------------------------------------------------
+  
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#endif
diff --git a/itk/clitkRelativePositionDataBase.h b/itk/clitkRelativePositionDataBase.h
new file mode 100644 (file)
index 0000000..57cdcec
--- /dev/null
@@ -0,0 +1,156 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKRELATIVEPOSITIONDATABASE_H
+#define CLITKRELATIVEPOSITIONDATABASE_H
+
+// clitk
+#include "clitkCommon.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    FIXME
+   */
+  //--------------------------------------------------------------------
+  
+
+  //--------------------------------------------------------------------
+   class RelativePositionDirectionType {
+  public:
+    double angle1;
+    double angle2;
+    bool notFlag;
+
+    void Print(std::ostream & os = std::cout) const {
+      os << clitk::rad2deg(angle1) << " " << clitk::rad2deg(angle2) << " ";
+      if (notFlag) os << "true"; 
+      else os << "false";
+      os << " ";
+    }
+    
+    void PrintOptions(std::ostream & os = std::cout) const {
+      os << "angle1 = " << clitk::rad2deg(angle1) << std::endl
+         << "angle2 = " << clitk::rad2deg(angle2) << std::endl;
+      if (notFlag) os << "inverse" << std::endl;
+    }
+    
+    void Println(std::ostream & os = std::cout) const {
+      Print(os);
+      os << std::endl;
+    }
+
+    bool operator< (const RelativePositionDirectionType &compare) const
+    {
+      if (angle1 < compare.angle1) return true;
+      if (angle1 > compare.angle1) return false;
+        
+      if (angle2 < compare.angle2) return true;
+      if (angle2 > compare.angle2) return false;
+        
+      if (notFlag == true) {
+        if (compare.notFlag == false) return true;
+        else return false;
+      }
+      return false;
+    }
+  };
+  //--------------------------------------------------------------------
+
+  //--------------------------------------------------------------------
+  class RelativePositionDataBaseIndexType {
+  public:
+    std::string patient;
+    std::string station;
+    std::string object;
+    RelativePositionDirectionType direction;
+    void Print(std::ostream & os = std::cout) const {
+      os << patient << " " << station << " " << object << " ";
+      direction.Print(os);
+    }
+    void Println(std::ostream & os = std::cout) const {
+      Print(os);
+      os << std::endl;
+    }
+  };
+  //--------------------------------------------------------------------
+  
+
+  //--------------------------------------------------------------------
+  class RelativePositionInformationType {
+  public:
+    double threshold;
+    int sizeBeforeThreshold;
+    int sizeAfterThreshold;
+    int sizeReference;
+    void Print(std::ostream & os = std::cout) const {
+      os << threshold << " " << sizeBeforeThreshold << " " 
+         << sizeAfterThreshold << " " << sizeReference;
+    }
+    void Println(std::ostream & os = std::cout) const {
+      Print(os);
+      os << std::endl;
+    }
+  };
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  class RelativePositionDataBase {
+    
+  public:    
+    RelativePositionDataBase() {}
+    ~RelativePositionDataBase() {}
+
+    typedef RelativePositionDataBaseIndexType IndexType;
+
+    void Read(const std::string & filename);
+    double GetAreaGain(const IndexType & index) const;
+    double GetThreshold(const IndexType & index) const;
+    int GetNumberOfPatient(const IndexType & index) const;
+    std::vector<std::string> & GetListOfPatients(const IndexType & index) const;
+    void GetListOfObjects(const std::string & station, std::vector<std::string> & objects) const;
+    void GetListOfDirections(const std::string & station, 
+                               const std::string & object, 
+                               std::vector<RelativePositionDirectionType> & directions) const;
+    bool CheckIndex(const IndexType & index) const;
+
+  protected:
+    typedef std::map<std::string, RelativePositionInformationType> MapByPatientType;
+    typedef std::map<RelativePositionDirectionType, MapByPatientType> MapByDirectionType;
+    typedef std::map<std::string, MapByDirectionType> MapByObjectType;
+    typedef std::map<std::string, MapByObjectType> MapByStationType;
+    MapByStationType m_DB;
+    
+    void ReadIndex(std::istream & is, IndexType & index);
+    void ReadInformation(std::istream & is, RelativePositionInformationType & v);
+
+    const MapByDirectionType & GetMapByDirection(const IndexType & index) const;
+    const MapByPatientType & GetMapByPatient(const IndexType & index) const;
+    const RelativePositionInformationType & GetInformation(const IndexType & index) const;
+    const MapByObjectType & GetMapByObject(const std::string & station) const;
+
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#endif
diff --git a/itk/clitkRelativePositionDataBaseAnalyzerFilter.h b/itk/clitkRelativePositionDataBaseAnalyzerFilter.h
new file mode 100644 (file)
index 0000000..7066c63
--- /dev/null
@@ -0,0 +1,78 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKRELATIVEPOSITIONANALYZERFILTER_H
+#define CLITKRELATIVEPOSITIONANALYZERFILTER_H
+
+// clitk
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
+#include "clitkFilterBase.h"
+#include "clitkRelativePositionDataBase.h"
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Load a database of relative positions. Analyze it and provide
+    common relative position for each patient. 
+  */
+  //--------------------------------------------------------------------
+  
+  class RelativePositionDataBaseAnalyzerFilter:
+    public virtual clitk::FilterBase,
+    public clitk::FilterWithAnatomicalFeatureDatabaseManagement
+  {
+
+  public:
+    RelativePositionDataBaseAnalyzerFilter();
+    virtual ~RelativePositionDataBaseAnalyzerFilter() {}
+    
+    // Input
+    itkGetConstMacro(DatabaseFilename, std::string);
+    itkSetMacro(DatabaseFilename, std::string);
+    itkGetConstMacro(StationName, std::string);
+    itkSetMacro(StationName, std::string);
+    itkGetConstMacro(ObjectName, std::string);
+    itkSetMacro(ObjectName, std::string);
+    itkGetConstMacro(OutputFilename, std::string);
+    itkSetMacro(OutputFilename, std::string);
+    
+    // For debug
+    void PrintOptions();
+    
+    // Go !
+    virtual void Update();
+
+  protected:
+    std::string m_DatabaseFilename;
+    std::string m_StationName;
+    std::string m_ObjectName;
+    std::string m_OutputFilename;
+    clitk::RelativePositionDataBase db;
+
+    bool ComputeOptimalThreshold(RelativePositionDataBaseIndexType & index, double & threshold);
+
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#include "clitkRelativePositionDataBaseAnalyzerFilter.txx"
+
+#endif
diff --git a/itk/clitkRelativePositionDataBaseAnalyzerFilter.txx b/itk/clitkRelativePositionDataBaseAnalyzerFilter.txx
new file mode 100644 (file)
index 0000000..28f3bd0
--- /dev/null
@@ -0,0 +1,134 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+clitk::RelativePositionDataBaseAnalyzerFilter::
+RelativePositionDataBaseAnalyzerFilter():
+  clitk::FilterBase(),
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement()
+{
+  VerboseFlagOff();
+  SetDatabaseFilename("default.dbrp");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+void 
+clitk::RelativePositionDataBaseAnalyzerFilter::
+PrintOptions() 
+{
+  DD("TODO");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+void 
+clitk::RelativePositionDataBaseAnalyzerFilter::
+Update() 
+{
+  // Load DB of relative position
+  db.Read(GetDatabaseFilename());
+
+  // Get list of objects, list of orientation
+  std::vector<std::string> m_ListOfObjects;
+  db.GetListOfObjects(GetStationName(), m_ListOfObjects);
+  
+  // Set initial index in the DB
+  clitk::RelativePositionDataBase::IndexType index;
+  index.station = GetStationName();
+
+  // Loop over objects
+  std::vector<double> m_ListOfThresholds;
+  for(int i=0; i<m_ListOfObjects.size(); i++) {
+    // DD(i);
+    // DD(m_ListOfObjects[i]);
+    // Set current index
+    index.object = m_ListOfObjects[i];
+    // Get the list of direction
+    std::vector<clitk::RelativePositionDirectionType> m_ListOfDirections;
+    db.GetListOfDirections(GetStationName(), index.object, m_ListOfDirections);
+    
+    // Loop over direction
+    for(int j=0; j<m_ListOfDirections.size(); j++) {
+      // DD(j);
+      // m_ListOfDirections[j].Println();
+      // Set current index
+      index.direction = m_ListOfDirections[j];
+      // Compute the best RelPos parameters 
+      double threshold;
+      bool ok = ComputeOptimalThreshold(index, threshold);
+      m_ListOfThresholds.push_back(threshold);
+      
+      // Print debug FIXME
+      if (ok) {
+        /*std::cout << m_ListOfObjects[i] << " ";
+        m_ListOfDirections[j].Print();
+        std::cout << " " << threshold << " " << ok << std::endl;
+        */
+        std::cout << "# -----------------------" << std::endl
+                  << "object = " << m_ListOfObjects[i] << std::endl;
+        m_ListOfDirections[j].PrintOptions();
+        std::cout << "threshold = " << threshold << std::endl
+                  << "sliceBySlice" << std::endl << std::endl; // FIXME spacing ?
+      }
+    }
+  }
+}    
+//--------------------------------------------------------------------
+    
+
+//--------------------------------------------------------------------
+bool
+clitk::RelativePositionDataBaseAnalyzerFilter::
+ComputeOptimalThreshold(RelativePositionDataBaseIndexType & index, double & threshold) 
+{
+  // Get list of patient
+  std::vector<std::string> & ListOfPatients = db.GetListOfPatients(index);
+  //  DD(ListOfPatients.size());
+  // index.direction.Println();
+
+  // For a given station, object, direction
+  bool stop=false;
+  int i=0;
+  if (index.direction.notFlag) threshold = 0.0;
+  else threshold = 1.0;
+  while (!stop && (i<ListOfPatients.size())) {
+    index.patient = ListOfPatients[i];
+    // Check index
+    if (!db.CheckIndex(index)) {
+      std::cout << "Warning index does not exist in the DB. index = "; 
+      index.Println(std::cout);
+    }
+    else {
+      if (index.direction.notFlag) threshold = std::max(db.GetThreshold(index), threshold);
+      else threshold = std::min(db.GetThreshold(index), threshold);
+    }
+    ++i;
+  } // end while
+
+  if (index.direction.notFlag)  {
+    if (threshold >=1) return false; // not useful
+  }
+  else {
+    if (threshold <=0) return false; // not useful
+  }
+  return true;
+}
+//--------------------------------------------------------------------
diff --git a/itk/clitkRelativePositionDataBaseBuilderFilter.h b/itk/clitkRelativePositionDataBaseBuilderFilter.h
new file mode 100644 (file)
index 0000000..bad3d83
--- /dev/null
@@ -0,0 +1,153 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+#ifndef CLITKRelativePositionDataBaseBuilderFILTER_H
+#define CLITKRelativePositionDataBaseBuilderFILTER_H
+
+// clitk
+#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
+#include "clitkFilterBase.h"
+#include "clitkRelativePositionAnalyzerFilter.h"
+#include "clitkRelativePositionDataBase.h"
+
+// itk
+#include <itkImageToImageFilter.h>
+
+namespace clitk {
+  
+  //--------------------------------------------------------------------
+  /*
+    Analyze the relative position of a Target (mask image) according
+    to some Object, in a given Support. Indicate the main important
+    position of this Target according the Object. 
+  */
+  //--------------------------------------------------------------------
+  
+  template <class ImageType>
+  class RelativePositionDataBaseBuilderFilter:
+    public virtual FilterBase,
+    public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
+    public itk::ImageToImageFilter<ImageType, ImageType>
+  {
+
+  public:
+    /** Standard class typedefs. */
+    typedef itk::ImageToImageFilter<ImageType, ImageType>      Superclass;
+    typedef RelativePositionDataBaseBuilderFilter<ImageType>          Self;
+    typedef itk::SmartPointer<Self>                            Pointer;
+    typedef itk::SmartPointer<const Self>                      ConstPointer;
+       
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(RelativePositionDataBaseBuilderFilter, ImageToImageFilter);
+
+    /** Some convenient typedefs. */
+    typedef typename ImageType::ConstPointer ImageConstPointer;
+    typedef typename ImageType::Pointer      ImagePointer;
+    typedef typename ImageType::RegionType   RegionType; 
+    typedef typename ImageType::PixelType    PixelType;
+    typedef typename ImageType::SpacingType  SpacingType;
+    typedef typename ImageType::SizeType     SizeType;
+    typedef typename ImageType::IndexType    IndexType;
+    typedef typename ImageType::PointType    PointType;
+    
+    /** ImageDimension constants */
+    itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+    FILTERBASE_INIT;
+    typedef itk::Image<float, ImageDimension> FloatImageType;
+   
+    // Inputs
+    itkGetConstMacro(SupportName, std::string);
+    itkSetMacro(SupportName, std::string);
+
+    itkGetConstMacro(TargetName, std::string);
+    itkSetMacro(TargetName, std::string);
+
+    void AddObjectName(std::string s) { m_ObjectNames.push_back(s); }
+    std::string & GetObjectName(int i) { return m_ObjectNames[i]; }
+    int GetNumberOfObjects() { return m_ObjectNames.size(); }
+
+    // Options   
+    itkGetConstMacro(BackgroundValue, PixelType);
+    itkSetMacro(BackgroundValue, PixelType);
+
+    itkGetConstMacro(ForegroundValue, PixelType);
+    itkSetMacro(ForegroundValue, PixelType);
+    
+    itkGetConstMacro(NumberOfBins, int);
+    itkSetMacro(NumberOfBins, int);
+
+    itkGetConstMacro(NumberOfAngles, int);
+    itkSetMacro(NumberOfAngles, int);
+
+    itkGetConstMacro(AreaLossTolerance, double);
+    itkSetMacro(AreaLossTolerance, double);
+
+    // For debug
+    void PrintOptions();
+
+    // I dont want to verify inputs information
+    virtual void VerifyInputInformation() { }
+    
+   protected:
+    RelativePositionDataBaseBuilderFilter();
+    virtual ~RelativePositionDataBaseBuilderFilter() {}
+    
+    PixelType m_BackgroundValue;
+    PixelType m_ForegroundValue;
+
+    ImagePointer m_Support;
+    ImagePointer m_Object;
+    ImagePointer m_Target;
+
+    std::string m_SupportName;
+    std::string m_TargetName;
+    std::vector<std::string> m_ObjectNames;
+
+    int m_NumberOfAngles;
+    std::vector<double> m_ListOfAngles;
+    std::vector<clitk::RelativePositionDirectionType> m_ListOfDirections;
+
+    int m_NumberOfBins;
+    double m_AreaLossTolerance;
+    
+    virtual void GenerateOutputInformation();
+    virtual void GenerateInputRequestedRegion();
+    virtual void GenerateData();
+
+    typename FloatImageType::Pointer
+    ComputeFuzzyMap(ImageType * object, ImageType * target, double angle);
+    
+    void
+    ComputeOptimalThresholds(FloatImageType * map, ImageType * target, int bins, double tolerance, 
+                             double & threshold, double & reverseThreshold);
+  private:
+    RelativePositionDataBaseBuilderFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  }; // end class
+  //--------------------------------------------------------------------
+
+} // end namespace clitk
+//--------------------------------------------------------------------
+
+#include "clitkRelativePositionDataBaseBuilderFilter.txx"
+
+#endif
diff --git a/itk/clitkRelativePositionDataBaseBuilderFilter.txx b/itk/clitkRelativePositionDataBaseBuilderFilter.txx
new file mode 100644 (file)
index 0000000..af482ca
--- /dev/null
@@ -0,0 +1,160 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template <class ImageType>
+clitk::RelativePositionDataBaseBuilderFilter<ImageType>::
+RelativePositionDataBaseBuilderFilter():
+  clitk::FilterBase(),
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
+  itk::ImageToImageFilter<ImageType, ImageType>()
+{
+  this->SetNumberOfRequiredInputs(0); // support
+  VerboseFlagOff();
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+  SetNumberOfBins(100);
+  SetNumberOfAngles(4);
+  SetAreaLossTolerance(0.01);
+  m_ListOfAngles.clear();
+  // SetSupportSize(0);
+  // SetTargetSize(0);
+  // SetSizeWithThreshold(0);
+  // SetSizeWithReverseThreshold(0);  
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionDataBaseBuilderFilter<ImageType>::
+PrintOptions() 
+{
+  DD("TODO");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionDataBaseBuilderFilter<ImageType>::
+GenerateOutputInformation() 
+{ 
+  // ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  // ImagePointer outputImage = this->GetOutput(0);
+  // outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionDataBaseBuilderFilter<ImageType>::
+GenerateInputRequestedRegion() 
+{
+  // Call default
+  // itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
+  // // Get input pointers and set requested region to common region
+  // ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
+  // input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::RelativePositionDataBaseBuilderFilter<ImageType>::
+GenerateData() 
+{
+  // Load database of anatomical elements
+  static const unsigned int dim = ImageType::ImageDimension;
+  this->LoadAFDB();
+
+  // Get some information
+  std::string patient = this->GetAFDB()->GetTagValue("PatientID");
+
+  // Get input pointers
+  m_Support = this->GetAFDB()->template GetImage <ImageType>(GetSupportName());
+  m_Target = this->GetAFDB()->template GetImage <ImageType>(GetTargetName());
+
+  // Build the list of tested directions
+  m_ListOfAngles.clear();
+  for(uint i=0; i<GetNumberOfAngles(); i++) {
+    double a = i*360.0/GetNumberOfAngles();
+    if (a>180) a = 180-a;
+    m_ListOfAngles.push_back(clitk::deg2rad(a));
+    RelativePositionDirectionType r;
+    r.angle1 = clitk::deg2rad(a);
+    r.angle2 = 0;
+    r.notFlag = false;
+    m_ListOfDirections.push_back(r); // only one direction
+  }
+
+
+  // Perform the RelativePositionAnalyzerFilter for each objects
+  typedef typename clitk::RelativePositionAnalyzerFilter<ImageType> FilterType;
+  for (int i=0; i<GetNumberOfObjects(); i++) {
+    m_Object = this->GetAFDB()->template GetImage <ImageType>(GetObjectName(i));
+
+    for (int j=0; j<m_ListOfDirections.size(); j++) {
+      clitk::RelativePositionDirectionType direction = m_ListOfDirections[j];
+      
+      // Create the filter
+      typename FilterType::Pointer filter = FilterType::New();
+      filter->SetInputSupport(m_Support);
+      filter->SetInputTarget(m_Target);
+      filter->SetInputObject(m_Object); // FIXME do AndNot before + only compute supportSize once.
+      filter->SetNumberOfBins(GetNumberOfBins());
+      filter->SetAreaLossTolerance(GetAreaLossTolerance());
+      filter->SetDirection(direction);
+      filter->Update();
+
+      // Results
+      std::ostringstream s;
+      s << patient << " " 
+        << GetSupportName() << " " 
+        // << GetTargetName() << " " // No need
+        << GetObjectName(i) <<" ";
+      // Normal 
+      // if (filter->GetInfo().sizeAfterThreshold != filter->GetInfo().sizeBeforeThreshold) {
+        std::ostringstream os;
+        os << s.str();
+        direction.notFlag = false;
+        direction.Print(os);
+        filter->GetInfo().Print(os);
+        std::cout << os.str() << std::endl;
+      // }
+      // Inverse
+      // if (filter->GetInfoReverse().sizeAfterThreshold != filter->GetInfoReverse().sizeBeforeThreshold) {
+        std::ostringstream oos;
+        oos << s.str();
+        direction.notFlag = true;
+        direction.Print(oos);
+        filter->GetInfoReverse().Print(oos);
+        std::cout << oos.str() << std::endl;
+      // }
+    } // end direction
+
+  } // end object
+}
+//--------------------------------------------------------------------
+
+
index 70388fe6cdb7380511bbda45373abd7f71a1200a..6972d154ab8f4436a672247090da66efff9eb331 100644 (file)
 namespace clitk {
 
   //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeBBFromImageRegion(const ImageType * image, 
-                                typename ImageType::RegionType region,
-                                typename itk::BoundingBox<unsigned long, 
-                                                          ImageType::ImageDimension>::Pointer bb);
-  
-  //--------------------------------------------------------------------
-  template<int Dimension>
-  void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2);
-
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeRegionFromBB(const ImageType * image, 
-                           const typename itk::BoundingBox<unsigned long, 
-                                                           ImageType::ImageDimension>::Pointer bb, 
-                           typename ImageType::RegionType & region);
-  //--------------------------------------------------------------------
   template<class TInternalImageType, class TMaskInternalImageType>
   typename TInternalImageType::Pointer
   SetBackground(const TInternalImageType * input,
@@ -136,13 +117,6 @@ namespace clitk {
                           int minimalComponentSize,
                           LabelizeParameters<typename TImageType::PixelType> * param);
 
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  typename ImageType::Pointer
-  ResizeImageLike(const ImageType * input,
-                  const itk::ImageBase<ImageType::ImageDimension> * like, 
-                  typename ImageType::PixelType BG);
-
 
   //--------------------------------------------------------------------
   template<class MaskImageType>
@@ -156,6 +130,18 @@ namespace clitk {
                                double spacing=-1, 
                                bool autocropflag=true, 
                                bool singleObjectCCL=true);
+  template<class MaskImageType>
+  typename MaskImageType::Pointer
+  SliceBySliceRelativePosition(const MaskImageType * input,
+                              const MaskImageType * object,
+                              int direction, 
+                              double threshold, 
+                              double angle, 
+                               bool inverseflag,
+                               bool uniqueConnectedComponent=false, 
+                               double spacing=-1, 
+                               bool autocropflag=true, 
+                               bool singleObjectCCL=true);
 
   //--------------------------------------------------------------------
   // In a binary image, search for the point belonging to the FG that
index 2f0d935a7cbbc88d038000768d6bed04bfd2451f..76572b594540e9f7393e38a535a40ff3f4ffcb52 100644 (file)
 
 namespace clitk {
 
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeBBFromImageRegion(const ImageType * image, 
-                                typename ImageType::RegionType region,
-                                typename itk::BoundingBox<unsigned long, 
-                                ImageType::ImageDimension>::Pointer bb) {
-    typedef typename ImageType::IndexType IndexType;
-    IndexType firstIndex;
-    IndexType lastIndex;
-    for(unsigned int i=0; i<image->GetImageDimension(); i++) {
-      firstIndex[i] = region.GetIndex()[i];
-      lastIndex[i] = firstIndex[i]+region.GetSize()[i];
-    }
-
-    typedef itk::BoundingBox<unsigned long, 
-                             ImageType::ImageDimension> BBType;
-    typedef typename BBType::PointType PointType;
-    PointType lastPoint;
-    PointType firstPoint;
-    image->TransformIndexToPhysicalPoint(firstIndex, firstPoint);
-    image->TransformIndexToPhysicalPoint(lastIndex, lastPoint);
-
-    bb->SetMaximum(lastPoint);
-    bb->SetMinimum(firstPoint);
-  }
-  //--------------------------------------------------------------------
-
-
-  //--------------------------------------------------------------------
-  template<int Dimension>
-  void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
-
-    typedef itk::BoundingBox<unsigned long, Dimension> BBType;
-    typedef typename BBType::PointType PointType;
-    PointType lastPoint;
-    PointType firstPoint;
-
-    for(unsigned int i=0; i<Dimension; i++) {
-      firstPoint[i] = std::max(bbi1->GetMinimum()[i], 
-                               bbi2->GetMinimum()[i]);
-      lastPoint[i] = std::min(bbi1->GetMaximum()[i], 
-                              bbi2->GetMaximum()[i]);
-    }
-
-    bbo->SetMaximum(lastPoint);
-    bbo->SetMinimum(firstPoint);
-  }
-  //--------------------------------------------------------------------
-
-
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeRegionFromBB(const ImageType * image, 
-                           const typename itk::BoundingBox<unsigned long, 
-                                                           ImageType::ImageDimension>::Pointer bb, 
-                           typename ImageType::RegionType & region) {
-    // Types
-    typedef typename ImageType::IndexType  IndexType;
-    typedef typename ImageType::PointType  PointType;
-    typedef typename ImageType::RegionType RegionType;
-    typedef typename ImageType::SizeType   SizeType;
-
-    // Region starting point
-    IndexType regionStart;
-    PointType start = bb->GetMinimum();
-    image->TransformPhysicalPointToIndex(start, regionStart);
-    
-    // Region size
-    SizeType regionSize;
-    PointType maxs = bb->GetMaximum();
-    PointType mins = bb->GetMinimum();
-    for(unsigned int i=0; i<ImageType::ImageDimension; i++) {
-      regionSize[i] = lrint((maxs[i] - mins[i])/image->GetSpacing()[i]);
-    }
-   
-    // Create region
-    region.SetIndex(regionStart);
-    region.SetSize(regionSize);
-  }
-  //--------------------------------------------------------------------
-
   //--------------------------------------------------------------------
   template<class ImageType, class TMaskImageType>
   typename ImageType::Pointer
@@ -313,19 +230,37 @@ namespace clitk {
 
 
   //--------------------------------------------------------------------
-  template<class ImageType>
-  typename ImageType::Pointer
-  ResizeImageLike(const ImageType * input,                       
-                  const itk::ImageBase<ImageType::ImageDimension> * like, 
-                  typename ImageType::PixelType backgroundValue) 
+  template<class MaskImageType>
+  typename MaskImageType::Pointer
+  SliceBySliceRelativePosition(const MaskImageType * input,
+                               const MaskImageType * object,
+                               int direction, 
+                               double threshold, 
+                               std::string orientation, 
+                               bool uniqueConnectedComponent, 
+                               double spacing, 
+                               bool autocropFlag, 
+                               bool singleObjectCCL) 
   {
-    typedef CropLikeImageFilter<ImageType> CropFilterType;
-    typename CropFilterType::Pointer cropFilter = CropFilterType::New();
-    cropFilter->SetInput(input);
-    cropFilter->SetCropLikeImage(like);
-    cropFilter->SetBackgroundValue(backgroundValue);
-    cropFilter->Update();
-    return cropFilter->GetOutput();  
+    typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+    typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+    sliceRelPosFilter->VerboseStepFlagOff();
+    sliceRelPosFilter->WriteStepFlagOff();
+    sliceRelPosFilter->SetInput(input);
+    sliceRelPosFilter->SetInputObject(object);
+    sliceRelPosFilter->SetDirection(direction);
+    sliceRelPosFilter->SetFuzzyThreshold(threshold);
+    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    sliceRelPosFilter->SetIntermediateSpacingFlag((spacing != -1));
+    sliceRelPosFilter->SetIntermediateSpacing(spacing);
+    sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(uniqueConnectedComponent);
+    sliceRelPosFilter->ObjectCCLSelectionFlagOff();
+    sliceRelPosFilter->SetUseTheLargestObjectCCLFlag(singleObjectCCL);
+    //    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
+    sliceRelPosFilter->SetAutoCropFlag(autocropFlag); 
+    sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
+    sliceRelPosFilter->Update();
+    return sliceRelPosFilter->GetOutput();
   }
   //--------------------------------------------------------------------
 
@@ -337,13 +272,14 @@ namespace clitk {
                                const MaskImageType * object,
                                int direction, 
                                double threshold, 
-                               std::string orientation, 
+                               double angle,
+                               bool inverseflag,
                                bool uniqueConnectedComponent, 
                                double spacing, 
                                bool autocropFlag, 
                                bool singleObjectCCL) 
   {
-    typedef SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+    typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
     typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
     sliceRelPosFilter->VerboseStepFlagOff();
     sliceRelPosFilter->WriteStepFlagOff();
@@ -351,13 +287,14 @@ namespace clitk {
     sliceRelPosFilter->SetInputObject(object);
     sliceRelPosFilter->SetDirection(direction);
     sliceRelPosFilter->SetFuzzyThreshold(threshold);
-    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    //    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    sliceRelPosFilter->AddAnglesInRad(angle, 0.0);
     sliceRelPosFilter->SetIntermediateSpacingFlag((spacing != -1));
     sliceRelPosFilter->SetIntermediateSpacing(spacing);
     sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(uniqueConnectedComponent);
     sliceRelPosFilter->ObjectCCLSelectionFlagOff();
     sliceRelPosFilter->SetUseTheLargestObjectCCLFlag(singleObjectCCL);
-    //    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
+    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
     sliceRelPosFilter->SetAutoCropFlag(autocropFlag); 
     sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
     sliceRelPosFilter->Update();
@@ -448,7 +385,11 @@ namespace clitk {
     typename ImageType::PointType p;
     image->TransformIndexToPhysicalPoint(image->GetLargestPossibleRegion().GetIndex()+
                                          image->GetLargestPossibleRegion().GetSize(), p);
-    return CropImageAlongOneAxis<ImageType>(image, dim, max, p[dim], autoCrop, BG);
+    // Add GetSpacing because remove Lower or equal than
+    // DD(max);
+    // DD(p);
+    // DD(max+image->GetSpacing()[dim]);
+    return CropImageAlongOneAxis<ImageType>(image, dim, max+image->GetSpacing()[dim], p[dim], autoCrop, BG);
   }
   //--------------------------------------------------------------------
 
index e4fe7a4a129f15c25ac1b8c30c5f51ee9abd8fe7..90a1b2567e8cb4779bd8d9f21bfeeed15478b09e 100644 (file)
@@ -53,6 +53,7 @@ namespace clitk {
     /** ImageDimension constants */
     itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
     typedef itk::Image<float, ImageDimension> FloatImageType;
+    typedef itk::Image<float, ImageDimension-1> FloatSliceType;
 
     /** Some convenient typedefs. */
     typedef typename ImageType::ConstPointer ImageConstPointer;
index 0548146d2051ffe0b61289dc2d07fbf52d6af95b..0df2987312797c94f34fb72365359fda82b4043a 100644 (file)
@@ -17,6 +17,7 @@
   ======================================================================-====*/
 
 // clitk
+#include "clitkCropLikeImageFilter.h"
 #include "clitkSegmentationUtils.h"
 #include "clitkExtractSliceFilter.h"
 #include "clitkResampleImageWithOptionsFilter.h"
@@ -77,8 +78,11 @@ PrintOptions(std::ostream & os)
 {
   os << "Slice direction = " << this->GetDirection() << std::endl
      << "BG value        = " << this->GetBackgroundValue() << std::endl;
-  for(int i=0; i<this->GetNumberOfAngles(); i++)
+  for(int i=0; i<this->GetNumberOfAngles(); i++) {
     os << "Orientation     = " << this->GetOrientationTypeString()[i] << std::endl;
+    os << "Angles     = " << clitk::rad2deg(this->GetAngle1InRad(i)) 
+       << " " << clitk::rad2deg(this->GetAngle2InRad(i)) << std::endl;
+  }
   os << "InverseOrientationFlag  = " << this->GetInverseOrientationFlag() << std::endl        
      << "SpacingFlag     = " << this->GetIntermediateSpacingFlag() << std::endl
      << "Spacing         = " << this->GetIntermediateSpacing() << std::endl
@@ -182,6 +186,11 @@ GenerateOutputInformation()
   extractSliceFilter->GetOutputSlices(mObjectSlices);
   this->template StopCurrentStep<SliceType>(mObjectSlices[0]);
 
+  //--------------------------------------------------------------------
+  // Prepare fuzzy slices (if needed)
+  std::vector<typename FloatSliceType::Pointer> mFuzzyMapSlices;
+  mFuzzyMapSlices.resize(mInputSlices.size());
+
   //--------------------------------------------------------------------
   // Perform slice by slice relative position
   this->StartNewStep("Perform slice by slice relative position");
@@ -190,91 +199,124 @@ GenerateOutputInformation()
     // Count the number of CCL (allow to ignore empty slice)
     int nb=0;
     mObjectSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mObjectSlices[i], 0, true, 1, nb);
-    if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
 
-      // Select or not a single CCL ?
-      if (GetUseTheLargestObjectCCLFlag()) {
-        mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
-      }
+    // If no object and empty slices :
+    if ((nb==0) && (this->GetFuzzyMapOnlyFlag())) {
+      typename FloatSliceType::Pointer one = FloatSliceType::New();
+      one->CopyInformation(mObjectSlices[0]);
+      one->SetRegions(mObjectSlices[0]->GetLargestPossibleRegion());
+      one->Allocate();
+      one->FillBuffer(2.0);
+      mFuzzyMapSlices[i] = one;
+    }
+    else {
+      if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
 
-      // Select a single according to a position if more than one CCL
-      if (GetObjectCCLSelectionFlag()) {
-        // if several CCL, choose the most extrema according a direction, 
-        // if not -> should we consider this slice ? 
-        if (nb<2) {
-          if (GetObjectCCLSelectionIgnoreSingleCCLFlag()) {
-            mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
-                                                                   1, this->GetBackgroundValue(), 
-                                                                   true);
-          }
+        // Select or not a single CCL ?
+        if (GetUseTheLargestObjectCCLFlag()) {
+          mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
         }
-        int dim = GetObjectCCLSelectionDimension();
-        int direction = GetObjectCCLSelectionDirection();
-        std::vector<typename SliceType::PointType> centroids;
-        ComputeCentroids<SliceType>(mObjectSlices[i], this->GetBackgroundValue(), centroids);
-        uint index=1;
-        for(uint j=1; j<centroids.size(); j++) {
-          if (direction == 1) {
-            if (centroids[j][dim] > centroids[index][dim]) index = j;
+
+        // Select a single according to a position if more than one CCL
+        if (GetObjectCCLSelectionFlag()) {
+          // if several CCL, choose the most extrema according a direction, 
+          // if not -> should we consider this slice ? 
+          if (nb<2) {
+            if (GetObjectCCLSelectionIgnoreSingleCCLFlag()) {
+              mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
+                                                                     1, this->GetBackgroundValue(), 
+                                                                     true);
+            }
+          }
+          int dim = GetObjectCCLSelectionDimension();
+          int direction = GetObjectCCLSelectionDirection();
+          std::vector<typename SliceType::PointType> centroids;
+          ComputeCentroids<SliceType>(mObjectSlices[i], this->GetBackgroundValue(), centroids);
+          uint index=1;
+          for(uint j=1; j<centroids.size(); j++) {
+            if (direction == 1) {
+              if (centroids[j][dim] > centroids[index][dim]) index = j;
+            }
+            else {
+              if (centroids[j][dim] < centroids[index][dim]) index = j;
+            }
           }
-          else {
-            if (centroids[j][dim] < centroids[index][dim]) index = j;
+          for(uint v=1; v<centroids.size(); v++) {
+            if (v != index) {
+              mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
+                                                                     (char)v, this->GetBackgroundValue(), 
+                                                                     true);
+            }
           }
+        } // end GetbjectCCLSelectionFlag = true
+
+        // Relative position
+        typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
+        typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+
+        relPosFilter->VerboseStepFlagOff();
+        relPosFilter->WriteStepFlagOff();
+        relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
+        relPosFilter->SetInput(mInputSlices[i]); 
+        relPosFilter->SetInputObject(mObjectSlices[i]); 
+        relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
+        // This flag (InverseOrientation) *must* be set before
+        // AddOrientation because AddOrientation can change it.
+        relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
+        for(int j=0; j<this->GetNumberOfAngles(); j++) {
+          //          relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
+          relPosFilter->AddAnglesInRad(this->GetAngle1InRad(j), this->GetAngle2InRad(j));
+          // DD(this->GetOrientationTypeString(j));
         }
-        for(uint v=1; v<centroids.size(); v++) {
-          if (v != index) {
-            mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
-                                                                   (char)v, this->GetBackgroundValue(), 
-                                                                   true);
+        // DD(this->GetInverseOrientationFlag());
+        //relPosFilter->SetOrientationType(this->GetOrientationType());
+        relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
+        relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
+        relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
+        relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
+        relPosFilter->SetCombineWithOrFlag(this->GetCombineWithOrFlag()); 
+
+        // should we stop after fuzzy map ?
+        relPosFilter->SetFuzzyMapOnlyFlag(this->GetFuzzyMapOnlyFlag());
+      
+        // Go !
+        relPosFilter->Update();
+
+        // If we stop after the fuzzy map, store the fuzzy slices
+        if (this->GetFuzzyMapOnlyFlag()) {
+          mFuzzyMapSlices[i] = relPosFilter->GetFuzzyMap();
+          // writeImage<FloatSliceType>(mFuzzyMapSlices[i], "slice_"+toString(i)+".mha");
+        }
+        else  {
+          mInputSlices[i] = relPosFilter->GetOutput();
+          // Select main CC if needed
+          if (GetUniqueConnectedComponentBySliceFlag()) {
+            mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
+            mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
           }
+        
         }
-      } // end GetbjectCCLSelectionFlag = true
-
-      // Relative position
-      typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
-      typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
-
-      relPosFilter->VerboseStepFlagOff();
-      relPosFilter->WriteStepFlagOff();
-      relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
-      relPosFilter->SetInput(mInputSlices[i]); 
-      relPosFilter->SetInputObject(mObjectSlices[i]); 
-      relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
-      // This flag (InverseOrientation) *must* be set before
-      // AddOrientation because AddOrientation can change it.
-      relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
-      for(int j=0; j<this->GetNumberOfAngles(); j++) {
-        relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
-        //DD(this->GetOrientationTypeString(j));
-      }
-      //DD(this->GetInverseOrientationFlag());
-      //relPosFilter->SetOrientationType(this->GetOrientationType());
-      relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
-      relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
-      relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
-      relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
-      relPosFilter->SetCombineWithOrFlag(this->GetCombineWithOrFlag()); 
-      relPosFilter->Update();
-      mInputSlices[i] = relPosFilter->GetOutput();
-
-      // Select main CC if needed
-      if (GetUniqueConnectedComponentBySliceFlag()) {
-        mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
-        mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
-      }
 
+      }
       /*
       // Select unique CC according to the most in a given direction
       if (GetUniqueConnectedComponentBySliceAccordingToADirection()) {
-        int nb;
-        mInputSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mInputSlices[i], 0, true, 1, nb);
-        std::vector<typename ImageType::PointType> & centroids;
-        ComputeCentroids
-        }
+      int nb;
+      mInputSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mInputSlices[i], 0, true, 1, nb);
+      std::vector<typename ImageType::PointType> & centroids;
+      ComputeCentroids
+      }
       */
     }
   }
 
+  // Join the fuzzy map if needed
+  if (this->GetFuzzyMapOnlyFlag()) {
+    this->m_FuzzyMap = clitk::JoinSlices<FloatImageType>(mFuzzyMapSlices, input, GetDirection());
+    this->template StopCurrentStep<FloatImageType>(this->m_FuzzyMap);
+    return;
+  }
+
   // Join the slices
   m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, input, GetDirection());
   this->template StopCurrentStep<ImageType>(m_working_input);
@@ -309,6 +351,7 @@ GenerateData()
   //--------------------------------------------------------------------  
   // Final Step -> set output
   //this->SetNthOutput(0, m_working_input);
+  if (this->GetFuzzyMapOnlyFlag()) return; // no output in this case
   this->GraftOutput(m_working_input);
   return;
 }
diff --git a/itk/itkLabelOverlapMeasuresImageFilter.h b/itk/itkLabelOverlapMeasuresImageFilter.h
new file mode 100644 (file)
index 0000000..978fed3
--- /dev/null
@@ -0,0 +1,212 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkLabelOverlapMeasuresImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __itkLabelOverlapMeasuresImageFilter_h
+#define __itkLabelOverlapMeasuresImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "itkFastMutexLock.h"
+#include "itkNumericTraits.h"
+
+//#include "itk_hash_map.h"
+#include "itksys/hash_map.hxx"
+
+namespace itk {
+
+/** \class LabelOverlapMeasuresImageFilter
+ * \brief Computes overlap measures between the set same set of labels of
+ * pixels of two images.  Background is assumed to be 0.
+ *
+ * \sa LabelOverlapMeasuresImageFilter
+ *
+ * \ingroup MultiThreaded
+ */
+template<class TLabelImage>
+class ITK_EXPORT LabelOverlapMeasuresImageFilter :
+    public ImageToImageFilter<TLabelImage, TLabelImage>
+{
+public:
+  /** Standard Self typedef */
+  typedef LabelOverlapMeasuresImageFilter                Self;
+  typedef ImageToImageFilter<TLabelImage,TLabelImage>    Superclass;
+  typedef SmartPointer<Self>                             Pointer;
+  typedef SmartPointer<const Self>                       ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro( Self );
+
+  /** Runtime information support. */
+  itkTypeMacro( LabelOverlapMeasuresImageFilter, ImageToImageFilter );
+
+    virtual void VerifyInputInformation() { }
+
+
+  /** Image related typedefs. */
+  typedef TLabelImage                                   LabelImageType;
+  typedef typename TLabelImage::Pointer                 LabelImagePointer;
+  typedef typename TLabelImage::ConstPointer            LabelImageConstPointer;
+
+  typedef typename TLabelImage::RegionType              RegionType;
+  typedef typename TLabelImage::SizeType                SizeType;
+  typedef typename TLabelImage::IndexType               IndexType;
+
+  typedef typename TLabelImage::PixelType               LabelType;
+
+  /** Type to use form computations. */
+  typedef typename NumericTraits<LabelType>::RealType RealType;
+
+  /** \class LabelLabelOverlapMeasuress
+   * \brief Metrics stored per label */
+  class LabelSetMeasures
+    {
+    public:
+    // default constructor
+    LabelSetMeasures()
+      {
+      m_Source = 0;
+      m_Target = 0;
+      m_Union = 0;
+      m_Intersection = 0;
+      m_SourceComplement = 0;
+      m_TargetComplement = 0;
+      }
+
+  // added for completeness
+    LabelSetMeasures& operator=( const LabelSetMeasures& l )
+      {
+      m_Source = l.m_Source;
+      m_Target = l.m_Target;
+      m_Union = l.m_Union;
+      m_Intersection = l.m_Intersection;
+      m_SourceComplement = l.m_SourceComplement;
+      m_TargetComplement = l.m_TargetComplement;
+      }
+
+    unsigned long m_Source;
+    unsigned long m_Target;
+    unsigned long m_Union;
+    unsigned long m_Intersection;
+    unsigned long m_SourceComplement;
+    unsigned long m_TargetComplement;
+    };
+
+  /** Type of the map used to store data per label */
+  typedef itksys::hash_map<LabelType, LabelSetMeasures> MapType;
+  typedef typename MapType::iterator MapIterator;
+  typedef typename MapType::const_iterator MapConstIterator;
+
+  /** Image related typedefs. */
+  itkStaticConstMacro( ImageDimension, unsigned int,
+    TLabelImage::ImageDimension );
+
+  /** Set the source image. */
+  void SetSourceImage( const LabelImageType * image )
+    { this->SetNthInput( 0, const_cast<LabelImageType *>( image ) ); }
+
+  /** Set the target image. */
+  void SetTargetImage( const LabelImageType * image )
+    { this->SetNthInput( 1, const_cast<LabelImageType *>( image ) ); }
+
+  /** Get the source image. */
+  const LabelImageType * GetSourceImage( void )
+    { return this->GetInput( 0 ); }
+
+  /** Get the target image. */
+  const LabelImageType * GetTargetImage( void )
+    { return this->GetInput( 1 ); }
+
+  /** Get the label set measures */
+  MapType GetLabelSetMeasures()
+    { return this->m_LabelSetMeasures; }
+
+  /**
+   * tric overlap measures
+   */
+  /** measures over all labels */
+  RealType GetTotalOverlap();
+  RealType GetUnionOverlap();
+  RealType GetMeanOverlap();
+  RealType GetVolumeSimilarity();
+  RealType GetFalseNegativeError();
+  RealType GetFalsePositiveError();
+  /** measures over individual labels */
+  RealType GetTargetOverlap( LabelType );
+  RealType GetUnionOverlap( LabelType );
+  RealType GetMeanOverlap( LabelType );
+  RealType GetVolumeSimilarity( LabelType );
+  RealType GetFalseNegativeError( LabelType );
+  RealType GetFalsePositiveError( LabelType );
+  /** alternative names */
+  RealType GetJaccardCoefficient()
+    { return this->GetUnionOverlap(); }
+  RealType GetJaccardCoefficient( LabelType label )
+    { return this->GetUnionOverlap( label ); }
+  RealType GetDiceCoefficient()
+    { return this->GetMeanOverlap(); }
+  RealType GetDiceCoefficient( LabelType label )
+    { return this->GetMeanOverlap( label ); }
+
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro( Input1HasNumericTraitsCheck,
+    ( Concept::HasNumericTraits<LabelType> ) );
+  /** End concept checking */
+#endif
+
+protected:
+  LabelOverlapMeasuresImageFilter();
+  ~LabelOverlapMeasuresImageFilter(){};
+  void PrintSelf( std::ostream& os, Indent indent ) const;
+
+  /**
+   * Pass the input through unmodified. Do this by setting the output to the
+   * source this by setting the output to the source image in the
+   * AllocateOutputs() method.
+   */
+  void AllocateOutputs();
+
+  void BeforeThreadedGenerateData();
+
+  void AfterThreadedGenerateData();
+
+  /** Multi-thread version GenerateData. */
+  void ThreadedGenerateData( const RegionType&, int );
+
+  // Override since the filter needs all the data for the algorithm
+  void GenerateInputRequestedRegion();
+
+  // Override since the filter produces all of its output
+  void EnlargeOutputRequestedRegion( DataObject *data );
+
+private:
+  LabelOverlapMeasuresImageFilter( const Self& ); //purposely not implemented
+  void operator=( const Self& ); //purposely not implemented
+
+  std::vector<MapType>                            m_LabelSetMeasuresPerThread;
+  MapType                                         m_LabelSetMeasures;
+
+  SimpleFastMutexLock                             m_Mutex;
+
+}; // end of class
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkLabelOverlapMeasuresImageFilter.txx"
+#endif
+
+#endif
diff --git a/itk/itkLabelOverlapMeasuresImageFilter.txx b/itk/itkLabelOverlapMeasuresImageFilter.txx
new file mode 100644 (file)
index 0000000..ced277b
--- /dev/null
@@ -0,0 +1,437 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkLabelOverlapMeasuresImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef _itkLabelOverlapMeasuresImageFilter_txx
+#define _itkLabelOverlapMeasuresImageFilter_txx
+
+#include "itkLabelOverlapMeasuresImageFilter.h"
+
+#include "itkImageRegionConstIterator.h"
+#include "itkProgressReporter.h"
+
+namespace itk {
+
+#if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
+/** Used for mutex locking */
+#define LOCK_HASHMAP this->m_Mutex.Lock()
+#define UNLOCK_HASHMAP this->m_Mutex.Unlock()
+#else
+#define LOCK_HASHMAP
+#define UNLOCK_HASHMAP
+#endif
+
+template<class TLabelImage>
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::LabelOverlapMeasuresImageFilter()
+{
+  // this filter requires two input images
+  this->SetNumberOfRequiredInputs( 2 );
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GenerateInputRequestedRegion()
+{
+  Superclass::GenerateInputRequestedRegion();
+  if( this->GetSourceImage() )
+    {
+    LabelImagePointer source = const_cast
+      <LabelImageType *>( this->GetSourceImage() );
+    source->SetRequestedRegionToLargestPossibleRegion();
+    }
+  if( this->GetTargetImage() )
+    {
+    LabelImagePointer target = const_cast
+      <LabelImageType *>( this->GetTargetImage() );
+    target->SetRequestedRegionToLargestPossibleRegion();
+    }
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::EnlargeOutputRequestedRegion( DataObject *data )
+{
+  Superclass::EnlargeOutputRequestedRegion( data );
+  data->SetRequestedRegionToLargestPossibleRegion();
+}
+
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::AllocateOutputs()
+{
+  // Pass the source through as the output
+  LabelImagePointer image =
+    const_cast<TLabelImage *>( this->GetSourceImage() );
+  this->SetNthOutput( 0, image );
+
+  // Nothing that needs to be allocated for the remaining outputs
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::BeforeThreadedGenerateData()
+{
+  int numberOfThreads = this->GetNumberOfThreads();
+
+  // Resize the thread temporaries
+  this->m_LabelSetMeasuresPerThread.resize( numberOfThreads );
+
+  // Initialize the temporaries
+  for( int n = 0; n < numberOfThreads; n++ )
+    {
+    this->m_LabelSetMeasuresPerThread[n].clear();
+    }
+
+  // Initialize the final map
+  this->m_LabelSetMeasures.clear();
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::AfterThreadedGenerateData()
+{
+  // Run through the map for each thread and accumulate the set measures.
+  for( int n = 0; n < this->GetNumberOfThreads(); n++ )
+    {
+    // iterate over the map for this thread
+    for( MapConstIterator threadIt = this->m_LabelSetMeasuresPerThread[n].begin();
+      threadIt != this->m_LabelSetMeasuresPerThread[n].end();
+      ++threadIt )
+      {
+      // does this label exist in the cumulative stucture yet?
+      MapIterator mapIt = this->m_LabelSetMeasures.find( ( *threadIt ).first );
+      if( mapIt == this->m_LabelSetMeasures.end() )
+        {
+        // create a new entry
+        typedef typename MapType::value_type MapValueType;
+        mapIt = this->m_LabelSetMeasures.insert( MapValueType(
+          (*threadIt).first, LabelSetMeasures() ) ).first;
+        }
+
+      // accumulate the information from this thread
+      (*mapIt).second.m_Source += (*threadIt).second.m_Source;
+      (*mapIt).second.m_Target += (*threadIt).second.m_Target;
+      (*mapIt).second.m_Union += (*threadIt).second.m_Union;
+      (*mapIt).second.m_Intersection +=
+        (*threadIt).second.m_Intersection;
+      (*mapIt).second.m_SourceComplement +=
+        (*threadIt).second.m_SourceComplement;
+      (*mapIt).second.m_TargetComplement +=
+        (*threadIt).second.m_TargetComplement;
+      } // end of thread map iterator loop
+    } // end of thread loop
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::ThreadedGenerateData( const RegionType& outputRegionForThread,
+  int threadId )
+{
+  ImageRegionConstIterator<LabelImageType> ItS( this->GetSourceImage(),
+    outputRegionForThread );
+  ImageRegionConstIterator<LabelImageType> ItT( this->GetTargetImage(),
+    outputRegionForThread );
+
+  // support progress methods/callbacks
+  ProgressReporter progress( this, threadId,
+    2*outputRegionForThread.GetNumberOfPixels() );
+
+  for( ItS.GoToBegin(), ItT.GoToBegin(); !ItS.IsAtEnd(); ++ItS, ++ItT )
+    {
+    LabelType sourceLabel = ItS.Get();
+    LabelType targetLabel = ItT.Get();
+
+    // is the label already in this thread?
+    MapIterator mapItS =
+      this->m_LabelSetMeasuresPerThread[threadId].find( sourceLabel );
+    MapIterator mapItT =
+      this->m_LabelSetMeasuresPerThread[threadId].find( targetLabel );
+
+    if( mapItS == this->m_LabelSetMeasuresPerThread[threadId].end() )
+      {
+      // create a new label set measures object
+      typedef typename MapType::value_type MapValueType;
+      LOCK_HASHMAP;
+      mapItS = this->m_LabelSetMeasuresPerThread[threadId].insert(
+        MapValueType( sourceLabel, LabelSetMeasures() ) ).first;
+      UNLOCK_HASHMAP;
+      }
+
+    if( mapItT == this->m_LabelSetMeasuresPerThread[threadId].end() )
+      {
+      // create a new label set measures object
+      typedef typename MapType::value_type MapValueType;
+      LOCK_HASHMAP;
+      mapItT = this->m_LabelSetMeasuresPerThread[threadId].insert(
+        MapValueType( targetLabel, LabelSetMeasures() ) ).first;
+      UNLOCK_HASHMAP;
+      }
+
+    (*mapItS).second.m_Source++;
+    (*mapItT).second.m_Target++;
+
+    if( sourceLabel == targetLabel )
+      {
+      (*mapItS).second.m_Intersection++;
+      (*mapItS).second.m_Union++;
+      }
+    else
+      {
+      (*mapItS).second.m_Union++;
+      (*mapItT).second.m_Union++;
+
+      (*mapItS).second.m_SourceComplement++;
+      (*mapItT).second.m_TargetComplement++;
+      }
+
+    progress.CompletedPixel();
+    }
+}
+
+/**
+ *  measures
+ */
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetTotalOverlap()
+{
+  RealType numerator = 0.0;
+  RealType denominator = 0.0;
+  for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
+    mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
+    {
+    // Do not include the background in the final value.
+    if( (*mapIt).first == NumericTraits<LabelType>::Zero )
+      {
+      continue;
+      }
+    numerator += static_cast<RealType>( (*mapIt).second.m_Intersection );
+    denominator += static_cast<RealType>( (*mapIt).second.m_Target );
+    }
+  return ( numerator / denominator );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetTargetOverlap( LabelType label )
+{
+  MapIterator mapIt = this->m_LabelSetMeasures.find( label );
+  if( mapIt == this->m_LabelSetMeasures.end() )
+    {
+    itkWarningMacro( "Label " << label << " not found." );
+    return 0.0;
+    }
+  RealType value =
+    static_cast<RealType>( (*mapIt).second.m_Intersection ) /
+    static_cast<RealType>( (*mapIt).second.m_Target );
+  return value;
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetUnionOverlap()
+{
+  RealType numerator = 0.0;
+  RealType denominator = 0.0;
+  for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
+    mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
+    {
+    // Do not include the background in the final value.
+    if( (*mapIt).first == NumericTraits<LabelType>::Zero )
+      {
+      continue;
+      }
+    numerator += static_cast<RealType>( (*mapIt).second.m_Intersection );
+    denominator += static_cast<RealType>( (*mapIt).second.m_Union );
+    }
+  return ( numerator / denominator );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetUnionOverlap( LabelType label )
+{
+  MapIterator mapIt = this->m_LabelSetMeasures.find( label );
+  if( mapIt == this->m_LabelSetMeasures.end() )
+    {
+    itkWarningMacro( "Label " << label << " not found." );
+    return 0.0;
+    }
+  RealType value =
+    static_cast<RealType>( (*mapIt).second.m_Intersection ) /
+    static_cast<RealType>( (*mapIt).second.m_Union );
+  return value;
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetMeanOverlap()
+{
+  RealType uo = this->GetUnionOverlap();
+  return ( 2.0 * uo / ( 1.0 + uo ) );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetMeanOverlap( LabelType label )
+{
+  RealType uo = this->GetUnionOverlap( label );
+  return ( 2.0 * uo / ( 1.0 + uo ) );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetVolumeSimilarity()
+{
+  RealType numerator = 0.0;
+  RealType denominator = 0.0;
+  for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
+    mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
+    {
+    // Do not include the background in the final value.
+    if( (*mapIt).first == NumericTraits<LabelType>::Zero )
+      {
+      continue;
+      }
+    numerator += ( ( static_cast<RealType>( (*mapIt).second.m_Source ) -
+      static_cast<RealType>( (*mapIt).second.m_Target ) ) );
+    denominator += ( ( static_cast<RealType>( (*mapIt).second.m_Source ) +
+      static_cast<RealType>( (*mapIt).second.m_Target ) ) );
+    }
+  return ( 2.0 * numerator / denominator );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetVolumeSimilarity( LabelType label )
+{
+  MapIterator mapIt = this->m_LabelSetMeasures.find( label );
+  if( mapIt == this->m_LabelSetMeasures.end() )
+    {
+    itkWarningMacro( "Label " << label << " not found." );
+    return 0.0;
+    }
+  RealType value = 2.0 *
+    ( static_cast<RealType>( (*mapIt).second.m_Source ) -
+      static_cast<RealType>( (*mapIt).second.m_Target ) ) /
+    ( static_cast<RealType>( (*mapIt).second.m_Source ) +
+      static_cast<RealType>( (*mapIt).second.m_Target ) );
+  return value;
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetFalseNegativeError()
+{
+  RealType numerator = 0.0;
+  RealType denominator = 0.0;
+  for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
+    mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
+    {
+    // Do not include the background in the final value.
+    if( (*mapIt).first == NumericTraits<LabelType>::Zero )
+      {
+      continue;
+      }
+    numerator += static_cast<RealType>( (*mapIt).second.m_TargetComplement );
+    denominator += static_cast<RealType>( (*mapIt).second.m_Target );
+    }
+  return ( numerator / denominator );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetFalseNegativeError( LabelType label )
+{
+  MapIterator mapIt = this->m_LabelSetMeasures.find( label );
+  if( mapIt == this->m_LabelSetMeasures.end() )
+    {
+    itkWarningMacro( "Label " << label << " not found." );
+    return 0.0;
+    }
+  RealType value =
+    static_cast<RealType>( (*mapIt).second.m_TargetComplement ) /
+    static_cast<RealType>( (*mapIt).second.m_Target );
+  return value;
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetFalsePositiveError()
+{
+  RealType numerator = 0.0;
+  RealType denominator = 0.0;
+  for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
+    mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
+    {
+    // Do not include the background in the final value.
+    if( (*mapIt).first == NumericTraits<LabelType>::Zero )
+      {
+      continue;
+      }
+    numerator += static_cast<RealType>( (*mapIt).second.m_SourceComplement );
+    denominator += static_cast<RealType>( (*mapIt).second.m_Source );
+    }
+  return ( numerator / denominator );
+}
+
+template<class TLabelImage>
+typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::GetFalsePositiveError( LabelType label )
+{
+  MapIterator mapIt = this->m_LabelSetMeasures.find( label );
+  if( mapIt == this->m_LabelSetMeasures.end() )
+    {
+    itkWarningMacro( "Label " << label << " not found." );
+    return 0.0;
+    }
+  RealType value =
+    static_cast<RealType>( (*mapIt).second.m_SourceComplement ) /
+    static_cast<RealType>( (*mapIt).second.m_Source );
+  return value;
+}
+
+template<class TLabelImage>
+void
+LabelOverlapMeasuresImageFilter<TLabelImage>
+::PrintSelf( std::ostream& os, Indent indent ) const
+{
+  Superclass::PrintSelf( os, indent );
+
+}
+
+
+}// end namespace itk
+#endif
index 8ea7e2c3903935ffc16c3927c5ce7a42b037916a..239745f5348c9daade6feefb3108ace546fea60a 100755 (executable)
@@ -80,8 +80,15 @@ registration()
       motion_mask=$mask_dir/mm_$phase_nb.mhd
       vf_result=$vf_dir/vf_${ref_phase_nb}_$phase_nb.mhd
       clitkCombineImage -i $vf_in -j $vf_out -m $motion_mask -o $vf_result
+      abort_on_error registration $? clean_up_registration
+
       clitkZeroVF -i $vf_in -o vf_zero.mhd
+      abort_on_error registration $? clean_up_registration
+
+      patient_mask=$mask_dir/patient_mask_$phase_nb.mhd
       clitkCombineImage -i $vf_result -j vf_zero.mhd -m $patient_mask -o $vf_result
+      abort_on_error registration $? clean_up_registration
+
       rm vf_zero.*
 
       # save for later...
@@ -91,6 +98,7 @@ registration()
 
   # create (zero) vf from reference to reference
   clitkZeroVF -i $vf_ref -o $vf_dir/vf_${ref_phase_nb}_${ref_phase_nb}.mhd
+  abort_on_error registration $? clean_up_registration
 
   # create 4D vf
   create_mhd_4D_pattern.sh $vf_dir/vf_${ref_phase_nb}_
@@ -120,14 +128,20 @@ midp()
   midp=$midp_dir/midp_$phase_nb.mhd
   # average the vf's from reference phase to phase
   clitkAverageTemporalDimension -i $vf_dir/vf_${ref_phase_nb}_4D.mhd -o $vf_midp
+  abort_on_error midp $? clean_up_midp
+
   # invert the vf (why?)
   clitkInvertVF -i $vf_midp -o $vf_midp
+  abort_on_error midp $? clean_up_midp
+
   # create the midp by warping the reference phase with the reference vf
   clitkWarpImage -i $ref_phase_file -o $midp --vf=$vf_midp -s 1
+  abort_on_error midp $? clean_up_midp
 
   ref_vf_midp=$vf_midp
   ref_midp=$midp
   clitkImageConvert -i $ref_midp -o $ref_midp -t float
+  abort_on_error midp $? clean_up_midp
 
   ########### calculate the midp wrt the other phases
   for i in $( seq 0 $((${#phase_files[@]} - 1))); do
@@ -141,16 +155,25 @@ midp()
       # calculate vf from phase to midp, using the vf from reference phase to midp (-i)
       # and the vf from reference phase to phase (-j)
       clitkComposeVF -i $ref_vf_midp -j $vf_dir/vf_$ref_phase_nb\_$phase_nb.mhd -o $vf_midp
+      abort_on_error midp $? clean_up_midp
+      
       clitkWarpImage -i $phase_file -o $midp --vf=$vf_midp -s 1
+      abort_on_error midp $? clean_up_midp
+      
       clitkImageConvert -i $midp -o $midp -t float
+      abort_on_error midp $? clean_up_midp
     fi
   done
 
   create_mhd_4D_pattern.sh $midp_dir/midp_
+
   echo "Calculating midp_avg.mhd..."
   clitkAverageTemporalDimension -i $midp_dir/midp_4D.mhd -o $midp_dir/midp_avg.mhd
+  abort_on_error midp $? clean_up_midp
+
   echo "Calculating midp_med.mhd..."
   clitkMedianTemporalDimension -i $midp_dir/midp_4D.mhd -o $midp_dir/midp_med.mhd
+  abort_on_error midp $? clean_up_midp
 
   # clean-up
   rm $midp_dir/vf_*
index f5738e0107c464a68fd0e97cba98a7e2719bd193..bbf44f0fa9a857da69581133681ddb046f715905 100755 (executable)
@@ -1,5 +1,5 @@
-#! /bin/bash -x
-
+#! /bin/bash 
+  
 ###############################################################################
 #
 # FILE: create_midP-2.0.sh
@@ -21,7 +21,10 @@ extract_patient()
 {
   echo "$phase_file -> Extracting patient..."
   clitkExtractPatient -i $phase_file -o $mask_dir_tmp/patient_mask_$phase_nb.mhd --noAutoCrop -a $afdb_file $ExtractPatientExtra
+#   abort_on_error clitkExtractPatient $?
+
   clitkSetBackground -i $phase_file -o $mask_dir_tmp/patient_$phase_nb.mhd --mask $mask_dir_tmp/patient_mask_$phase_nb.mhd --outsideValue -1000
+#   abort_on_error clitkSetBackground $?
 }
 
 extract_bones()
@@ -39,15 +42,16 @@ extract_bones()
 
 extract_lungs()
 {
-  echo "$phase_file -> Extracting lungs..."
-  clitkExtractLung -i $phase_file -o $mask_dir_tmp/lungs_$phase_nb.mhd -a $afdb_file --noAutoCrop
+  echo "$phase_file -> Extracting lungs..."  
+  clitkExtractLung -i $phase_file -o $mask_dir_tmp/lungs_$phase_nb.mhd -a $afdb_file --noAutoCrop --doNotSeparateLungs
 }
 
+
+
 resample()
 {
   echo "$phase_file -> Resampling..."
   clitkResampleImage -i $mask_dir_tmp/patient_$phase_nb.mhd -o $mask_dir_tmp/patient_$phase_nb.mhd --spacing $resample_spacing --interp $resample_algo
-
   clitkResampleImage -i $mask_dir_tmp/lungs_$phase_nb.mhd -o $mask_dir_tmp/lungs_$phase_nb.mhd --like $mask_dir_tmp/patient_$phase_nb.mhd
 }
 
@@ -198,6 +202,7 @@ motion_mask()
     mkdir -p $mask_log_dir
 
     # multi-threaded pre-processing for motion mask calcs
+    pids=( )
     for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
       phase_nb=${phase_nbs[$i]}
       phase_file=${phase_files[$i]}
@@ -205,6 +210,12 @@ motion_mask()
 
       check_threads $MAX_THREADS
       mm_preprocessing &
+      pids=( "${pids[@]}" "$!" )
+    done
+
+    wait_pids ${pids[@]}
+    for ret in $ret_codes; do
+      abort_on_error mm_preprocessing $ret clean_up_masks
     done
 
     # single-threaded motion mask calc
@@ -215,16 +226,25 @@ motion_mask()
       check_threads 1
       echo "$phase_file -> Computing motion mask..."
       compute_motion_mask > $mask_log_dir/motion_mask_$phase_file.log
+      abort_on_error compute_motion_mask $? clean_up_masks
     done
 
     # multi-threaded post-processing of motion mask calcs
+    pids=( )
     for i in $( seq 0 $((${#phase_nbs[@]} - 1))); do
       phase_nb=${phase_nbs[$i]}
       phase_file=${phase_files[$i]}
 
       check_threads $MAX_THREADS 
       mm_postprocessing &
+      pids=( "${pids[@]}" "$!" )
     done
+  
+    wait_pids ${pids[@]}
+    for ret in $ret_codes; do
+      abort_on_error mm_postprocessing $ret clean_up_masks
+    done
+
 
     # rename tmp mask directory after mask creation
     check_threads 1
index 0f767070e217639fc5b2548db0e2b315610f6608..aa500ae9a959885bd66eb8ee1cbf82426565e8ea 100755 (executable)
@@ -1,4 +1,4 @@
-#! /bin/sh +x
+#! /bin/sh -x
 
 ###############################################################################
 #
@@ -9,7 +9,72 @@
 #
 ###############################################################################
 
+#
+# check return value passed and abort if it represents an error (ie, ret != 0)
+# optionally, a function can be passed as a 3rd parameter, to be called just
+# before exiting. this is useful for cleaning up, for example.
+#
+abort_on_error()
+{
+  if [ $2 != 0 ]; then
+    echo Aborted at $1 with code $2
+    if [ $# = 3 ]; then
+      eval $3
+    fi
 
+    exit $2
+  fi
+}
+
+#
+# wait for all processes in the list and return their exit codes
+# in the ret_codes variable.
+#
+# OBS: this function must always be called in the same shell
+# that launched the processes.
+#
+wait_pids()
+{
+  local pids=$*
+  local ret=
+  local rets=
+#   echo PIDS: $pids
+  for p in $pids; do
+#     echo waiting $p
+    wait $p > /dev/null 2> /dev/null
+    ret=$?
+    if [ ret != 127 ]; then
+      rets=$rets" "$ret
+    else
+      rets=$rets" "0
+    fi
+      
+  done
+
+  ret_codes=$rets
+}
+
+#
+# clean-up functions for maks, registration, and midp
+#
+clean_up_masks()
+{
+  rm -fr $mask_dir_tmp
+}
+
+clean_up_midp()
+{
+  rm -fr $midp_dir
+}
+
+clean_up_registration()
+{
+  rm -fr $vf_dir
+  rm -fr $output_dir
+}
+
+
+#
 # block execution untill the number of threads (jobs) launched by the
 # current process is below the given number of threads. 
 MAX_THREADS=2
index 40d5fbe41dc7e0467faf028caab8bcffcb636f5d..724e3ac392f804e842e408bc67e92733fd52c6fa 100755 (executable)
@@ -31,6 +31,8 @@
 #
 ###############################################################################
 
+source `dirname $0`/midp_common.sh
+
 
 ################# BLUTDIR #####################
 registration_blutdir()
@@ -56,6 +58,8 @@ registration_blutdir()
   blutdir_params="--levels $nb_levels  --metric $metric --optimizer $optimizer --samples $nb_samples --spacing $spacing,$spacing,$spacing --bins $hist_bins --maxIt $nb_iter --interp $interpolator --verbose"
   cmd="clitkBLUTDIR -r $reference -t $target -m $mask_ref --targetMask $mask_targ --vf $vf -o $result $blutdir_params"
   $cmd > $log
+
+  abort_on_error registration_blutdir $? clean_up_registration
 }
 
 ################# ELASTIX #####################
@@ -105,10 +109,12 @@ registration_elastix()
   # image registration
   cmd="elastix -f $reference -m $target -fMask $mask_ref -mMask $mask_targ -out $result_dir -p params_BSpline_${suffix}.txt"
   $cmd  > /dev/null
+  abort_on_error registration_elastix $? clean_up_registration
 
   # generate vector field
   cmd="transformix -tp $result_dir/TransformParameters.0.txt -out $vf_dir -def all"
   $cmd  > /dev/null
+  abort_on_error registration_elastix $? clean_up_registration
 
   # post-processing
   mv $vf_dir/deformationField.mhd $vf
index c86b2df07f7e4d056463861196589b9c7364ece0..0f5bfdd64a549714aef543b9ddc60801e0cc95bd 100644 (file)
 //--------------------------------------------------------------------
 clitk::AnatomicalFeatureDatabase::AnatomicalFeatureDatabase() 
 { 
-  SetFilename("default.afdb"); 
+  SetFilename("default.afdb");
+  SetPath("./");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+clitk::AnatomicalFeatureDatabase::Pointer clitk::AnatomicalFeatureDatabase::New(std::string filename) 
+{ 
+  Pointer a = AnatomicalFeatureDatabase::New();
+  a->SetFilename(filename);
+  a->Load();
+  return a;
 }
 //--------------------------------------------------------------------
 
@@ -115,6 +127,19 @@ double clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, int dim)
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+std::string clitk::AnatomicalFeatureDatabase::GetTagValue(std::string tag)
+{
+  if (!TagExist(tag)) {
+    clitkExceptionMacro("Could not find the tag <" << tag << "> in the DB");
+    return "";
+  }
+  std::string s = m_MapOfTag[tag];
+  return s;
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 void clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, PointType3D & p)
 {
index bd574d384fa3107f7bc5aea8628c65bc893574fd..59e8decc07e2008c71996d3f7d3c237495035518 100644 (file)
@@ -34,10 +34,17 @@ namespace clitk {
   class AnatomicalFeatureDatabase: public itk::Object
   {
   public:
-    AnatomicalFeatureDatabase();
-
+    // typedef
     typedef std::string TagType;
 
+    // New macro
+    typedef itk::Object                    Superclass;
+    typedef AnatomicalFeatureDatabase      Self;
+    typedef itk::SmartPointer<Self>        Pointer;
+    typedef itk::SmartPointer<const Self>  ConstPointer;
+    itkNewMacro(Self);
+    static Pointer New(std::string filename);
+
     // Set/Get filename 
     itkSetMacro(Filename, std::string);
     itkGetConstMacro(Filename, std::string);
@@ -45,6 +52,8 @@ namespace clitk {
     // Read and write DB
     void Write();
     void Load();
+    itkGetConstMacro(Path, std::string);
+    itkSetMacro(Path, std::string);
     
     // Set Get landmarks
     typedef itk::Point<double,3> PointType3D;
@@ -52,7 +61,8 @@ namespace clitk {
     void GetPoint3D(TagType tag, PointType3D & p);
     double GetPoint3D(std::string tag, int dim);
     bool TagExist(std::string tag);
-    
+    std::string GetTagValue(std::string tag);
+
     // Set Get image
     void SetImageFilename(TagType tag, std::string f);
     template<class ImageType>
@@ -70,16 +80,23 @@ namespace clitk {
     void RemoveTag(TagType tag);
 
   protected:
+    AnatomicalFeatureDatabase();
+    ~AnatomicalFeatureDatabase() {}
+
     std::string m_Filename;
+    std::string m_Path;
     typedef itk::ImageBase<3> ImageBaseType;
     typedef std::map<TagType, std::string> MapTagType;
-        typedef std::map<TagType, ImageBaseType*> MapTagImageType; 
+    typedef std::map<TagType, ImageBaseType*> MapTagImageType; 
     MapTagType m_MapOfTag;
     MapTagImageType m_MapOfImage;
 
   }; // end class
   //--------------------------------------------------------------------
 
+#define NewAFDB(NAME, FILE)                                             \
+  clitk::AnatomicalFeatureDatabase::Pointer NAME = clitk::AnatomicalFeatureDatabase::New(FILE);
+
   #include "clitkAnatomicalFeatureDatabase.txx" 
 
 } // end namespace clitk
index 02907716c64c198674b95699cc15b481a657a201..c155d44084c2581a6940e03069fee49f7bc9de03 100644 (file)
@@ -34,7 +34,7 @@ GetImage(std::string tag, bool reload)
     else {
       std::string s = m_MapOfTag[tag];
       // Read the file
-      image = readImage<ImageType>(s);
+      image = readImage<ImageType>(GetPath()+"/"+s);
       // I add a reference count because the cache is not a smartpointer
       image->SetReferenceCount(image->GetReferenceCount()+1);
       // Insert into the cache
index 3e27657c57aa7250eaa9cd2c6950294ba3da05a4..4d3302fa502ca18f97eeabc6d1e03f0d8ffde396 100644 (file)
@@ -34,11 +34,7 @@ int main(int argc, char * argv[])
 
   filter->SetArgsInfo(args_info);
   
-  try {
-    filter->Update();
-  } catch(std::runtime_error e) {
-    std::cout << e.what() << std::endl;
-  }
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   return EXIT_SUCCESS;
 } // This is the end, my friend
index 36fa4e84be349ebc4277f5d9eadc954cc90df487..1b5fda927f4caf78a975afac9617b85ce58780e1 100644 (file)
@@ -33,11 +33,7 @@ int main(int argc, char * argv[])
 
   filter->SetArgsInfo(args_info);
   
-  try {
-    filter->Update();
-  } catch(std::runtime_error e) {
-    std::cerr << e.what() << std::endl;
-  }
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   return EXIT_SUCCESS;
 } // This is the end, my friend
index 12dd3e7040823c00e0676c005d95ec63d7522c94..98ddbd80d3dc29f1dcb53355d663a6dc7e1a4638 100644 (file)
@@ -61,4 +61,7 @@ section "Step 6 : fill holes"
 option "doNotFillHoles"                -  "Do not fill holes if set"                 flag on
 option "dir"                   d  "Directions (axes) to perform filling (defaults to 2,1,0)"   int multiple no
 
+section "Step 7 : lung separation (labelling)"
+option "doNotSeparateLungs"   -  "Do not separate lungs if set"                 flag off
+
 option "noAutoCrop"    -       "If set : do no crop final mask to BoundingBox"                         flag    off
index fa472ba711db3bff2c7ed8094380fc6b3505936c..23fbbc7a8fd427a8f5f749aaee81c69eae275064 100644 (file)
@@ -191,6 +191,11 @@ namespace clitk {
     itkGetConstMacro(FillHolesFlag, bool);
     itkBooleanMacro(FillHolesFlag);
 
+    // Separate lungs
+    itkSetMacro(SeparateLungsFlag, bool);
+    itkGetConstMacro(SeparateLungsFlag, bool);
+    itkBooleanMacro(SeparateLungsFlag);
+
     // Step Auto Crop
     itkSetMacro(AutoCrop, bool);
     itkGetConstMacro(AutoCrop, bool);
@@ -250,6 +255,8 @@ namespace clitk {
     bool m_FillHolesFlag;    
     InputImageSizeType m_FillHolesDirections;
 
+    bool m_SeparateLungsFlag;
+    
     // Main functions
     virtual void GenerateOutputInformation();
     virtual void GenerateInputRequestedRegion();
index 0954c2a3de46a11249c21237b9644e9a4a123404..d2bff5edd5962647512fd2d1070017b17a5dab34 100644 (file)
@@ -414,49 +414,51 @@ GenerateOutputInformation()
     StopCurrentStep<MaskImageType>(working_mask);
   }
 
-  //--------------------------------------------------------------------
-  //--------------------------------------------------------------------
-  StartNewStep("Separate Left/Right lungs");
-    PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
-  // Initial label
-  working_mask = Labelize<MaskImageType>(working_mask, 
-                                         GetBackgroundValue(), 
-                                         false, 
-                                         GetMinimalComponentSize());
-
-  PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
-
-  // Count the labels
-  typedef itk::StatisticsImageFilter<MaskImageType> StatisticsImageFilterType;
-  typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
-  statisticsImageFilter->SetInput(working_mask);
-  statisticsImageFilter->Update();
-  unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
-  working_mask = statisticsImageFilter->GetOutput();   
+  if (GetSeparateLungsFlag()) {
+    //--------------------------------------------------------------------
+    //--------------------------------------------------------------------
+    StartNewStep("Separate Left/Right lungs");
+      PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
+    // Initial label
+    working_mask = Labelize<MaskImageType>(working_mask, 
+                                          GetBackgroundValue(), 
+                                          false, 
+                                          GetMinimalComponentSize());
+
+    PrintMemory(GetVerboseMemoryFlag(), "After Labelize");
+
+    // Count the labels
+    typedef itk::StatisticsImageFilter<MaskImageType> StatisticsImageFilterType;
+    typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+    statisticsImageFilter->SetInput(working_mask);
+    statisticsImageFilter->Update();
+    unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
+    working_mask = statisticsImageFilter->GetOutput(); 
+    
+    PrintMemory(GetVerboseMemoryFlag(), "After count label");
   
-  PrintMemory(GetVerboseMemoryFlag(), "After count label");
-  // Decompose the first label
-  if (initialNumberOfLabels<2) {
-    // Structuring element radius
-    typename ImageType::SizeType radius;
-    for (unsigned int i=0;i<Dim;i++) radius[i]=1;
-    typedef clitk::DecomposeAndReconstructImageFilter<MaskImageType,MaskImageType> DecomposeAndReconstructFilterType;
-    typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
-    decomposeAndReconstructFilter->SetInput(working_mask);
-    decomposeAndReconstructFilter->SetVerbose(false);
-    decomposeAndReconstructFilter->SetRadius(radius);
-    decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
-    decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize());
-    decomposeAndReconstructFilter->SetMinimumNumberOfIterations(1);
-    decomposeAndReconstructFilter->SetBackgroundValue(this->GetBackgroundValue());
-    decomposeAndReconstructFilter->SetForegroundValue(this->GetForegroundValue());
-    decomposeAndReconstructFilter->SetFullyConnected(true);
-    decomposeAndReconstructFilter->SetNumberOfNewLabels(1);
-    decomposeAndReconstructFilter->Update();
-    working_mask = decomposeAndReconstructFilter->GetOutput();      
+    // Decompose the first label
+    if (initialNumberOfLabels<2) {
+      // Structuring element radius
+      typename ImageType::SizeType radius;
+      for (unsigned int i=0;i<Dim;i++) radius[i]=1;
+      typedef clitk::DecomposeAndReconstructImageFilter<MaskImageType,MaskImageType> DecomposeAndReconstructFilterType;
+      typename DecomposeAndReconstructFilterType::Pointer decomposeAndReconstructFilter=DecomposeAndReconstructFilterType::New();
+      decomposeAndReconstructFilter->SetInput(working_mask);
+      decomposeAndReconstructFilter->SetVerbose(false);
+      decomposeAndReconstructFilter->SetRadius(radius);
+      decomposeAndReconstructFilter->SetMaximumNumberOfLabels(2);
+      decomposeAndReconstructFilter->SetMinimumObjectSize(this->GetMinimalComponentSize());
+      decomposeAndReconstructFilter->SetMinimumNumberOfIterations(1);
+      decomposeAndReconstructFilter->SetBackgroundValue(this->GetBackgroundValue());
+      decomposeAndReconstructFilter->SetForegroundValue(this->GetForegroundValue());
+      decomposeAndReconstructFilter->SetFullyConnected(true);
+      decomposeAndReconstructFilter->SetNumberOfNewLabels(1);
+      decomposeAndReconstructFilter->Update();
+      working_mask = decomposeAndReconstructFilter->GetOutput();      
+    }
+    PrintMemory(GetVerboseMemoryFlag(), "After decomposeAndReconstructFilter");
   }
-  PrintMemory(GetVerboseMemoryFlag(), "After decomposeAndReconstructFilter");
 
   // Retain labels ('1' is largset lung, so right. '2' is left)
   typedef itk::ThresholdImageFilter<MaskImageType> ThresholdImageFilterType;
index 2dd396fb3a2498fb0a5ff15e3dc01a2bf6af6db8..b40dc28fc49de81bd0a4784fba74158b7dd333f6 100644 (file)
@@ -108,6 +108,11 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
     f->SetFillHolesFlag(false);
   else
     f->SetFillHolesFlag(true);
+
+  if (mArgsInfo.doNotSeparateLungs_given)
+    f->SetSeparateLungsFlag(false);
+  else
+    f->SetSeparateLungsFlag(true);
 }
 //--------------------------------------------------------------------
 
index e973ed02d07655caac505bbbf2c78a24403320dd..50e394852123e6fec950275934f2de39978a84ec 100644 (file)
@@ -148,19 +148,10 @@ ExtractStation_3A_Post_Limits_With_Dilated_Aorta_S6_Support()
   Aorta = clitk::Dilate<MaskImageType>(Aorta, radius, GetBackgroundValue(), GetForegroundValue(), false);
   
   // Now, insert this image in the AFDB (but do not store on disk)
-  GetAFDB()->template SetImage<MaskImageType>("Aorta_Dilated_Anteriorly", "bidon", 
-                                              Aorta, false);
-  /*
-  // Not Post to
-  m_Working_Support = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, Aorta, 2, 
-                                                       GetFuzzyThreshold("3A", "Aorta"), 
-                                                       "NotPostTo", true, 
-                                                       Aorta->GetSpacing()[0], false, false);
-
-  */
+  GetAFDB()->template SetImage<MaskImageType>("Aorta_Dilated_Anteriorly", "seg/Aorta_Dilated_Anteriorly.mha", Aorta, false);
+  writeImage<MaskImageType>(Aorta, "seg/Aorta_Dilated_Anteriorly.mha");
+  GetAFDB()->Write();
 
-  
   StopCurrentStep<MaskImageType>(m_Working_Support);
   m_ListOfStations["3A"] = m_Working_Support;
 }
index 15201878c1d57cf6136277c5afcfeaa007073849..8eb1fbdd2c19e4940b8cf51456dd9600a48892ad 100644 (file)
@@ -14,20 +14,42 @@ ExtractStation_4RL_SetDefaultValues()
 template <class TImageType>
 void 
 clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_4RL() {
-  if ((!CheckForStation("4R")) && (!CheckForStation("4L"))) return;
-
-  StartNewStep("Stations 4RL");
+ExtractStation_4R() {
+  if (!CheckForStation("4R")) return;
+  StartNewStep("Stations 4R");
   StartSubStep(); 
 
   // Get the current support 
-  StartNewStep("[Station 4RL] Get the current 4RL suppport");
+  StartNewStep("[Station 4R] Get the current 4RL suppport");
   m_ListOfStations["4R"] = m_ListOfSupports["S4R"];
-  m_ListOfStations["4L"] = m_ListOfSupports["S4L"];
   StopCurrentStep<MaskImageType>(m_ListOfStations["4R"]);
     
   // Generic RelativePosition processes
   m_ListOfStations["4R"] = this->ApplyRelativePositionList("Station_4R", m_ListOfStations["4R"]);
+
+  // Store image filenames into AFDB 
+  WriteImageStation("4R");
+  StopSubStep();
+  ComputeOverlapWithRef("4R");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_4L() {
+  if (!CheckForStation("4L")) return;
+  StartNewStep("Stations 4L");
+  StartSubStep(); 
+
+  // Get the current support 
+  StartNewStep("[Station 4L] Get the current 4RL suppport");
+  m_ListOfStations["4L"] = m_ListOfSupports["S4L"];
+  StopCurrentStep<MaskImageType>(m_ListOfStations["4L"]);
+    
+  // Generic RelativePosition processes
   m_ListOfStations["4L"] = this->ApplyRelativePositionList("Station_4L", m_ListOfStations["4L"]);
 
   // Separation Ant/Post
@@ -43,13 +65,9 @@ ExtractStation_4RL() {
   StopCurrentStep<MaskImageType>(m_ListOfStations["4L"]);
 
   // Store image filenames into AFDB 
-  writeImage<MaskImageType>(m_ListOfStations["4R"], "seg/Station4R.mhd");
-  writeImage<MaskImageType>(m_ListOfStations["4L"], "seg/Station4L.mhd");
-  GetAFDB()->SetImageFilename("Station4R", "seg/Station4R.mhd"); 
-  GetAFDB()->SetImageFilename("Station4L", "seg/Station4L.mhd"); 
-  WriteAFDB(); 
+  WriteImageStation("4L");
   StopSubStep();
-
+  ComputeOverlapWithRef("4L");
 }
 //--------------------------------------------------------------------
 
index 2cde97dd98b7465ae1addea1e6bcfc11965a4281..fa640a291cfd5c484f28251b3f877799efb536e1 100644 (file)
@@ -11,91 +11,74 @@ ExtractStationSupports()
   // Get initial Mediastinum
   m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
 
-  // Consider sup/inf to Carina
-  double m_CarinaZ = FindCarina();
-  MaskImagePointer m_Support_Superior_to_Carina = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, 
-                                                   m_CarinaZ, true, GetBackgroundValue());
-  MaskImagePointer m_Support_Inferior_to_Carina = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, 
-                                                     m_CarinaZ, true, GetBackgroundValue());
-  m_ListOfSupports["Support_Superior_to_Carina"] = m_Support_Superior_to_Carina;
-  m_ListOfSupports["Support_Inferior_to_Carina"] = m_Support_Inferior_to_Carina;
-  writeImage<MaskImageType>(m_Support_Inferior_to_Carina, "seg/Support_Inf_Carina.mha");
-  this->GetAFDB()->SetImageFilename("Support_Inf_Carina", "seg/Support_Inf_Carina.mha");
-  writeImage<MaskImageType>(m_Support_Superior_to_Carina, "seg/Support_Sup_Carina.mha");
-  this->GetAFDB()->SetImageFilename("Support_Sup_Carina", "seg/Support_Sup_Carina.mha");
+  // Remove some computed structures
+  this->GetAFDB()->RemoveTag("CarinaZ");
+  this->GetAFDB()->RemoveTag("ApexOfTheChestZ");  
+
+  // Superior and inferior limits.
+  Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0); 
+  Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]); 
+
+  // Initialise all others supports
+  // m_ListOfSupports["S1R"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S1L"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S2R"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S2L"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S3A"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S3P"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S4R"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S4L"] = m_ListOfSupports["Sup_to_Carina"];
+  // m_ListOfSupports["S5"] = m_Mediastinum; // Not above Carina
+  // m_ListOfSupports["S6"] = m_Mediastinum; // Not above Carina
+  
+  // Read all support limits in a file and apply them
+  ReadSupportLimits(GetSupportLimitsFilename());  
+  for(int i=0; i<m_ListOfSupportLimits.size(); i++) {
+    SupportLimitsType s = m_ListOfSupportLimits[i];
+    Support_SI_Limit(s.station_limit, s.station, s.structure_limit, 
+                     s.structure, s.offset*m_Working_Support->GetSpacing()[2]);
+  }
 
   // S1RL
-  Support_SupInf_S1RL();
   Support_LeftRight_S1R_S1L();
 
   // S2RL
-  Support_SupInf_S2R_S2L();
   Support_LeftRight_S2R_S2L();
 
   // S4RL
-  Support_SupInf_S4R_S4L();
   Support_LeftRight_S4R_S4L();
   
   // Post limits of S1,S2,S4
   Support_Post_S1S2S4();
 
-  // S3AP
-  Support_S3P();
-  Support_S3A();
-  
-  // S5, S6
-  Support_S5();
-  Support_S6();
+  // S3P
+  StartNewStep("[Support] Ant limits of S3P with trachea");
+  m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10);
+
+  // S3A
+  StartNewStep("[Support] Ant limits of S3A with trachea");
+  m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10);
   
+  // I will do it later
   // Below Carina S7,8,9,10
-  m_ListOfSupports["S7"] = clitk::Clone<MaskImageType>(m_Support_Inferior_to_Carina);
-  m_ListOfSupports["S8"] = clitk::Clone<MaskImageType>(m_Support_Inferior_to_Carina);
-  m_ListOfSupports["S9"] = clitk::Clone<MaskImageType>(m_Support_Inferior_to_Carina);
-  m_ListOfSupports["S10"] = clitk::Clone<MaskImageType>(m_Support_Inferior_to_Carina);
-  m_ListOfSupports["S11"] = clitk::Clone<MaskImageType>(m_Support_Inferior_to_Carina);
+  m_ListOfSupports["S7"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+  m_ListOfSupports["S8"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+  m_ListOfSupports["S9"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+  m_ListOfSupports["S10"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+  m_ListOfSupports["S11"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
 
   // Store image filenames into AFDB 
-  writeImage<MaskImageType>(m_ListOfSupports["S1R"], "seg/Support_S1R.mha");
-  this->GetAFDB()->SetImageFilename("Support_S1R", "seg/Support_S1R.mha");
-  writeImage<MaskImageType>(m_ListOfSupports["S1L"], "seg/Support_S1L.mha");
-  this->GetAFDB()->SetImageFilename("Support_S1L", "seg/Support_S1L.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S2L"], "seg/Support_S2L.mha");
-  this->GetAFDB()->SetImageFilename("Support_S2L", "seg/Support_S2L.mha");
-  writeImage<MaskImageType>(m_ListOfSupports["S2R"], "seg/Support_S2R.mha");
-  this->GetAFDB()->SetImageFilename("Support_S2R", "seg/Support_S2R.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S3P"], "seg/Support_S3P.mha");
-  this->GetAFDB()->SetImageFilename("Support_S3P", "seg/Support_S3P.mha");
-  writeImage<MaskImageType>(m_ListOfSupports["S3A"], "seg/Support_S3A.mha");
-  this->GetAFDB()->SetImageFilename("Support_S3A", "seg/Support_S3A.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S4L"], "seg/Support_S4L.mha");
-  this->GetAFDB()->SetImageFilename("Support_S4L", "seg/Support_S4L.mha");
-  writeImage<MaskImageType>(m_ListOfSupports["S4R"], "seg/Support_S4R.mha");
-  this->GetAFDB()->SetImageFilename("Support_S4R", "seg/Support_S4R.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S5"], "seg/Support_S5.mha");
-  this->GetAFDB()->SetImageFilename("Support_S5", "seg/Support_S5.mha");
-  writeImage<MaskImageType>(m_ListOfSupports["S6"], "seg/Support_S6.mha");
-  this->GetAFDB()->SetImageFilename("Support_S6", "seg/Support_S6.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S7"], "seg/Support_S7.mha");
-  this->GetAFDB()->SetImageFilename("Support_S7", "seg/Support_S7.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S8"], "seg/Support_S8.mha");
-  this->GetAFDB()->SetImageFilename("Support_S8", "seg/Support_S8.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S9"], "seg/Support_S9.mha");
-  this->GetAFDB()->SetImageFilename("Support_S9", "seg/Support_S9.mha");
-
-  writeImage<MaskImageType>(m_ListOfSupports["S10"], "seg/Support_S10.mha");
-  this->GetAFDB()->SetImageFilename("Support_S10", "seg/Support_S10.mha");  
-
-  writeImage<MaskImageType>(m_ListOfSupports["S11"], "seg/Support_S11.mha");
-  this->GetAFDB()->SetImageFilename("Support_S11", "seg/Support_S11.mha");  
+  WriteImageSupport("S1R"); WriteImageSupport("S1L");
+  WriteImageSupport("S2R"); WriteImageSupport("S2L");
+  WriteImageSupport("S3A"); WriteImageSupport("S3P");
+  WriteImageSupport("S4R"); WriteImageSupport("S4L");
+  WriteImageSupport("S5");
+  WriteImageSupport("S6");
+  WriteImageSupport("S7");
+  WriteImageSupport("S8");
+  WriteImageSupport("S9");
+  WriteImageSupport("S10");
+  WriteImageSupport("S11");
   WriteAFDB();
 }
 //--------------------------------------------------------------------
@@ -105,31 +88,143 @@ ExtractStationSupports()
 template <class ImageType>
 void 
 clitk::ExtractLymphStationsFilter<ImageType>::
-Support_SupInf_S1RL()
+Support_SI_Limit(const std::string station_limit, const std::string station, 
+                 const std::string structure_limit, const std::string structure, 
+                 const double offset)
 {
-  // Step : S1RL
-  StartNewStep("[Support] Sup-Inf S1RL");
-  /*
-    2R: Upper border: apex of the right lung and pleural space, and in
-    the midline, the upper border of the manubrium
-    
-    2L: Upper border: apex of the left lung and pleural space, and in the
-    midline, the upper border of the manubrium
+  if (!GetCheckSupportFlag()) 
+    StartNewStep("[Support] "+station_limit+" limit of "+station+" is "+structure_limit+" limit of "+structure);
 
-    => apex / manubrium = up Sternum
-  */
-  m_Working_Support = m_ListOfSupports["Support_Superior_to_Carina"];
-  MaskImagePointer Sternum = this->GetAFDB()->template GetImage <MaskImageType>("Sternum");
-  MaskImagePointType p;
-  p[0] = p[1] = p[2] =  0.0; // to avoid warning
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Sternum, GetBackgroundValue(), 2, false, p);
-  MaskImagePointer S1RL = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, 
-                                                   p[2], true, GetBackgroundValue());
-  m_Working_Support = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, 
-                                                     p[2], true, GetBackgroundValue());
-  m_ListOfSupports["S1RL"] = S1RL;
+  // Check
+  if ((station_limit != "superior") && (station_limit != "inferior")) {
+    clitkExceptionMacro("Error station_limit must be 'inferior' or 'superior', not '"<< station_limit);
+  }
+  if ((structure_limit != "superior") && (structure_limit != "inferior")) {
+    clitkExceptionMacro("Error structure_limit must be 'inferior' or 'superior', not '"<< structure_limit);
+  }
+
+  // Get current support
+  if (m_ListOfSupports.find(station) == m_ListOfSupports.end()) {
+    // std::cerr << "Warning: support " << station << " not initialized" << std::endl;
+    m_ListOfSupports[station] = m_Mediastinum;
+  }
+  m_Working_Support = m_ListOfSupports[station];
+  
+  // Get structure or structureZ
+  double z;
+  int found=0;
+  std::string file;
+
+  // Try to load structure and compute extrema point
+  if (this->GetAFDB()->TagExist(structure)) {
+    MaskImagePointer Structure = this->GetAFDB()->template GetImage <MaskImageType>(structure);
+    file = this->GetAFDB()->GetTagValue(structure);
+    MaskImagePointType p;
+    p[0] = p[1] = p[2] =  0.0; // to avoid warning
+    if (structure_limit == "superior") 
+      clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
+    else 
+      clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
+    z = p[2];
+    found=1;
+  }
+
+  // Try to load structureZ
+  if ((found==0) && (this->GetAFDB()->TagExist(structure+"Z"))) {
+    z = this->GetAFDB()->GetDouble(structure+"Z");
+    found=2;
+  }
+  
+  // Try to load structurePoint
+  if ((found==0) && (this->GetAFDB()->TagExist(structure+"Point"))) {
+    MaskImagePointType p;
+    this->GetAFDB()->GetPoint3D(structure+"Point", p);
+    z = p[2];
+    found=3;
+  }
+
+  // Try to see if it is an already computed support
+  if (found==0) {
+    if (m_ListOfSupports.find(structure) != m_ListOfSupports.end()) {
+      MaskImagePointer Structure = m_ListOfSupports[structure];
+      MaskImagePointType p;
+      if (structure_limit == "superior") 
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
+      else 
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
+      z = p[2];
+      found=4;
+    }
+  }
+  
+  // Try special case : "FindApexOfTheChest"
+  if (structure == "FindApexOfTheChest") {
+    z = FindApexOfTheChest();
+    found=5;
+  }
+  if (structure == "FindInferiorBorderOfAorticArch") {
+    z = FindInferiorBorderOfAorticArch();
+    found=6;
+  }
+  if (structure == "FindSuperiorBorderOfAorticArch") {
+    z = FindSuperiorBorderOfAorticArch();
+    found=6;
+  }
+
+  // If we find anything
+  if (found == 0) {
+    std::cerr << "ERROR : I could not find " << structure << " nor " << structure << "Z nor " 
+              << structure << "Point" << std::endl;
+    exit(EXIT_FAILURE);
+  }
+
+  // Apply offset
+  z += offset;
+
+  // Remove Lower or greater
+  if (station_limit == "inferior") {
+    m_Working_Support = 
+      clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
+  }
+  else {
+    m_Working_Support = 
+      clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
+  }
+  
+  // Check: if reference station is given, display information
+  if (GetCheckSupportFlag())  {
+    try {
+      MaskImagePointer Ref = this->GetAFDB()->template GetImage <MaskImageType>(station+"_Ref");
+      MaskImagePointType p_support;
+      MaskImagePointType p_ref;
+      if (station_limit == "superior") {
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, false, p_ref);
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, false, p_support);
+      }
+      else {
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, true, p_ref);
+        clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, true, p_support);
+      }
+      std::ostringstream os;
+      os << "[Support] \t" << station << "\t" << station_limit << " "
+         << "Z = " << z << std::setprecision(2) << std::fixed
+         << "\tSupport = " << p_support[2]
+         << "\tRef = " << p_ref[2]
+         << "\tdiff = " << p_support[2]-p_ref[2] << "\t"
+         << structure << " " << structure_limit;
+      if (found==1) os << " (S "+file+")";
+      if (found==2) os << " (Z)";
+      if (found==3) os << " (P)";
+      if (found==4) os << " (p)";
+      if (found==5) os << " (Apex)";
+      if (found==6) os << " (AorticArch)";
+      StartNewStep(os.str());
+    } catch(clitk::ExceptionObject e) { }
+  }
+  
+  // Set support
+  m_ListOfSupports[station] = m_Working_Support;  
+  StopCurrentStep<MaskImageType>(m_Working_Support);  
 }
 //--------------------------------------------------------------------
 
@@ -146,7 +241,7 @@ Support_LeftRight_S1R_S1L()
   std::vector<ImagePointType> B;
   // Search for centroid positions of trachea
   MaskImagePointer Trachea = this->GetAFDB()->template GetImage <MaskImageType>("Trachea");
-  MaskImagePointer S1RL = m_ListOfSupports["S1RL"];
+  MaskImagePointer S1RL = m_ListOfSupports["S1R"];
   Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, S1RL, GetBackgroundValue());
   std::vector<MaskSlicePointer> slices;
   clitk::ExtractSlices<MaskImageType>(Trachea, 2, slices);
@@ -170,102 +265,20 @@ Support_LeftRight_S1R_S1L()
 
   // Right part
   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B, 
-                                                                    GetBackgroundValue(), 0, -10);
+                                                                    GetBackgroundValue(), 0, 10);
   S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
   m_ListOfSupports["S1R"] = S1R;
 
   // Left part
   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B, 
-                                                                    GetBackgroundValue(), 0, 10);
+                                                                    GetBackgroundValue(), 0, -10);
   S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
   m_ListOfSupports["S1L"] = S1L;
+  StopCurrentStep<MaskImageType>(m_ListOfSupports["S1L"]);
 }
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_SupInf_S2R_S2L()
-{
-  // Step : S2RL Sup-Inf limits
-  /*
-    2R Lower border: intersection of caudal margin of innominate vein with
-    the trachea
-    2L Lower border: superior border of the aortic arch
-  */
-  StartNewStep("[Support] Sup-Inf S2RL");
-  m_Working_Support = m_ListOfSupports["Support_Superior_to_Carina"];
-  
-  // S2R Caudal Margin Of Left BrachiocephalicVein
-  MaskImagePointer BrachioCephalicVein = this->GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
-  MaskImagePointType p;
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(BrachioCephalicVein, GetBackgroundValue(), 2, true, p);
-
-  // I add slightly more than a slice --> NO !!
-  double CaudalMarginOfLeftBrachiocephalicVeinZ=p[2];//+ 1.1*m_Working_Support->GetSpacing()[2];
-
-  this->GetAFDB()->SetDouble("CaudalMarginOfLeftBrachiocephalicVeinZ", CaudalMarginOfLeftBrachiocephalicVeinZ);
-  MaskImagePointer S2R = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, 
-                                                   CaudalMarginOfLeftBrachiocephalicVeinZ, true,
-                                                   GetBackgroundValue());
-  // S2L : Top Of Aortic Arch
-  MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Aorta, GetBackgroundValue(), 2, false, p);
-
-  // Save the TopOfAorticArchZ
-  this->GetAFDB()->SetDouble("TopOfAorticArchZ", p[2]);
-
-  // I substract slightly more than a slice to respect delineation
-  double TopOfAorticArchZ=p[2]- 1.1*m_Working_Support->GetSpacing()[2];
-  //  this->GetAFDB()->SetDouble("TopOfAorticArchZ", TopOfAorticArchZ);
-
-  MaskImagePointer S2L = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, 
-                                                   TopOfAorticArchZ, true,
-                                                   GetBackgroundValue());
-
-  /*
-  // S2RL: Superior support, I use inferior part of S1RL
-  MaskImagePointer S1L = m_ListOfSupports["S1L"];
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(S1L, GetBackgroundValue(), 2, true, p);
-  DD(p);
-  S2L = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S2L, 2, 
-                                                     p[2], true,
-                                                     GetBackgroundValue());
-
-  MaskImagePointer S1R = m_ListOfSupports["S1R"];
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(S1R, GetBackgroundValue(), 2, true, p);
-  DD(p);
-  S2R = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S2R, 2, 
-                                                     p[2], true,
-                                                     GetBackgroundValue());          
-  */
-
-  // Superior limits, use Sternum (but not strictly inf to S1RL
-  MaskImagePointer Sternum = this->GetAFDB()->template GetImage <MaskImageType>("Sternum");
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Sternum, GetBackgroundValue(), 2, false, p);
-  // Add one slice
-  p[2] = p[2] +  m_Working_Support->GetSpacing()[2];
-  S2L = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S2L, 2, 
-                                                     p[2], true, GetBackgroundValue());
-  S2R = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S2R, 2, 
-                                                     p[2], true, GetBackgroundValue());
-
-  // The is the end
-  m_ListOfSupports["S2L"] = S2L;
-  m_ListOfSupports["S2R"] = S2R;
-}
-//--------------------------------------------------------------------
-
-
-
 //--------------------------------------------------------------------
 template <class ImageType>
 void 
@@ -284,6 +297,8 @@ Support_LeftRight_S2R_S2L()
   MaskImagePointer S2L = m_ListOfSupports["S2L"];
   S2R = LimitsWithTrachea(S2R, 0, 1, -10);
   S2L = LimitsWithTrachea(S2L, 0, 1, 10);
+  S2R = clitk::AutoCrop<MaskImageType>(S2R, GetBackgroundValue());
+  S2L = clitk::AutoCrop<MaskImageType>(S2L, GetBackgroundValue());
   m_ListOfSupports["S2R"] = S2R;
   m_ListOfSupports["S2L"] = S2L;  
   this->GetAFDB()->template ReleaseImage<MaskImageType>("Trachea");
@@ -291,71 +306,6 @@ Support_LeftRight_S2R_S2L()
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_SupInf_S4R_S4L()
-{
-  // ---------------------------------------------------------------------------
-  /* Step : S4RL Sup-Inf
-     - start at the end of 2R and 2L
-     - stop ?
-     - 4R
-     Rod says : "The inferior border is at the lower border of the azygous vein."
-     Rod says : difficulties
-     (was : "ends at the upper lobe bronchus or where the right pulmonary artery
-     crosses the midline of the mediastinum ")
-     - 4L
-     Rod says : "The lower border is to upper margin of the left main pulmonary artery."
-     (was LLL bronchus)
-  */
-  StartNewStep("[Support] Sup-Inf limits of 4R/4L");
-
-  // Start from the support
-  MaskImagePointer S4RL = clitk::Clone<MaskImageType>(m_Working_Support);
-  MaskImagePointer S4R = clitk::Clone<MaskImageType>(S4RL);
-  MaskImagePointer S4L = clitk::Clone<MaskImageType>(S4RL);
-
-  // Keep only what is lower than S2
-  MaskImagePointer S2R = m_ListOfSupports["S2R"];
-  MaskImagePointer S2L = m_ListOfSupports["S2L"];
-  MaskImagePointType p;
-  // Right part
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(S2R, GetBackgroundValue(), 
-                                                          2, true, p);
-  S4R = clitk::CropImageRemoveGreaterThan<MaskImageType>(S4R, 2, 
-                                                       p[2], true, GetBackgroundValue());
-  // Left part
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(S2L, GetBackgroundValue(), 
-                                                          2, true, p);
-  S4L = clitk::CropImageRemoveGreaterThan<MaskImageType>(S4L, 2, 
-                                                         p[2], true, GetBackgroundValue());
-
-  // Get AzygousVein and limit according to LowerBorderAzygousVein
-  MaskImagePointer LowerBorderAzygousVein 
-    = this->GetAFDB()->template GetImage<MaskImageType>("LowerBorderAzygousVein");
-  std::vector<MaskImagePointType> c;
-  clitk::ComputeCentroids<MaskImageType>(LowerBorderAzygousVein, GetBackgroundValue(), c);
-  S4R = clitk::CropImageRemoveLowerThan<MaskImageType>(S4R, 2, 
-                                                       c[1][2], true, GetBackgroundValue());
-  S4R = clitk::AutoCrop<MaskImageType>(S4R, GetBackgroundValue());
-  m_ListOfSupports["S4R"] = S4R;
-
-
-  // Limit according to LeftPulmonaryArtery
-  MaskImagePointer LeftPulmonaryArtery 
-    = this->GetAFDB()->template GetImage<MaskImageType>("LeftPulmonaryArtery");
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(LeftPulmonaryArtery, GetBackgroundValue(), 
-                                                          2, false, p);
-  S4L = clitk::CropImageRemoveLowerThan<MaskImageType>(S4L, 2, 
-                                                       p[2], true, GetBackgroundValue());
-  S4L = clitk::AutoCrop<MaskImageType>(S4L, GetBackgroundValue());
-  m_ListOfSupports["S4L"] = S4L;
-}
-//--------------------------------------------------------------------
-
-
 //--------------------------------------------------------------------
 template <class ImageType>
 void 
@@ -472,121 +422,13 @@ Support_Post_S1S2S4()
   MaskImagePointer S2L = m_ListOfSupports["S2L"];
   MaskImagePointer S4R = m_ListOfSupports["S4R"];
   MaskImagePointer S4L = m_ListOfSupports["S4L"];
-  S1L = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
-  S1R = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
-  S2R = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest);
-  S2L = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest);
-  S4R = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest);
-  S4L = LimitsWithTrachea(S4L, 1, 0, -10, m_ApexOfTheChest);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_S3P()
-{
-  StartNewStep("[Support] Ant limits of S3P and Post limits of S1RL, S2RL, S4RL");
-  
-  // Initial S3P support
-  MaskImagePointer S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["Support_Superior_to_Carina"]);
-
-  // Stop at Lung Apex
-  double m_ApexOfTheChest = FindApexOfTheChest();
-  S3P = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S3P, 2, 
-                                                     m_ApexOfTheChest, true,
-                                                     GetBackgroundValue());
-  // Ant limits with Trachea
-  S3P = LimitsWithTrachea(S3P, 1, 0, 10);
-  m_ListOfSupports["S3P"] = S3P;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_S3A()
-{
-  StartNewStep("[Support] Sup-Inf and Post limits for S3A");
-
-  // Initial S3A support
-  MaskImagePointer S3A = clitk::Clone<MaskImageType>(m_ListOfSupports["Support_Superior_to_Carina"]);
-
-  // Stop at Lung Apex or like S2/S1 (upper border Sternum - manubrium) ?
-
-  //double m_ApexOfTheChest = FindApexOfTheChest();
-
-  MaskImagePointer Sternum = this->GetAFDB()->template GetImage <MaskImageType>("Sternum");
-  MaskImagePointType p;
-  p[0] = p[1] = p[2] =  0.0; // to avoid warning
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Sternum, GetBackgroundValue(), 2, false, p);
-  p[2] += Sternum->GetSpacing()[2]; // we add one slice to stop 3A at the same slice than Sternum stop
-  S3A = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(S3A, 2, 
-                                                     //m_ApexOfTheChest
-                                                     p[2], true,
-                                                     GetBackgroundValue());
-  // Ant limits with Trachea
-  S3A = LimitsWithTrachea(S3A, 1, 0, -10);
-  m_ListOfSupports["S3A"] = S3A;  
+  m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
+  m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
+  m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest);
+  m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest);
+  m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest);
+  m_ListOfSupports["S4L"] = LimitsWithTrachea(S4L, 1, 0, -10, m_ApexOfTheChest);
 }
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_S5()
-{
-  StartNewStep("[Support] Sup-Inf limits S5 with Aorta and MainPulmonaryArtery");
-
-  // Initial S5 support
-  MaskImagePointer S5 = 
-    clitk::Clone<MaskImageType>(this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true));
-
-  // Sup limits with Aorta
-  double sup = FindInferiorBorderOfAorticArch();
-  
-  // Inf limits with "upper rim of the left main pulmonary artery"
-  // For the moment only, it will change.
-  MaskImagePointer MainPulmonaryArtery = this->GetAFDB()->template GetImage<MaskImageType>("MainPulmonaryArtery");
-  MaskImagePointType p;
-  p[0] = p[1] = p[2] =  0.0; // to avoid warning
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(MainPulmonaryArtery, GetBackgroundValue(), 2, false, p);
-  p[2] += MainPulmonaryArtery->GetSpacing()[2];
-  
-  // Cut Sup/Inf
-  S5 = clitk::CropImageAlongOneAxis<MaskImageType>(S5, 2, p[2], sup, true, GetBackgroundValue());
-
-  m_ListOfSupports["S5"] = S5; 
-}
-//--------------------------------------------------------------------
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void
-clitk::ExtractLymphStationsFilter<ImageType>::
-Support_S6()
-{
-  StartNewStep("[Support] Sup-Inf limits S6 with aorta");
-
-  // Initial S6 support like S3A
-  MaskImagePointer S6 = clitk::Clone<MaskImageType>(m_ListOfSupports["S3A"]);
-
-  // Inf Sup limits with Aorta
-  double sup = FindSuperiorBorderOfAorticArch();
-  double inf = FindInferiorBorderOfAorticArch();
-  
-  // Cut Sup/Inf
-  S6 = clitk::CropImageAlongOneAxis<MaskImageType>(S6, 2, inf, sup, true, GetBackgroundValue());
-
-  m_ListOfSupports["S6"] = S6;  
-}
-//--------------------------------------------------------------------
-
index ec41a4e5acac639048cf6b1508b9066d6d50279e..25b52894dea649c773802d5bed4662bb3a8f4c7b 100644 (file)
@@ -38,6 +38,7 @@ int main(int argc, char * argv[])
     filter->Update();
   } catch(std::runtime_error e) {
     std::cout << e.what() << std::endl;
+    return EXIT_FAILURE;
   }
 
   return EXIT_SUCCESS;
index 82ed33b8943dcf4343c41634ddd79ec15ee92cfe..457f64e933d19174c37db836b435de6be1a99dc0 100644 (file)
@@ -3,25 +3,30 @@ package "clitkExtractLymphStations"
 version "1.0"
 purpose "Extract LymphStations with help of TODO"
 
-option "config" - "Config file" string no
-option "imagetypes" - "Display allowed image types" flag off
-option "verbose" v "Verbose" flag off
-option "verboseStep" - "Verbose each step" flag off
-option "writeStep" w "Write image at each step" flag off
-option "verboseOption" - "Display options values" flag off
-option "verboseWarningOff" - "Do not display warning" flag off
-option "verboseMemory" - "Display memory usage" flag off
+option "config"             - "Config file"                 string no
+option "imagetypes"         - "Display allowed image types" flag   off
+option "verbose"            v "Verbose"                     flag   off
+option "verboseStep"        - "Verbose each step"           flag   off
+option "writeStep"          w "Write image at each step"    flag   off
+option "verboseOption"      - "Display options values"      flag   off
+option "verboseWarningOff"  - "Do not display warning"      flag   off
+option "verboseMemory"      - "Display memory usage"        flag   off
 
 section "I/O"
 
-option "afdb" a "Input Anatomical Feature DB" string no
-option "input" i "Input filename" string no
-option "output" o "Output lungs mask filename" string no
+option "afdb"       a "Input Anatomical Feature DB"  string no
+option "afdb_path"  p "Input path for image in AFDB" string default="./" no
+option "input"      i "Input filename"               string no
+option "support_limits" - "Filename to read the support limits"                           string yes
+option "check_support_limits" - "Display stat on the support limits" flag off
+option "output"     o "Output lungs mask filename"   string no
 
 section "Options for all stations"
-option "station" - "Force to compute station even if already exist in the DB" string no multiple
-option "nosupport" - "Do not recompute the station supports if already available" flag off
-option "relpos" - "List of filenames for relativeposition operations" string no multiple
+option "force_support"  - "Force to compute all supports even if already available"       flag   off
+option "station"        - "Force to compute this station even if already exist in the DB" string no multiple
+option "relpos"         - "List of filenames for relativeposition operations"             string no multiple
+
+
 
 # section "Options for Station 3A"
 # section "Options for Station 2RL"
index b7b8c3b939bf0039542db04cb0a6e1411c688820..080bdb7185169bfed1113a1e6ee19935330caa04 100644 (file)
 
 // clitk
 #include "clitkStructuresExtractionFilter.h"
+#include "clitkLabelImageOverlapMeasureFilter.h"
 
 // vtk
 #include <vtkPolyData.h>
 
 namespace clitk {
   
+  class SupportLimitsType {
+  public:
+    std::string station_limit;
+    std::string station;
+    std::string structure_limit;
+    std::string structure;
+    double offset;
+    void Read(istream & is) {
+      is >> station_limit;
+      is >> station;
+      is >> structure_limit;
+      is >> structure;
+      std::string s;
+      is >> s;
+      offset = atof(s.c_str());
+    }
+  };
+
   //--------------------------------------------------------------------
   /*
     Try to extract the LymphStations part of a thorax CT.
@@ -106,9 +125,16 @@ namespace clitk {
     double GetFuzzyThreshold(std::string station, std::string tag);
     void SetThreshold(std::string station, std::string tag, double value);
     double GetThreshold(std::string station, std::string tag);
-    itkGetConstMacro(ComputeStationsSupportsFlag, bool);
-    itkSetMacro(ComputeStationsSupportsFlag, bool);
-    itkBooleanMacro(ComputeStationsSupportsFlag);
+    itkGetConstMacro(ForceSupportsFlag, bool);
+    itkSetMacro(ForceSupportsFlag, bool);
+    itkBooleanMacro(ForceSupportsFlag);
+
+    itkGetConstMacro(CheckSupportFlag, bool);
+    itkSetMacro(CheckSupportFlag, bool);
+    itkBooleanMacro(CheckSupportFlag);
+
+    itkGetConstMacro(SupportLimitsFilename, std::string);
+    itkSetMacro(SupportLimitsFilename, std::string);
 
   protected:
     ExtractLymphStationsFilter();
@@ -137,9 +163,18 @@ namespace clitk {
     MaskImagePixelType m_BackgroundValue;
     MaskImagePixelType m_ForegroundValue;
     std::map<std::string, bool> m_ComputeStationMap;
+    std::string m_SupportLimitsFilename;
+    std::vector<SupportLimitsType> m_ListOfSupportLimits;
 
     bool CheckForStation(std::string station);
     void Remove_Structures(std::string station, std::string s);
+    void WriteImageSupport(std::string support);
+    void WriteImageStation(std::string station);
+    void ComputeOverlapWithRef(std::string station);
+    void Support_SI_Limit(const std::string station_limit, const std::string station, 
+                          const std::string structure_limit, const std::string structure, 
+                          const double offset);
+    void ReadSupportLimits(std::string filename);
 
     // Functions common to several stations
     double FindCarina();
@@ -159,17 +194,10 @@ namespace clitk {
 
     // Station's supports
     void ExtractStationSupports();
-    void Support_SupInf_S1RL();
     void Support_LeftRight_S1R_S1L();
-    void Support_SupInf_S2R_S2L();
     void Support_LeftRight_S2R_S2L();
-    void Support_SupInf_S4R_S4L();
     void Support_LeftRight_S4R_S4L();
     void Support_Post_S1S2S4();
-    void Support_S3P();
-    void Support_S3A();
-    void Support_S5();
-    void Support_S6();
 
     MaskImagePointer LimitsWithTrachea(MaskImageType * input, 
                                        int extremaDirection, int lineDirection, 
@@ -226,7 +254,8 @@ namespace clitk {
 
     // Station 4RL
     void ExtractStation_4RL_SetDefaultValues();
-    void ExtractStation_4RL();
+    void ExtractStation_4L();
+    void ExtractStation_4R();
     void ExtractStation_S4L_S5_Limits_Aorta_LeftPulmonaryArtery(int KeepPoint);
 
     // Station 5
@@ -249,7 +278,8 @@ namespace clitk {
     void ExtractStation_7_Posterior_Limits();   
     void ExtractStation_7_Remove_Structures();
     bool m_S7_UseMostInferiorPartOnlyFlag;
-    bool m_ComputeStationsSupportsFlag;
+    bool m_ForceSupportsFlag;
+    bool m_CheckSupportFlag;
     MaskImagePointer m_Working_Trachea;
     MaskImagePointer m_LeftBronchus;
     MaskImagePointer m_RightBronchus;
diff --git a/segmentation/clitkExtractLymphStationsFilter.old.h b/segmentation/clitkExtractLymphStationsFilter.old.h
deleted file mode 100644 (file)
index 6be4764..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*=========================================================================
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
-
-  Authors belong to: 
-  - University of LYON              http://www.universite-lyon.fr/
-  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
-
-  This software is distributed WITHOUT ANY WARRANTY; without even
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-  PURPOSE.  See the copyright notices for more information.
-
-  It is distributed under dual licence
-
-  - BSD        See included LICENSE.txt file
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-  ======================================================================-====*/
-
-#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_H
-#define CLITKEXTRACTLYMPHSTATIONSFILTER_H
-
-// clitk
-#include "clitkFilterBase.h"
-#include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
-
-namespace clitk {
-  
-  //--------------------------------------------------------------------
-  /*
-    Try to extract the LymphStations part of a thorax CT.
-    Inputs : 
-    - Patient label image
-    - Lungs label image
-    - Bones label image
-  */
-  //--------------------------------------------------------------------
-  
-  template <class TImageType>
-  class ITK_EXPORT ExtractLymphStationsFilter: 
-    public virtual clitk::FilterBase, 
-    public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
-    public itk::ImageToImageFilter<TImageType, itk::Image<uchar, 3> >
-  {
-
-  public:
-    /** Standard class typedefs. */
-    typedef itk::ImageToImageFilter<TImageType, itk::Image<uchar, 3> > Superclass;
-    typedef ExtractLymphStationsFilter          Self;
-    typedef itk::SmartPointer<Self>             Pointer;
-    typedef itk::SmartPointer<const Self>       ConstPointer;
-    
-    /** Method for creation through the object factory. */
-    itkNewMacro(Self);
-    
-    /** Run-time type information (and related methods). */
-    itkTypeMacro(ExtractLymphStationsFilter, InPlaceImageFilter);
-
-    /** Some convenient typedefs. */
-    typedef TImageType                       ImageType;
-    typedef typename ImageType::ConstPointer ImageConstPointer;
-    typedef typename ImageType::Pointer      ImagePointer;
-    typedef typename ImageType::RegionType   ImageRegionType; 
-    typedef typename ImageType::PixelType    ImagePixelType; 
-    typedef typename ImageType::SizeType     ImageSizeType; 
-    typedef typename ImageType::IndexType    ImageIndexType; 
-    typedef typename ImageType::PointType    ImagePointType; 
-        
-    typedef uchar MaskImagePixelType;
-    typedef itk::Image<MaskImagePixelType, 3> MaskImageType;  
-    typedef typename MaskImageType::Pointer   MaskImagePointer;
-
-    /** Connect inputs */
-    //    void SetInput(const TImageType * image);
-  
-    /** ImageDimension constants */
-    itkStaticConstMacro(ImageDimension, unsigned int, TImageType::ImageDimension);
-    FILTERBASE_INIT;
-   
-    itkGetConstMacro(BackgroundValue, ImagePixelType);
-    itkGetConstMacro(ForegroundValue, ImagePixelType);
-    itkSetMacro(BackgroundValue, ImagePixelType);
-    itkSetMacro(ForegroundValue, ImagePixelType);
-    
-    itkSetMacro(FuzzyThreshold, double);
-    itkGetConstMacro(FuzzyThreshold, double);
-
-  protected:
-    ExtractLymphStationsFilter();
-    virtual ~ExtractLymphStationsFilter() {}
-    
-    virtual void GenerateOutputInformation();
-    virtual void GenerateInputRequestedRegion();
-    virtual void GenerateData();
-       
-    MaskImagePointer m_mediastinum;
-    MaskImagePointer m_trachea;
-    MaskImagePointer m_working_mediastinum;
-    MaskImagePointer m_working_trachea;  
-    MaskImagePointer m_output;  
-    
-    ImagePixelType m_BackgroundValue;
-    ImagePixelType m_ForegroundValue;
-    double m_CarinaZPositionInMM;
-    bool   m_CarinaZPositionInMMIsSet;
-    double m_MiddleLobeBronchusZPositionInMM; 
-
-    double m_IntermediateSpacing;
-    double m_FuzzyThreshold;
-    
-  private:
-    ExtractLymphStationsFilter(const Self&); //purposely not implemented
-    void operator=(const Self&); //purposely not implemented
-    
-  }; // end class
-  //--------------------------------------------------------------------
-
-} // end namespace clitk
-//--------------------------------------------------------------------
-
-#ifndef ITK_MANUAL_INSTANTIATION
-#include "clitkExtractLymphStationsFilter.txx"
-#endif
-
-#endif
diff --git a/segmentation/clitkExtractLymphStationsFilter.old.txx b/segmentation/clitkExtractLymphStationsFilter.old.txx
deleted file mode 100644 (file)
index c95be39..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/*=========================================================================
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
-
-  Authors belong to: 
-  - University of LYON              http://www.universite-lyon.fr/
-  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
-
-  This software is distributed WITHOUT ANY WARRANTY; without even
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-  PURPOSE.  See the copyright notices for more information.
-
-  It is distributed under dual licence
-
-  - BSD        See included LICENSE.txt file
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-  ======================================================================-====*/
-
-#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
-#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
-
-// clitk
-#include "clitkCommon.h"
-#include "clitkExtractLymphStationsFilter.h"
-#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
-#include "clitkSegmentationUtils.h"
-#include "clitkAutoCropFilter.h"
-#include "clitkSegmentationUtils.h"
-#include "clitkSliceBySliceRelativePositionFilter.h"
-
-// itk
-#include <itkStatisticsLabelMapFilter.h>
-#include <itkLabelImageToStatisticsLabelMapFilter.h>
-#include <itkRegionOfInterestImageFilter.h>
-#include <itkBinaryThresholdImageFilter.h>
-#include <itkImageSliceConstIteratorWithIndex.h>
-#include <itkImageSliceIteratorWithIndex.h>
-#include <itkBinaryThinningImageFilter.h>
-
-// itk ENST
-#include "RelativePositionPropImageFilter.h"
-
-//--------------------------------------------------------------------
-template <class TImageType>
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractLymphStationsFilter():
-  clitk::FilterBase(),
-  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
-  itk::ImageToImageFilter<TImageType, MaskImageType>()
-{
-  this->SetNumberOfRequiredInputs(1);
-  SetBackgroundValue(0);
-  SetForegroundValue(1);
-  SetFuzzyThreshold(0.5);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateOutputInformation() { 
-  //  Superclass::GenerateOutputInformation();
-  
-  // Get input
-  LoadAFDB();
-  m_mediastinum = GetAFDB()->template GetImage <MaskImageType>("mediastinum");  
-  m_trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");  
-  ImagePointType carina;
-  GetAFDB()->GetPoint3D("carina", carina);
-  m_CarinaZPositionInMM = carina[2];
-  DD(m_CarinaZPositionInMM);
-  ImagePointType mlb;
-  GetAFDB()->GetPoint3D("middleLobeBronchus", mlb);
-  m_MiddleLobeBronchusZPositionInMM = mlb[2];
-  DD(m_MiddleLobeBronchusZPositionInMM);
-
-  // ----------------------------------------------------------------
-  // ----------------------------------------------------------------
-  // Superior limit = carina
-  // Inferior limit = origin right middle lobe bronchus
-  StartNewStep("Inf/Sup mediastinum limits with carina/bronchus");
-  m_working_mediastinum = 
-    clitk::CropImageAlongOneAxis<MaskImageType>(m_mediastinum, 2, 
-                                                m_MiddleLobeBronchusZPositionInMM, 
-                                                m_CarinaZPositionInMM, true,
-                                                GetBackgroundValue());
-  StopCurrentStep<MaskImageType>(m_working_mediastinum);
-  m_output = m_working_mediastinum;
-
-  // ----------------------------------------------------------------
-  // ----------------------------------------------------------------
-  // Superior limit = carina
-  // Inferior limit = origin right middle lobe bronchus
-  StartNewStep("Inf/Sup trachea limits with carina/bronchus");
-  m_working_trachea = 
-    clitk::CropImageAlongOneAxis<MaskImageType>(m_trachea, 2, 
-                                                m_MiddleLobeBronchusZPositionInMM, 
-                                                m_CarinaZPositionInMM, true,
-                                                GetBackgroundValue());
-  StopCurrentStep<MaskImageType>(m_working_trachea);
-
-  // ----------------------------------------------------------------
-  // ----------------------------------------------------------------
-  // Separate trachea in two CCL
-  StartNewStep("Separate trachea under carina");
-
-  // Labelize and consider two main labels
-  m_working_trachea = Labelize<MaskImageType>(m_working_trachea, 0, true, 1);
-
-  // Carina position must at the first slice that separate the two main bronchus (not superiorly) 
-  // Check that upper slice is composed of at least two labels
-  typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
-  SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
-  iter.SetFirstDirection(0);
-  iter.SetSecondDirection(1);
-  iter.GoToReverseBegin(); // Start from the end (because image is IS not SI)
-  int maxLabel=0;
-  while (!iter.IsAtReverseEndOfSlice()) {
-    while (!iter.IsAtReverseEndOfLine()) {    
-      //  DD(iter.GetIndex());
-      if (iter.Get() > maxLabel) maxLabel = iter.Get();
-      --iter;
-    }
-    iter.PreviousLine();
-  }
-  if (maxLabel < 2) {
-    clitkExceptionMacro("First slice form Carina does not seems to seperate the two main bronchus. Abort");
-  }
-
-  // Compute centroid of both parts to identify the left from the right bronchus
-  typedef long LabelType;
-  static const unsigned int Dim = ImageType::ImageDimension;
-  typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
-  typedef itk::LabelMap< LabelObjectType > LabelMapType;
-  typedef itk::LabelImageToLabelMapFilter<MaskImageType, LabelMapType> ImageToMapFilterType;
-  typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); 
-  typedef itk::ShapeLabelMapFilter<LabelMapType, MaskImageType> ShapeFilterType; 
-  typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
-  imageToLabelFilter->SetBackgroundValue(GetBackgroundValue());
-  imageToLabelFilter->SetInput(m_working_trachea);
-  statFilter->SetInput(imageToLabelFilter->GetOutput());
-  statFilter->Update();
-  typename LabelMapType::Pointer labelMap = statFilter->GetOutput();
-
-  ImagePointType C1 = labelMap->GetLabelObject(1)->GetCentroid();
-  ImagePointType C2 = labelMap->GetLabelObject(2)->GetCentroid();
-
-  ImagePixelType leftLabel;
-  ImagePixelType rightLabel;  
-  if (C1[0] < C2[0]) { leftLabel = 1; rightLabel = 2; }
-  else { leftLabel = 2; rightLabel = 1; }
-  DD(leftLabel);
-  DD(rightLabel);
-
-  StopCurrentStep<MaskImageType>(m_working_trachea);
-
-  //-----------------------------------------------------
-  StartNewStep("Left limits with bronchus (slice by slice)");  
-  // Select LeftLabel (set one label to Backgroundvalue)
-  MaskImagePointer leftBronchus = 
-    SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, 
-                                                rightLabel, GetBackgroundValue());
-  MaskImagePointer rightBronchus  = 
-    SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, 
-                                                leftLabel, GetBackgroundValue());
-  writeImage<MaskImageType>(leftBronchus, "left.mhd");
-  writeImage<MaskImageType>(rightBronchus, "right.mhd");
-
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      leftBronchus, 2, 
-                                                       GetFuzzyThreshold(), "RightTo", 
-                                                       true, 4);
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      rightBronchus, 
-                                                      2, GetFuzzyThreshold(), "LeftTo", 
-                                                       true, 4);
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      leftBronchus, 
-                                                      2, GetFuzzyThreshold(), "AntTo", 
-                                                       true, 4, true); // NOT
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      rightBronchus, 
-                                                      2, GetFuzzyThreshold(), "AntTo", 
-                                                       true, 4, true);
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      leftBronchus, 
-                                                      2, GetFuzzyThreshold(), "PostTo", 
-                                                       true, 4, true);
-  m_working_mediastinum = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_mediastinum, 
-                                                      rightBronchus, 
-                                                      2, GetFuzzyThreshold(), "PostTo", 
-                                                       true, 4, true);
-  m_output = m_working_mediastinum;
-  StopCurrentStep<MaskImageType>(m_output);
-
-  //-----------------------------------------------------
-  //-----------------------------------------------------
-  StartNewStep("Posterior limits");  
-
-  // Left Bronchus slices
-  typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
-  typedef typename ExtractSliceFilterType::SliceType SliceType;
-  typename ExtractSliceFilterType::Pointer 
-    extractSliceFilter = ExtractSliceFilterType::New();
-  extractSliceFilter->SetInput(leftBronchus);
-  extractSliceFilter->SetDirection(2);
-  extractSliceFilter->Update();
-  std::vector<typename SliceType::Pointer> leftBronchusSlices;
-  extractSliceFilter->GetOutputSlices(leftBronchusSlices);
-  
-  // Right Bronchus slices
-  extractSliceFilter = ExtractSliceFilterType::New();
-  extractSliceFilter->SetInput(rightBronchus);
-  extractSliceFilter->SetDirection(2);
-  extractSliceFilter->Update();
-  std::vector<typename SliceType::Pointer> rightBronchusSlices ;
-  extractSliceFilter->GetOutputSlices(rightBronchusSlices);
-  
-  assert(leftBronchusSlices.size() == rightBronchusSlices.size());
-  
-  std::vector<MaskImageType::PointType> leftPoints;
-  std::vector<MaskImageType::PointType> rightPoints;
-  for(uint i=0; i<leftBronchusSlices.size(); i++) {
-    // Keep main CCL
-    leftBronchusSlices[i] = Labelize<SliceType>(leftBronchusSlices[i], 0, true, 10);
-    leftBronchusSlices[i] = KeepLabels<SliceType>(leftBronchusSlices[i], 
-                                                  GetBackgroundValue(), 
-                                                  GetForegroundValue(), 1, 1, true);
-    rightBronchusSlices[i] = Labelize<SliceType>(rightBronchusSlices[i], 0, true, 10);
-    rightBronchusSlices[i] = KeepLabels<SliceType>(rightBronchusSlices[i], 
-                                                   GetBackgroundValue(), 
-                                                   GetForegroundValue(), 1, 1, true);
-    double distance_max_from_center_point = 15;
-
-    // ------- Find point in left Bronchus ------- 
-    // find right most point in left  = rightMost
-    SliceType::PointType a;
-    SliceType::PointType rightMost = 
-      clitk::FindExtremaPointInAGivenDirection<SliceType>(leftBronchusSlices[i], 
-                                                          GetBackgroundValue(), 
-                                                          0, false, a, 0);
-    // find post most point in left, not far away from rightMost
-    SliceType::PointType p = 
-      clitk::FindExtremaPointInAGivenDirection<SliceType>(leftBronchusSlices[i], 
-                                                          GetBackgroundValue(), 
-                                                          1, false, rightMost, 
-                                                          distance_max_from_center_point);
-    MaskImageType::PointType pp;
-    pp[0] = p[0]; pp[1] = p[1];
-    pp[2] = i*leftBronchus->GetSpacing()[2] + leftBronchus->GetOrigin()[2];
-    leftPoints.push_back(pp);
-
-    // ------- Find point in right Bronchus ------- 
-    // find left most point in right  = leftMost
-    SliceType::PointType leftMost = 
-      clitk::FindExtremaPointInAGivenDirection<SliceType>(rightBronchusSlices[i], 
-                                                          GetBackgroundValue(), 
-                                                          0, true, a, 0);
-    // find post most point in left, not far away from leftMost
-    p = clitk::FindExtremaPointInAGivenDirection<SliceType>(rightBronchusSlices[i], 
-                                                            GetBackgroundValue(), 
-                                                            1, false, leftMost, 
-                                                            distance_max_from_center_point);
-    pp[0] = p[0]; pp[1] = p[1];
-    pp[2] = i*rightBronchus->GetSpacing()[2] + rightBronchus->GetOrigin()[2];
-    rightPoints.push_back(pp);
-  }
-
-  // DEBUG
-  std::ofstream osl;
-  openFileForWriting(osl, "left.txt");
-  osl << "LANDMARKS1" << std::endl;
-  std::ofstream osr;
-  openFileForWriting(osr, "right.txt");
-  osr << "LANDMARKS1" << std::endl;
-  for(uint i=0; i<leftBronchusSlices.size(); i++) {
-    osl << i << " " << leftPoints[i][0] << " " << leftPoints[i][1] 
-        << " " << leftPoints[i][2] << " 0 0 " << std::endl;
-    osr << i << " " << rightPoints[i][0] << " " << rightPoints[i][1] 
-        << " " << rightPoints[i][2] << " 0 0 " << std::endl;
-  }
-  osl.close();
-  osr.close();
-
-  // Now uses these points to limit, slice by slice 
-  // http://www.gamedev.net/community/forums/topic.asp?topic_id=542870
-  /*
-    Assuming the points are (Ax,Ay) (Bx,By) and (Cx,Cy), you need to compute:
-    (Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax)
-    This will equal zero if the point C is on the line formed by points A and B, and will have a different sign depending on the side. Which side this is depends on the orientation of your (x,y) coordinates, but you can plug test values for A,B and C into this formula to determine whether negative values are to the left or to the right.
-
-    => to accelerate, start with formula, when change sign -> stop and fill
-  */
-  //  typedef itk::ImageSliceIteratorWithIndex<MaskImageType> SliceIteratorType;
-  iter = SliceIteratorType(m_working_mediastinum, m_working_mediastinum->GetLargestPossibleRegion());
-  iter.SetFirstDirection(0);
-  iter.SetSecondDirection(1);
-  iter.GoToBegin();
-  int i=0;
-  MaskImageType::PointType A;
-  MaskImageType::PointType B;
-  MaskImageType::PointType C;
-  while (!iter.IsAtEnd()) {
-    A = leftPoints[i];
-    B = rightPoints[i];
-    C = A;
-    C[1] -= 10; // I know I must keep this point
-    double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
-    bool isPositive = s<0;
-    while (!iter.IsAtEndOfSlice()) {
-      while (!iter.IsAtEndOfLine()) {
-        // Very slow, I know ... but image should be very small
-        m_working_mediastinum->TransformIndexToPhysicalPoint(iter.GetIndex(), C);
-        double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
-        if (s == 0) iter.Set(2);
-        if (isPositive) {
-          if (s > 0) iter.Set(GetBackgroundValue());
-        }
-        else {
-          if (s < 0) iter.Set(GetBackgroundValue());
-        }
-        ++iter;
-      }
-      iter.NextLine();
-    }
-    iter.NextSlice();
-    ++i;
-  }
-
-  //-----------------------------------------------------
-  //-----------------------------------------------------
-  // StartNewStep("Anterior limits");  
-
-  // MISSING FROM NOW 
-  
-  // Station 4R, Station 4L, the right pulmonary artery, and/or the
-  // left superior pulmonary vein
-
-
-  //-----------------------------------------------------
-  //-----------------------------------------------------
-  // ALSO SUBSTRACT ARTERY/VEIN (initially in the support)
-
-  
-  // Set output image information (required)
-  MaskImagePointer outputImage = this->GetOutput(0);
-  outputImage->SetRegions(m_working_mediastinum->GetLargestPossibleRegion());
-  outputImage->SetOrigin(m_working_mediastinum->GetOrigin());
-  outputImage->SetRequestedRegion(m_working_mediastinum->GetLargestPossibleRegion());
-
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateInputRequestedRegion() {
-  DD("GenerateInputRequestedRegion");
-  // Call default
-  //  Superclass::GenerateInputRequestedRegion();
-  // Following needed because output region can be greater than input (trachea)
-  //ImagePointer mediastinum = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
-  //ImagePointer trachea = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
-  DD("set reg");
-  m_mediastinum->SetRequestedRegion(m_mediastinum->GetLargestPossibleRegion());
-  m_trachea->SetRequestedRegion(m_trachea->GetLargestPossibleRegion());
-  DD("end");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateData() {
-  DD("GenerateData");
-  // Final Step -> graft output (if SetNthOutput => redo)
-  this->GraftOutput(m_output);
-}
-//--------------------------------------------------------------------
-  
-
-#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
index ec93c098b3421ea3d8a9105f5677c1212771ed45..68b81eebe3cb220f36e2cc15039621dceda0f05a 100644 (file)
@@ -55,7 +55,9 @@ ExtractLymphStationsFilter():
   this->SetNumberOfRequiredInputs(1);
   SetBackgroundValue(0);
   SetForegroundValue(1);
-  ComputeStationsSupportsFlagOn();
+  ForceSupportsFlagOn();
+  SetSupportLimitsFilename("none");
+  CheckSupportFlagOff();
 
   // Default values
   ExtractStation_3P_SetDefaultValues();
@@ -84,34 +86,39 @@ GenerateOutputInformation() {
   m_Mediastinum = this->GetAFDB()->template GetImage <MaskImageType>("Mediastinum");
 
   // Clean some computer landmarks to force the recomputation
+  // FIXME -> to put elsewhere ?
   this->GetAFDB()->RemoveTag("AntPostVesselsSeparation");
 
-  // Global supports for stations
+  // Must I compute the supports ?
   bool supportsExist = true;
-  try {
-    m_ListOfSupports["S1R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S1R");
-    m_ListOfSupports["S1L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S1L");
-    m_ListOfSupports["S2R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2R");
-    m_ListOfSupports["S2L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2L");
-    m_ListOfSupports["S4R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4R");
-    m_ListOfSupports["S4L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4L");
-    
-    m_ListOfSupports["S3A"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3A");
-    m_ListOfSupports["S3P"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3P");
-    m_ListOfSupports["S5"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S5");
-    m_ListOfSupports["S6"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S6");
-    m_ListOfSupports["S7"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S7");
-    m_ListOfSupports["S8"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S8");
-    m_ListOfSupports["S9"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S9");
-    m_ListOfSupports["S10"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S10");
-    m_ListOfSupports["S11"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S11");
-  } catch(clitk::ExceptionObject o) {
-    supportsExist = false;
+  if (!GetForceSupportsFlag()) {
+    try {
+      m_ListOfSupports["S1R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S1R");
+      m_ListOfSupports["S1L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S1L");
+      m_ListOfSupports["S2R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2R");
+      m_ListOfSupports["S2L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S2L");
+      m_ListOfSupports["S4R"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4R");
+      m_ListOfSupports["S4L"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S4L");
+      
+      m_ListOfSupports["S3A"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3A");
+      m_ListOfSupports["S3P"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S3P");
+      m_ListOfSupports["S5"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S5");
+      m_ListOfSupports["S6"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S6");
+      m_ListOfSupports["S7"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S7");
+      m_ListOfSupports["S8"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S8");
+      m_ListOfSupports["S9"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S9");
+      m_ListOfSupports["S10"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S10");
+      m_ListOfSupports["S11"] = this->GetAFDB()->template GetImage<MaskImageType>("Support_S11");
+    } catch(clitk::ExceptionObject o) {
+      supportsExist = false;
+    }
   }
 
-  if (!supportsExist || GetComputeStationsSupportsFlag()) {
+  if (!supportsExist || GetForceSupportsFlag()) {
     this->StartNewStep("Supports for stations");
     this->StartSubStep(); 
+    
+    // FIXME : why should I remove theses tags ???
     this->GetAFDB()->RemoveTag("CarinaZ");
     this->GetAFDB()->RemoveTag("ApexOfTheChestZ");
     this->GetAFDB()->RemoveTag("ApexOfTheChest");
@@ -130,11 +137,12 @@ GenerateOutputInformation() {
   ExtractStation_2RL();
   ExtractStation_3P();
   ExtractStation_3A();
-  ExtractStation_4RL();
+  ExtractStation_4R();
+  ExtractStation_4L();
   ExtractStation_5();
   ExtractStation_6();
 
-  // ---------- TODO -----------------------
+  // ---------- todo -----------------------
 
   // Extract Station8
   //  ExtractStation_8();
@@ -165,7 +173,7 @@ void
 clitk::ExtractLymphStationsFilter<TImageType>::
 GenerateData() {
   // Final Step -> graft output (if SetNthOutput => redo)
-  this->GraftOutput(m_ListOfStations["8"]);
+  // this->GraftOutput(m_ListOfStations["8"]);
 }
 //--------------------------------------------------------------------
   
@@ -180,25 +188,29 @@ CheckForStation(std::string station)
   std::string s = "Station"+station;
   
 
+  // Define the starting support 
+  // if (GetComputeStation(station)) {
+  //   std::cout << "Station " << station << " already exists, but re-computation forced." << std::endl;
+  // }
+  if (GetComputeStation(station)) {
+    m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
+    return true;
+  }
+  else return false;
+  // else {
+  //   std::cout << "Station " << station << " found. I used it" << std::endl;
+  //   return false;
+  // }
+
   // Check if station already exist in DB
+  
+  // FIXME -> do nothing if not on the command line. Is it what I want ?
   bool found = false;
   if (this->GetAFDB()->TagExist(s)) {
     m_ListOfStations[station] = this->GetAFDB()->template GetImage<MaskImageType>(s);
     found = true;
   }
 
-  // Define the starting support 
-  if (found && GetComputeStation(station)) {
-    std::cout << "Station " << station << " already exists, but re-computation forced." << std::endl;
-  }
-  if (!found || GetComputeStation(station)) {
-    m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
-    return true;
-  }
-  else {
-    std::cout << "Station " << station << " found. I used it" << std::endl;
-    return false;
-  }
 }
 //--------------------------------------------------------------------
 
@@ -438,7 +450,7 @@ FindCarina()
     z = this->GetAFDB()->GetDouble("CarinaZ");
   }
   catch(clitk::ExceptionObject e) {
-    DD("FindCarinaSlicePosition");
+    //DD("FindCarinaSlicePosition");
     // Get Carina
     MaskImagePointer Carina = this->GetAFDB()->template GetImage<MaskImageType>("Carina");
     
@@ -471,7 +483,9 @@ FindApexOfTheChest()
     z = this->GetAFDB()->GetDouble("ApexOfTheChestZ");
   }
   catch(clitk::ExceptionObject e) {
-    DD("FindApexOfTheChestPosition");
+
+    /*
+    //DD("FindApexOfTheChestPosition");
     MaskImagePointer Lungs = this->GetAFDB()->template GetImage<MaskImageType>("Lungs");
     MaskImagePointType p;
     p[0] = p[1] = p[2] =  0.0; // to avoid warning
@@ -486,6 +500,23 @@ FindApexOfTheChest()
     this->GetAFDB()->SetDouble("ApexOfTheChestZ", p[2]);
     this->WriteAFDB();
     z = p[2];
+    */
+    
+    // the superior border becomes the more inferior of the two apices
+    MaskImagePointer RightLung = this->GetAFDB()->template GetImage<MaskImageType>("RightLung");
+    MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
+    MaskImagePointType pr;
+    MaskImagePointType pl;
+    clitk::FindExtremaPointInAGivenDirection<MaskImageType>(RightLung, GetBackgroundValue(), 2, false, pr);
+    clitk::FindExtremaPointInAGivenDirection<MaskImageType>(LeftLung, GetBackgroundValue(), 2, false, pl);
+    // We dont need Lungs structure from now
+    this->GetAFDB()->template ReleaseImage<MaskImageType>("RightLung");
+    this->GetAFDB()->template ReleaseImage<MaskImageType>("LeftLung");
+    // Put inside the AFDB
+    if (pr[2] < pl[2]) z = pr[2];
+    else z = pl[2];
+    this->GetAFDB()->SetDouble("ApexOfTheChestZ", z);
+    this->WriteAFDB();
   }
   return z;
 }
@@ -596,7 +627,7 @@ FindSuperiorBorderOfAorticArch()
     z = this->GetAFDB()->GetDouble("SuperiorBorderOfAorticArchZ");
   }
   catch(clitk::ExceptionObject e) {
-    DD("FindSuperiorBorderOfAorticArch");
+    //    DD("FindSuperiorBorderOfAorticArch");
     MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
     MaskImagePointType p;
     p[0] = p[1] = p[2] =  0.0; // to avoid warning
@@ -628,7 +659,7 @@ FindInferiorBorderOfAorticArch()
     z = this->GetAFDB()->GetDouble("InferiorBorderOfAorticArchZ");
   }
   catch(clitk::ExceptionObject e) {
-    DD("FindInferiorBorderOfAorticArch");
+    //DD("FindInferiorBorderOfAorticArch");
     MaskImagePointer Aorta = this->GetAFDB()->template GetImage<MaskImageType>("Aorta");
     std::vector<MaskSlicePointer> slices;
     clitk::ExtractSlices<MaskImageType>(Aorta, 2, slices);
@@ -1383,6 +1414,65 @@ FindAntPostVessels2()
 }
 //--------------------------------------------------------------------
 
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+WriteImageSupport(std::string support)
+{
+  writeImage<MaskImageType>(m_ListOfSupports[support], this->GetAFDBPath()+"/"+"seg/Support_"+support+".mha");
+  this->GetAFDB()->SetImageFilename("Support_"+support, "seg/Support_"+support+".mha");
+}
+//--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+WriteImageStation(std::string station)
+{
+  writeImage<MaskImageType>(m_ListOfStations[station], GetAFDB()->GetPath()+"/seg/Station"+station+".mha");
+  GetAFDB()->SetImageFilename("Station"+station, "seg/Station"+station+".mha"); 
+  WriteAFDB();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ComputeOverlapWithRef(std::string station)
+{
+  if (GetComputeStation(station)) {
+    MaskImagePointer ref = this->GetAFDB()->template GetImage <MaskImageType>("Station"+station+"_Ref");
+    typedef clitk::LabelImageOverlapMeasureFilter<MaskImageType> FilterType;
+    typename FilterType::Pointer filter = FilterType::New();
+    filter->SetInput(0, m_ListOfStations[station]);
+    filter->SetInput(1, ref);
+    filter->Update();
+  }
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ReadSupportLimits(std::string filename)
+{
+  m_ListOfSupportLimits.clear();
+  ifstream is;
+  openFileForReading(is, filename);
+  while (is) {
+    skipComment(is);
+    SupportLimitsType s;
+    s.Read(is);
+    if (is) m_ListOfSupportLimits.push_back(s);
+  }
+}
+//--------------------------------------------------------------------
+
 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
+
diff --git a/segmentation/clitkExtractLymphStationsFilter.txx.save b/segmentation/clitkExtractLymphStationsFilter.txx.save
deleted file mode 100644 (file)
index a7b3244..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*=========================================================================
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
-
-  Authors belong to: 
-  - University of LYON              http://www.universite-lyon.fr/
-  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
-
-  This software is distributed WITHOUT ANY WARRANTY; without even
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-  PURPOSE.  See the copyright notices for more information.
-
-  It is distributed under dual licence
-
-  - BSD        See included LICENSE.txt file
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-  ======================================================================-====*/
-
-#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
-#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
-
-// clitk
-#include "clitkCommon.h"
-#include "clitkExtractLymphStationsFilter.h"
-#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
-#include "clitkSegmentationUtils.h"
-#include "clitkAutoCropFilter.h"
-#include "clitkSegmentationUtils.h"
-#include "clitkSliceBySliceRelativePositionFilter.h"
-
-// itk
-#include <itkStatisticsLabelMapFilter.h>
-#include <itkLabelImageToStatisticsLabelMapFilter.h>
-#include <itkRegionOfInterestImageFilter.h>
-#include <itkBinaryThresholdImageFilter.h>
-#include <itkImageSliceConstIteratorWithIndex.h>
-#include <itkBinaryThinningImageFilter.h>
-
-// itk ENST
-#include "RelativePositionPropImageFilter.h"
-
-//--------------------------------------------------------------------
-template <class TImageType>
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractLymphStationsFilter():
-  clitk::FilterBase(),
-  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
-  itk::ImageToImageFilter<TImageType, MaskImageType>()
-{
-  this->SetNumberOfRequiredInputs(1);
-  SetBackgroundValue(0);
-  SetForegroundValue(1);
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateOutputInformation() { 
-  //  Superclass::GenerateOutputInformation();
-  
-  // Get input
-  LoadAFDB();
-  m_mediastinum = GetAFDB()->template GetImage <MaskImageType>("mediastinum");  
-  m_trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");  
-  ImagePointType carina;
-  GetAFDB()->GetPoint3D("carina", carina);
-  DD(carina);
-  m_CarinaZPositionInMM = carina[2];
-  DD(m_CarinaZPositionInMM);
-  ImagePointType mlb;
-  GetAFDB()->GetPoint3D("middleLobeBronchus", mlb);
-  m_MiddleLobeBronchusZPositionInMM = mlb[2];
-  DD(m_MiddleLobeBronchusZPositionInMM);
-
-  // ----------------------------------------------------------------
-  // ----------------------------------------------------------------
-  // Superior limit = carina
-  // Inferior limit = origin right middle lobe bronchus
-  StartNewStep("Inf/Sup mediastinum limits with carina/bronchus");
-  ImageRegionType region = m_mediastinum->GetLargestPossibleRegion(); DD(region);
-  ImageSizeType size = region.GetSize();
-  ImageIndexType index = region.GetIndex();
-  DD(m_CarinaZPositionInMM);
-  DD(m_MiddleLobeBronchusZPositionInMM);
-  index[2] = floor((m_MiddleLobeBronchusZPositionInMM - m_mediastinum->GetOrigin()[2]) / m_mediastinum->GetSpacing()[2]);
-  size[2] = 1+ceil((m_CarinaZPositionInMM-m_MiddleLobeBronchusZPositionInMM) / m_mediastinum->GetSpacing()[2]); // +1 to 
-  region.SetSize(size);
-  region.SetIndex(index);
-  DD(region);
-  typedef itk::RegionOfInterestImageFilter<MaskImageType, MaskImageType> CropFilterType;
-  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
-  cropFilter->SetInput(m_mediastinum);
-  cropFilter->SetRegionOfInterest(region);
-  cropFilter->Update();
-  m_working_image = cropFilter->GetOutput();
-  // Auto Crop (because following rel pos is faster)
-  m_working_image = clitk::AutoCrop<MaskImageType>(m_working_image, 0); 
-  StopCurrentStep<MaskImageType>(m_working_image);
-  m_output = m_working_image;
-
-  // ----------------------------------------------------------------
-  // ----------------------------------------------------------------
-  // Separate trachea in two CCL
-  StartNewStep("Separate trachea under carina");
-  // DD(region);
-  ImageRegionType trachea_region = m_trachea->GetLargestPossibleRegion();
-  for(int i=0; i<3; i++) {
-    index[i] = floor(((index[i]*m_mediastinum->GetSpacing()[i])+m_mediastinum->GetOrigin()[i]
-                      -m_trachea->GetOrigin()[i])/m_trachea->GetSpacing()[i]);
-    // DD(index[i]);
-    size[i] = ceil((size[i]*m_mediastinum->GetSpacing()[i])/m_trachea->GetSpacing()[i]);
-    //  DD(size[i]);
-    if (index[i] < 0) { 
-      size[i] += index[i];
-      index[i] = 0;       
-    }
-    if (size[i]+index[i] > (trachea_region.GetSize()[i] + trachea_region.GetIndex()[i])) {
-      size[i] = trachea_region.GetSize()[i] + trachea_region.GetIndex()[i] - index[i];
-    }
-  }
-  // DD(index);
-  //   DD(size);
-  region.SetIndex(index);
-  region.SetSize(size);  
-  //  typedef itk::RegionOfInterestImageFilter<MaskImageType, MaskImageType> CropFilterType;
-  //  typename CropFilterType::Pointer 
-  cropFilter = CropFilterType::New();
- //  m_trachea.Print(std::cout);
-  cropFilter->SetInput(m_trachea);
-  cropFilter->SetRegionOfInterest(region);
-  cropFilter->Update();
-  m_working_trachea = cropFilter->GetOutput();
-
-  // Labelize and consider two main labels
-  m_working_trachea = Labelize<MaskImageType>(m_working_trachea, 0, true, 1);
-
-  // Detect wich label is at Left
-  typedef itk::ImageSliceConstIteratorWithIndex<MaskImageType> SliceIteratorType;
-  SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
-  iter.SetFirstDirection(0);
-  iter.SetSecondDirection(1);
-  iter.GoToBegin();
-  bool stop = false;
-  ImagePixelType leftLabel;
-  ImagePixelType rightLabel;
-  while (!stop) {
-    if (iter.Get() != GetBackgroundValue()) {
-      //     DD(iter.GetIndex());
-      //       DD((int)iter.Get());
-      leftLabel = iter.Get();
-      stop = true;
-    }
-    ++iter;
-  }
-  if (leftLabel == 1) rightLabel = 2;
-  else rightLabel = 1;
-  DD((int)leftLabel);
-  DD((int)rightLabel);  
-
-  // End step
-  StopCurrentStep<MaskImageType>(m_working_trachea);
-  
-  //-----------------------------------------------------
-  /*  DD("TEST Skeleton");
-  typedef itk::BinaryThinningImageFilter<MaskImageType, MaskImageType> SkeletonFilterType;
-  typename SkeletonFilterType::Pointer skeletonFilter = SkeletonFilterType::New();
-  skeletonFilter->SetInput(m_working_trachea);
-  skeletonFilter->Update();
-  writeImage<MaskImageType>(skeletonFilter->GetOutput(), "skel.mhd");
-  writeImage<MaskImageType>(skeletonFilter->GetThinning(), "skel2.mhd");  
-  */
-
-  //-----------------------------------------------------
-  StartNewStep("Left limits with bronchus (slice by slice)");  
-  // Select LeftLabel (set right label to 0)
-  MaskImagePointer temp = SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, rightLabel, 0);
-  writeImage<MaskImageType>(temp, "temp1.mhd");
-
-  m_working_image = 
-    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_image, 
-                                                      temp, 
-                                                      2, GetFuzzyThreshold(), "RightTo");
-  /*
-  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
-  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
-  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
-  sliceRelPosFilter->VerboseStepOn();
-  sliceRelPosFilter->WriteStepOn();
-  sliceRelPosFilter->SetInput(m_working_image);
-  sliceRelPosFilter->SetInputObject(temp);
-  sliceRelPosFilter->SetDirection(2);
-  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
-  sliceRelPosFilter->SetOrientationTypeString("RightTo");
-  sliceRelPosFilter->Update();
-  m_working_image = sliceRelPosFilter->GetOutput();*/
-  writeImage<MaskImageType>(m_working_image, "afterslicebyslice.mhd");
-
-
-  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
-  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
-
-
-  //-----------------------------------------------------
-  StartNewStep("Right limits with bronchus (slice by slice)");
-  // Select LeftLabel (set right label to 0)
-  temp = SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, leftLabel, 0);
-  writeImage<MaskImageType>(temp, "temp2.mhd");
-
-  sliceRelPosFilter = SliceRelPosFilterType::New();
-  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
-  sliceRelPosFilter->VerboseStepOff();
-  sliceRelPosFilter->WriteStepOff();
-  sliceRelPosFilter->SetInput(m_working_image);
-  sliceRelPosFilter->SetInputObject(temp);
-  sliceRelPosFilter->SetDirection(2);
-  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
-  sliceRelPosFilter->SetOrientationTypeString("LeftTo");
-  sliceRelPosFilter->Update();
-  m_working_image = sliceRelPosFilter->GetOutput();
-  writeImage<MaskImageType>(m_working_image, "afterslicebyslice.mhd");
-  DD("end");
-  m_output = m_working_image;
-  StopCurrentStep<MaskImageType>(m_output);
-
-  //-----------------------------------------------------
-  StartNewStep("Trial Post position according to trachea");
-  // Post: do not extend past the post wall of the 2 main bronchi
-  sliceRelPosFilter = SliceRelPosFilterType::New();
-  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
-  sliceRelPosFilter->VerboseStepOn();
-  sliceRelPosFilter->WriteStepOn();
-  sliceRelPosFilter->SetInput(m_output);
-  sliceRelPosFilter->SetInputObject(m_trachea);
-  sliceRelPosFilter->SetDirection(2);
-  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
-  // It means "not PostTo" (different from AntTo)
-  sliceRelPosFilter->NotFlagOn();
-  //sliceRelPosFilter->SetOrientationType(SliceRelPosFilterType::RelPosFilterType::PostTo);
-  sliceRelPosFilter->SetOrientationTypeString("PostTo");
-  sliceRelPosFilter->Update();
-  m_output = sliceRelPosFilter->GetOutput();
-  writeImage<MaskImageType>(m_output, "postrelpos.mhd");
-
-
-  // Set output image information (required)
-  MaskImagePointer outputImage = this->GetOutput(0);
-  outputImage->SetRegions(m_working_image->GetLargestPossibleRegion());
-  outputImage->SetOrigin(m_working_image->GetOrigin());
-  outputImage->SetRequestedRegion(m_working_image->GetLargestPossibleRegion());
-  DD("end2");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateInputRequestedRegion() {
-  DD("GenerateInputRequestedRegion");
-  // Call default
-  //  Superclass::GenerateInputRequestedRegion();
-  // Following needed because output region can be greater than input (trachea)
-  //ImagePointer mediastinum = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
-  //ImagePointer trachea = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
-  DD("set reg");
-  m_mediastinum->SetRequestedRegion(m_mediastinum->GetLargestPossibleRegion());
-  m_trachea->SetRequestedRegion(m_trachea->GetLargestPossibleRegion());
-  DD("end");
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-GenerateData() {
-  DD("GenerateData");
-  // Final Step -> graft output (if SetNthOutput => redo)
-  this->GraftOutput(m_output);
-}
-//--------------------------------------------------------------------
-  
-
-#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
index 317c78ab588b1e0d36f53fe0c4d76241de15c1b7..a27b4a629e41e2893b95513646ef599f5a790485 100644 (file)
@@ -68,8 +68,10 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
   f->SetWriteStepFlag(mArgsInfo.writeStep_flag);
   f->SetVerboseMemoryFlag(mArgsInfo.verboseMemory_flag);
   f->SetAFDBFilename(mArgsInfo.afdb_arg);  
-
-  f->SetComputeStationsSupportsFlag(!mArgsInfo.nosupport_flag);
+  if (mArgsInfo.afdb_path_given) f->SetAFDBPath(mArgsInfo.afdb_path_arg);  
+  f->SetForceSupportsFlag(mArgsInfo.force_support_flag);
+  f->SetSupportLimitsFilename(mArgsInfo.support_limits_arg);
+  f->SetCheckSupportFlag(mArgsInfo.check_support_limits_flag);
 
   // Station 8
   //f->SetDistanceMaxToAnteriorPartOfTheSpine(mArgsInfo.S8_maxAntSpine_arg);
index 39e5542b5df9fdaf670c5e66bc354f103532ab0f..27cb661b0616ebf86fee19f7bfa8d0192d04351a 100644 (file)
@@ -340,7 +340,10 @@ GenerateOutputInformation() {
   // Generic RelativePosition processes
   output = this->ApplyRelativePositionList("Mediastinum", output);
 
+
   //--------------------------------------------------------------------
+  // FIXME --> do not put this limits here !
+  /*
   // Step : SI limits It is better to do this limit *AFTER* the
   // RelativePosition to avoid some issue due to superior boundaries.
   this->StartNewStep("[Mediastinum] Keep inferior to CricoidCartilag");
@@ -357,6 +360,7 @@ GenerateOutputInformation() {
   }
   output = clitk::CropImageRemoveGreaterThan<MaskImageType>(output, 2, p[2], true, this->GetBackgroundValue());
   this->template StopCurrentStep<MaskImageType>(output);
+  */
 
   //--------------------------------------------------------------------
   // Step: Get CCL
index 43a086388a9b138e1e75d3d57c31b74a7c1227d5..ebbd3ade15618efb6dfaad1a3834a9100edfb046 100644 (file)
@@ -33,11 +33,7 @@ int main(int argc, char * argv[]) {
   
   filter->SetArgsInfo(args_info);
   
-  try {
-    filter->Update();
-  } catch(std::runtime_error e) {
-    std::cout << e.what() << std::endl;
-  }
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   return EXIT_SUCCESS;
 } // This is the end, my friend
index 3dfde0d0d46c180c2c9603c8920602fbd894303a..88c9cb8ea99e7bb4eb3906a501f2ba72ac3be6e7 100644 (file)
@@ -37,7 +37,7 @@ namespace clitk
   //-----------------------------------------------------------
   // Constructor
   //-----------------------------------------------------------
-  ExtractPatientGenericFilter::ExtractPatientGenericFilter()
+  ExtractPatientGenericFilter:::ExtractPatientGenericFilter()
   {
     m_Verbose=false;
     m_InputFileName="";
index bec6b9e59a8a24d380b2b4f45c086e2765ae64b5..6db7c4b934dee61ba449fc65164c4838159a09c8 100644 (file)
@@ -25,6 +25,7 @@ FilterWithAnatomicalFeatureDatabaseManagement()
 {
   m_AFDB = NULL; 
   SetAFDBFilename("default.afdb");
+  SetAFDBPath("./");
 }
 //--------------------------------------------------------------------
 
@@ -42,6 +43,7 @@ void clitk::FilterWithAnatomicalFeatureDatabaseManagement::WriteAFDB()
 void clitk::FilterWithAnatomicalFeatureDatabaseManagement::LoadAFDB() 
 {
   GetAFDB()->SetFilename(GetAFDBFilename());
+  GetAFDB()->SetPath(GetAFDBPath());
   try {
     GetAFDB()->Load();
   } catch (clitk::ExceptionObject e) {
@@ -53,10 +55,10 @@ void clitk::FilterWithAnatomicalFeatureDatabaseManagement::LoadAFDB()
 
 
 //--------------------------------------------------------------------
-clitk::AnatomicalFeatureDatabase * clitk::FilterWithAnatomicalFeatureDatabaseManagement::GetAFDB() 
+clitk::AnatomicalFeatureDatabase::Pointer clitk::FilterWithAnatomicalFeatureDatabaseManagement::GetAFDB() 
 {
-  if (m_AFDB == NULL) {
-    m_AFDB = new clitk::AnatomicalFeatureDatabase;
+  if (!m_AFDB) {
+    m_AFDB = clitk::AnatomicalFeatureDatabase::New();
   }
   return m_AFDB;
 }
index ca8fd9800c3895fa8de0253cbeaed551fc36d011..a1f9f29f54d35e023c3c5d988e0193d6524894a4 100644 (file)
@@ -42,19 +42,28 @@ namespace clitk {
     itkTypeMacro(FilterWithAnatomicalFeatureDatabaseManagement, Object);
 
     // Set/Get filename 
-    itkBooleanMacro(AFDBFilenameGivenFlag);
-    itkSetMacro(AFDBFilenameGivenFlag, bool);
-    itkGetConstMacro(AFDBFilenameGivenFlag, bool);
-    GGO_DefineOption_Flag(afdb, SetAFDBFilenameGivenFlag);
+    // itkBooleanMacro(AFDBFilenameGivenFlag);
+    // itkSetMacro(AFDBFilenameGivenFlag, bool);
+    // itkGetConstMacro(AFDBFilenameGivenFlag, bool);
+    // GGO_DefineOption_Flag(afdb, SetAFDBFilenameGivenFlag);
+
+    // itkBooleanMacro(AFDBPathGivenFlag);
+    // itkSetMacro(AFDBPathGivenFlag, bool);
+    // itkGetConstMacro(AFDBPathGivenFlag, bool);
+    // GGO_DefineOption_Flag(afdb_path, SetAFDBPathGivenFlag);
 
     itkSetMacro(AFDBFilename, std::string);
     itkGetConstMacro(AFDBFilename, std::string);
-    GGO_DefineOption_WithTest(afdb, SetAFDBFilename, std::string, AFDBFilenameGivenFlag);
+    // GGO_DefineOption_WithTest(afdb, SetAFDBFilename, std::string, AFDBFilenameGivenFlag);
+
+    itkSetMacro(AFDBPath, std::string);
+    itkGetConstMacro(AFDBPath, std::string);
+    // GGO_DefineOption_WithTest(afdb_path, SetAFDBPath, std::string, AFDBPathGivenFlag);
 
     void WriteAFDB();
     void LoadAFDB();
 
-    AnatomicalFeatureDatabase * GetAFDB();
+    AnatomicalFeatureDatabase::Pointer GetAFDB();
     void SetAFDB(AnatomicalFeatureDatabase * a) { m_AFDB = a; }
 
   protected:
@@ -62,8 +71,10 @@ namespace clitk {
     virtual ~FilterWithAnatomicalFeatureDatabaseManagement() {}    
     
     std::string m_AFDBFilename;
-    bool m_AFDBFilenameGivenFlag;
-    clitk::AnatomicalFeatureDatabase * m_AFDB;
+    // bool m_AFDBFilenameGivenFlag;
+    std::string m_AFDBPath;
+    // bool m_AFDBPathGivenFlag;
+    clitk::AnatomicalFeatureDatabase::Pointer m_AFDB;
 
   private:
     FilterWithAnatomicalFeatureDatabaseManagement(const Self&); //purposely not implemented
index 46e348971e8242433f42f7d6b755ec12c247278e..25c40df134f496ec960fab8db3032ae2dead8430 100644 (file)
@@ -36,11 +36,7 @@ int main(int argc, char * argv[]) {
   // Passing the arguments to the generic filter
   filter->SetArgsInfo(args_info);
  
-  try {
-    filter->Update();
-  } catch(std::runtime_error e) {
-    std::cout << e.what() << std::endl;
-  }
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   return EXIT_SUCCESS;
 } // This is the end, my friend
index fdc31c7024976b10a93f730918978d5e75fc86b4..fd65c6457b173ca4a02ec71e2edef7b9336a96b7 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char * argv[]) {
   clitk::MotionMaskGenericFilter::Pointer genericFilter=clitk::MotionMaskGenericFilter::New();
   
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index ec49a548fdad4859038c70df544481ab3605e9c0..7a53a99dc1eb3248c230b6690ef346b0906003be 100644 (file)
@@ -146,10 +146,12 @@ GenerateOutputInformation() {
   // Loop on RelativePositionList of operations
   std::string s = GetInputName();
   for(uint i=0; i<mArgsInfoList.size(); i++) {
-    std::string text = "["+s+"] limits "+
-      mArgsInfoList[i].orientation_arg[0]+" "+
-      mArgsInfoList[i].object_arg+" "+
-      toString(mArgsInfoList[i].threshold_arg);
+    std::string text = "["+s+"] limits ";
+    if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
+    else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
+           toString(mArgsInfoList[i].angle2_arg)+" "+
+           (mArgsInfoList[i].inverse_flag==true?"true":"false")+") ";
+    text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
     if (mArgsInfoList[i].sliceBySlice_flag) {
       text += " slice by slice";
     }
@@ -211,9 +213,10 @@ void
 clitk::RelativePositionList<TImageType>::
 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
 
-  if (options.orientation_given != 1) {
-    DD("ERRROR DEBUG TODO no more than 1 orientation yet");
-    exit(0);
+  if (options.orientation_given > 1) {
+    clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
+                        << " Current options are for obj = '" << options.object_arg
+                        << "', threshold = " << options.threshold_arg << std::endl);
   }
 
   ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
@@ -222,8 +225,21 @@ SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & optio
   filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
   filter->SetFuzzyThreshold(options.threshold_arg);
   filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
-  for(uint i=0; i<options.orientation_given; i++) 
-    filter->AddOrientationTypeString(options.orientation_arg[i]);
+
+  if (options.orientation_given == 1)  {
+    for(uint i=0; i<options.orientation_given; i++) 
+      filter->AddOrientationTypeString(options.orientation_arg[i]);
+  }
+  else {
+    if (options.angle1_given && options.angle2_given) {
+      filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
+    }
+    else {
+      clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
+                          << " Current options are for obj = '" << options.object_arg
+                          << "', threshold = " << options.threshold_arg << std::endl);
+    }
+  }
   filter->SetIntermediateSpacing(options.spacing_arg);
   if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
   else filter->IntermediateSpacingFlagOn();
index eb04d25a276cc3222deaa14c213ba7133f0e900e..bd565421b4a05493b26ef8bcf3df9b1466c75b4b 100644 (file)
@@ -315,6 +315,26 @@ IF (CLITK_BUILD_TOOLS)
   TARGET_LINK_LIBRARIES(clitkRelativePosition clitkCommon ${ITK_LIBRARIES})
   SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkRelativePosition)
 
+  WRAP_GGO(clitkLabelImageOverlapMeasure_GGO_C clitkLabelImageOverlapMeasure.ggo)
+  ADD_EXECUTABLE(clitkLabelImageOverlapMeasure clitkLabelImageOverlapMeasure.cxx ${clitkLabelImageOverlapMeasure_GGO_C})
+  TARGET_LINK_LIBRARIES(clitkLabelImageOverlapMeasure clitkSegmentationGgoLib clitkCommon ${ITK_LIBRARIES} )
+  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkLabelImageOverlapMeasure)
+
+  WRAP_GGO(clitkRelativePositionAnalyzer_GGO_C clitkRelativePositionAnalyzer.ggo)
+  ADD_EXECUTABLE(clitkRelativePositionAnalyzer clitkRelativePositionAnalyzer.cxx ${clitkRelativePositionAnalyzer_GGO_C})
+  TARGET_LINK_LIBRARIES(clitkRelativePositionAnalyzer clitkSegmentationGgoLib clitkCommon ${ITK_LIBRARIES})
+  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkRelativePositionAnalyzer)
+
+  WRAP_GGO(clitkRelativePositionDataBaseAnalyzer_GGO_C clitkRelativePositionDataBaseAnalyzer.ggo)
+  ADD_EXECUTABLE(clitkRelativePositionDataBaseAnalyzer ../itk/clitkRelativePositionDataBase.cxx clitkRelativePositionDataBaseAnalyzer.cxx ${clitkRelativePositionDataBaseAnalyzer_GGO_C})
+  TARGET_LINK_LIBRARIES(clitkRelativePositionDataBaseAnalyzer clitkSegmentationGgoLib clitkCommon ${ITK_LIBRARIES})
+  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkRelativePositionDataBaseAnalyzer)
+
+  WRAP_GGO(clitkRelativePositionDataBaseBuilder_GGO_C clitkRelativePositionDataBaseBuilder.ggo)
+  ADD_EXECUTABLE(clitkRelativePositionDataBaseBuilder clitkRelativePositionDataBaseBuilder.cxx ${clitkRelativePositionDataBaseBuilder_GGO_C})
+  TARGET_LINK_LIBRARIES(clitkRelativePositionDataBaseBuilder clitkSegmentationGgoLib clitkCommon ${ITK_LIBRARIES})
+  SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkRelativePositionDataBaseBuilder)
+
   WRAP_GGO(clitkTransformLandmarks_GGO_C clitkTransformLandmarks.ggo)
   ADD_EXECUTABLE(clitkTransformLandmarks clitkTransformLandmarks.cxx ${clitkTransformLandmarks_GGO_C})
   TARGET_LINK_LIBRARIES(clitkTransformLandmarks clitkCommon ${ITK_LIBRARIES})
index d6434547711f2da9763a7ea9833836efa6f021c9..6304aed44d0fdd0e578c9c1cc1f29af8dd4224e2 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char * argv[])
   FilterType::Pointer genericFilter = FilterType::New();
 
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index 1bfc8386b96eb0f78bb4762bccfb227bb25e3e1a..70d99926cab3c705e05204ea34709f7805998890 100644 (file)
@@ -34,11 +34,7 @@ int main(int argc, char * argv[])
 
   filter->SetArgsInfo(args_info);
 
-  try {
-    filter->Update();
-  } catch(std::runtime_error e) {
-    std::cout << e.what() << std::endl;
-  }
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   return EXIT_SUCCESS;
 } // This is the end, my friend
index a78b131a7b3962f45ac7db46edb8813fa5419728..ee8de0ded1c3cf502a8050bf3ac345be504bd4bb 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char * argv[]) {
   clitk::CombineImageGenericFilter::Pointer genericFilter=clitk::CombineImageGenericFilter::New();
   
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index 08cff6585d0e52022ad4ac23e83be208b36b7c4d..72b95cf3f0fce8d02792232b05e89a0c915b2d38 100644 (file)
@@ -39,7 +39,7 @@ int main( int argc, char *argv[] )
   //JV how to pass for different dims?
   //ComposeVFGenericFilter->SetEdgePaddingValue(args_info.pad_arg);
   ComposeVFGenericFilter->SetVerbose(args_info.verbose_flag);
-  ComposeVFGenericFilter->Update();  
+  CLITK_TRY_CATCH_EXIT(ComposeVFGenericFilter->Update());  
 
   return EXIT_SUCCESS;
 }
index 73b1b7a1af1ff46e45a9128a4f8aaa28c787a1c8..57c607a909b415e8d1bf2d2101581330cd38e146 100644 (file)
 
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
-===========================================================================**/
+  ===========================================================================**/
 #ifndef clitkGetSpacingGenericFilter_cxx
 #define clitkGetSpacingGenericFilter_cxx
 
-/* =================================================
- * @file   clitkGetSpacingGenericFilter.cxx
- * @author 
- * @date   
- * 
- * @brief 
- * 
- ===================================================*/
-
 #include "clitkGetSpacingGenericFilter.h"
 
-
 namespace clitk
 {
 
-
   //-----------------------------------------------------------
   // Constructor
   //-----------------------------------------------------------
index 61dbcb1de2e7dc7cd53cd5318a327c75e451cc19..4cb22ca85c806ae1bb0d9f941913e8e91a152b01 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char * argv[])
 
   // Go !
   filter->SetArgsInfo(args_info);
-  filter->Update();
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   // this is the end my friend
   return EXIT_SUCCESS;
index 297b63711f6c107f389ea487b9049221582a4b44..64bcfe180a32a50f9f8759341e6e63d0d1b3efba 100644 (file)
@@ -60,7 +60,7 @@ int main(int argc, char * argv[])
   if (args_info.type_given) filter->SetOutputPixelType(args_info.type_arg);
 
   // Go !
-  filter->Update();
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   // this is the end my friend
   return 0;
index 0aec22548c64b5d7d6251bfbcec52cf61c0080ec..145863a93670c6c4d5afab0628a7bb35124ff33c 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char * argv[])
   FilterType::Pointer genericFilter = FilterType::New();
 
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
diff --git a/tools/clitkLabelImageOverlapMeasure.cxx b/tools/clitkLabelImageOverlapMeasure.cxx
new file mode 100644 (file)
index 0000000..9a7b625
--- /dev/null
@@ -0,0 +1,46 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+// clitk
+#include "clitkIO.h"
+#include "clitkLabelImageOverlapMeasure_ggo.h"
+#include "clitkLabelImageOverlapMeasureGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkLabelImageOverlapMeasure, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::LabelImageOverlapMeasureGenericFilter<args_info_clitkLabelImageOverlapMeasure> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  
+  filter->SetArgsInfo(args_info);
+  
+  try {
+    filter->Update();
+  } catch(std::runtime_error e) {
+    std::cout << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/tools/clitkLabelImageOverlapMeasure.ggo b/tools/clitkLabelImageOverlapMeasure.ggo
new file mode 100644 (file)
index 0000000..17c28ed
--- /dev/null
@@ -0,0 +1,21 @@
+#File clitkLabelImageOverlapMeasure.ggo
+package "clitkLabelImageOverlapMeasure"
+version "1.0"
+purpose "Compute Dice and other coefficients between label images"
+
+section "General options"
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+option "imagetypes"     -       "Display allowed image types"     flag          off
+
+section "Input"
+option "input1"         i      "Input mask 1"          string          yes
+option "input2"                j       "Input mask 2"          string          yes
+
+option "label1"                l       "Label in input1"       int          no      default="1"
+option "label2"                m       "Label in input2"       int          no      default="1"
+option "BG"            b       "Background value"      int          no      default="0"
+
+
+
+
diff --git a/tools/clitkLabelImageOverlapMeasureGenericFilter.h b/tools/clitkLabelImageOverlapMeasureGenericFilter.h
new file mode 100644 (file)
index 0000000..a6f8028
--- /dev/null
@@ -0,0 +1,76 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+#ifndef CLITKLABELIMAGEOVERLAPMEASUREGENERICFILTER_H
+#define CLITKLABELIMAGEOVERLAPMEASUREGENERICFILTER_H
+
+// clitk 
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkLabelImageOverlapMeasureFilter.h"
+#include "clitkBoundingBoxUtils.h"
+#include "clitkCropLikeImageFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+
+  template<class ArgsInfoType>
+  class ITK_EXPORT LabelImageOverlapMeasureGenericFilter:
+    public ImageToImageGenericFilter<LabelImageOverlapMeasureGenericFilter<ArgsInfoType> >
+  {
+  public:
+    //--------------------------------------------------------------------
+    LabelImageOverlapMeasureGenericFilter();
+  
+    //--------------------------------------------------------------------
+    typedef ImageToImageGenericFilter<LabelImageOverlapMeasureGenericFilter<ArgsInfoType> > Superclass;
+    typedef LabelImageOverlapMeasureGenericFilter Self;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+   
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(LabelImageOverlapMeasureGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+    template<class FilterType> 
+      void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+      ArgsInfoType mArgsInfo;
+
+  private:
+    LabelImageOverlapMeasureGenericFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  };// end class
+  //--------------------------------------------------------------------
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkLabelImageOverlapMeasureGenericFilter.txx"
+#endif
+
+#endif // #define CLITKRELATIVEPOSITIONANALYZERGENERICFILTER_H
diff --git a/tools/clitkLabelImageOverlapMeasureGenericFilter.txx b/tools/clitkLabelImageOverlapMeasureGenericFilter.txx
new file mode 100644 (file)
index 0000000..bb1b6eb
--- /dev/null
@@ -0,0 +1,100 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::LabelImageOverlapMeasureGenericFilter<ArgsInfoType>::
+LabelImageOverlapMeasureGenericFilter():
+  ImageToImageGenericFilter<Self>("LabelImageOverlapMeasure")
+{
+  // Default values
+  cmdline_parser_clitkLabelImageOverlapMeasure_init(&mArgsInfo);
+  //InitializeImageType<2>();
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::LabelImageOverlapMeasureGenericFilter<ArgsInfoType>::
+InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::LabelImageOverlapMeasureGenericFilter<ArgsInfoType>::
+SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.input1_given) AddInputFilename(mArgsInfo.input1_arg);
+  if (mArgsInfo.input2_given) AddInputFilename(mArgsInfo.input2_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::LabelImageOverlapMeasureGenericFilter<ArgsInfoType>::
+SetOptionsFromArgsInfoToFilter(FilterType * f) 
+{
+  f->SetLabel1(mArgsInfo.label1_arg);  
+  f->SetLabel2(mArgsInfo.label2_arg);  
+}
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::LabelImageOverlapMeasureGenericFilter<ArgsInfoType>::
+UpdateWithInputImageType() 
+{ 
+  // Reading input
+  typename ImageType::Pointer input1 = this->template GetInput<ImageType>(0);
+  typename ImageType::Pointer input2 = this->template GetInput<ImageType>(1);
+
+  // Create filter
+  typedef clitk::LabelImageOverlapMeasureFilter<ImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+  
+  // Set global Options 
+  filter->SetInput(0, input1);
+  filter->SetInput(1, input2);
+  SetOptionsFromArgsInfoToFilter<FilterType>(filter);
+
+  // Go !
+  filter->Update();
+  
+  // Write/Save results
+  // typename ImageType::Pointer output = filter->GetOutput();
+  // this->template SetNextOutput<ImageType>(output); 
+}
+//--------------------------------------------------------------------
+
+
index 5af8a7fb44c117bcfb9cdb513c145d5ea736d351..cf50f6852797bdcb4c00af396229c5e1f95a568a 100644 (file)
@@ -45,7 +45,7 @@ int main(int argc, char * argv[])
   FilterType::Pointer genericFilter = FilterType::New();
 
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
diff --git a/tools/clitkRelativePositionAnalyzer.cxx b/tools/clitkRelativePositionAnalyzer.cxx
new file mode 100644 (file)
index 0000000..bb0986d
--- /dev/null
@@ -0,0 +1,45 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+// clitk
+#include "clitkRelativePositionAnalyzer_ggo.h"
+#include "clitkRelativePositionAnalyzerGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkRelativePositionAnalyzer, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::RelativePositionAnalyzerGenericFilter<args_info_clitkRelativePositionAnalyzer> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  filter->SetArgsInfo(args_info);
+  
+  // Go !
+  try {
+    filter->Update();
+  } catch(std::runtime_error e) {
+    std::cout << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/tools/clitkRelativePositionAnalyzer.ggo b/tools/clitkRelativePositionAnalyzer.ggo
new file mode 100644 (file)
index 0000000..cf0feb1
--- /dev/null
@@ -0,0 +1,31 @@
+#File clitkRelativePositionAnalyzer.ggo
+package "clitkRelativePositionAnalyzer"
+version "1.0"
+purpose "Analyze relative position of a target according to structures"
+
+section "General options"
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+option "imagetypes"     -       "Display allowed image types"     flag          off
+
+section "Input/Output"
+option "support"       i       "Input mask support"      string        yes
+option "object"                j       "Input mask object"       string        yes
+option "target"                t       "Input mask target"       string        yes
+option "output"        o       "Output image "                         string yes
+
+section "Options for building the relative positions"
+option "bins"           -       "Number of histo bins for fuzzy map"      int default="100" no
+option "tol"            -       "Target area loss tolerance (|0-1])"      double default="0.01" no
+
+option "angle1"        a       "Angle 1 (deg)"                    double       no      default="0"
+option "angle2"        b       "Angle 2 (deg)"                    double       no      default="0"
+option "inverse"        n       "Not flag : inverse of the orientation"     flag   off
+
+
+section "Compute some statistic on afdb"
+option "afdb"           -       "Input Anatomical Feature DB"           string no multiple
+option "afdb_path"      -       "Path to search image in afdb"          string no multiple
+option "station"       -       "Station name"                          string no
+
+
diff --git a/tools/clitkRelativePositionAnalyzerGenericFilter.h b/tools/clitkRelativePositionAnalyzerGenericFilter.h
new file mode 100644 (file)
index 0000000..fc5f67e
--- /dev/null
@@ -0,0 +1,77 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+#ifndef CLITKRELATIVEPOSITIONANALYZERGENERICFILTER_H
+#define CLITKRELATIVEPOSITIONANALYZERGENERICFILTER_H
+
+// clitk 
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkRelativePositionAnalyzerFilter.h"
+#include "clitkSliceBySliceRelativePositionFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+
+  template<class ArgsInfoType>
+  class ITK_EXPORT RelativePositionAnalyzerGenericFilter:
+    public ImageToImageGenericFilter<RelativePositionAnalyzerGenericFilter<ArgsInfoType> >
+  {
+  public:
+    //--------------------------------------------------------------------
+    RelativePositionAnalyzerGenericFilter();
+    ~RelativePositionAnalyzerGenericFilter() {}
+  
+    //--------------------------------------------------------------------
+    typedef ImageToImageGenericFilter<RelativePositionAnalyzerGenericFilter<ArgsInfoType> > Superclass;
+    typedef RelativePositionAnalyzerGenericFilter Self;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+   
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(RelativePositionAnalyzerGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+    template<class FilterType> 
+      void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+      ArgsInfoType mArgsInfo;
+
+  private:
+    RelativePositionAnalyzerGenericFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  };// end class
+  //--------------------------------------------------------------------
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkRelativePositionAnalyzerGenericFilter.txx"
+#endif
+
+#endif // #define CLITKRELATIVEPOSITIONANALYZERGENERICFILTER_H
diff --git a/tools/clitkRelativePositionAnalyzerGenericFilter.txx b/tools/clitkRelativePositionAnalyzerGenericFilter.txx
new file mode 100644 (file)
index 0000000..5074504
--- /dev/null
@@ -0,0 +1,110 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::RelativePositionAnalyzerGenericFilter<ArgsInfoType>::
+RelativePositionAnalyzerGenericFilter():
+  ImageToImageGenericFilter<Self>("RelativePositionAnalyzer")
+{
+  // Default values
+  cmdline_parser_clitkRelativePositionAnalyzer_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::RelativePositionAnalyzerGenericFilter<ArgsInfoType>::
+InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::RelativePositionAnalyzerGenericFilter<ArgsInfoType>::
+SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+  if (mArgsInfo.support_given) AddInputFilename(mArgsInfo.support_arg);
+  if (mArgsInfo.object_given) AddInputFilename(mArgsInfo.object_arg);
+  if (mArgsInfo.target_given) AddInputFilename(mArgsInfo.target_arg);
+  if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::RelativePositionAnalyzerGenericFilter<ArgsInfoType>::
+SetOptionsFromArgsInfoToFilter(FilterType * f) 
+{
+  f->SetNumberOfBins(mArgsInfo.bins_arg);
+  f->SetAreaLossTolerance(mArgsInfo.tol_arg);
+  clitk::RelativePositionDirectionType d;
+  if (mArgsInfo.angle1_given) d.angle1 = clitk::deg2rad(mArgsInfo.angle1_arg);
+  if (mArgsInfo.angle2_given) d.angle2 = clitk::deg2rad(mArgsInfo.angle2_arg);
+  if (mArgsInfo.inverse_given) d.notFlag = clitk::deg2rad(mArgsInfo.inverse_flag);
+  f->SetDirection(d);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::RelativePositionAnalyzerGenericFilter<ArgsInfoType>::
+UpdateWithInputImageType() 
+{ 
+  // Create filter
+  typedef clitk::RelativePositionAnalyzerFilter<ImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+  
+  // Reading input
+  typename ImageType::Pointer support = this->template GetInput<ImageType>(0);
+  typename ImageType::Pointer object = this->template GetInput<ImageType>(1);
+  typename ImageType::Pointer target = this->template GetInput<ImageType>(2);
+  filter->SetInputSupport(support);
+  filter->SetInputObject(object);
+  filter->SetInputTarget(target);
+
+  // Set global Options 
+  SetOptionsFromArgsInfoToFilter<FilterType>(filter);
+
+  // Go !
+  filter->Update();
+
+  // Display output
+  filter->GetInfo().Println();
+  filter->GetInfoReverse().Println();
+}
+//--------------------------------------------------------------------
+
+
diff --git a/tools/clitkRelativePositionDataBaseAnalyzer.cxx b/tools/clitkRelativePositionDataBaseAnalyzer.cxx
new file mode 100644 (file)
index 0000000..b74cec4
--- /dev/null
@@ -0,0 +1,48 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+// clitk
+#include "clitkRelativePositionDataBaseAnalyzer_ggo.h"
+#include "clitkIO.h"
+#include "clitkRelativePositionDataBaseAnalyzerFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkRelativePositionDataBaseAnalyzer, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::RelativePositionDataBaseAnalyzerFilter FilterType;
+  FilterType filter;  
+  filter.SetDatabaseFilename(args_info.db_arg);
+  filter.SetStationName(args_info.station_arg);
+  // filter.SetStationName(args_info.object_arg);//FIXME
+  filter.SetOutputFilename(args_info.output_arg);
+
+  try {
+    filter.Update();
+  } catch(std::runtime_error e) {
+    std::cout << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/tools/clitkRelativePositionDataBaseAnalyzer.ggo b/tools/clitkRelativePositionDataBaseAnalyzer.ggo
new file mode 100644 (file)
index 0000000..0da0bcd
--- /dev/null
@@ -0,0 +1,14 @@
+#File clitkRelativePositionDataBaseAnalyzer.ggo
+package "clitkRelativePositionDataBaseAnalyzer"
+version "1.0"
+purpose "Analyze a DB of relative positions for several patient and structures"
+
+section "General options"
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "Input/Output"
+option "db"             i      "Input database of RelPost"       string        yes
+option "station"       s       "Studied station name"            string        yes
+option "object"                -       "Studied object/struct name"      string        no
+option "output"        o       "Output rpl file"                 string        yes
diff --git a/tools/clitkRelativePositionDataBaseBuilder.cxx b/tools/clitkRelativePositionDataBaseBuilder.cxx
new file mode 100644 (file)
index 0000000..4c8db03
--- /dev/null
@@ -0,0 +1,52 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+// clitk
+#include "clitkRelativePositionDataBaseBuilder_ggo.h"
+#include "clitkRelativePositionDataBaseBuilderGenericFilter.h"
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkRelativePositionDataBaseBuilder, args_info);
+  CLITK_INIT;
+
+  // Filter
+  typedef clitk::RelativePositionDataBaseBuilderGenericFilter<args_info_clitkRelativePositionDataBaseBuilder> FilterType;
+  FilterType::Pointer filter = FilterType::New();
+  
+  // Set options
+  filter->SetArgsInfo(args_info);
+  
+  // Add an input to determine the type of image
+  NewAFDB(afdb, args_info.afdb_arg);
+  std::string f = afdb->GetTagValue(args_info.supportName_arg);
+  f = std::string(args_info.afdb_path_arg)+"/"+f;
+  filter->AddInputFilename(f);
+  
+  try {
+    filter->Update();
+  } catch(std::runtime_error e) {
+    std::cout << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+} // This is the end, my friend
+//--------------------------------------------------------------------
diff --git a/tools/clitkRelativePositionDataBaseBuilder.ggo b/tools/clitkRelativePositionDataBaseBuilder.ggo
new file mode 100644 (file)
index 0000000..c71c462
--- /dev/null
@@ -0,0 +1,25 @@
+#File clitkRelativePositionDataBaseBuilder.ggo
+package "clitkRelativePositionDataBaseBuilder"
+version "1.0"
+purpose "Analyze relative position of a target according to structures"
+
+section "General options"
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+option "imagetypes"     -       "Display allowed image types"     flag          off
+
+section "Input/Output"
+option "afdb"           a       "Input Anatomical Feature DB"           string yes
+option "afdb_path"      -       "Path to search image in afdb"          string no
+
+option "supportName"   i       "Input mask support name in afdb"       string yes
+option "targetName"    t       "Input mask target name in afdb"        string yes
+option "objectName"    j       "Input mask object name in afdb"        string yes multiple
+
+option "output"        o       "Output image "                         string yes
+
+section "Options for building the relative positions"
+option "bins"           b       "Number of histo bins for fuzzy map"      int default="100" no
+option "nb"             n       "Number of angles to test"                int default="4" no
+option "tol"            -       "Target area loss tolerance (|0-1])"      double default="0.01" no
+
diff --git a/tools/clitkRelativePositionDataBaseBuilderGenericFilter.h b/tools/clitkRelativePositionDataBaseBuilderGenericFilter.h
new file mode 100644 (file)
index 0000000..bf88269
--- /dev/null
@@ -0,0 +1,76 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+===========================================================================**/
+
+#ifndef CLITKRelativePositionDataBaseBuilderGENERICFILTER_H
+#define CLITKRelativePositionDataBaseBuilderGENERICFILTER_H
+
+// clitk 
+#include "clitkIO.h"
+#include "clitkImageToImageGenericFilter.h"
+#include "clitkRelativePositionDataBaseBuilderFilter.h"
+#include "clitkSliceBySliceRelativePositionFilter.h"
+
+//--------------------------------------------------------------------
+namespace clitk 
+{
+
+  template<class ArgsInfoType>
+  class ITK_EXPORT RelativePositionDataBaseBuilderGenericFilter:
+    public ImageToImageGenericFilter<RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType> >
+  {
+  public:
+    //--------------------------------------------------------------------
+    RelativePositionDataBaseBuilderGenericFilter();
+  
+    //--------------------------------------------------------------------
+    typedef ImageToImageGenericFilter<RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType> > Superclass;
+    typedef RelativePositionDataBaseBuilderGenericFilter Self;
+    typedef itk::SmartPointer<Self>       Pointer;
+    typedef itk::SmartPointer<const Self> ConstPointer;
+   
+    //--------------------------------------------------------------------
+    itkNewMacro(Self);  
+    itkTypeMacro(RelativePositionDataBaseBuilderGenericFilter, LightObject);
+
+    //--------------------------------------------------------------------
+    void SetArgsInfo(const ArgsInfoType & a);
+    template<class FilterType> 
+      void SetOptionsFromArgsInfoToFilter(FilterType * f) ;
+
+    //--------------------------------------------------------------------
+    // Main function called each time the filter is updated
+    template<class ImageType>  
+    void UpdateWithInputImageType();
+
+  protected:
+    template<unsigned int Dim> void InitializeImageType();
+      ArgsInfoType mArgsInfo;
+
+  private:
+    RelativePositionDataBaseBuilderGenericFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+  };// end class
+  //--------------------------------------------------------------------
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkRelativePositionDataBaseBuilderGenericFilter.txx"
+#endif
+
+#endif // #define CLITKRelativePositionDataBaseBuilderGENERICFILTER_H
diff --git a/tools/clitkRelativePositionDataBaseBuilderGenericFilter.txx b/tools/clitkRelativePositionDataBaseBuilderGenericFilter.txx
new file mode 100644 (file)
index 0000000..6ce6a2a
--- /dev/null
@@ -0,0 +1,101 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://www.centreleonberard.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ===========================================================================**/
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+clitk::RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType>::
+RelativePositionDataBaseBuilderGenericFilter():
+  ImageToImageGenericFilter<Self>("RelativePositionDataBaseBuilder")
+{
+  // Default values
+  cmdline_parser_clitkRelativePositionDataBaseBuilder_init(&mArgsInfo);
+  InitializeImageType<3>();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<unsigned int Dim>
+void clitk::RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType>::
+InitializeImageType() 
+{  
+  ADD_IMAGE_TYPE(Dim, uchar);
+}
+//--------------------------------------------------------------------
+  
+
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+void clitk::RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType>::
+SetArgsInfo(const ArgsInfoType & a) 
+{
+  mArgsInfo=a;
+  SetIOVerbose(mArgsInfo.verbose_flag);
+  if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class FilterType>
+void clitk::RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType>::
+SetOptionsFromArgsInfoToFilter(FilterType * f) 
+{
+  f->SetAFDBFilename(mArgsInfo.afdb_arg);
+  f->SetAFDBPath(mArgsInfo.afdb_path_arg);
+  f->SetNumberOfBins(mArgsInfo.bins_arg);
+  f->SetNumberOfAngles(mArgsInfo.nb_arg);
+  f->SetAreaLossTolerance(mArgsInfo.tol_arg);
+  f->SetSupportName(mArgsInfo.supportName_arg);
+  f->SetTargetName(mArgsInfo.targetName_arg);
+  for(int i=0; i<mArgsInfo.objectName_given; i++)
+    f->AddObjectName(mArgsInfo.objectName_arg[i]);  
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+// Update with the number of dimensions and the pixeltype
+//--------------------------------------------------------------------
+template<class ArgsInfoType>
+template<class ImageType>
+void clitk::RelativePositionDataBaseBuilderGenericFilter<ArgsInfoType>::
+UpdateWithInputImageType() 
+{ 
+  // Create filter
+  typedef clitk::RelativePositionDataBaseBuilderFilter<ImageType> FilterType;
+  typename FilterType::Pointer filter = FilterType::New();
+  
+  // Set global Options 
+  SetOptionsFromArgsInfoToFilter<FilterType>(filter);
+
+  // Go !
+  filter->Update();
+  
+  // Write/Save results
+  //  typename ImageType::Pointer output = filter->GetOutput();
+  //this->template SetNextOutput<ImageType>(output); 
+
+}
+//--------------------------------------------------------------------
+
+
index 84ac3e01cb034fcbe8d4a3389b091212c54b3444..bb9ec6faa8336c13317829c2396324730dacf011 100644 (file)
@@ -16,8 +16,8 @@
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ===========================================================================**/
 
-#ifndef CLITKEXTRACTPATIENTGENERICFILTER_H
-#define CLITKEXTRACTPATIENTGENERICFILTER_H
+#ifndef CLITKRELATIVEPOSITIONGENERICFILTER_H
+#define CLITKRELATIVEPOSITIONGENERICFILTER_H
 
 // clitk 
 #include "clitkIO.h"
@@ -73,4 +73,4 @@ namespace clitk
 #include "clitkRelativePositionGenericFilter.txx"
 #endif
 
-#endif // #define CLITKEXTRACTPATIENTGENERICFILTER_H
+#endif // #define CLITKRELATIVEPOSITIONGENERICFILTER_H
index 66c4be47cfa9c80e9e5b687675e30ecf6f6e1061..8af353a495d5b71c2f7143aba82928389063f32d 100644 (file)
@@ -69,6 +69,9 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
   f->SetVerboseStepFlag(mArgsInfo.verboseStep_flag);
   f->SetWriteStepFlag(mArgsInfo.writeStep_flag);
 
+  // Must be set before AddOrientationTypeString
+  f->SetInverseOrientationFlag(mArgsInfo.inverse_flag);
+  
   for(uint i=0; i<mArgsInfo.orientation_given; i++) {
     f->AddOrientationTypeString(mArgsInfo.orientation_arg[i]);
   }
@@ -85,8 +88,6 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
   f->SetRemoveObjectFlag(!mArgsInfo.doNotRemoveObject_flag);
   f->SetAutoCropFlag(!mArgsInfo.noAutoCrop_flag);
   f->SetCombineWithOrFlag(mArgsInfo.combineWithOr_flag);
-  f->SetInverseOrientationFlag(mArgsInfo.inverse_flag);
-  
 }
 
 //--------------------------------------------------------------------
@@ -143,7 +144,7 @@ UpdateWithInputImageType()
     filter->SetInput(input);
     filter->SetInputObject(object);
     if (mArgsInfo.angle1_given && mArgsInfo.angle2_given)
-      filter->AddAngles(mArgsInfo.angle1_arg, mArgsInfo.angle2_arg);
+      filter->AddAnglesInDeg(mArgsInfo.angle1_arg, mArgsInfo.angle2_arg);
     SetOptionsFromArgsInfoToFilter<FilterType>(filter);
    
     // Go !
index 661e1839a86f5a9a4a3969d13a2ea0478a472b09..bd2f3747cc5e5d5c042eb6face19c04e7756b4fe 100644 (file)
@@ -33,7 +33,7 @@ int main(int argc, char * argv[])
   FilterType::Pointer filter = FilterType::New();
 
   filter->SetArgsInfo(args_info);
-  filter->Update();
+  CLITK_TRY_CATCH_EXIT(filter->Update());
 
   // this is the end my friend
   return EXIT_SUCCESS;
index a44b4eb00f7c9599231a1adf91947e9d2f04018c..b70799990b4044f0db55c468fb831bdf41d9742f 100644 (file)
@@ -34,7 +34,7 @@ int main(int argc, char * argv[])
   clitk::SetBackgroundGenericFilter::Pointer genericFilter=clitk::SetBackgroundGenericFilter::New();
 
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index cf1dec0fd8b07a814cc62f6a047db23a8a9357d2..3360661b1a74a0a76a0c0d33164e54d9f0b67fb6 100644 (file)
@@ -44,7 +44,7 @@ int main(int argc, char * argv[])
   clitk::WarpImageGenericFilter::Pointer genericFilter=clitk::WarpImageGenericFilter::New();
 
   genericFilter->SetArgsInfo(args_info);
-  genericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(genericFilter->Update());
 
   return EXIT_SUCCESS;
 }// end main
index f19e567fc5ab8e348cc81e7764790d80fe21e6c7..52b3a2af40784981ae0068bbaa52dccb86b4c533 100644 (file)
@@ -50,7 +50,7 @@ int main( int argc, char *argv[] )
   zeroVFGenericFilter->SetVerbose(args_info.verbose_flag);
 
   //update
-  zeroVFGenericFilter->Update();
+  CLITK_TRY_CATCH_EXIT(zeroVFGenericFilter->Update());
   return EXIT_SUCCESS;
 }
 #endif