]> Creatis software - clitk.git/commitdiff
Add initial step: select BB supports.
authordsarrut <david.sarrut@gmail.com>
Tue, 12 Jul 2011 06:14:58 +0000 (08:14 +0200)
committerdsarrut <david.sarrut@gmail.com>
Tue, 12 Jul 2011 06:14:58 +0000 (08:14 +0200)
segmentation/clitkExtractLymphStation_7.txx
segmentation/clitkExtractLymphStation_8.txx
segmentation/clitkExtractLymphStation_Supports.txx [new file with mode: 0644]
segmentation/clitkExtractLymphStations.ggo
segmentation/clitkExtractLymphStationsFilter.h
segmentation/clitkExtractLymphStationsFilter.txx
segmentation/clitkExtractLymphStationsGenericFilter.txx

index 7bb4643cfcae9fcd6dd11ddc1060cdfee07db359..b12fa521b4b9dfa4e22f56d4876f470efb04cb47 100644 (file)
@@ -11,6 +11,28 @@ ExtractStation_7_SetDefaultValues()
   SetFuzzyThreshold("7", "RightPulmonaryArtery", 0.3);
   SetFuzzyThreshold("7", "LeftPulmonaryArtery", 0.5);
   SetFuzzyThreshold("7", "SVC", 0.2);
+  SetS7_UseMostInferiorPartOnlyFlag(false);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_7() {
+  if (CheckForStation("7")) {
+  ExtractStation_7_SI_Limits();
+  ExtractStation_7_RL_Interior_Limits();
+
+  //  ExtractStation_7_Posterior_Limits();
+  ExtractStation_8_Single_CCL_Limits();  
+  ExtractStation_7_Remove_Structures();
+  // Store image filenames into AFDB 
+  writeImage<MaskImageType>(m_ListOfStations["7"], "seg/Station7.mhd");
+  GetAFDB()->SetImageFilename("Station7", "seg/Station7.mhd");  
+  WriteAFDB();
+  }
 }
 //--------------------------------------------------------------------
 
@@ -21,44 +43,212 @@ void
 clitk::ExtractLymphStationsFilter<TImageType>::
 ExtractStation_7_SI_Limits() 
 {
-  StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLLBronchus");
+  StartNewStep("[Station7] Inf/Sup mediastinum limits with carina/LLL-RMLBronchus");
   // Get Inputs
   MaskImagePointer Trachea = GetAFDB()->template GetImage <MaskImageType>("Trachea");  
+  // Create line from A to B with
+  // A = upper border of LLL at left
+  // B = lower border of bronchus intermedius (BI) or RightMiddleLobeBronchus
+  ImagePointType A;
+  ImagePointType B;
+  FindLineForS7S8Separation(A, B);    
+
+  // // if option -> replace A[0] with B[0]
+  // if (GetS7_UseMostInferiorPartOnlyFlag()) {
+  //   A[0] = B[0];
+  // }
+
+  // Use line to remove the inferior part
+  m_Working_Support =
+    SliceBySliceSetBackgroundFromSingleLine<MaskImageType>(m_Working_Support, GetBackgroundValue(), 
+                                                           A, B, 2, 0, false);
+
+  // Get the CarinaZ position
+  m_CarinaZ = FindCarinaSlicePosition();
   
-  // We suppoe that CarinaZ was already computed (S8)
-  double m_CarinaZ = GetAFDB()->GetDouble("CarinaZ");
+  // Crop support
+  m_Working_Support = 
+    clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2, 
+                                                A[2], m_CarinaZ, true,
+                                                GetBackgroundValue());
+  // Crop trachea 
+  m_Working_Trachea = 
+    clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2, 
+                                                A[2], m_CarinaZ, true,
+                                                GetBackgroundValue()); 
   
-  //  double m_OriginOfRightMiddleLobeBronchusZ = GetAFDB()->GetPoint3D("OriginOfRightMiddleLobeBronchus", 2);
-  // DD(m_OriginOfRightMiddleLobeBronchusZ);
-  MaskImagePointer UpperBorderOfLLLBronchus = GetAFDB()->template GetImage<MaskImageType>("UpperBorderOfLLLBronchus");
+  StopCurrentStep<MaskImageType>(m_Working_Support);
+  m_ListOfStations["7"] = m_Working_Support;
+}
+//--------------------------------------------------------------------
 
-  // Search most inf point (WHY ? IS IT THE RIGHT STRUCTURE ??)
-  MaskImagePointType ps = UpperBorderOfLLLBronchus->GetOrigin(); // initialise to avoid warning 
-  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(UpperBorderOfLLLBronchus, GetBackgroundValue(), 2, true, ps);
-  double m_UpperBorderOfLLLBronchusZ = ps[2];
 
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_7_RL_Interior_Limits() 
+{
+  // ----------------------------------------------------------------
+  StartNewStep("[Station7] RL limits with bronchi");  
+  
   /*
-  std::vector<MaskImagePointType> centroids;
-  clitk::ComputeCentroids<MaskImageType>(UpperBorderOfLLLBronchus, GetBackgroundValue(), centroids);
-  double m_UpperBorderOfLLLBronchusZ = centroids[1][2];
-  DD(m_UpperBorderOfLLLBronchusZ)
+    Slice by Slice, consider most Left point of the Right
+    bronchus. Remove the Ant/Right corner
   */
 
-  /* Crop support */
+  // First consider bronchi
+  FindLeftAndRightBronchi();
+  m_RightBronchus = GetAFDB()->template GetImage <MaskImageType>("RightBronchus");
+  m_LeftBronchus = GetAFDB()->template GetImage <MaskImageType>("LeftBronchus");
+
+  // Resize like m_Working_Support
+  m_LeftBronchus = 
+    clitk::ResizeImageLike<MaskImageType>(m_LeftBronchus, m_Working_Support, GetBackgroundValue());
+  m_RightBronchus = 
+    clitk::ResizeImageLike<MaskImageType>(m_RightBronchus, m_Working_Support, GetBackgroundValue());
+
+  // Extract slices, Label, compute centroid, keep most central connected component
+  std::vector<MaskSlicePointer> slices_leftbronchus;
+  std::vector<MaskSlicePointer> slices_rightbronchus;
+  std::vector<MaskSlicePointer> slices_support;
+  clitk::ExtractSlices<MaskImageType>(m_LeftBronchus, 2, slices_leftbronchus);
+  clitk::ExtractSlices<MaskImageType>(m_RightBronchus, 2, slices_rightbronchus);
+  clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices_support);
+
+  // Keep only the CCL of the bronchus with the closest to the center
+  // Loop on slices for left bronchus
+  for(uint i=0; i<slices_leftbronchus.size(); i++) {
+    slices_leftbronchus[i] = Labelize<MaskSliceType>(slices_leftbronchus[i], 0, false, 10);
+    std::vector<typename MaskSliceType::PointType> c;
+    clitk::ComputeCentroids<MaskSliceType>(slices_leftbronchus[i], GetBackgroundValue(), c);
+    if (c.size() > 1) {
+      double most_at_left = c[1][0];
+      int most_at_left_index=1;
+      for(uint j=1; j<c.size(); j++) {
+        if (c[j][0] < most_at_left) {
+          most_at_left = c[j][0];
+          most_at_left_index = j;
+        }
+      }
+      // Put all other CCL to Background
+      slices_leftbronchus[i] = 
+        clitk::Binarize<MaskSliceType>(slices_leftbronchus[i], most_at_left_index, 
+                                       most_at_left_index, GetBackgroundValue(), GetForegroundValue());
+    } // end c.size
+  }
+  
+  // Loop on slices for right bronchus
+  for(uint i=0; i<slices_rightbronchus.size(); i++) {
+    slices_rightbronchus[i] = Labelize<MaskSliceType>(slices_rightbronchus[i], 0, false, 10);
+    std::vector<typename MaskSliceType::PointType> c;
+    clitk::ComputeCentroids<MaskSliceType>(slices_rightbronchus[i], GetBackgroundValue(), c);
+    if (c.size() > 1) {
+      double most_at_right = c[1][0];
+      int most_at_right_index=1;
+      for(uint j=1; j<c.size(); j++) {
+        if (c[j][0] > most_at_right) {
+          most_at_right = c[j][0];
+          most_at_right_index = j;
+        }
+      }
+      // Put all other CCL to Background
+      slices_rightbronchus[i] = 
+        clitk::Binarize<MaskSliceType>(slices_rightbronchus[i], most_at_right_index, 
+                                       most_at_right_index, GetBackgroundValue(), GetForegroundValue());
+    } // end c.size
+  }
+  
+  // Joint slices
+  m_LeftBronchus = clitk::JoinSlices<MaskImageType>(slices_leftbronchus, m_LeftBronchus, 2);
+  m_RightBronchus = clitk::JoinSlices<MaskImageType>(slices_rightbronchus, m_RightBronchus, 2);
+
+  // For Right bronchus, Find most Left point. Remove corner Ant/Right corner
+  for(uint i=0; i<slices_rightbronchus.size(); i++) {
+    // Find most point most at left
+    MaskSlicePointType p_left;
+    MaskSlicePointType p_post;
+    bool b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_rightbronchus[i], GetBackgroundValue(), 0, false, p_left);
+    if (b) {
+      b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post);
+    }
+    if (b) {
+      MaskSlicePointType p = p_left;
+      p[1] = p_post[1];
+      MaskSliceIndexType pi;
+      slices_rightbronchus[i]->TransformPhysicalPointToIndex(p, pi);
+      
+      // Build region to remove
+      MaskSliceRegionType region = slices_rightbronchus[i]->GetLargestPossibleRegion();
+      MaskSliceIndexType index = region.GetIndex();
+      MaskSliceSizeType size = region.GetSize();
+      size[0] = pi[0] - index[0];
+      size[1] = pi[1] - index[1];
+      region.SetSize(size);
+      
+      // Fill region with Background value
+      clitk::FillRegionWithValue<MaskSliceType>(slices_support[i], GetBackgroundValue(), region);
+    }
+  }
+
+  // For Left bronchus, Find most Right point. Remove corner Ant/Left corner
+  for(uint i=0; i<slices_leftbronchus.size(); i++) {
+    // Find most point most at right
+    MaskSlicePointType p_right;
+    MaskSlicePointType p_post;
+    bool b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_leftbronchus[i], GetBackgroundValue(), 0, true, p_right);
+    if (b) {
+      b = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(slices_rightbronchus[i], GetBackgroundValue(), 1, false, p_post);
+    }
+    if (b) {
+      MaskSlicePointType p = p_right;
+      p[1] = p_post[1];
+      MaskSliceIndexType pi;
+      slices_leftbronchus[i]->TransformPhysicalPointToIndex(p, pi);
+      
+      /*      typedef itk::ImageRegionIterator<ImageType> IteratorType;
+      IteratorType iter(input, region);
+      iter.GoToBegin();
+      while (!iter.IsAtEnd()) {
+        MaskSliceIndexType index = iter.GetIndex();
+        if (index[0] > pi[0]) && (index[1] > pi[1]) iter.Set(GetBackgroundValue());
+
+        ++iter;
+      } 
+      */  
+      
+
+      // Build region to remove
+      MaskSliceRegionType region = slices_leftbronchus[i]->GetLargestPossibleRegion();
+      MaskSliceIndexType index = region.GetIndex();
+      MaskSliceSizeType size = region.GetSize();
+      index[0] = pi[0];
+      size[0] = slices_leftbronchus[i]->GetLargestPossibleRegion().GetSize()[0] - pi[0];
+      size[1] = pi[1] - index[1];
+      region.SetSize(size);
+      region.SetIndex(index);
+      
+      // Fill region with Background value
+      clitk::FillRegionWithValue<MaskSliceType>(slices_support[i], GetBackgroundValue(), region);
+    }
+  }
+
+  m_Working_Support = clitk::JoinSlices<MaskImageType>(slices_support, m_Working_Support, 2);
+
+  // Also remove what is at right of the Right bronchus (left respectively)
   m_Working_Support = 
