]> Creatis software - clitk.git/commitdiff
Merge branch 'master' of git.creatis.insa-lyon.fr:clitk
authorDavid Sarrut <david.sarrut@gmail.com>
Mon, 5 Dec 2011 09:14:45 +0000 (10:14 +0100)
committerDavid Sarrut <david.sarrut@gmail.com>
Mon, 5 Dec 2011 09:14:45 +0000 (10:14 +0100)
1  2 
itk/clitkRelativePositionAnalyzerFilter.txx
itk/clitkSegmentationUtils.txx
segmentation/clitkExtractLymphStation_Supports.txx
segmentation/clitkExtractLymphStationsFilter.txx
segmentation/clitkRelativePositionList.txx

index 54ed9320c4b7eaebeeed4c671a49b66ce7cf7371,df12ea33437c42975282662ad74015745d625041..63af1191987386dfac0b632f0af23559ef967e10
@@@ -101,21 -101,14 +101,19 @@@ voi
  clitk::RelativePositionAnalyzerFilter<ImageType>::
  GenerateData() 
  {
-   static const unsigned int dim = ImageType::ImageDimension;
-   
    ImagePointer temp = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
    m_Object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
 -  m_Target = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
 +  ImagePointer temp2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
  
    // Remove object from support (keep initial image)
    m_Support = clitk::Clone<ImageType>(temp);
    clitk::AndNot<ImageType>(m_Support, m_Object, GetBackgroundValue());
    
 +  // Remove object from target. Important because sometimes, there is
 +  // overlap between target and object.
 +  m_Target = clitk::Clone<ImageType>(temp2);
 +  clitk::AndNot<ImageType>(m_Target, m_Object, GetBackgroundValue());
 +  
    // Define filter to compute statics on mask image
    typedef itk::LabelStatisticsImageFilter<ImageType, ImageType> StatFilterType;
    typename StatFilterType::Pointer statFilter = StatFilterType::New();
    double mReverseThreshold=1.0;
    ComputeOptimalThresholds(map, m_Target, bins, tolerance, mThreshold, mReverseThreshold);
  
 +  // DD(mThreshold);
 +  // DD(mReverseThreshold);
 +
    // Use the threshold to compute new support
    int s1 = GetSupportSize();
    if (mThreshold > 0.0) {
      s2 = statFilter->GetCount(GetForegroundValue());
    }
    
 +  // Check threshold, if we gain nothing, we force to max/min thresholds
 +  // DD(GetSupportSize());
 +  // DD(s1);
 +  // DD(s2);
 +  if (s1 >= GetSupportSize()) mThreshold = 0.0;
 +  if (s2 >= GetSupportSize()) mReverseThreshold = 1.0;
 +
    // Set results values
    m_Info.threshold = mThreshold;
    m_Info.sizeAfterThreshold = s1;
@@@ -227,19 -210,15 +225,19 @@@ ComputeFuzzyMap(ImageType * object, Ima
    // sliceRelPosFilter->PrintOptions();
    sliceRelPosFilter->Update();
    typename FloatImageType::Pointer map = sliceRelPosFilter->GetFuzzyMap();
 +  writeImage<FloatImageType>(map, "fuzzy_0_"+toString(clitk::rad2deg(angle))+".mha");
  
 -  // Resize map like object to allow SetBackground
 -  map = clitk::ResizeImageLike<FloatImageType>(map, object, GetBackgroundValue());
 +  // Resize object like map to allow SetBackground
 +  ImagePointer temp = clitk::ResizeImageLike<ImageType>(object, map, GetBackgroundValue());
 +  //  writeImage<FloatImageType>(map, "fuzzy_1_"+toString(clitk::rad2deg(angle))+".mha");
    
    // Remove initial object from the fuzzy map
 -  map = clitk::SetBackground<FloatImageType, ImageType>(map, object, GetForegroundValue(), 0.0, true);
 +  map = clitk::SetBackground<FloatImageType, ImageType>(map, temp, GetForegroundValue(), 0.0, true);
 +  writeImage<FloatImageType>(map, "fuzzy_2_"+toString(clitk::rad2deg(angle))+".mha");
    
    // Resize the fuzzy map like the target, put 2.0 when outside
    map = clitk::ResizeImageLike<FloatImageType>(map, target, 2.0);  // Put 2.0 when out of initial map
 +  writeImage<FloatImageType>(map, "fuzzy_3_"+toString(clitk::rad2deg(angle))+".mha");
    
    // end
    return map;
@@@ -260,10 -239,9 +258,10 @@@ ComputeOptimalThresholds(FloatImageTyp
    f->SetInput(map);
    f->SetLabelInput(target);
    f->UseHistogramsOn();
 -  f->SetHistogramParameters(bins, 0.0, 1.1);
 +  f->SetHistogramParameters(bins, 0.0-(1.0/bins), 1.0+(1.0/bins));
    f->Update();
    int count = f->GetCount(GetForegroundValue());
 +  // DD(count);
    typename FloatStatFilterType::HistogramPointer h = f->GetHistogram(GetForegroundValue());
  
    // Debug : dump histogram
                    << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
    }
    histogramFile.close();  
 +  std::ofstream histogramFile2(std::string("fuzzy_histo_R_"+toString(i)+".txt").c_str());
 +  for(int j=bins-1; j>=0; j--) {
 +    histogramFile2 << h->GetMeasurement(j,0) 
 +                  << "\t" << h->GetFrequency(j) 
 +                  << "\t" << (double)h->GetFrequency(j)/(double)count << std::endl;
 +  }
 +  histogramFile2.close();  
    i++;
  
    // Analyze the histogram (direct)
    double sum = 0.0;
    bool found = false;
    threshold = 0.0;
 -  for(int j=0; j<bins; j++) {
 +  for(int j=0; j<bins-1; j++) {
      sum += ((double)h->GetFrequency(j)/(double)count);
 +     // DD(j);
 +     // DD(sum);
 +     // DD(threshold);
 +     // DD(h->GetBinMin(0,j));
 +     // DD(h->GetBinMax(0,j));
      if ((!found) && (sum > tolerance)) {
 -      if (j==0) threshold = h->GetBinMin(0,j);
 -      else threshold = h->GetBinMin(0,j-1); // the last before reaching the threshold
 +      // We consider as threshold the laste before current, because 
 +      if (j==0) 
 +        threshold = h->GetBinMin(0,j);
 +      else threshold = h->GetBinMin(0,j-1); // FIXME  ? the last before reaching the threshold
 +      // DD(threshold);
        found = true;
 +      j = bins;
      }
    }
  
    sum = 0.0;
    found = false;
    reverseThreshold = 1.0;
 -  for(int j=bins-1; j>=0; j--) {
 +  for(int j=bins-1; j>0; j--) {
      sum += ((double)h->GetFrequency(j)/(double)count);
 +     // DD(j);
 +     // DD(sum);
 +     // DD(reverseThreshold);
 +     // DD(h->GetBinMin(0,j));
 +     // DD(h->GetBinMax(0,j));
      if ((!found) && (sum > tolerance)) {
 -      if (j==bins-1) reverseThreshold = h->GetBinMax(0,j);
 -      else reverseThreshold = h->GetBinMax(0,j+1);
 +      if (j==bins-1) 
 +      reverseThreshold = h->GetBinMax(0,j);
 +      else reverseThreshold = h->GetBinMax(0,j-1);// FIXME  ? the last before reaching the threshold
 +      // DD(reverseThreshold);
        found = true;
 +      j = -1;
      }
    }
 +
  }
  //--------------------------------------------------------------------
  
index 24ca5194853595a1ac2b815aeeee60533f5412e1,501c64f86fedd8ace7de88f1e7e9388c4e6fd807..6171030d9109807f0c2d2a9cf80782087c7c8279
@@@ -766,7 -766,8 +766,7 @@@ namespace clitk 
    {
      assert((mainDirection==0) || (mainDirection==1));
      typedef itk::ImageSliceIteratorWithIndex<ImageType> SliceIteratorType;
 -    SliceIteratorType siter = SliceIteratorType(input, 
 -                                                input->GetLargestPossibleRegion());
 +    SliceIteratorType siter = SliceIteratorType(input, input->GetLargestPossibleRegion());
      siter.SetFirstDirection(0);
      siter.SetSecondDirection(1);
      siter.GoToBegin();
          A = lA[i];
          B = lB[i];
          C = A;
 -      
          // Check that the line is not a point (A=B)
          bool p = (A[0] == B[0]) && (A[1] == B[1]);
        
      iter2.GoToBegin();
      double dmin = 100000.0;
      typename ImageType::IndexType indexmin;
+     indexmin.Fill(0);
      while (!iter1.IsAtEnd()) {
        if (iter1.Get() != BG) {
          double d = iter2.Get();
index 952c08e57a0d21edba5d1caeadf6c1fecefe760a,a022392653df59bb5a3511295067980c43db274c..f480d842b2990cc3c16156b2500b5add84281ed7
@@@ -19,9 -19,21 +19,9 @@@ ExtractStationSupports(
    Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0); 
    Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]); 
  
 -  // Initialise all others supports
 -  // m_ListOfSupports["S1R"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S1L"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S2R"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S2L"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S3A"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S3P"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S4R"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S4L"] = m_ListOfSupports["Sup_to_Carina"];
 -  // m_ListOfSupports["S5"] = m_Mediastinum; // Not above Carina
 -  // m_ListOfSupports["S6"] = m_Mediastinum; // Not above Carina
 -  
    // Read all support limits in a file and apply them
    ReadSupportLimits(GetSupportLimitsFilename());  
-   for(int i=0; i<m_ListOfSupportLimits.size(); i++) {
+   for(unsigned int i=0; i<m_ListOfSupportLimits.size(); i++) {
      SupportLimitsType s = m_ListOfSupportLimits[i];
      Support_SI_Limit(s.station_limit, s.station, s.structure_limit, 
                       s.structure, s.offset*m_Working_Support->GetSpacing()[2]);
    Support_LeftRight_S4R_S4L();
    
    // Post limits of S1,S2,S4
 -  Support_Post_S1S2S4();
 +  Support_Post_S2S4();
  
 -  // S3P
 +  // S3P : "the anterior border is an imaginary horizontal line
 +  // extending along the posterior wall of the trachea"
    StartNewStep("[Support] Ant limits of S3P with trachea");
    m_ListOfSupports["S3P"] = LimitsWithTrachea(m_ListOfSupports["S3P"], 1, 0, 10);
  
 -  // S3A
 +  // S3A : "Posteriorly, the station is limited by station 2R and 2L,
 +  // but excludes the great vessels. An imaginary line joins the
 +  // midpoint of the vessel in the anterior to posterior plane. It is
 +  // here that station 2 contacts station 3a" ===> here limit with
 +  // trachea only
    StartNewStep("[Support] Ant limits of S3A with trachea");
    m_ListOfSupports["S3A"] = LimitsWithTrachea(m_ListOfSupports["S3A"], 1, 0, -10);
 +
 +  // S1RL - posterior limits when SI overlap with S3P
 +  Support_Post_S1_S3P();
 +  
 +  // S1RL - posterior limits with S2RL above sternal notch
 +  Support_Post_S1_Ant_S2RL();
    
    // I will do it later
    // Below Carina S7,8,9,10
@@@ -110,7 -111,7 +110,7 @@@ Support_SI_Limit(const std::string stat
    m_Working_Support = m_ListOfSupports[station];
    
    // Get structure or structureZ
-   double z;
+   double z=0.;
    int found=0;
    std::string file;
  
@@@ -234,11 -235,6 +234,11 @@@ voi
  clitk::ExtractLymphStationsFilter<ImageType>::
  Support_LeftRight_S1R_S1L()
  {
 +  /*
 +    Medially, station 1R and 1L are separated by the midline of the
 +    trachea, whilst excluding the thyroid gland.
 +  */
 +
    // Step S1RL : Left-Right
    StartNewStep("[Support] Left-Right S1R S1L");
    std::vector<ImagePointType> A;
  
    // Right part
    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B, 
 -                                                                    GetBackgroundValue(), 0, 10);
 +                                                                    GetBackgroundValue(), 0, -10);
    S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
    m_ListOfSupports["S1R"] = S1R;
  
    // Left part
    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B, 
 -                                                                    GetBackgroundValue(), 0, -10);
 +                                                                    GetBackgroundValue(), 0, 10);
    S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
    m_ListOfSupports["S1L"] = S1L;
    StopCurrentStep<MaskImageType>(m_ListOfSupports["S1L"]);
@@@ -290,14 -286,11 +290,14 @@@ clitk::ExtractLymphStationsFilter<Image
  Support_LeftRight_S2R_S2L()
  {
    // ---------------------------------------------------------------------------
 -  /* Step : S2RL LeftRight
 -     As for lymph node station 4R, 2R includes nodes extending to the
 -     left lateral border of the trachea
 -     Rod says:  "For station 2 there is a shift, dividing 2R from 2L, from midline
 -     to the left paratracheal border."
 +  /* Step : S2RL LeftRight As for lymph node station 4R, 2R includes
 +     nodes extending to the left lateral border of the trachea.
 +
 +     Rod says: "For station 2 there is a shift in the IASLC definition
 +     dividing 2R from 2L, from the midline to the left lateral
 +     tracheal border. This is represented in the atlas as a vertical
 +     line passing tangentially along the left lateral tracheal border
 +     "
    */
    StartNewStep("[Support] Separate 2R/2L according to Trachea");
    MaskImagePointer S2R = m_ListOfSupports["S2R"];
@@@ -320,10 -313,15 +320,10 @@@ clitk::ExtractLymphStationsFilter<Image
  Support_LeftRight_S4R_S4L()
  {
    // ---------------------------------------------------------------------------
 -  /* Step : S4RL LeftRight 
 -     
 -     - 4R: includes right paratracheal nodes, and pretracheal nodes
 -     extending to the left lateral border of trachea
 -     
 -     - 4L: includes nodes to the left of the left lateral border of
 -     the trachea, medial to the ligamentum arteriosum
 -     
 -     => same than 2RL
 +  /*      
 +          The medial border of station 4R is defined as an imaginary line
 +          running vertically from the left lateral tracheal border. This is
 +          the same medial border as was described for station 2R.
    */
    StartNewStep("[Support] Left Right separation of 4R/4L");
  
@@@ -411,21 -409,21 +411,21 @@@ LimitsWithTrachea(MaskImageType * input
  template <class ImageType>
  void
  clitk::ExtractLymphStationsFilter<ImageType>::
 -Support_Post_S1S2S4()
 +Support_Post_S2S4()
  {
 -  StartNewStep("[Support] Post limits of S1RL, S2RL, S4RL");
 +  StartNewStep("[Support] Post limits of S2RL, S4RL");
    
    double m_ApexOfTheChest = FindApexOfTheChest();
    
    // Post limits with Trachea 
 -  MaskImagePointer S1R = m_ListOfSupports["S1R"];
 -  MaskImagePointer S1L = m_ListOfSupports["S1L"];
 +  // MaskImagePointer S1R = m_ListOfSupports["S1R"];
 +  // MaskImagePointer S1L = m_ListOfSupports["S1L"];
    MaskImagePointer S2R = m_ListOfSupports["S2R"];
    MaskImagePointer S2L = m_ListOfSupports["S2L"];
    MaskImagePointer S4R = m_ListOfSupports["S4R"];
    MaskImagePointer S4L = m_ListOfSupports["S4L"];
 -  m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
 -  m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
 +  // m_ListOfSupports["S1R"] = LimitsWithTrachea(S1L, 1, 0, -10, m_ApexOfTheChest);
 +  // m_ListOfSupports["S1L"] = LimitsWithTrachea(S1R, 1, 0, -10, m_ApexOfTheChest);
    m_ListOfSupports["S2R"] = LimitsWithTrachea(S2R, 1, 0, -10, m_ApexOfTheChest);
    m_ListOfSupports["S2L"] = LimitsWithTrachea(S2L, 1, 0, -10, m_ApexOfTheChest);
    m_ListOfSupports["S4R"] = LimitsWithTrachea(S4R, 1, 0, -10, m_ApexOfTheChest);
  //--------------------------------------------------------------------
  
  
 +//--------------------------------------------------------------------
 +template <class ImageType>
 +void
 +clitk::ExtractLymphStationsFilter<ImageType>::
 +Support_Post_S1_S3P()
 +{
 +  StartNewStep("[Support] If S1RL and S3P have Sup-Inf overlap, define S1RL posterior limits with S3P anterior limits (post wall trachea)");
 +
 +  // Get current supports
 +  MaskImagePointer S1R = m_ListOfSupports["S1R"];
 +  MaskImagePointer S1L = m_ListOfSupports["S1L"];
 +
 +  // Find extrema ant positions for 3P
 +  std::vector<MaskImagePointType> A;
 +  std::vector<MaskImagePointType> B;
 +
 +  // Crop S3P like S1R
 +  MaskImagePointer S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
 +  S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1R, GetBackgroundValue());
 +
 +  // Slice by slice, build the separation line 
 +  clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P, 
 +                                                                               GetBackgroundValue(), 2, 
 +                                                                               1, true, // Ant-Post
 +                                                                               0, // Horizontal line 
 +                                                                               0, // margins 
 +                                                                               A, B);
 +
 +  // clitk::WriteListOfLandmarks<MaskImageType>(A, "A-S1S3P.txt");
 +  // clitk::WriteListOfLandmarks<MaskImageType>(B, "B-S1S3P.txt");
 +
 +  // Cut post to this line 
 +  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1R, A, B,
 +                                                                    GetBackgroundValue(), 
 +                                                                    1, -10); 
 +  
 +  // Crop S3P like S1L  (Redo for S1L)
 +  S3P = clitk::Clone<MaskImageType>(m_ListOfSupports["S3P"]);
 +  S3P = clitk::ResizeImageLike<MaskImageType>(S3P, S1L, GetBackgroundValue());
 +
 +  // Slice by slice, build the separation line
 +  A.clear();
 +  B.clear();
 +  clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(S3P, 
 +                                                                               GetBackgroundValue(), 2, 
 +                                                                               1, true, // Ant-Post
 +                                                                               0, // Horizontal line 
 +                                                                               0, // margins 
 +                                                                               A, B);
 +  // Cut post to this line 
 +  clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(S1L, A, B,
 +                                                                    GetBackgroundValue(), 
 +                                                                    1, -10); 
 +
 +  // Crop both images
 +  S1R = clitk::AutoCrop<MaskImageType>(S1R, GetBackgroundValue());
 +  S1L = clitk::AutoCrop<MaskImageType>(S1L, GetBackgroundValue());
 +
 +  StopCurrentStep<MaskImageType>(S1R);
 +  
 +  m_ListOfSupports["S1R"] = S1R;
 +  m_ListOfSupports["S1L"] = S1L;
 +}
 +//--------------------------------------------------------------------
 +
 +
 +//--------------------------------------------------------------------
 +template <class ImageType>
 +void
 +clitk::ExtractLymphStationsFilter<ImageType>::
 +Support_Post_S1_Ant_S2RL()
 +{
 +  StartNewStep("[Support] Define S1RL posterior limits with S2RL anterior limits when overlap");
 +
 +  // Get RightLung
 +  MaskImagePointer RightLung = this->GetAFDB()->template GetImage<MaskImageType>("RightLung");
 +
 +  // Find common area between S1 and S2
 +  MaskImagePointType p_min;
 +  MaskImagePointType p_max;
 +  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2R"], 
 +                                                          GetBackgroundValue(), 2, false, p_max);
 +  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1R"], 
 +                                                          GetBackgroundValue(), 2, true, p_min);
 +  p_min[2] -= RightLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
 +  p_max[2] += RightLung->GetSpacing()[2]; // consider the slice abov  (remove greater or equal)
 +  
 +  if (p_min[2] > p_max[2]) {
 +
 +    // Crop RightLung
 +    RightLung = clitk::Clone<MaskImageType>(RightLung);
 +    RightLung = clitk::ResizeImageLike<MaskImageType>(RightLung, m_ListOfSupports["S1R"], GetBackgroundValue());
 +    RightLung = clitk::CropImageRemoveLowerThan<MaskImageType>(RightLung, 2, p_min[2], true, GetBackgroundValue());
 +    RightLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(RightLung, 2, p_max[2], true, GetBackgroundValue());
 +
 +    // Find extrema ant positions for RightLung
 +    std::vector<MaskImagePointType> A;
 +    std::vector<MaskImagePointType> B;
 +    clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(RightLung, 
 +                                                                                 GetBackgroundValue(), 2, 
 +                                                                                 1, true, // Ant-Post
 +                                                                                 0, // Horizontal line 
 +                                                                                 0, // margins 
 +                                                                                 A, B);
 +    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1R"],
 +                                                                      A, B,
 +                                                                      GetBackgroundValue(), 
 +                                                                      1, -10); 
 +    // I add one pixel to abupt S2R to S1R
 +    for(int i=0; i<A.size(); i++) {
 +      A[i][1] -= RightLung->GetSpacing()[1];
 +      B[i][1] -= RightLung->GetSpacing()[1];
 +    }
 +    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2R"],
 +                                                                      A, B,
 +                                                                      GetBackgroundValue(), 
 +                                                                      1, 10);
 +  }
 +
 +  // Get LeftLung, crop
 +  MaskImagePointer LeftLung = this->GetAFDB()->template GetImage<MaskImageType>("LeftLung");
 +  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S2L"], 
 +                                                          GetBackgroundValue(), 2, false, p_max);
 +  clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_ListOfSupports["S1L"], 
 +                                                          GetBackgroundValue(), 2, true, p_min);
 +  p_min[2] -= LeftLung->GetSpacing()[2]; // consider the slice below (remove lower or equal)
 +  p_max[2] += LeftLung->GetSpacing()[2]; // consider the slice abov  (remove greater or equal)  
 +  
 +  if (p_min[2] > p_max[2]) {
 +    LeftLung = clitk::ResizeImageLike<MaskImageType>(LeftLung, m_ListOfSupports["S1L"], GetBackgroundValue());
 +    LeftLung = clitk::CropImageRemoveLowerThan<MaskImageType>(LeftLung, 2, p_min[2], true, GetBackgroundValue());
 +    LeftLung = clitk::CropImageRemoveGreaterThan<MaskImageType>(LeftLung, 2, p_max[2], true, GetBackgroundValue());
 +
 +    // Find extrema ant positions for LeftLung
 +    std::vector<MaskImagePointType> A;
 +    std::vector<MaskImagePointType> B;
 +    clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(LeftLung, 
 +                                                                                 GetBackgroundValue(), 2, 
 +                                                                                 1, true, // Ant-Post
 +                                                                                 0, // Horizontal line 
 +                                                                                 0, // margins 
 +                                                                                 A, B);
 +    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S1L"],
 +                                                                      A, B,
 +                                                                      GetBackgroundValue(), 
 +                                                                      1, -10); 
 +    // I add one pixel to abupt S2R to S1R
 +    for(int i=0; i<A.size(); i++) {
 +      A[i][1] -= LeftLung->GetSpacing()[1];
 +      B[i][1] -= LeftLung->GetSpacing()[1];
 +    }
 +    clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_ListOfSupports["S2L"],
 +                                                                      A, B,
 +                                                                      GetBackgroundValue(), 
 +                                                                      1, 10); 
 +  }
 +}
 +//--------------------------------------------------------------------
