]> Creatis software - clitk.git/blob - segmentation/clitkExtractLymphStation_2RL.txx
Add a clitk version of itkPasteImageFilter because, with itkv4, there is a new Verify...
[clitk.git] / segmentation / clitkExtractLymphStation_2RL.txx
1
2
3 // vtk
4 #include <vtkAppendPolyData.h>
5 #include <vtkPolyDataWriter.h>
6 #include <vtkCellArray.h>
7
8 // clitk
9 #include "clitkMeshToBinaryImageFilter.h"
10
11 // itk
12 #include <itkImageDuplicator.h>
13
14 //--------------------------------------------------------------------
15 template <class ImageType>
16 void 
17 clitk::ExtractLymphStationsFilter<ImageType>::
18 ExtractStation_2RL_SetDefaultValues()
19 {
20   SetFuzzyThreshold("2RL", "CommonCarotidArtery", 0.7);
21   SetFuzzyThreshold("2RL", "BrachioCephalicArtery", 0.7);
22   SetFuzzyThreshold("2RL", "BrachioCephalicVein", 0.3);
23   SetFuzzyThreshold("2RL", "Aorta", 0.7);
24   SetFuzzyThreshold("2RL", "SubclavianArteryRight", 0.5);
25   SetFuzzyThreshold("2RL", "SubclavianArteryLeft", 0.8);
26 }
27 //--------------------------------------------------------------------
28
29
30 //--------------------------------------------------------------------
31 template <class TImageType>
32 void 
33 clitk::ExtractLymphStationsFilter<TImageType>::
34 ExtractStation_2RL()
35 {
36   if (CheckForStation("2RL")) {
37     ExtractStation_2RL_SI_Limits();
38     ExtractStation_2RL_Post_Limits();
39
40     ExtractStation_2RL_Ant_Limits2();
41     //ExtractStation_2RL_Ant_Limits(); 
42
43     ExtractStation_2RL_LR_Limits(); 
44     ExtractStation_2RL_Remove_Structures(); 
45     ExtractStation_2RL_SeparateRL(); 
46     
47     // Store image filenames into AFDB 
48     writeImage<MaskImageType>(m_ListOfStations["2R"], "seg/Station2R.mhd");
49     writeImage<MaskImageType>(m_ListOfStations["2L"], "seg/Station2L.mhd");
50     GetAFDB()->SetImageFilename("Station2R", "seg/Station2R.mhd"); 
51     GetAFDB()->SetImageFilename("Station2L", "seg/Station2L.mhd"); 
52     WriteAFDB(); 
53   }
54 }
55 //--------------------------------------------------------------------
56
57
58 //--------------------------------------------------------------------
59 template <class ImageType>
60 void 
61 clitk::ExtractLymphStationsFilter<ImageType>::
62 ExtractStation_2RL_SI_Limits() 
63 {
64   // Apex of the chest or Sternum & Carina.
65   StartNewStep("[Station 2RL] Inf/Sup limits with Sternum and TopOfAorticArch/CaudalMarginOfLeftBrachiocephalicVein");
66
67   /* Rod says: "For the inferior border, unlike in Atlas – UM, there
68    is now a difference between 2R and 2L.  2R stops at the
69    intersection of the caudal margin of the innominate vein with the
70    trachea.  2L extends less inferiorly to the superior border of the
71    aortic arch." */
72
73   /* Get TopOfAorticArch and CaudalMarginOfLeftBrachiocephalicVein 
74      - TopOfAorticArch -> can be obtain from Aorta -> most sup part.  
75      - CaudalMarginOfLeftBrachiocephalicVein -> must inf part of BrachicephalicVein
76    */
77   MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
78   MaskImagePointType p = Aorta->GetOrigin(); // initialise to avoid warning 
79   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Aorta, GetBackgroundValue(), 2, false, p);
80   double TopOfAorticArchZ=p[2];
81   GetAFDB()->SetDouble("TopOfAorticArchZ", TopOfAorticArchZ);
82
83   MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
84   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(BrachioCephalicVein, GetBackgroundValue(), 2, true, p);
85   double CaudalMarginOfLeftBrachiocephalicVeinZ=p[2];
86   GetAFDB()->SetDouble("CaudalMarginOfLeftBrachiocephalicVeinZ", CaudalMarginOfLeftBrachiocephalicVeinZ);
87   
88   // First, cut on the most inferior part. Add one slice because this
89   // inf slice should not be included.
90   double inf = std::min(CaudalMarginOfLeftBrachiocephalicVeinZ, TopOfAorticArchZ) + m_Working_Support->GetSpacing()[2];
91
92   // Get Sternum and search for the upper position
93   MaskImagePointer Sternum = GetAFDB()->template GetImage<MaskImageType>("Sternum");
94
95   // Search most sup point
96   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Sternum, GetBackgroundValue(), 2, false, p);
97   double m_SternumZ = p[2];
98   // +Sternum->GetSpacing()[2]; // One more slice, because it is below this point // NOT HERE ?? WHY DIFFERENT FROM 3A ??
99
100   //* Crop support :
101   m_Working_Support = 
102     clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2, 
103                                                 inf, m_SternumZ, true,
104                                                 GetBackgroundValue());
105
106   StopCurrentStep<MaskImageType>(m_Working_Support);
107   m_ListOfStations["2R"] = m_Working_Support;
108   m_ListOfStations["2L"] = m_Working_Support;
109 }
110 //--------------------------------------------------------------------
111
112
113 //--------------------------------------------------------------------
114 template <class ImageType>
115 void 
116 clitk::ExtractLymphStationsFilter<ImageType>::
117 ExtractStation_2RL_Ant_Limits() 
118 {
119   // -----------------------------------------------------
120   /* Rod says: "The anterior border, as with the Atlas – UM, is
121     posterior to the vessels (right subclavian vein, left
122     brachiocephalic vein, right brachiocephalic vein, left subclavian
123     artery, left common carotid artery and brachiocephalic trunk).
124     These vessels are not included in the nodal station.  The anterior
125     border is drawn to the midpoint of the vessel and an imaginary
126     line joins the middle of these vessels.  Between the vessels,
127     station 2 is in contact with station 3a." */
128
129   // -----------------------------------------------------
130   StartNewStep("[Station 2RL] Ant limits with CommonCarotidArtery");
131
132   // Get CommonCarotidArtery
133   MaskImagePointer CommonCarotidArtery = GetAFDB()->template GetImage<MaskImageType>("CommonCarotidArtery");
134   
135   // Remove Ant to CommonCarotidArtery
136   typedef SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
137   typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
138   sliceRelPosFilter->VerboseStepFlagOff();
139   sliceRelPosFilter->WriteStepFlagOff();
140   sliceRelPosFilter->SetInput(m_Working_Support);
141   sliceRelPosFilter->SetInputObject(CommonCarotidArtery);
142   sliceRelPosFilter->SetDirection(2);
143   sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("2RL", "CommonCarotidArtery"));
144   sliceRelPosFilter->AddOrientationTypeString("NotAntTo");
145   sliceRelPosFilter->IntermediateSpacingFlagOn();
146   sliceRelPosFilter->SetIntermediateSpacing(2);
147   sliceRelPosFilter->UniqueConnectedComponentBySliceOff();
148   sliceRelPosFilter->UseASingleObjectConnectedComponentBySliceFlagOff();
149   sliceRelPosFilter->AutoCropFlagOn(); 
150   sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
151   sliceRelPosFilter->RemoveObjectFlagOff();
152   sliceRelPosFilter->Update();
153   m_Working_Support = sliceRelPosFilter->GetOutput();
154
155   // End
156   StopCurrentStep<MaskImageType>(m_Working_Support);
157   m_ListOfStations["2R"] = m_Working_Support;
158   m_ListOfStations["2L"] = m_Working_Support;
159
160   // -----------------------------------------------------
161   // Remove Ant to H line from the Ant most part of the
162   // CommonCarotidArtery until we reach the first slice of
163   // BrachioCephalicArtery
164   StartNewStep("[Station 2RL] Ant limits with CommonCarotidArtery, H line");
165
166   // First, find the first slice of BrachioCephalicArtery
167   MaskImagePointer BrachioCephalicArtery = GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicArtery");
168   MaskImagePointType p = BrachioCephalicArtery->GetOrigin(); // initialise to avoid warning 
169   clitk::FindExtremaPointInAGivenDirection<MaskImageType>(BrachioCephalicArtery, GetBackgroundValue(), 2, false, p);
170   double TopOfBrachioCephalicArteryZ=p[2] + BrachioCephalicArtery->GetSpacing()[2]; // Add one slice
171
172   // Remove CommonCarotidArtery below this point
173   CommonCarotidArtery = clitk::CropImageRemoveLowerThan<MaskImageType>(CommonCarotidArtery, 2, TopOfBrachioCephalicArteryZ, true, GetBackgroundValue());  
174
175   // Find most Ant points
176   std::vector<MaskImagePointType> ccaAntPositionA;
177   std::vector<MaskImagePointType> ccaAntPositionB;
178   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(CommonCarotidArtery, 
179                                                                                GetBackgroundValue(), 2,
180                                                                                1, true, // Ant
181                                                                                0, // Horizontal line
182                                                                                -3, // margin
183                                                                                ccaAntPositionA, 
184                                                                                ccaAntPositionB);
185   // Cut ant to this line
186   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
187                                                                     ccaAntPositionA,
188                                                                     ccaAntPositionB,
189                                                                     GetBackgroundValue(), 1, 10); 
190
191   // End
192   StopCurrentStep<MaskImageType>(m_Working_Support);
193   m_ListOfStations["2R"] = m_Working_Support;
194   m_ListOfStations["2L"] = m_Working_Support;
195
196   // -----------------------------------------------------
197   // Ant limit with the BrachioCephalicArtery
198   StartNewStep("[Station 2RL] Ant limits with BrachioCephalicArtery line");
199
200   // Remove Ant to BrachioCephalicArtery
201   m_Working_Support = 
202     clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, BrachioCephalicArtery, 2, 
203                                                        GetFuzzyThreshold("2RL", "BrachioCephalicArtery"), "NotAntTo", false, 2, true, false);
204   // End
205   StopCurrentStep<MaskImageType>(m_Working_Support);
206   m_ListOfStations["2R"] = m_Working_Support;
207   m_ListOfStations["2L"] = m_Working_Support;
208
209   // -----------------------------------------------------
210   // Ant limit with the BrachioCephalicArtery H line
211   StartNewStep("[Station 2RL] Ant limits with BrachioCephalicArtery, Horizontal line");
212   
213   // Find most Ant points
214   std::vector<MaskImagePointType> bctAntPositionA;
215   std::vector<MaskImagePointType> bctAntPositionB;
216   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(BrachioCephalicArtery, 
217                                                                                GetBackgroundValue(), 2,
218                                                                                1, true, // Ant
219                                                                                0, // Horizontal line
220                                                                                -1, // margin
221                                                                                bctAntPositionA, 
222                                                                                bctAntPositionB);
223   // Cut ant to this line
224   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
225                                                                     bctAntPositionA,
226                                                                     bctAntPositionB,
227                                                                     GetBackgroundValue(), 1, 10); 
228  // End
229   StopCurrentStep<MaskImageType>(m_Working_Support);
230   m_ListOfStations["2R"] = m_Working_Support;
231   m_ListOfStations["2L"] = m_Working_Support;
232
233   // -----------------------------------------------------
234   // Ant limit with the BrachioCephalicVein
235   StartNewStep("[Station 2RL] Ant limits with BrachioCephalicVein");
236
237   // Remove Ant to BrachioCephalicVein
238   MaskImagePointer BrachioCephalicVein = GetAFDB()->template GetImage<MaskImageType>("BrachioCephalicVein");
239   m_Working_Support = 
240     clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, BrachioCephalicVein, 2, 
241                                                        GetFuzzyThreshold("2RL", "BrachioCephalicVein"), "NotAntTo", false, 2, true, false);
242   // End
243   StopCurrentStep<MaskImageType>(m_Working_Support);
244   m_ListOfStations["2R"] = m_Working_Support;
245   m_ListOfStations["2L"] = m_Working_Support;
246 }
247 //--------------------------------------------------------------------
248
249
250 //--------------------------------------------------------------------
251 template <class ImageType>
252 void 
253 clitk::ExtractLymphStationsFilter<ImageType>::
254 ExtractStation_2RL_Ant_Limits2()
255 {
256   // -----------------------------------------------------
257   StartNewStep("[Station 2RL] Ant limits with vessels centroids");
258   
259   // WARNING, as I used "And" after, empty slice in binarizedContour
260   // lead to remove part of the support, although we want to keep
261   // unchanged. So we decide to ResizeImageLike but pad with
262   // ForegroundValue instead of BG
263
264   // Get or compute the binary mask that separate Ant/Post part
265   // according to vessels
266   MaskImagePointer binarizedContour = FindAntPostVessels2();
267   binarizedContour = clitk::ResizeImageLike<MaskImageType>(binarizedContour, 
268                                                            m_Working_Support, 
269                                                            GetForegroundValue());
270   
271   // remove from support
272   typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
273   typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
274   boolFilter->InPlaceOn();
275   boolFilter->SetInput1(m_Working_Support);
276   boolFilter->SetInput2(binarizedContour);
277   boolFilter->SetBackgroundValue1(GetBackgroundValue());
278   boolFilter->SetBackgroundValue2(GetBackgroundValue());
279   boolFilter->SetOperationType(BoolFilterType::And);
280   boolFilter->Update();
281   m_Working_Support = boolFilter->GetOutput();
282
283   // End
284   StopCurrentStep<MaskImageType>(m_Working_Support);
285   m_ListOfStations["2R"] = m_Working_Support;
286   m_ListOfStations["2L"] = m_Working_Support;
287 }
288 //--------------------------------------------------------------------
289
290
291 //--------------------------------------------------------------------
292 template <class ImageType>
293 void 
294 clitk::ExtractLymphStationsFilter<ImageType>::
295 ExtractStation_2RL_Post_Limits() 
296 {
297   StartNewStep("[Station 2RL] Post limits with post wall of Trachea");
298
299   // Get Trachea
300   MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
301   
302   // Resize like the current support (to have the same number of slices)
303   Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, m_Working_Support, GetBackgroundValue());
304
305   // Find extrema post positions
306   std::vector<MaskImagePointType> tracheaPostPositionsA;
307   std::vector<MaskImagePointType> tracheaPostPositionsB;
308   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(Trachea, 
309                                                                                GetBackgroundValue(), 2, 
310                                                                                1, false, // Post
311                                                                                0, // Horizontal line 
312                                                                                1, 
313                                                                                tracheaPostPositionsA, 
314                                                                                tracheaPostPositionsB);
315   // Cut post to this line
316   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
317                                                                     tracheaPostPositionsA,
318                                                                     tracheaPostPositionsB,
319                                                                     GetBackgroundValue(), 1, -10); 
320   // END
321   StopCurrentStep<MaskImageType>(m_Working_Support);
322   m_ListOfStations["2R"] = m_Working_Support;
323   m_ListOfStations["2L"] = m_Working_Support;
324 }
325 //--------------------------------------------------------------------
326
327
328 //--------------------------------------------------------------------
329 // Build a vtk mesh from a list of slice number/closed-contours
330 template <class ImageType>
331 vtkSmartPointer<vtkPolyData> 
332 clitk::ExtractLymphStationsFilter<ImageType>::
333 Build3DMeshFrom2DContour(const std::vector<ImagePointType> & points)
334 {
335   // create a contour, polydata. 
336   vtkSmartPointer<vtkPolyData> mesh = vtkSmartPointer<vtkPolyData>::New();
337   mesh->Allocate(); //for cell structures
338   mesh->SetPoints(vtkPoints::New());
339   vtkIdType ids[2];
340   int point_number = points.size();
341   for (unsigned int i=0; i<points.size(); i++) {
342     mesh->GetPoints()->InsertNextPoint(points[i][0],points[i][1],points[i][2]);
343     ids[0]=i;
344     ids[1]=(ids[0]+1)%point_number; //0-1,1-2,...,n-1-0
345     mesh->GetLines()->InsertNextCell(2,ids);
346   }
347   // Return
348   return mesh;
349 }
350 //--------------------------------------------------------------------
351
352
353 //--------------------------------------------------------------------
354 template <class ImageType>
355 void
356 clitk::ExtractLymphStationsFilter<ImageType>::
357 ExtractStation_2RL_LR_Limits()
358 {
359   // ---------------------------------------------------------------------------
360   StartNewStep("[Station 2RL] Left/Right limits with Aorta");
361   MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
362   //  DD(GetFuzzyThreshold("2RL", "BrachioCephalicVein"));
363   m_Working_Support = 
364     clitk::SliceBySliceRelativePosition<MaskImageType>(m_Working_Support, Aorta, 2, 
365                                                        GetFuzzyThreshold("2RL", "Aorta"),
366                                                        "RightTo", false, 2, true, false);  
367   // END
368   StopCurrentStep<MaskImageType>(m_Working_Support);
369   m_ListOfStations["2R"] = m_Working_Support;
370   m_ListOfStations["2L"] = m_Working_Support;
371
372   // ---------------------------------------------------------------------------
373   StartNewStep("[Station 2RL] Left/Right limits with SubclavianArtery (Right)");
374   
375   // SliceBySliceRelativePosition + select CCL most at Right
376   MaskImagePointer SubclavianArtery = GetAFDB()->template GetImage<MaskImageType>("SubclavianArtery");
377   typedef SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
378   typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
379   sliceRelPosFilter->VerboseStepFlagOff();
380   sliceRelPosFilter->WriteStepFlagOff();
381   sliceRelPosFilter->SetInput(m_Working_Support);
382   sliceRelPosFilter->SetInputObject(SubclavianArtery);
383   sliceRelPosFilter->SetDirection(2);
384   sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("2RL", "SubclavianArteryRight"));
385   sliceRelPosFilter->AddOrientationTypeString("NotRightTo");
386   sliceRelPosFilter->IntermediateSpacingFlagOn();
387   sliceRelPosFilter->SetIntermediateSpacing(2);
388   sliceRelPosFilter->UniqueConnectedComponentBySliceOff();
389   sliceRelPosFilter->UseASingleObjectConnectedComponentBySliceFlagOff();
390
391   sliceRelPosFilter->CCLSelectionFlagOn(); // select one CCL by slice
392   sliceRelPosFilter->SetCCLSelectionDimension(0); // select according to X (0) axis
393   sliceRelPosFilter->SetCCLSelectionDirection(-1); // select most at Right
394   sliceRelPosFilter->CCLSelectionIgnoreSingleCCLFlagOn(); // ignore if only one CCL
395
396   sliceRelPosFilter->AutoCropFlagOn(); 
397   sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
398   sliceRelPosFilter->RemoveObjectFlagOff();
399   sliceRelPosFilter->Update();
400   m_Working_Support = sliceRelPosFilter->GetOutput();
401
402   // END
403   StopCurrentStep<MaskImageType>(m_Working_Support);
404   m_ListOfStations["2R"] = m_Working_Support;
405   m_ListOfStations["2L"] = m_Working_Support;
406
407
408   // ---------------------------------------------------------------------------
409   StartNewStep("[Station 2RL] Left/Right limits with SubclavianArtery (Left)");
410   
411   // SliceBySliceRelativePosition + select CCL most at Right
412    sliceRelPosFilter = SliceRelPosFilterType::New();
413   sliceRelPosFilter->VerboseStepFlagOff();
414   sliceRelPosFilter->WriteStepFlagOff();
415   sliceRelPosFilter->SetInput(m_Working_Support);
416   sliceRelPosFilter->SetInputObject(SubclavianArtery);
417   sliceRelPosFilter->SetDirection(2);
418   sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold("2RL", "SubclavianArteryLeft"));
419   sliceRelPosFilter->AddOrientationTypeString("NotLeftTo");
420   sliceRelPosFilter->IntermediateSpacingFlagOn();
421   sliceRelPosFilter->SetIntermediateSpacing(2);
422   sliceRelPosFilter->UniqueConnectedComponentBySliceOff();
423   sliceRelPosFilter->UseASingleObjectConnectedComponentBySliceFlagOff();
424
425   sliceRelPosFilter->CCLSelectionFlagOn(); // select one CCL by slice
426   sliceRelPosFilter->SetCCLSelectionDimension(0); // select according to X (0) axis
427   sliceRelPosFilter->SetCCLSelectionDirection(+1); // select most at Left
428   sliceRelPosFilter->CCLSelectionIgnoreSingleCCLFlagOff(); // do not ignore if only one CCL
429
430   sliceRelPosFilter->AutoCropFlagOn(); 
431   sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
432   sliceRelPosFilter->RemoveObjectFlagOff();
433   sliceRelPosFilter->Update();
434   m_Working_Support = sliceRelPosFilter->GetOutput();
435
436   // END
437   StopCurrentStep<MaskImageType>(m_Working_Support);
438   m_ListOfStations["2R"] = m_Working_Support;
439   m_ListOfStations["2L"] = m_Working_Support;
440 }
441 //--------------------------------------------------------------------
442
443 //--------------------------------------------------------------------
444 template <class ImageType>
445 void
446 clitk::ExtractLymphStationsFilter<ImageType>::
447 ExtractStation_2RL_Remove_Structures()
448 {
449   Remove_Structures("2RL", "BrachioCephalicVein");
450   Remove_Structures("2RL", "CommonCarotidArtery");
451   Remove_Structures("2RL", "SubclavianArtery");
452   Remove_Structures("2RL", "Thyroid");
453   Remove_Structures("2RL", "Aorta");
454   
455   // END
456   StopCurrentStep<MaskImageType>(m_Working_Support);
457   m_ListOfStations["2R"] = m_Working_Support;
458   m_ListOfStations["2L"] = m_Working_Support;
459 }
460 //--------------------------------------------------------------------
461
462
463 //--------------------------------------------------------------------
464 template <class ImageType>
465 void
466 clitk::ExtractLymphStationsFilter<ImageType>::
467 ExtractStation_2RL_SeparateRL()
468 {
469   // ---------------------------------------------------------------------------
470   StartNewStep("[Station 2RL] Separate 2R/2L according to Trachea");
471
472   /*Rod says: 
473     
474    "For station 2 there is a shift, dividing 2R from 2L, from midline
475    to the left paratracheal border."
476
477    Algo: 
478     - Consider Trachea SliceBySlice
479     - find extrema at Left
480     - add margins towards Right
481     - remove what is at Left of this line
482    */
483
484   // Get Trachea
485   MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
486   
487   // Resize like the current support (to have the same number of slices)
488   Trachea = clitk::ResizeImageLike<MaskImageType>(Trachea, m_Working_Support, GetBackgroundValue());
489
490   // Find extrema post positions
491   std::vector<MaskImagePointType> tracheaLeftPositionsA;
492   std::vector<MaskImagePointType> tracheaLeftPositionsB;
493   clitk::SliceBySliceBuildLineSegmentAccordingToExtremaPosition<MaskImageType>(Trachea, 
494                                                                                GetBackgroundValue(), 2, 
495                                                                                0, false, // Left
496                                                                                1, // Vertical line 
497                                                                                1, // margins 
498                                                                                tracheaLeftPositionsA, 
499                                                                                tracheaLeftPositionsB);
500   // Copy support for R and L
501   typedef itk::ImageDuplicator<MaskImageType> DuplicatorType;
502   DuplicatorType::Pointer duplicator = DuplicatorType::New();
503   duplicator->SetInputImage(m_Working_Support);
504   duplicator->Update();
505   MaskImageType::Pointer m_Working_Support2 = duplicator->GetOutput();
506   
507   // Cut post to this line for Right part
508   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support, 
509                                                                     tracheaLeftPositionsA,
510                                                                     tracheaLeftPositionsB,
511                                                                     GetBackgroundValue(), 0, -10); 
512   writeImage<MaskImageType>(m_Working_Support, "R.mhd");
513
514   // Cut post to this line for Left part
515   clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support2, 
516                                                                     tracheaLeftPositionsA,
517                                                                     tracheaLeftPositionsB,
518                                                                     GetBackgroundValue(), 0, +10); 
519   writeImage<MaskImageType>(m_Working_Support2, "L.mhd");
520
521   // END
522   StopCurrentStep<MaskImageType>(m_Working_Support);
523   m_ListOfStations["2R"] = m_Working_Support;
524   m_ListOfStations["2L"] = m_Working_Support2;
525 }
526 //--------------------------------------------------------------------