-    clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2, 
-                                                m_UpperBorderOfLLLBronchusZ, 
-                                                m_CarinaZ, true,
-                                                GetBackgroundValue());
-  /* Crop trachea */
-  m_Working_Trachea = 
-    clitk::CropImageAlongOneAxis<MaskImageType>(Trachea, 2, 
-                                                m_UpperBorderOfLLLBronchusZ, 
-                                                m_CarinaZ, true,
-                                                GetBackgroundValue());
+    clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_LeftBronchus, 2, 
+                                                       GetFuzzyThreshold("7", "Bronchi"), "NotLeftTo", 
+                                                       false, 3, false);
+  m_Working_Support = 
+    clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, m_RightBronchus, 2, 
+                                                       GetFuzzyThreshold("7", "Bronchi"), "NotRightTo", 
+                                                       false, 3, false);
+
+  // SECOND PART 
 
   StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["7"] = m_Working_Support;
 }
 //--------------------------------------------------------------------
 
@@ -67,7 +257,7 @@ ExtractStation_7_SI_Limits()
 template <class TImageType>
 void 
 clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_7_RL_Limits() 
+ExtractStation_7_RL_Limits_OLD() 
 {
   // ----------------------------------------------------------------
   StartNewStep("[Station7] Limits with bronchus : RightTo the left bronchus");  
@@ -82,6 +272,10 @@ ExtractStation_7_RL_Limits()
   clitk::ExtractSlices<MaskImageType>(m_LeftBronchus, 2, slices_leftbronchus);
   clitk::ExtractSlices<MaskImageType>(m_RightBronchus, 2, slices_rightbronchus);
   
+  // Version #1 with limit = centroid of the bronchus (OUTDATED)
+  // Step1 = keep only the CCL of the bronchus with the closest to the center
+  // Step2 = SliceBySlice Rel pos to both bronchi
+
   // Loop on slices
   for(uint i=0; i<slices_leftbronchus.size(); i++) {
     slices_leftbronchus[i] = Labelize<MaskSliceType>(slices_leftbronchus[i], 0, false, 10);
@@ -345,13 +539,22 @@ ExtractStation_7_Remove_Structures()
 
   Remove_Structures("7", "AzygousVein");
   Remove_Structures("7", "Aorta");
-  Remove_Structures("7", "Esophagus");
   Remove_Structures("7", "RightPulmonaryArtery");
   Remove_Structures("7", "LeftPulmonaryArtery");
   Remove_Structures("7", "LeftSuperiorPulmonaryVein");
   Remove_Structures("7", "PulmonaryTrunk");
   Remove_Structures("7", "VertebralBody");
 
+  // Keep only one CCL by slice (before removing Esophagus)
+  //  DD("SliceBySliceKeepMainCCL");
+
+  // TODO -> replace by keep the one that contains point at the middle of the line between the bronchus
+  //      -> new function "keep/select" the ccl that contains this point (2D)
+
+  //m_Working_Support = clitk::SliceBySliceKeepMainCCL<MaskImageType>(m_Working_Support, GetBackgroundValue(), GetForegroundValue());
+
+  Remove_Structures("7", "Esophagus");
+
   // END
   StopCurrentStep<MaskImageType>(m_Working_Support);
   m_ListOfStations["7"] = m_Working_Support;
index fc39203ebf7ee646fbc2b169adfad864d9aabd92..7402a626bebd7e86bd06c92c43f843b5291f930e 100644 (file)
@@ -8,7 +8,6 @@ void
 clitk::ExtractLymphStationsFilter<ImageType>::
 ExtractStation_8_SetDefaultValues()
 {
-  SetDistanceMaxToAnteriorPartOfTheSpine(10);
   MaskImagePointType p;
   p[0] = 15; p[1] = 2; p[2] = 1;
   SetEsophagusDiltationForAnt(p);
@@ -19,6 +18,29 @@ ExtractStation_8_SetDefaultValues()
 }
 //--------------------------------------------------------------------
 
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_8() 
+{
+  if (CheckForStation("8")) {
+    ExtractStation_8_SI_Limits();         // OK, validated
+    ExtractStation_8_Ant_Limits();        // OK, validated
+    ExtractStation_8_Left_Sup_Limits();   // OK, validated
+    ExtractStation_8_Left_Inf_Limits();   // OK, validated
+    ExtractStation_8_Single_CCL_Limits(); // OK, validated
+    ExtractStation_8_Remove_Structures(); // OK, validated
+
+    // Store image filenames into AFDB 
+    writeImage<MaskImageType>(m_ListOfStations["8"], "seg/Station8.mhd");
+    GetAFDB()->SetImageFilename("Station8", "seg/Station8.mhd");  
+    WriteAFDB();
+  }
+}
+//--------------------------------------------------------------------
+
+
 //--------------------------------------------------------------------
 template <class ImageType>
 void 
@@ -42,63 +64,42 @@ ExtractStation_8_SI_Limits()
     left; the lower border of the bronchus intermedius on the right"
 
   */
-  StartNewStep("[Station8] Inf/Sup mediastinum limits with carina/diaphragm junction");
-
-  // Get Carina Z position
-  MaskImagePointer Carina = GetAFDB()->template GetImage<MaskImageType>("Carina");
+  StartNewStep("[Station8] Sup/Inf limits with LeftLower/RightMiddle Lobe and diaphragm");
 
-  std::vector<MaskImagePointType> centroids;
-  clitk::ComputeCentroids<MaskImageType>(Carina, GetBackgroundValue(), centroids);
-  m_CarinaZ = centroids[1][2];
-  // DD(m_CarinaZ);
-  // add one slice to include carina ?
-  m_CarinaZ += m_Mediastinum->GetSpacing()[2];
-  // We dont need Carina structure from now
-  Carina->Delete();
-  GetAFDB()->SetDouble("CarinaZ", m_CarinaZ);
+  /* -----------------------------------------------
+     NEW SUPERIOR LIMIT = LeftLowerLobeBronchus /
+     RightMiddleLobeBronchus See FindLineForS7S8Separation
+     -----------------------------------------------
+  */
+  ImagePointType A;
+  ImagePointType B;
+  FindLineForS7S8Separation(A, B);
+
+  // add one slice to be adjacent to Station7
+  B[2] += m_Working_Support->GetSpacing()[2];
+  A[2] += m_Working_Support->GetSpacing()[2];
+
+  // Use the line to remove the inferior part
+  m_Working_Support =
+    SliceBySliceSetBackgroundFromSingleLine<MaskImageType>(m_Working_Support, 
+                                                           GetBackgroundValue(), A, B, 2, 0, true);
   
+  /* -----------------------------------------------
+     INFERIOR LIMIT = Diaphragm
+     -----------------------------------------------
+  */  
+
   // Found most inferior part of the lung
   MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
   // It should be already croped, so I took the origin and add 10mm above 
   m_DiaphragmInferiorLimit = Lungs->GetOrigin()[2]+10;
-  //  Lungs->Delete(); // we don't need it, release memory -> it we want to release, also free in AFDB
-  clitk::PrintMemory(GetVerboseMemoryFlag(), "after reading lungs");
   GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
-  clitk::PrintMemory(GetVerboseMemoryFlag(), "after release lungs");
 
-  /* Crop support :
-     Superior limit = carina
-     Inferior limit = DiaphragmInferiorLimit (old=Gastroesphogeal junction) */
   m_Working_Support = 
     clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2, 
-                                                m_DiaphragmInferiorLimit, //GOjunctionZ, 
-                                                m_CarinaZ, true,
+                                                m_DiaphragmInferiorLimit,
+                                                B[2], true,
                                                 GetBackgroundValue());
-  
-  // Remove some structures that we know are excluded 
-  MaskImagePointer VertebralBody = 
-    GetAFDB()->template GetImage <MaskImageType>("VertebralBody");  
-  MaskImagePointer Aorta = 
-    GetAFDB()->template GetImage <MaskImageType>("Aorta");  
-
-  typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
-  typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
-  boolFilter->InPlaceOn();
-  boolFilter->SetInput1(m_Working_Support);
-  boolFilter->SetInput2(VertebralBody);    
-  boolFilter->SetOperationType(BoolFilterType::AndNot);
-  boolFilter->Update(); 
-  /*
-    
-    DO NOT REMOVE AORTA YET (LATER)
-
-    boolFilter->SetInput1(boolFilter->GetOutput());
-    boolFilter->SetInput2(Aorta);    
-    boolFilter->SetOperationType(BoolFilterType::AndNot);
-    boolFilter->Update();    
-  */ 
-  m_Working_Support = boolFilter->GetOutput();
-
   // Done.
   StopCurrentStep<MaskImageType>(m_Working_Support);
   m_ListOfStations["8"] = m_Working_Support;
@@ -110,290 +111,8 @@ ExtractStation_8_SI_Limits()
 template <class ImageType>
 void 
 clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Post_Limits() 
-{
-  /*
-    Station 8: paraeosphageal nodes
-
-    Anteriorly, it is in contact with Station 7 and the
-    left main stem bronchus in its superior aspect (Fig. 3C–H) and
-    with the heart more inferiorly. Posteriorly, Station 8 abuts the
-    descending aorta and the anterior aspect of the vertebral body
-    until an imaginary horizontal line running 1 cm posterior to the
-    anterior border of the vertebral body (Fig. 3C). 
-
-    New classification IASCL 2009 :
-
-    "Nodes lying adjacent to the wall of the esophagus and to the
-    right or left of the midline, excluding subcarinal nodes (S7)
-    Upper"
-
-  */
-
-  StartNewStep("[Station8] Post limits with vertebral body");
-  MaskImagePointer VertebralBody = 
-    GetAFDB()->template GetImage <MaskImageType>("VertebralBody");  
-
-  // Consider vertebral body slice by slice
-  typedef clitk::ExtractSliceFilter<MaskImageType> ExtractSliceFilterType;
-  typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
-  typedef typename ExtractSliceFilterType::SliceType SliceType;
-  std::vector<typename SliceType::Pointer> vertebralSlices;
-  extractSliceFilter->SetInput(VertebralBody);
-  extractSliceFilter->SetDirection(2);
-  extractSliceFilter->Update();
-  extractSliceFilter->GetOutputSlices(vertebralSlices);
-
-  // For each slice, compute the most anterior point
-  std::map<int, typename SliceType::PointType> vertebralAntPositionBySlice;
-  for(uint i=0; i<vertebralSlices.size(); i++) {
-    typename SliceType::PointType p;
-    bool found = clitk::FindExtremaPointInAGivenDirection<SliceType>(vertebralSlices[i], 
-                                                                     GetBackgroundValue(), 
-                                                                     1, true, p);
-    if (found) {
-      vertebralAntPositionBySlice[i] = p;
-    }
-    else { 
-      // no Foreground in this slice (it appends generally at the
-      // beginning and the end of the volume). Do nothing in this
-      // case.
-    }
-  }
-
-  // Convert 2D points in slice into 3D points
-  std::vector<MaskImagePointType> vertebralAntPositions;
-  clitk::PointsUtils<MaskImageType>::Convert2DMapTo3DList(vertebralAntPositionBySlice, 
-                                                          VertebralBody, 
-                                                          vertebralAntPositions);
-
-  // DEBUG : write list of points
-  clitk::WriteListOfLandmarks<MaskImageType>(vertebralAntPositions, 
-                                             "S8-vertebralMostAntPositions-points.txt");
-
-  // Cut support posteriorly 1cm the most anterior point of the
-  // VertebralBody. Do nothing below and above the VertebralBody. To
-  // do that compute several region, slice by slice and fill. 
-  MaskImageRegionType region;
-  MaskImageSizeType size;
-  MaskImageIndexType start;
-  size[2] = 1; // a single slice
-  start[0] = m_Working_Support->GetLargestPossibleRegion().GetIndex()[0];
-  size[0] = m_Working_Support->GetLargestPossibleRegion().GetSize()[0];
-  for(uint i=0; i<vertebralAntPositions.size(); i++) {
-    typedef typename itk::ImageRegionIterator<MaskImageType> IteratorType;
-    IteratorType iter = 
-      IteratorType(m_Working_Support, m_Working_Support->GetLargestPossibleRegion());
-    MaskImageIndexType index;
-    // Consider some cm posterior to most anterior positions (usually
-    // 1 cm).
-    vertebralAntPositions[i][1] += GetDistanceMaxToAnteriorPartOfTheSpine();
-    // Get index of this point
-    m_Working_Support->TransformPhysicalPointToIndex(vertebralAntPositions[i], index);
-    // Compute region (a single slice)
-    start[2] = index[2];
-    start[1] = m_Working_Support->GetLargestPossibleRegion().GetIndex()[1]+index[1];
-    size[1] = m_Working_Support->GetLargestPossibleRegion().GetSize()[1]-start[1];
-    region.SetSize(size);
-    region.SetIndex(start);
-    // Fill region
-    if (m_Working_Support->GetLargestPossibleRegion().IsInside(start))  {
-      itk::ImageRegionIterator<MaskImageType> it(m_Working_Support, region);
-      it.GoToBegin();
-      while (!it.IsAtEnd()) {
-        it.Set(GetBackgroundValue());
-        ++it;
-      }
-    }
-  }
-
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Ant_Sup_Limits() 
+ExtractStation_8_Ant_Limits() 
 {
-  //--------------------------------------------------------------------
-  StartNewStep("[Station8] Ant limits with S7 above Carina");
-  /*
-    Anteriorly, it is in contact with Station 7 and the
-    left main stem bronchus in its superior aspect (Fig. 3C–H) and
-    with the heart more inferiorly. 
-
-    1) line post wall bronchi (S7), till originRMLB
-    - LUL bronchus : to detect in trachea. But not needed here ??
-    2) heart ! -> not delineated.
-    ==> below S7, crop CT not to far away (ant), then try with threshold
-    
-    1) ==> how to share with S7 ? Prepare both support at the same time !
-    NEED vector of initial support for each station ? No -> map if it exist before, take it !!
-
-  */
-
-  // Ant limit from carina (start) to end of S7 = originRMLB
-  // Get Trachea
-  MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
-  MaskImagePointer m_Working_Trachea = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(Trachea, 2, m_CarinaZ, true, // AutoCrop
-                                         GetBackgroundValue());
-
-  // Seprate into two main bronchi
-  MaskImagePointer RightBronchus;
-  MaskImagePointer LeftBronchus;
-
-  // Labelize and consider the two first (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). We thus first check that the
-  // 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()) {    
-      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 3D centroids of both parts to identify the left from the
-  // right bronchus
-  std::vector<ImagePointType> c;
-  clitk::ComputeCentroids<MaskImageType>(m_Working_Trachea, GetBackgroundValue(), c);
-  ImagePointType C1 = c[1];
-  ImagePointType C2 = c[2];
-
-  ImagePixelType rightLabel;
-  ImagePixelType leftLabel;  
-  if (C1[0] < C2[0]) { rightLabel = 1; leftLabel = 2; }
-  else { rightLabel = 2; leftLabel = 1; }
-
-  // Select LeftLabel (set one label to Backgroundvalue)
-  RightBronchus = 
-    clitk::Binarize<MaskImageType>(m_Working_Trachea, rightLabel, rightLabel, 
-                                   GetBackgroundValue(), GetForegroundValue());
-  /*
-    SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea, 
-    leftLabel, GetBackgroundValue(), false);
-  */
-  LeftBronchus = clitk::Binarize<MaskImageType>(m_Working_Trachea, leftLabel, leftLabel, 
-                                                GetBackgroundValue(), GetForegroundValue());
-  /*
-    SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea, 
-    rightLabel, GetBackgroundValue(), false);
-  */
-
-  // Crop images
-  RightBronchus = clitk::AutoCrop<MaskImageType>(RightBronchus, GetBackgroundValue()); 
-  LeftBronchus = clitk::AutoCrop<MaskImageType>(LeftBronchus, GetBackgroundValue()); 
-
-  // Insert int AFDB if need after 
-  GetAFDB()->template SetImage <MaskImageType>("RightBronchus", "seg/rightBronchus.mhd", 
-                                               RightBronchus, true);
-  GetAFDB()->template SetImage <MaskImageType>("LeftBronchus", "seg/leftBronchus.mhd", 
-                                               LeftBronchus, true);
-
-  // Now crop below OriginOfRightMiddleLobeBronchusZ
-  // It is not done before to keep entire bronchi.
-  
-  MaskImagePointer OriginOfRightMiddleLobeBronchus = 
-    GetAFDB()->template GetImage<MaskImageType>("OriginOfRightMiddleLobeBronchus");
-  std::vector<MaskImagePointType> centroids;
-  clitk::ComputeCentroids<MaskImageType>(OriginOfRightMiddleLobeBronchus, GetBackgroundValue(), centroids);
-  m_OriginOfRightMiddleLobeBronchusZ = centroids[1][2];
-  // add one slice to include carina ?
-  m_OriginOfRightMiddleLobeBronchusZ += RightBronchus->GetSpacing()[2];
-  // We dont need Carina structure from now
-  OriginOfRightMiddleLobeBronchus->Delete();
-
-  RightBronchus = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(RightBronchus, 2, 
-                                         m_OriginOfRightMiddleLobeBronchusZ, 
-                                         true, // AutoCrop
-                                         GetBackgroundValue());
-  LeftBronchus = 
-    clitk::CropImageRemoveLowerThan<MaskImageType>(LeftBronchus, 2, 
-                                         m_OriginOfRightMiddleLobeBronchusZ, 
-                                         true, // AutoCrop
-                                         GetBackgroundValue());
-
-  // Search for points that are the most left/post/ant and most
-  // right/post/ant of the left and right bronchus
-  // 15  = not 15 mm more distance than the middle point.
-  FindExtremaPointsInBronchus(RightBronchus, 0, 10, m_LeftMostInRightBronchus, 
-                             m_AntMostInRightBronchus, m_PostMostInRightBronchus);
-
-  FindExtremaPointsInBronchus(LeftBronchus, 1, 10, m_RightMostInLeftBronchus, 
-                             m_AntMostInLeftBronchus, m_PostMostInLeftBronchus);
-
-  // DEBUG : write the list of points
-  ListOfPointsType v;
-  v.reserve(m_LeftMostInRightBronchus.size()+m_AntMostInRightBronchus.size()+
-            m_PostMostInRightBronchus.size());
-  v.insert(v.end(), m_LeftMostInRightBronchus.begin(), m_LeftMostInRightBronchus.end() );
-  v.insert(v.end(), m_AntMostInRightBronchus.begin(), m_AntMostInRightBronchus.end() );
-  v.insert(v.end(), m_PostMostInRightBronchus.begin(), m_PostMostInRightBronchus.end() );
-  clitk::WriteListOfLandmarks<MaskImageType>(v, "S8-RightBronchus-points.txt");
-
-  v.clear();
-  v.reserve(m_RightMostInLeftBronchus.size()+m_AntMostInLeftBronchus.size()+
-            m_PostMostInLeftBronchus.size());
-  v.insert(v.end(), m_RightMostInLeftBronchus.begin(), m_RightMostInLeftBronchus.end() );
-  v.insert(v.end(), m_AntMostInLeftBronchus.begin(), m_AntMostInLeftBronchus.end() );
-  v.insert(v.end(), m_PostMostInLeftBronchus.begin(), m_PostMostInLeftBronchus.end() );
-  clitk::WriteListOfLandmarks<MaskImageType>(v, "S8-LeftBronchus-points.txt");
-
-  v.clear();
-  v.reserve(m_PostMostInLeftBronchus.size()+m_PostMostInRightBronchus.size());
-  v.insert(v.end(), m_PostMostInLeftBronchus.begin(), m_PostMostInLeftBronchus.end() );
-  v.insert(v.end(), m_PostMostInRightBronchus.begin(), m_PostMostInRightBronchus.end() );
-  clitk::WriteListOfLandmarks<MaskImageType>(v, "S8-RightLeftBronchus-points.txt");
-
-
-  // Now uses these points to limit, slice by slice 
-  // line is mainly horizontal, so mainDirection=1
-  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
-                                                                    m_PostMostInRightBronchus,
-                                                                    m_PostMostInLeftBronchus,
-                                                                    GetBackgroundValue(), 1, 10); 
-
-  // Keep main 3D CCL :
-  m_Working_Support = Labelize<MaskImageType>(m_Working_Support, 0, false, 10);
-  m_Working_Support = KeepLabels<MaskImageType>(m_Working_Support, 
-                                                GetBackgroundValue(), 
-                                                GetForegroundValue(), 1, 1, true);
-  
-  // Autocrop
-  m_Working_Support = clitk::AutoCrop<MaskImageType>(m_Working_Support, GetBackgroundValue()); 
-
-  // End of step
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  //  m_ListOfStations["8"] = m_Working_Support;
-
-}
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Ant_Inf_Limits() 
-{
-
   //--------------------------------------------------------------------
   StartNewStep("[Station8] Ant part: not post to Esophagus");
   /*
@@ -404,7 +123,6 @@ ExtractStation_8_Ant_Inf_Limits()
   
   // Get Esophagus
   m_Esophagus = GetAFDB()->template GetImage<MaskImageType>("Esophagus");
-  clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Esophagus");
 
   // In images from the original article, Atlas – UM, the oesophagus
   //was included in nodal stations 3p and 8.  Having said that, in the
@@ -416,46 +134,17 @@ ExtractStation_8_Ant_Inf_Limits()
   //prospective, the oesophagus should be excluded from these nodal
   //stations.
 
-  /* NOT YET !! DO IT LATER
-
-     typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
-     typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
-     boolFilter->InPlaceOn();
-     boolFilter->SetInput1(m_Working_Support);
-     boolFilter->SetInput2(m_Esophagus);    
-     boolFilter->SetOperationType(BoolFilterType::AndNot);
-     boolFilter->Update();    
-     m_Working_Support = boolFilter->GetOutput();
-
-  */
-
-  // Crop Esophagus : keep only below the OriginOfRightMiddleLobeBronchusZ
+  // Resize Esophagus like current support
   m_Esophagus = 
-    clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Esophagus, 2, 
-                                         m_OriginOfRightMiddleLobeBronchusZ, 
-                                         true, // AutoCrop
-                                         GetBackgroundValue());
+    clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue()); // Needed ?
 
   // Dilate to keep only not Anterior positions
   MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt();