index 384f70c159c7b11bcc1f8bdd26dab1bfa52f7d06,98768b278bfdaf105662efb118684db4d5c2713d..64455a87a218b79c28d86ee391b7b4a4e5c784e8
@@@ -85,9 -85,6 +85,9 @@@ GenerateOutputInformation() 
    m_Input = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
    m_Mediastinum = this->GetAFDB()->template GetImage <MaskImageType>("Mediastinum");
  
 +  // DD(this->GetVerboseMemoryFlag());
 +  // clitk::PrintMemory(this->GetVerboseMemoryFlag(), "Start"); 
 +
    // Clean some computer landmarks to force the recomputation
    // FIXME -> to put elsewhere ?
    this->GetAFDB()->RemoveTag("AntPostVesselsSeparation");
@@@ -208,10 -205,10 +208,10 @@@ CheckForStation(std::string station
    // Check if station already exist in DB
    
    // FIXME -> do nothing if not on the command line. Is it what I want ?
-   bool found = false;
+   //bool found = false;
    if (this->GetAFDB()->TagExist(s)) {
      m_ListOfStations[station] = this->GetAFDB()->template GetImage<MaskImageType>(s);
-     found = true;
+     //found = true;
    }
  
  }
index b3ea760064d2edb39176fad950983cbca3cf6b5a,254fa4c4581cd6895444789003d8b70138f8387f..e0258d5e71fb560e166c81d1a86a6608c6fe1bcb
@@@ -146,12 -146,11 +146,12 @@@ GenerateOutputInformation() 
    // Loop on RelativePositionList of operations
    std::string s = GetInputName();
    for(uint i=0; i<mArgsInfoList.size(); i++) {
 +    // clitk::PrintMemory(true, "Start"); 
      std::string text = "["+s+"] limits ";
      if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
      else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
             toString(mArgsInfoList[i].angle2_arg)+" "+
-            (mArgsInfoList[i].inverse_flag==true?"true":"false")+") ";
+            (mArgsInfoList[i].inverse_flag?"true":"false")+") ";
      text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
      if (mArgsInfoList[i].sliceBySlice_flag) {
        text += " slice by slice";
      relPosFilter->Update();
      m_working_input = relPosFilter->GetOutput();  
      StopCurrentStep<ImageType>(m_working_input);
 +    // clitk::PrintMemory(true, "End"); 
    }
  }
  //--------------------------------------------------------------------