-
-  //  m_Esophagus = EnlargeEsophagusDilatationRadiusInferiorly(m_Esophagus);
-
   m_Esophagus = clitk::Dilate<MaskImageType>(m_Esophagus, 
                                              radiusInMM, 
                                              GetBackgroundValue(), 
                                              GetForegroundValue(), true);
-
-  // Remove Anterior part according to this dilatated esophagus. Note:
-  // because we crop Esophagus with ORML, the support will also be
-  // croped in the same way. Here it is a desired feature. If we dont
-  // want, use SetIgnoreEmptySliceObject(true)
-
-  // In the new IASCL definition, it is not clear if sup limits is
-  //  around carina or On the right, it is “the lower border of the
-  //  bronchus intermedius”, indicated on the image set as a point
-  //  (“lower border of the bronchus intermedius”)
-
+  // Keep what is Posterior to Esophagus
   typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> RelPosFilterType;
   typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
   relPosFilter->VerboseStepFlagOff();
@@ -488,88 +177,10 @@ ExtractStation_8_Ant_Inf_Limits()
 template <class ImageType>
 void 
 clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_Ant_Injected_Limits() 
+ExtractStation_8_Left_Sup_Limits() 
 {
-
   //--------------------------------------------------------------------
-  StartNewStep("[Station8] Ant part (remove high density, injected part)");
-
-  // Consider initial image, crop to current support
-  ImagePointer working_input = 
-    clitk::ResizeImageLike<ImageType>(m_Input, 
-                                      m_Working_Support, 
-                                      (short)GetBackgroundValue());
-  
-  // Threshold
-  typedef itk::BinaryThresholdImageFilter<ImageType, MaskImageType> BinarizeFilterType; 
-  typename BinarizeFilterType::Pointer binarizeFilter = BinarizeFilterType::New();
-  binarizeFilter->SetInput(working_input);
-  binarizeFilter->SetLowerThreshold(GetInjectedThresholdForS8());
-  binarizeFilter->SetInsideValue(GetForegroundValue());
-  binarizeFilter->SetOutsideValue(GetBackgroundValue());
-  binarizeFilter->Update();
-  MaskImagePointer injected = binarizeFilter->GetOutput();
-  
-  // Combine with current support
-  clitk::AndNot<MaskImageType>(m_Working_Support, injected, GetBackgroundValue());
-
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_1_Limits() 
-{
-  //--------------------------------------------------------------------
-  StartNewStep("[Station8] Left and Right (from Carina to PulmonaryTrunk): Right to LeftPulmonaryArtery");
-  
-  /*
-    We remove LeftPulmonaryArtery structure and what is at Left to
-    this structure.
-  */
-  MaskImagePointer LeftPulmonaryArtery = GetAFDB()->template GetImage<MaskImageType>("LeftPulmonaryArtery");
-
-  // Relative Position : not at Left
-  typedef clitk::AddRelativePositionConstraintToLabelImageFilter<MaskImageType> RelPosFilterType;
-  typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
-  relPosFilter->VerboseStepFlagOff();
-  relPosFilter->WriteStepFlagOff();
-  relPosFilter->SetBackgroundValue(GetBackgroundValue());
-  relPosFilter->SetInput(m_Working_Support); 
-  relPosFilter->SetInputObject(LeftPulmonaryArtery); 
-  relPosFilter->RemoveObjectFlagOn(); // remove the object too
-  relPosFilter->AddOrientationTypeString("L");
-  relPosFilter->InverseOrientationFlagOn(); // Not at Left
-  relPosFilter->SetIntermediateSpacing(3);
-  relPosFilter->IntermediateSpacingFlagOn();
-  relPosFilter->SetFuzzyThreshold(0.7);
-  relPosFilter->AutoCropFlagOn();
-  relPosFilter->Update();   
-  m_Working_Support = relPosFilter->GetOutput();
-
-  // Release LeftPulmonaryArtery
-  GetAFDB()->template ReleaseImage<MaskImageType>("LeftPulmonaryArtery");
-
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_2_Limits() 
-{
-  //--------------------------------------------------------------------
-  StartNewStep("[Station8] Left and Right (from PulmTrunk to OriginMiddleLobeBronchus) Right to line from Aorta to PulmonaryTrunk");
+  StartNewStep("[Station8] Left limits: remove Left to line from Aorta to PulmonaryTrunk");
 
   /*
     We consider a line from Left part of Aorta to left part of
@@ -682,280 +293,14 @@ ExtractStation_8_Single_CCL_Limits()
 template <class ImageType>
 void 
 clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_Limits_old2() 
-{
-
-  //--------------------------------------------------------------------
-  StartNewStep("[Station8] Left and Right limits arround esophagus (below Carina)");
-
-  // Estract slices for current support for slice by slice processing
-  std::vector<typename MaskSliceType::Pointer> slices;
-  clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
-  
-  // Dilate the Esophagus to consider a margins around
-  MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt();
-  m_Esophagus = clitk::Dilate<MaskImageType>(m_Esophagus, 
-                                             radiusInMM, 
-                                             GetBackgroundValue(), 
-                                             GetForegroundValue(), true);
-
-  // Remove what is outside the mediastinum in this enlarged Esophagus -> it allows to select
-  // 'better' extrema points (not too post).
-  MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
-  clitk::AndNot<MaskImageType>(m_Esophagus, Lungs, GetBackgroundValue());
-  GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
-
-  // Estract slices of Esophagus (resize like support before to have the same set of slices)
-  MaskImagePointer EsophagusForSlice = clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue());
-
-  std::vector<typename MaskSliceType::Pointer> eso_slices;
-  clitk::ExtractSlices<MaskImageType>(EsophagusForSlice, 2, eso_slices);
-
-  // Estract slices of Vertebral (resize like support before to have the same set of slices)
-  MaskImagePointer VertebralBody = GetAFDB()->template GetImage<MaskImageType>("VertebralBody");
-  VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
-  std::vector<typename MaskSliceType::Pointer> vert_slices;
-  clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, vert_slices);
-
-  // Estract slices of Aorta (resize like support before to have the same set of slices)
-  MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
-  Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, m_Working_Support, GetBackgroundValue());
-  std::vector<typename MaskSliceType::Pointer> aorta_slices;
-  clitk::ExtractSlices<MaskImageType>(Aorta, 2, aorta_slices);
-
-  // Extract slices of Mediastinum (resize like support before to have the same set of slices)
-  m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum");
-  m_Mediastinum = clitk::ResizeImageLike<MaskImageType>(m_Mediastinum, m_Working_Support, GetBackgroundValue());
-  std::vector<typename MaskSliceType::Pointer> mediast_slices;
-  clitk::ExtractSlices<MaskImageType>(m_Mediastinum, 2, mediast_slices);
-
-  // List of points
-  std::vector<MaskImagePointType> p_RightMostAnt;
-  std::vector<MaskImagePointType> p_RightMostPost;
-  std::vector<MaskImagePointType> p_LeftMostAnt;
-  std::vector<MaskImagePointType> p_LeftMostPost;
-  std::vector<MaskImagePointType> p_AllPoints;
-  std::vector<MaskImagePointType> p_LeftAorta;
-  std::vector<MaskImagePointType> p_LeftEso;
-
-  /*
-    In the following, we search for the LeftRight limits.  We search
-    for the most Right points in Esophagus and in VertebralBody and
-    consider a line between those to most right points. All points in
-    the support which are most right to this line are discarded. Same
-    for the left part. The underlying assumption is that the support
-    is concave between Eso/VertebralBody. Esophagus is a bit
-    dilatated. On VertebralBody we go right (or left) until we reach
-    the lung (but no more 20 mm).
-  */
-
-  // Loop slices
-  MaskImagePointType p;
-  MaskImagePointType pp;
-  for(uint i=0; i<slices.size() ; i++) {
-    // Declare all needed points (sp = slice point)
-    typename MaskSliceType::PointType sp_maxRight_Eso;    
-    typename MaskSliceType::PointType sp_maxRight_Aorta;    
-    typename MaskSliceType::PointType sp_maxRight_Vertebra;
-    typename MaskSliceType::PointType sp_maxLeft_Eso; 
-    typename MaskSliceType::PointType sp_maxLeft_Aorta;   
-    typename MaskSliceType::PointType sp_maxLeft_Vertebra;
-    
-    // Right is at left on screen, coordinate decrease
-    // Left is at right on screen, coordinate increase
-    
-    // Find limit of Vertebral -> only at most Post part of current
-    // slice support.  First found most ant point in VertebralBody
-    typedef MaskSliceType SliceType;
-    typename SliceType::PointType p_slice_ant;
-    bool found = clitk::FindExtremaPointInAGivenDirection<SliceType>(vert_slices[i], GetBackgroundValue(), 1, true, p_slice_ant);
-    if (!found) {
-      // It should not happen ! But sometimes, a contour is missing or
-      // the VertebralBody is not delineated enough inferiorly ... in
-      // those cases, we consider the first found slice.
-      std::cerr << "No foreground pixels in this VertebralBody slices !?? I try with the previous/next slice" << std::endl;
-      int j=i++;
-      bool found = false;
-      while (!found) {
-        found = clitk::FindExtremaPointInAGivenDirection<SliceType>(vert_slices[j], GetBackgroundValue(), 1, true, p_slice_ant);
-        //clitkExceptionMacro("No foreground pixels in this VertebralBody slices ??");
-        j++;
-      }
-    }
-    p_slice_ant[1] += GetDistanceMaxToAnteriorPartOfTheSpine(); // Consider offset
-    
-    // The, find most Right and Left points on that AP position
-    typename SliceType::IndexType indexR;
-    typename SliceType::IndexType indexL;
-    vert_slices[i]->TransformPhysicalPointToIndex(p_slice_ant, indexR);
-    indexL = indexR;
-    // Check that is inside the mask
-    indexR[1] = std::min(indexR[1], (long)vert_slices[i]->GetLargestPossibleRegion().GetSize()[1]-1);
-    indexL[1] = indexR[1];
-    while (vert_slices[i]->GetPixel(indexR) != GetBackgroundValue()) {
-      indexR[0] --; // Go to the right
-    }
-    while (vert_slices[i]->GetPixel(indexL) != GetBackgroundValue()) {
-      indexL[0] ++; // Go to the left
-    }
-    vert_slices[i]->TransformIndexToPhysicalPoint(indexR, sp_maxRight_Vertebra);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Vertebra, VertebralBody, i, p);
-    p_AllPoints.push_back(p);
-    vert_slices[i]->TransformIndexToPhysicalPoint(indexL, sp_maxLeft_Vertebra);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Vertebra, VertebralBody, i, p);
-    p_AllPoints.push_back(p);
-    
-    // Find last point out of the mediastinum on this line, Right :
-    mediast_slices[i]->TransformPhysicalPointToIndex(sp_maxRight_Vertebra, indexR);
-    double distance = 0.0;
-    while (mediast_slices[i]->GetPixel(indexR) != GetBackgroundValue()) {
-      indexR[0] --;
-      distance += mediast_slices[i]->GetSpacing()[0];
-    }
-    if (distance < 30) { // Ok in this case, we found limit with lung
-      mediast_slices[i]->TransformIndexToPhysicalPoint(indexR, sp_maxRight_Vertebra);
-      clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Vertebra, m_Mediastinum, i, p);
-    }
-    else { // in that case, we are probably below the diaphragm, so we
-           // add aribtrarly few mm
-      sp_maxRight_Vertebra[0] -= 2; // Leave 2 mm around the VertebralBody 
-      clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Vertebra, m_Mediastinum, i, p);
-    }
-    p_RightMostPost.push_back(p);
-    p_AllPoints.push_back(p);
-
-    // Find last point out of the mediastinum on this line, Left :
-    mediast_slices[i]->TransformPhysicalPointToIndex(sp_maxLeft_Vertebra, indexL);
-    distance = 0.0;
-    while (mediast_slices[i]->GetPixel(indexL) != GetBackgroundValue()) {
-      indexL[0] ++;
-      distance += mediast_slices[i]->GetSpacing()[0];
-    }
-    if (distance < 30) { // Ok in this case, we found limit with lung
-      mediast_slices[i]->TransformIndexToPhysicalPoint(indexL, sp_maxLeft_Vertebra);
-      clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Vertebra, m_Mediastinum, i, p);
-    }
-    else { // in that case, we are probably below the diaphragm, so we
-           // add aribtrarly few mm
-      sp_maxLeft_Vertebra[0] += 2; // Leave 2 mm around the VertebralBody 
-      clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Vertebra, m_Mediastinum, i, p);
-    }
-    p_LeftMostPost.push_back(p);
-    p_AllPoints.push_back(p);
-
-    // Find Eso slice centroid and do not consider what is post to
-    // this centroid.
-    std::vector<typename MaskSliceType::PointType> c;
-    clitk::ComputeCentroids<MaskSliceType>(eso_slices[i], GetBackgroundValue(), c);
-    if (c.size() >1) {
-      eso_slices[i] = 
-        clitk::CropImageRemoveGreaterThan<MaskSliceType>(eso_slices[i], 1, c[1][1], false, GetBackgroundValue());
-      eso_slices[i] = 
-        clitk::ResizeImageLike<MaskSliceType>(eso_slices[i], aorta_slices[i], GetBackgroundValue());
-      // writeImage<MaskSliceType>(eso_slices[i], "eso-slice-"+toString(i)+".mhd");
-    }
-
-    // Find right limit of Esophagus and Aorta
-    bool f = 
-      clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 
-                                                              0, true, sp_maxRight_Eso);
-    f = f && 
-      clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 
-                                                              0, true, sp_maxRight_Aorta);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Eso, EsophagusForSlice, i, p);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Aorta, Aorta, i, pp);
-    pp[0] -= 2; // Add a margin of 2 mm to include the Aorta 'wall'
-    p_AllPoints.push_back(p);
-    if (f) {
-      p_AllPoints.push_back(pp);
-      MaskImagePointType A = p_RightMostPost.back();
-      MaskImagePointType B = p;
-      MaskImagePointType C = pp;
-      double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
-      if (s>0) p_RightMostAnt.push_back(p);
-      else p_RightMostAnt.push_back(pp);
-    }
-    else { // No more Esophagus in this slice : do nothing
-      //      p_RightMostAnt.push_back(p); 
-      p_RightMostPost.pop_back();
-    }
-
-    // --------------------------------------------------------------------------
-    // Find the limit on the Left: most left point between Eso and
-    // Eso. (Left is left on screen, coordinate increase)
-    
-    // Find left limit of Esophagus
-    clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, false, sp_maxLeft_Eso);
-    f = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, false, sp_maxLeft_Aorta);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Eso, EsophagusForSlice, i, p);
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Aorta, Aorta, i, pp);
-    p_AllPoints.push_back(p);
-    pp[0] += 2; // Add a margin of 2 mm to include the 'wall'
-    if (f) { // not below Aorta
-      p_AllPoints.push_back(pp);
-      MaskImagePointType A = p_LeftMostPost.back();
-      MaskImagePointType B = p;
-      MaskImagePointType C = pp;
-      double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
-      if (s<0) {
-        p_LeftMostAnt.push_back(p); // Insert point most at Left, Eso
-      }
-      else {
-        // in this case -> two lines !
-        p_LeftMostAnt.push_back(pp);  // Insert point most at Left, Aorta (Vert to Aorta)
-        // but also consider Aorta to Eso
-        p_LeftAorta.push_back(pp);
-        p_LeftEso.push_back(p);
-      }
-    }
-    else { // No more Esophagus in this slice : do nothing
-      p_LeftMostPost.pop_back();
-      //p_LeftMostAnt.push_back(p);
-    }
-  } // End of slice loop
-  
-  clitk::WriteListOfLandmarks<MaskImageType>(p_AllPoints, "S8-LR-Eso-Vert.txt");
-  clitk::WriteListOfLandmarks<MaskImageType>(p_LeftEso, "S8-Left-Eso.txt");
-  clitk::WriteListOfLandmarks<MaskImageType>(p_LeftAorta, "S8-Left-Aorta.txt");
-
-  // Now uses these points to limit, slice by slice 
-  // Line is mainly vertical, so mainDirection=0
-  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
-                                                                    p_RightMostAnt, p_RightMostPost,
-                                                                    GetBackgroundValue(), 0, 10);
-  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
-                                                                    p_LeftMostAnt, p_LeftMostPost,
-                                                                    GetBackgroundValue(), 0, -10);
-  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
-                                                                    p_LeftEso,p_LeftAorta, 
-                                                                    GetBackgroundValue(), 0, -10);
-  // END
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["8"] = m_Working_Support;
-  return;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_Limits() 
+ExtractStation_8_Left_Inf_Limits() 
 {
-
   //--------------------------------------------------------------------
-  StartNewStep("[Station8] Left and Right limits arround esophagus with lines from VertebralBody-Aorta-Esophagus");
+  StartNewStep("[Station8] Left limits around esophagus with lines from VertebralBody-Aorta-Esophagus");
 
   // Estract slices for current support for slice by slice processing
   std::vector<typename MaskSliceType::Pointer> slices;
   clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
-  
-  // Dilate the Esophagus to consider a margins around
-  MaskImagePointType radiusInMM = GetEsophagusDiltationForAnt();
-  m_Esophagus = clitk::Dilate<MaskImageType>(m_Esophagus, radiusInMM, 
-                                             GetBackgroundValue(), GetForegroundValue(), true);
-  //  m_Esophagus = EnlargeEsophagusDilatationRadiusInferiorly(m_Esophagus);
 
   // Remove what is outside the mediastinum in this enlarged Esophagus -> it allows to select
   // 'better' extrema points (not too post).
@@ -964,13 +309,18 @@ ExtractStation_8_LR_Limits()
   GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
 
   // Estract slices of Esophagus (resize like support before to have the same set of slices)
-  MaskImagePointer EsophagusForSlice = clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue());
+  MaskImagePointer EsophagusForSlice = 
+    clitk::ResizeImageLike<MaskImageType>(m_Esophagus, m_Working_Support, GetBackgroundValue());
   std::vector<typename MaskSliceType::Pointer> eso_slices;
   clitk::ExtractSlices<MaskImageType>(EsophagusForSlice, 2, eso_slices);
 
   // Estract slices of Vertebral (resize like support before to have the same set of slices)
   MaskImagePointer VertebralBody = GetAFDB()->template GetImage<MaskImageType>("VertebralBody");
   VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
+  // Remove what is outside the support to not consider what is to
+  // posterior in the VertebralBody (post the horizontal line)
+  clitk::And<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
+  // writeImage<MaskImageType>(VertebralBody, "vb.mhd");
   std::vector<typename MaskSliceType::Pointer> vert_slices;
   clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, vert_slices);
 
@@ -1006,80 +356,67 @@ ExtractStation_8_LR_Limits()
   // Temporary 3D point
   MaskImagePointType p;
 
+  typename MaskSliceType::PointType minSlicePoint;
+  typename MaskSliceType::PointType maxSlicePoint;
+  clitk::GetMinMaxPointPosition<MaskSliceType>(vert_slices[0], minSlicePoint, maxSlicePoint);
+
   // Loop slices
   for(uint i=0; i<slices.size() ; i++) {
     // Declare all needed 2D points (sp = slice point)
-    typename MaskSliceType::PointType sp_MostRightVertebralBody;
+    //    typename MaskSliceType::PointType sp_MostRightVertebralBody;
     typename MaskSliceType::PointType sp_MostLeftVertebralBody;
     typename MaskSliceType::PointType sp_MostLeftAorta;
     typename MaskSliceType::PointType sp_temp;
     typename MaskSliceType::PointType sp_MostLeftEsophagus;
-    
-    // Right is at left on screen, coordinate decrease
-    // Left is at right on screen, coordinate increase
-    
+
     /* -------------------------------------------------------------------------------------
-       Find most Left point in VertebralBody. Consider only the
-       horizontal line which is 'DistanceMaxToAnteriorPartOfTheSpine'
-       away from the most ant point.
-     */
-    typename MaskSliceType::PointType sp_MostAntVertebralBody;
-    bool found = false;
-    int j=i;
-    while (!found) {
-      found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 1, true, sp_MostAntVertebralBody);
-      if (!found) {
-        // It should not happen ! But sometimes, a contour is missing or
-        // the VertebralBody is not delineated enough inferiorly ... in
-        // those cases, we consider the first found slice.
-        std::cerr << "No foreground pixels in this VertebralBody slices !?? I try with the previous/next slice" << std::endl;
-        j++;
-      }
-    }
-    sp_MostAntVertebralBody[1] += GetDistanceMaxToAnteriorPartOfTheSpine(); // Consider offset
+        Find first point not in mediastinum at LEFT
+    */
+    clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[i], GetBackgroundValue(), 
+                                                            0, false, sp_MostLeftVertebralBody);
+    // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
+    // DD(p);
 
-    // Crop the vertebralbody below this most post line
-    vert_slices[j] = 
-      clitk::CropImageRemoveGreaterThan<MaskSliceType>(vert_slices[j], 1, sp_MostAntVertebralBody[1], false, GetBackgroundValue());
-    vert_slices[j] = 
-      clitk::ResizeImageLike<MaskSliceType>(vert_slices[j], aorta_slices[i], GetBackgroundValue());
-    //    writeImage<MaskSliceType>(vert_slices[i], "vert-slice-"+toString(i)+".mhd");
+    sp_MostLeftVertebralBody = 
+      clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false, 
+                                                         sp_MostLeftVertebralBody, GetBackgroundValue(), 30);
+    // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
+    // DD(p);
 
-    // Find first point not in mediastinum
-    clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 0, false, sp_MostLeftVertebralBody);
-    sp_MostLeftVertebralBody = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, false, sp_MostLeftVertebralBody, GetBackgroundValue(), 30);
     sp_MostLeftVertebralBody[0] += 2; // 2mm margin
-    clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[j], GetBackgroundValue(), 0, true, sp_MostRightVertebralBody);
-    sp_MostRightVertebralBody = clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, true, sp_MostRightVertebralBody, GetBackgroundValue(),30);
-    sp_MostRightVertebralBody[0] -= 2; // 2 mm margin
+    // clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
+    // DD(p);
 
     // Convert 2D points into 3D
-    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostRightVertebralBody, VertebralBody, i, p);
-    p_MostRightVertebralBody.push_back(p);
     clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftVertebralBody, VertebralBody, i, p);
     p_MostLeftVertebralBody.push_back(p);
 
+    /* -------------------------------------------------------------------------------------
+       Find first point not in mediastinum at RIGHT. Not used yet.
+    clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(vert_slices[i], GetBackgroundValue(), 
+                                                            0, true, sp_MostRightVertebralBody);
+    sp_MostRightVertebralBody = 
+      clitk::FindExtremaPointInAGivenLine<MaskSliceType>(mediast_slices[i], 0, true, 
+                                                         sp_MostRightVertebralBody, GetBackgroundValue(),30);
+    sp_MostRightVertebralBody[0] -= 2; // 2 mm margin
+    
+    // Convert 2D points into 3D
+    clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostRightVertebralBody, VertebralBody, i, p);
+    p_MostRightVertebralBody.push_back(p);
+    */
+
+
     /* -------------------------------------------------------------------------------------
        Find most Left point in Esophagus
      */
-    found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftEsophagus);
+    bool found = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, false, sp_MostLeftEsophagus);
     if (!found) { // No more Esophagus, I remove the previous point
-
-      // if (p_MostLeftEsophagus.size() < 1)  {
-      p_MostLeftVertebralBody.pop_back();      
-      // }
-      // else {
-      //   // Consider the previous point
-      //   p = p_MostLeftEsophagus.back();
-      //   p_MostLeftEsophagus.push_back(p);
-      //   sp_MostLeftEsophagus = sp_temp; // Retrieve previous 2D position
-      //   found = true;
-      // }
+      //DD("no eso pop back");
+      p_MostLeftVertebralBody.pop_back();
     }
     else {
       clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_MostLeftEsophagus, EsophagusForSlice, i, p);
       p_MostLeftEsophagus.push_back(p);
-      // sp_temp = sp_MostLeftEsophagus; // Store previous 2D position
     }
       
     /* -------------------------------------------------------------------------------------
@@ -1101,7 +438,7 @@ ExtractStation_8_LR_Limits()
   } // End of slice loop
   
   clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftVertebralBody, "S8-MostLeft-VB-points.txt");
-  clitk::WriteListOfLandmarks<MaskImageType>(p_MostRightVertebralBody, "S8-MostRight-VB-points.txt");
+  //  clitk::WriteListOfLandmarks<MaskImageType>(p_MostRightVertebralBody, "S8-MostRight-VB-points.txt");
   clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftAorta, "S8-MostLeft-Aorta-points.txt");
   clitk::WriteListOfLandmarks<MaskImageType>(p_MostLeftEsophagus, "S8-MostLeft-eso-points.txt");
 
@@ -1112,7 +449,6 @@ ExtractStation_8_LR_Limits()
   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
                                                                     p_MostLeftAorta, p_MostLeftEsophagus,
                                                                     GetBackgroundValue(), 0, -10);
-
   // END
   StopCurrentStep<MaskImageType>(m_Working_Support);
   m_ListOfStations["8"] = m_Working_Support;
@@ -1127,12 +463,10 @@ void
 clitk::ExtractLymphStationsFilter<ImageType>::
 ExtractStation_8_Remove_Structures()
 {
-
   //--------------------------------------------------------------------
-  StartNewStep("[Station8] remove some structures");
-
   Remove_Structures("8", "Aorta");
   Remove_Structures("8", "Esophagus");
+  Remove_Structures("8", "VertebralBody");  
 
   // END
   StopCurrentStep<MaskImageType>(m_Working_Support);
@@ -1142,143 +476,6 @@ ExtractStation_8_Remove_Structures()
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class ImageType>
-typename clitk::ExtractLymphStationsFilter<ImageType>::MaskImagePointer
-clitk::ExtractLymphStationsFilter<ImageType>::
-EnlargeEsophagusDilatationRadiusInferiorly(MaskImagePointer & Esophagus)
-{
-  // Check if Esophagus is delineated at least until Diaphragm. Now,
-  // because we use AutoCrop, Origin[2] gives this max inferior
-  // position.
-
-  DD("BUGGY DONT USE");
-  exit(0);
-
-  if (Esophagus->GetOrigin()[2] > m_DiaphragmInferiorLimit) {
-    // crop first slice without mask
-    MaskImagePointType pt;
-    clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Esophagus, GetBackgroundValue(), 2, true, pt);
-    DD(pt);
-    Esophagus = 
-      clitk::CropImageRemoveLowerThan<MaskImageType>(Esophagus, 2, 
-                                           pt[2], 
-                                           false, // AutoCrop
-                                           GetBackgroundValue());
-    writeImage<MaskImageType>(Esophagus, "crop-eso.mhd");
-
-    std::cout << "Warning Esophagus is not delineated until Diaphragm. I mirror-pad it." 
-              << std::endl;
-    double extraSize = Esophagus->GetOrigin()[2]-m_DiaphragmInferiorLimit; 
-    
-    // Pad with few more slices
-    typedef itk::MirrorPadImageFilter<MaskImageType, MaskImageType> PadFilterType;
-    typename PadFilterType::Pointer padFilter = PadFilterType::New();
-    padFilter->SetInput(Esophagus);
-    MaskImageSizeType b;
-    b[0] = 0; b[1] = 0; b[2] = (uint)ceil(extraSize/Esophagus->GetSpacing()[2])+1;
-    padFilter->SetPadLowerBound(b);
-    padFilter->Update();
-    Esophagus = padFilter->GetOutput();
-  }
-  return Esophagus;
-}
-//--------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------
-template <class ImageType>
-void 
-clitk::ExtractLymphStationsFilter<ImageType>::
-ExtractStation_8_LR_Limits_old() 
-{
-  /*
-    Station 8: paraeosphageal nodes
-
-    Laterally, it is within the pleural envelope and again abuts the
-    descending aorta on the left. Reasonably, the delineation of
-    Station 8 is limited to the soft tissue surrounding the esophagus
-    (Fig.  3C–H). 
-  */
-
-  StartNewStep("[Station8] Right limits (around esophagus)");
-  // Get Esophagus
-  MaskImagePointer Esophagus = GetAFDB()->template GetImage<MaskImageType>("Esophagus");
-
-  // Autocrop to get first slice with starting Esophagus
-  Esophagus = clitk::AutoCrop<MaskImageType>(Esophagus, GetBackgroundValue()); 
-
-  // Dilate 
-  // LR dilatation -> large to keep point inside
-  // AP dilatation -> few mm 
-  // SI dilatation -> enough to cover Diaphragm (old=GOjunctionZ)
-  MaskImagePointType radiusInMM = GetEsophagusDiltationForRight();
-  Esophagus = EnlargeEsophagusDilatationRadiusInferiorly(Esophagus);
-  Esophagus = clitk::Dilate<MaskImageType>(Esophagus, 
-                                           radiusInMM, 
-                                           GetBackgroundValue(), 
-                                           GetForegroundValue(), true);
-  writeImage<MaskImageType>(Esophagus, "dilateEso2.mhd");
-
-  writeImage<MaskImageType>(m_Working_Support, "before-relpos2.mhd");
-
-  // Remove Right (Left on the screen) part according to this
-  // dilatated esophagus
-  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> RelPosFilterType;
-  typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
-  relPosFilter->VerboseStepFlagOff();
-  relPosFilter->WriteStepFlagOff();
-  relPosFilter->SetInput(m_Working_Support);
-  relPosFilter->SetInputObject(Esophagus);
-  relPosFilter->AddOrientationTypeString("NotLeftTo");
-  //  relPosFilter->InverseOrientationFlagOn(); // Not Left to
-  relPosFilter->SetDirection(2); // Z axis
-  relPosFilter->UniqueConnectedComponentBySliceOff(); // important
-  relPosFilter->SetIntermediateSpacing(4);
-  relPosFilter->IntermediateSpacingFlagOn();
-  relPosFilter->SetFuzzyThreshold(0.9); // remove few part only
-  relPosFilter->RemoveObjectFlagOff();
-  relPosFilter->Update();
-  m_Working_Support = relPosFilter->GetOutput();
-
-  // Get a single 3D CCL
-  m_Working_Support = Labelize<MaskImageType>(m_Working_Support, 0, false, 10);
-  m_Working_Support = KeepLabels<MaskImageType>(m_Working_Support, 
-                                                GetBackgroundValue(), 
-                                                GetForegroundValue(), 1, 1, true);
-
-
-  /*
-  // Re-Add post to Esophagus -> sometimes previous relpos remove some
-  // correct part below esophagus.
-  MaskImagePointer Esophagus = GetAFDB()->template GetImage<MaskImageType>("Esophagus");
-  EnlargeEsophagusDilatationRadiusInferiorly(Esophagus);
-  writeImage<MaskImageType>(Esophagus, "e-again.mhd");
-  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> RelPosFilterType;
-  typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
-  relPosFilter->VerboseStepOff();
-  relPosFilter->WriteStepOff();
-  relPosFilter->SetInput(m_Working_Support);
-  relPosFilter->SetInputObject(Esophagus);
-  relPosFilter->SetOrientationTypeString("P");
-  relPosFilter->InverseOrientationFlagOff(); 
-  relPosFilter->SetDirection(2); // Z axis
-  relPosFilter->UniqueConnectedComponentBySliceOff(); // important
-  relPosFilter->SetIntermediateSpacing(4);
-  relPosFilter->IntermediateSpacingFlagOn();
-  relPosFilter->CombineWithOrFlagOn();
-  relPosFilter->SetFuzzyThreshold(0.9); // remove few part only
-  relPosFilter->RemoveObjectFlagOff();
-  relPosFilter->Update();
-  m_Working_Support = relPosFilter->GetOutput();
-  */
-
-  StopCurrentStep<MaskImageType>(m_Working_Support);
-  m_ListOfStations["8"] = m_Working_Support;
-}
-//--------------------------------------------------------------------
-
-
 //--------------------------------------------------------------------
 template <class TImageType>
 void 
diff --git a/segmentation/clitkExtractLymphStation_Supports.txx b/segmentation/clitkExtractLymphStation_Supports.txx
new file mode 100644 (file)
index 0000000..903948d
--- /dev/null
@@ -0,0 +1,74 @@
+
+#include <itkBinaryDilateImageFilter.h>
+#include <itkMirrorPadImageFilter.h>
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void 
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStationSupports()
+{
+  DD("ExtractStationSupports");
+
+  // Get initial Mediastinum
+  m_Working_Support = m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
+
+  // Superior limits: CricoidCartilag
+  // Inferior limits: lung
+  //  (the Mediastinum support already stop at this limit)
+
+  // Consider above Carina
+  m_CarinaZ = FindCarinaSlicePosition();
+  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());
+
+  // Consider only Superior to Carina
+  m_Working_Support = m_Support_Superior_to_Carina;
+
+  // Step : S1RL
+  StartNewStep("[Support] sup-inf S1RL");
+  /*
+    Lower border: clavicles bilaterally and, in the midline, the upper
+    border of the manubrium, 1R designates right-sided nodes, 1L,
+    left-sided nodes in this region
+    
+    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
+  */
+
+
+
+
+
+
+
+
+
+  // //  LeftRight cut along trachea
+  // MaskImagePointer Trachea = GetAFDB()->GetImage("Trachea");
+  // // build a ant-post line for each slice
+
+  // MaskImagePointer m_Support_SupRight = 
+  //   clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, 
+  //                                                  m_CarinaZ, true, GetBackgroundValue());
+
+
+
+
+
+  // Store image filenames into AFDB 
+  m_ListOfSupports["S1R"] = m_Working_Support;
+  writeImage<MaskImageType>(m_ListOfSupports["S1R"], "seg/Support_S1R.mhd");
+  GetAFDB()->SetImageFilename("Support_S1R", "seg/Support_S1R.mhd");
+  WriteAFDB();
+}
+//--------------------------------------------------------------------
+
+
index d789824756ce33ad9d6fb37e9adf725d44b6a0db..96ac9940799a7ed377e47cdced452bca33e571b4 100644 (file)
@@ -20,28 +20,27 @@ option "output"        o    "Output lungs mask filename"      string        no
 option "station"       -       "Force to compute station even if already exist in the DB"      string  no multiple
 
 section "Options for Station 8"
-option "maxAntSpine"                 - "Distance max to anterior part of the spine in mm"  double no default="10"
-option "esophagusDilatationForAnt"   - "Dilatation of esophagus, in mm, for 'anterior' limits (default=15,2,1)" double no multiple
-option "esophagusDilatationForRight" - "Dilatation of esophagus, in mm, for 'right' limits (default=5,10,1)" double no multiple
-option "tS8_Esophagus"               - "Threshold for 'Post' to dilated Esophagus" double default="0.5" no 
-option "injectedThresholdForS8"      - "Threshold injected areas in the ct" double default="150" no 
+option "S8_esophagusDilatationForAnt"   - "Dilatation of esophagus, in mm, for 'anterior' limits (default=15,2,1)" double no multiple
+option "S8_esophagusDilatationForRight" - "Dilatation of esophagus, in mm, for 'right' limits (default=5,10,1)" double no multiple
+option "S8_ft_Esophagus"                - "Fuzzy Threshold for 'Post' to dilated Esophagus" double default="0.5" no 
 
 section "Options for Station 7"
-option "tS7_Bronchi"                    - "Threshold for Left/Right bronchi" double default="0.1" no 
-option "tS7_LeftSuperiorPulmonaryVein"  - "Threshold for LeftSuperiorPulmonaryVein" double default="0.3" no 
-option "tS7_RightSuperiorPulmonaryVein" - "Threshold for RightSuperiorPulmonaryVein" double default="0.2" no 
-option "tS7_RightPulmonaryArtery"       - "Threshold for RightPulmonaryArtery" double default="0.3" no 
-option "tS7_LeftPulmonaryArtery"        - "Threshold for LeftPulmonaryArtery (NOT USEFUL YET)" double default="0.5" no 
-option "tS7_SVC"                        - "Threshold for SVC" double default="0.2" no 
+option "S7_ft_Bronchi"                    - "Fuzzy Threshold for Left/Right bronchi" double default="0.1" no 
+option "S7_ft_LeftSuperiorPulmonaryVein"  - "Fuzzy Threshold for LeftSuperiorPulmonaryVein" double default="0.3" no 
+option "S7_ft_RightSuperiorPulmonaryVein" - "Fuzzy Threshold for RightSuperiorPulmonaryVein" double default="0.2" no 
+option "S7_ft_RightPulmonaryArtery"       - "Fuzzy Threshold for RightPulmonaryArtery" double default="0.3" no 
+option "S7_ft_LeftPulmonaryArtery"        - "Fuzzy Threshold for LeftPulmonaryArtery (NOT USEFUL YET)" double default="0.5" no 
+option "S7_ft_SVC"                        - "Fuzzy Threshold for SVC" double default="0.2" no 
+option "S7_UseMostInferiorPartOnly"    - "Inferior separation with S8."  flag off
 
 section "Options for Station 3A"
-option "tS3A_Sternum"          - "Threshold for Post to Sternum" double default="0.5" no 
-option "tS3A_SubclavianArtery" - "Threshold for Ant to SubclavianArtery" double default="0.2" no 
+option "S3A_ft_Sternum"          - "Fuzzy Threshold for Post to Sternum" double default="0.5" no 
+option "S3A_ft_SubclavianArtery" - "Fuzzy Threshold for Ant to SubclavianArtery" double default="0.2" no 
 
 section "Options for Station 2RL"
-option "tS2RL_CommonCarotidArtery"   - "Threshold for NotAntTo to CommonCarotidArtery"   double default="0.7" no 
-option "tS2RL_BrachioCephalicTrunk"  - "Threshold for NotAntTo to BrachioCephalicTrunk"  double default="0.7" no 
-option "tS2RL_BrachioCephalicVein"   - "Threshold for NotAntTo to BrachioCephalicVein"   double default="0.3" no 
-option "tS2RL_Aorta"                 - "Threshold for RightTo  to Aorta"                 double default="0.7" no 
-option "tS2RL_SubclavianArteryRight" - "Threshold for NotLeft  to SubclavianArteryRight" double default="0.5" no 
-option "tS2RL_SubclavianArteryLeft"  - "Threshold for NotRight to SubclavianArteryLeft"  double default="0.8" no 
+option "S2RL_ft_CommonCarotidArtery"   - "Threshold for NotAntTo to CommonCarotidArtery"   double default="0.7" no 
+option "S2RL_ft_BrachioCephalicTrunk"  - "Threshold for NotAntTo to BrachioCephalicTrunk"  double default="0.7" no 
+option "S2RL_ft_BrachioCephalicVein"   - "Threshold for NotAntTo to BrachioCephalicVein"   double default="0.3" no 
+option "S2RL_ft_Aorta"                 - "Threshold for RightTo  to Aorta"                 double default="0.7" no 
+option "S2RL_ft_SubclavianArteryRight" - "Threshold for NotLeft  to SubclavianArteryRight" double default="0.5" no 
+option "S2RL_ft_SubclavianArteryLeft"  - "Threshold for NotRight to SubclavianArteryLeft"  double default="0.8" no 
index 8d160b1aad557945d3b13be3f54b7435b991f0b0..dd99c5fd4f8eced90f38eef544e1929417ddd802 100644 (file)
@@ -76,6 +76,9 @@ namespace clitk {
     typedef itk::Image<MaskImagePixelType, 2>    MaskSliceType;
     typedef typename MaskSliceType::Pointer      MaskSlicePointer;
     typedef typename MaskSliceType::PointType    MaskSlicePointType;
+    typedef typename MaskSliceType::RegionType   MaskSliceRegionType; 
+    typedef typename MaskSliceType::SizeType     MaskSliceSizeType; 
+    typedef typename MaskSliceType::IndexType    MaskSliceIndexType; 
 
     /** ImageDimension constants */
     itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
@@ -87,8 +90,8 @@ namespace clitk {
     itkSetMacro(ForegroundValue, MaskImagePixelType);
 
     // Station 8
-    itkSetMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
-    itkGetConstMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
+    // itkSetMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
+    //itkGetConstMacro(DistanceMaxToAnteriorPartOfTheSpine, double);
     itkSetMacro(EsophagusDiltationForAnt, MaskImagePointType);
     itkGetConstMacro(EsophagusDiltationForAnt, MaskImagePointType);
     itkSetMacro(EsophagusDiltationForRight, MaskImagePointType);
@@ -97,6 +100,9 @@ namespace clitk {
     itkGetConstMacro(InjectedThresholdForS8, double);
 
     // Station 7
+    itkGetConstMacro(S7_UseMostInferiorPartOnlyFlag, bool);
+    itkSetMacro(S7_UseMostInferiorPartOnlyFlag, bool);
+    itkBooleanMacro(S7_UseMostInferiorPartOnlyFlag);
 
     // All stations
     bool GetComputeStation(std::string s);
@@ -116,6 +122,7 @@ namespace clitk {
     MaskImagePointer   m_Mediastinum;
     MaskImagePointer   m_Working_Support;
     std::map<std::string, MaskImagePointer> m_ListOfStations;
+    std::map<std::string, MaskImagePointer> m_ListOfSupports;
     MaskImagePixelType m_BackgroundValue;
     MaskImagePixelType m_ForegroundValue;
     std::map<std::string, bool> m_ComputeStationMap;
@@ -123,12 +130,20 @@ namespace clitk {
     bool CheckForStation(std::string station);
     void Remove_Structures(std::string station, std::string s);
 
+    // Functions common to several stations
+    void FindLineForS7S8Separation(MaskImagePointType & A, MaskImagePointType & B);
+    double FindCarinaSlicePosition();
+    void FindLeftAndRightBronchi();
+
     // Global parameters
     typedef std::map<std::string, double> FuzzyThresholdByStructureType;
     std::map<std::string, FuzzyThresholdByStructureType> m_FuzzyThreshold;    
 
+    // Station's supports
+    void ExtractStationSupports();
+
     // Station 8
-    double m_DistanceMaxToAnteriorPartOfTheSpine;
+    // double m_DistanceMaxToAnteriorPartOfTheSpine;
     double m_DiaphragmInferiorLimit;
     double m_CarinaZ;
     double m_OriginOfRightMiddleLobeBronchusZ;
@@ -136,22 +151,16 @@ namespace clitk {
     MaskImagePointer m_Esophagus;
     MaskImagePointType m_EsophagusDiltationForAnt;
     MaskImagePointType m_EsophagusDiltationForRight;
-    MaskImagePointer EnlargeEsophagusDilatationRadiusInferiorly(MaskImagePointer & eso);
+
     void ExtractStation_8();
     void ExtractStation_8_SetDefaultValues();
     void ExtractStation_8_SI_Limits();
-    void ExtractStation_8_Post_Limits();
-    void ExtractStation_8_Ant_Sup_Limits();
-    void ExtractStation_8_Ant_Inf_Limits();
-    void ExtractStation_8_Ant_Injected_Limits();
-    void ExtractStation_8_LR_1_Limits();
-    void ExtractStation_8_LR_2_Limits();
+    void ExtractStation_8_Ant_Limits();
+    void ExtractStation_8_Left_Sup_Limits();
+    void ExtractStation_8_Left_Inf_Limits();
     void ExtractStation_8_Single_CCL_Limits();
-    void ExtractStation_8_LR_Limits();
     void ExtractStation_8_Remove_Structures();
-    void ExtractStation_8_LR_Limits_old();
-    void ExtractStation_8_LR_Limits_old2();
-    
+
     // Station 3P
     void ExtractStation_3P();
     void ExtractStation_3P_SetDefaultValues();
@@ -186,9 +195,13 @@ namespace clitk {
     void ExtractStation_7();
     void ExtractStation_7_SetDefaultValues();
     void ExtractStation_7_SI_Limits();
-    void ExtractStation_7_RL_Limits();
+    void ExtractStation_7_RL_Interior_Limits();
+
+
+    void ExtractStation_7_RL_Limits_OLD();
     void ExtractStation_7_Posterior_Limits();   
     void ExtractStation_7_Remove_Structures();
+    bool m_S7_UseMostInferiorPartOnlyFlag;
     MaskImagePointer m_Working_Trachea;
     MaskImagePointer m_LeftBronchus;
     MaskImagePointer m_RightBronchus;
@@ -226,6 +239,7 @@ namespace clitk {
 
 #ifndef ITK_MANUAL_INSTANTIATION
 #include "clitkExtractLymphStationsFilter.txx"
+#include "clitkExtractLymphStation_Supports.txx"
 #include "clitkExtractLymphStation_8.txx"
 #include "clitkExtractLymphStation_3P.txx"
 #include "clitkExtractLymphStation_2RL.txx"
index 1823e998c40cf228444cb29439c5adc760d5cd0e..58f2991d348426b184c92a37c6c7baf93848399a 100644 (file)
@@ -72,6 +72,12 @@ GenerateOutputInformation() {
   m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
   m_Mediastinum = GetAFDB()->template GetImage <MaskImageType>("Mediastinum");
 
+  // Global supports for stations
+  StartNewStep("Supports for stations");
+  StartSubStep(); 
+  ExtractStationSupports();
+  StopSubStep();  
+
   // Extract Station8
   StartNewStep("Station 8");
   StartSubStep(); 
@@ -85,10 +91,12 @@ GenerateOutputInformation() {
   StopSubStep();
 
   // Extract Station2RL
-  StartNewStep("Station 2RL");
-  StartSubStep(); 
-  ExtractStation_2RL();
-  StopSubStep();
+  /*
+    StartNewStep("Station 2RL");
+    StartSubStep(); 
+    ExtractStation_2RL();
+    StopSubStep();
+  */
 
   // Extract Station3A
   StartNewStep("Station 3A");
@@ -189,32 +197,6 @@ AddComputeStation(std::string station)
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_8() 
-{
-  if (CheckForStation("8")) {
-    ExtractStation_8_SI_Limits();
-    ExtractStation_8_Post_Limits();
-    ExtractStation_8_Ant_Sup_Limits();
-    ExtractStation_8_Ant_Inf_Limits();
-    ExtractStation_8_LR_1_Limits();
-    ExtractStation_8_LR_2_Limits();
-    ExtractStation_8_LR_Limits();
-    ExtractStation_8_Ant_Injected_Limits();
-    ExtractStation_8_Single_CCL_Limits();
-    ExtractStation_8_Remove_Structures();
-    // Store image filenames into AFDB 
-    writeImage<MaskImageType>(m_ListOfStations["8"], "seg/Station8.mhd");
-    GetAFDB()->SetImageFilename("Station8", "seg/Station8.mhd");  
-    WriteAFDB();
-  }
-}
-//--------------------------------------------------------------------
-
-
 //--------------------------------------------------------------------
 template <class TImageType>
 void 
@@ -239,26 +221,6 @@ ExtractStation_3P()
 //--------------------------------------------------------------------
 
 
-//--------------------------------------------------------------------
-template <class TImageType>
-void 
-clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_7() {
-  if (CheckForStation("7")) {
-  ExtractStation_7_SI_Limits();
-  ExtractStation_7_RL_Limits();
-  ExtractStation_7_Posterior_Limits();
-  //  ExtractStation_8_Single_CCL_Limits(); // Yes the same than 8
-  ExtractStation_7_Remove_Structures();
-  // Store image filenames into AFDB 
-  writeImage<MaskImageType>(m_ListOfStations["7"], "seg/Station7.mhd");
-  GetAFDB()->SetImageFilename("Station7", "seg/Station7.mhd");  
-  WriteAFDB();
-  }
-}
-//--------------------------------------------------------------------
-
-
 //--------------------------------------------------------------------
 template <class TImageType>
 void 
@@ -371,6 +333,171 @@ GetFuzzyThreshold(std::string station, std::string tag)
 //--------------------------------------------------------------------
 
 
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+FindLineForS7S8Separation(MaskImagePointType & A, MaskImagePointType & B)
+{
+  // Create line from A to B with
+  // A = upper border of LLL at left
+  // B = lower border of bronchus intermedius (BI) or RightMiddleLobeBronchus
+  
+  try {
+    GetAFDB()->GetPoint3D("LineForS7S8Separation_Begin", A); 
+    GetAFDB()->GetPoint3D("LineForS7S8Separation_End", B);
+  }
+  catch(clitk::ExceptionObject & o) {
+    
+    DD("FindLineForS7S8Separation");
+    // Load LeftLowerLobeBronchus and get centroid point
+    MaskImagePointer LeftLowerLobeBronchus = 
+      GetAFDB()->template GetImage <MaskImageType>("LeftLowerLobeBronchus");
+    std::vector<MaskImagePointType> c;
+    clitk::ComputeCentroids<MaskImageType>(LeftLowerLobeBronchus, GetBackgroundValue(), c);
+    A = c[1];
+    
+    // Load RightMiddleLobeBronchus and get superior point (not centroid here)
+    MaskImagePointer RightMiddleLobeBronchus = 
+      GetAFDB()->template GetImage <MaskImageType>("RightMiddleLobeBronchus");
+    bool b = FindExtremaPointInAGivenDirection<MaskImageType>(RightMiddleLobeBronchus, 
+                                                              GetBackgroundValue(), 
+                                                              2, false, B);
+    if (!b) {
+      clitkExceptionMacro("Error while searching most superior point in RightMiddleLobeBronchus. Abort");
+    }
+    
+    // Insert into the DB
+    GetAFDB()->SetPoint3D("LineForS7S8Separation_Begin", A);
+    GetAFDB()->SetPoint3D("LineForS7S8Separation_End", B);
+  }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+double 
+clitk::ExtractLymphStationsFilter<TImageType>::
+FindCarinaSlicePosition()
+{
+  double z;
+  try {
+    z = GetAFDB()->GetDouble("CarinaZ");
+  }
+  catch(clitk::ExceptionObject e) {
+    DD("FindCarinaSlicePosition");
+    // Get Carina
+    MaskImagePointer Carina = GetAFDB()->template GetImage<MaskImageType>("Carina");
+    
+    // Get Centroid and Z value
+    std::vector<MaskImagePointType> centroids;
+    clitk::ComputeCentroids<MaskImageType>(Carina, GetBackgroundValue(), centroids);
 
+    // We dont need Carina structure from now
+    Carina->Delete();
+    
+    // Put inside the AFDB
+    GetAFDB()->SetPoint3D("CarinaPoint", centroids[1]);
+    GetAFDB()->SetDouble("CarinaZ", centroids[1][2]);
+    WriteAFDB();
+    z = centroids[1][2];
+  }
+  return z;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+FindLeftAndRightBronchi()
+{
+  try {
+    m_RightBronchus = GetAFDB()->template GetImage <MaskImageType>("RightBronchus");
+    m_LeftBronchus = GetAFDB()->template GetImage <MaskImageType>("LeftBronchus");
+  }
+  catch(clitk::ExceptionObject & o) {
+
+    DD("FindLeftAndRightBronchi");
+    // The goal is to separate the trachea inferiorly to the carina into
+    // a Left and Right bronchus.
+  
+    // Get the trachea
+    MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
+
+    // Get the Carina position
+    m_CarinaZ = FindCarinaSlicePosition();
+
+    // Consider only inferiorly to the Carina
+    MaskImagePointer m_Working_Trachea = 
+      clitk::CropImageRemoveGreaterThan<MaskImageType>(Trachea, 2, m_CarinaZ, true, // AutoCrop
+                                                       GetBackgroundValue());
+
+    // Labelize the trachea
+    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). We thus first check that the
+    // upper slice is composed of at least two labels
+    MaskImagePointer RightBronchus;
+    MaskImagePointer LeftBronchus;
+    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()) {    
+        if (iter.Get() > maxLabel) maxLabel = iter.Get();
+        --iter;
+      }
+      iter.PreviousLine();
+    }
+    if (maxLabel < 2) {
+      clitkExceptionMacro("First slice from Carina does not seems to seperate the two main bronchus. Abort");
+    }
+
+    // Compute 3D centroids of both parts to identify the left from the
+    // right bronchus
+    std::vector<ImagePointType> c;
+    clitk::ComputeCentroids<MaskImageType>(m_Working_Trachea, GetBackgroundValue(), c);
+    ImagePointType C1 = c[1];
+    ImagePointType C2 = c[2];
+
+    ImagePixelType rightLabel;
+    ImagePixelType leftLabel;  
+    if (C1[0] < C2[0]) { rightLabel = 1; leftLabel = 2; }
+    else { rightLabel = 2; leftLabel = 1; }
+
+    // Select LeftLabel (set one label to Backgroundvalue)
+    RightBronchus = 
+      clitk::Binarize<MaskImageType>(m_Working_Trachea, rightLabel, rightLabel, 
+                                     GetBackgroundValue(), GetForegroundValue());
+    /*
+      SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea, 
+      leftLabel, GetBackgroundValue(), false);
+    */
+    LeftBronchus = clitk::Binarize<MaskImageType>(m_Working_Trachea, leftLabel, leftLabel, 
+                                                  GetBackgroundValue(), GetForegroundValue());
+    /*
+      SetBackground<MaskImageType, MaskImageType>(m_Working_Trachea, m_Working_Trachea, 
+      rightLabel, GetBackgroundValue(), false);
+    */
+
+    // Crop images
+    RightBronchus = clitk::AutoCrop<MaskImageType>(RightBronchus, GetBackgroundValue()); 
+    LeftBronchus = clitk::AutoCrop<MaskImageType>(LeftBronchus, GetBackgroundValue()); 
+
+    // Insert int AFDB if need after 
+    GetAFDB()->template SetImage <MaskImageType>("RightBronchus", "seg/rightBronchus.mhd", 
+                                                 RightBronchus, true);
+    GetAFDB()->template SetImage <MaskImageType>("LeftBronchus", "seg/leftBronchus.mhd", 
+                                                 LeftBronchus, true);
+  }
+}
+//--------------------------------------------------------------------
 
 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX
index ffa6c3c87e6a668373182b87b629a3a47040fd75..8b6167ec9090ca4fc1d17dcad7f33dd0b4a21767 100644 (file)
@@ -70,9 +70,9 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
   f->SetAFDBFilename(mArgsInfo.afdb_arg);  
 
   // Station 8
-  f->SetDistanceMaxToAnteriorPartOfTheSpine(mArgsInfo.maxAntSpine_arg);
-  f->SetFuzzyThreshold("8", "Esophagus", mArgsInfo.tS8_Esophagus_arg);
-  f->SetInjectedThresholdForS8(mArgsInfo.injectedThresholdForS8_arg);
+  //f->SetDistanceMaxToAnteriorPartOfTheSpine(mArgsInfo.S8_maxAntSpine_arg);
+  f->SetFuzzyThreshold("8", "Esophagus", mArgsInfo.S8_ft_Esophagus_arg);
+  //  f->SetInjectedThresholdForS8(mArgsInfo.tS8_injectedThreshold_arg);
 
   // Check multiple options for radius dilatation
   /*
@@ -83,27 +83,27 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
    */
   typename FilterType::MaskImagePointType p;
   p[0] = 7; p[1] = 5; p[2] = 0; // default value
-  if (mArgsInfo.esophagusDilatationForAnt_given == 3) {
+  if (mArgsInfo.S8_esophagusDilatationForAnt_given == 3) {
     for(uint i=0; i<3; i++)
-      p[i] = mArgsInfo.esophagusDilatationForAnt_arg[i];
+      p[i] = mArgsInfo.S8_esophagusDilatationForAnt_arg[i];
   }
   else {
-    if (mArgsInfo.esophagusDilatationForAnt_given == 1) {
+    if (mArgsInfo.S8_esophagusDilatationForAnt_given == 1) {
       for(uint i=0; i<3; i++)
-        p[i] = mArgsInfo.esophagusDilatationForAnt_arg[0];
+        p[i] = mArgsInfo.S8_esophagusDilatationForAnt_arg[0];
     }
   }
   f->SetEsophagusDiltationForAnt(p);
   
   p[0] = 5; p[1] = 10; p[2] = 1; // default value
-  if (mArgsInfo.esophagusDilatationForRight_given == 3) {
+  if (mArgsInfo.S8_esophagusDilatationForRight_given == 3) {
     for(uint i=0; i<3; i++)
-      p[i] = mArgsInfo.esophagusDilatationForRight_arg[i];
+      p[i] = mArgsInfo.S8_esophagusDilatationForRight_arg[i];
   }
   else {
-    if (mArgsInfo.esophagusDilatationForRight_given == 1) {
+    if (mArgsInfo.S8_esophagusDilatationForRight_given == 1) {
       for(uint i=0; i<3; i++)
-        p[i] = mArgsInfo.esophagusDilatationForRight_arg[0];
+        p[i] = mArgsInfo.S8_esophagusDilatationForRight_arg[0];
     }
   }
   f->SetEsophagusDiltationForRight(p);  
@@ -112,24 +112,25 @@ SetOptionsFromArgsInfoToFilter(FilterType * f)
     f->AddComputeStation(mArgsInfo.station_arg[i]);
 
   // Station 7
-  f->SetFuzzyThreshold("7", "Bronchi", mArgsInfo.tS7_Bronchi_arg);
-  f->SetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein", mArgsInfo.tS7_LeftSuperiorPulmonaryVein_arg);
-  f->SetFuzzyThreshold("7", "RightSuperiorPulmonaryVein", mArgsInfo.tS7_RightSuperiorPulmonaryVein_arg);
-  f->SetFuzzyThreshold("7", "RightPulmonaryArtery", mArgsInfo.tS7_RightPulmonaryArtery_arg);
-  f->SetFuzzyThreshold("7", "LeftPulmonaryArtery", mArgsInfo.tS7_LeftPulmonaryArtery_arg);
-  f->SetFuzzyThreshold("7", "SVC", mArgsInfo.tS7_SVC_arg);
+  f->SetFuzzyThreshold("7", "Bronchi", mArgsInfo.S7_ft_Bronchi_arg);
+  f->SetFuzzyThreshold("7", "LeftSuperiorPulmonaryVein", mArgsInfo.S7_ft_LeftSuperiorPulmonaryVein_arg);
+  f->SetFuzzyThreshold("7", "RightSuperiorPulmonaryVein", mArgsInfo.S7_ft_RightSuperiorPulmonaryVein_arg);
+  f->SetFuzzyThreshold("7", "RightPulmonaryArtery", mArgsInfo.S7_ft_RightPulmonaryArtery_arg);
+  f->SetFuzzyThreshold("7", "LeftPulmonaryArtery", mArgsInfo.S7_ft_LeftPulmonaryArtery_arg);
+  f->SetFuzzyThreshold("7", "SVC", mArgsInfo.S7_ft_SVC_arg);
+  f->SetS7_UseMostInferiorPartOnlyFlag(mArgsInfo.S7_UseMostInferiorPartOnly_flag);
 
   // Station 3A
-  f->SetFuzzyThreshold("3A", "Sternum", mArgsInfo.tS3A_Sternum_arg);
-  f->SetFuzzyThreshold("3A", "SubclavianArtery", mArgsInfo.tS3A_SubclavianArtery_arg);
+  f->SetFuzzyThreshold("3A", "Sternum", mArgsInfo.S3A_ft_Sternum_arg);
+  f->SetFuzzyThreshold("3A", "SubclavianArtery", mArgsInfo.S3A_ft_SubclavianArtery_arg);
   
   // Station 2RL
-  f->SetFuzzyThreshold("2RL", "CommonCarotidArtery", mArgsInfo.tS2RL_CommonCarotidArtery_arg);
-  f->SetFuzzyThreshold("2RL", "BrachioCephalicTrunk", mArgsInfo.tS2RL_BrachioCephalicTrunk_arg);
-  f->SetFuzzyThreshold("2RL", "BrachioCephalicVein", mArgsInfo.tS2RL_BrachioCephalicVein_arg);
-  f->SetFuzzyThreshold("2RL", "Aorta", mArgsInfo.tS2RL_Aorta_arg);
-  f->SetFuzzyThreshold("2RL", "SubclavianArteryLeft", mArgsInfo.tS2RL_SubclavianArteryLeft_arg);
-  f->SetFuzzyThreshold("2RL", "SubclavianArteryRight", mArgsInfo.tS2RL_SubclavianArteryRight_arg);
+  f->SetFuzzyThreshold("2RL", "CommonCarotidArtery", mArgsInfo.S2RL_ft_CommonCarotidArtery_arg);
+  f->SetFuzzyThreshold("2RL", "BrachioCephalicTrunk", mArgsInfo.S2RL_ft_BrachioCephalicTrunk_arg);
+  f->SetFuzzyThreshold("2RL", "BrachioCephalicVein", mArgsInfo.S2RL_ft_BrachioCephalicVein_arg);
+  f->SetFuzzyThreshold("2RL", "Aorta", mArgsInfo.S2RL_ft_Aorta_arg);
+  f->SetFuzzyThreshold("2RL", "SubclavianArteryLeft", mArgsInfo.S2RL_ft_SubclavianArteryLeft_arg);
+  f->SetFuzzyThreshold("2RL", "SubclavianArteryRight", mArgsInfo.S2RL_ft_SubclavianArteryRight_arg);
 }
 //--------------------------------------------------------------------