+ m_Working_Support = m_Mediastinum = this->GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
+
+ // Remove some computed structures
+ this->GetAFDB()->RemoveTag("CarinaZ");
+ this->GetAFDB()->RemoveTag("ApexOfTheChestZ");
+
+ // Superior and inferior limits.
+ Support_SI_Limit("inferior", "Sup_to_Carina", "inferior", "Carina", 0);
+ Support_SI_Limit("superior", "Inf_to_Carina", "inferior", "Carina", m_Working_Support->GetSpacing()[2]);
+
+ // Read all support limits in a file and apply them
+ ReadSupportLimits(GetSupportLimitsFilename());
+ 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]);
+ }
+
+ // S1RL
+ Support_LeftRight_S1R_S1L();
+
+ // S2RL
+ Support_LeftRight_S2R_S2L();
+
+ // S4RL
+ Support_LeftRight_S4R_S4L();
+
+ // Post limits of S1,S2,S4
+ Support_Post_S2S4();
+
+ // 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 : "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
+ m_ListOfSupports["S7"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+ m_ListOfSupports["S8"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+ m_ListOfSupports["S9"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+ m_ListOfSupports["S10"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+ m_ListOfSupports["S11"] = clitk::Clone<MaskImageType>(m_ListOfSupports["Inf_to_Carina"]);
+
+ // Store image filenames into AFDB
+ WriteImageSupport("S1R"); WriteImageSupport("S1L");
+ WriteImageSupport("S2R"); WriteImageSupport("S2L");
+ WriteImageSupport("S3A"); WriteImageSupport("S3P");
+ WriteImageSupport("S4R"); WriteImageSupport("S4L");
+ WriteImageSupport("S5");
+ WriteImageSupport("S6");
+ WriteImageSupport("S7");
+ WriteImageSupport("S8");
+ WriteImageSupport("S9");
+ WriteImageSupport("S10");
+ WriteImageSupport("S11");
+ WriteAFDB();
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+Support_SI_Limit(const std::string station_limit, const std::string station,
+ const std::string structure_limit, const std::string structure,
+ const double offset)
+{
+ if (!GetCheckSupportFlag())
+ StartNewStep("[Support] "+station_limit+" limit of "+station+" is "+structure_limit+" limit of "+structure);
+
+ // Check
+ if ((station_limit != "superior") && (station_limit != "inferior")) {
+ clitkExceptionMacro("Error station_limit must be 'inferior' or 'superior', not '"<< station_limit);
+ }
+ if ((structure_limit != "superior") && (structure_limit != "inferior")) {
+ clitkExceptionMacro("Error structure_limit must be 'inferior' or 'superior', not '"<< structure_limit);
+ }
+
+ // Get current support
+ if (m_ListOfSupports.find(station) == m_ListOfSupports.end()) {
+ // std::cerr << "Warning: support " << station << " not initialized" << std::endl;
+ m_ListOfSupports[station] = m_Mediastinum;
+ }
+ m_Working_Support = m_ListOfSupports[station];
+
+ // Get structure or structureZ
+ double z=0.;
+ int found=0;
+ std::string file;
+
+ // Try to load structure and compute extrema point
+ if (this->GetAFDB()->TagExist(structure)) {
+ MaskImagePointer Structure = this->GetAFDB()->template GetImage <MaskImageType>(structure);
+ file = this->GetAFDB()->GetTagValue(structure);
+ MaskImagePointType p;
+ p[0] = p[1] = p[2] = 0.0; // to avoid warning
+ if (structure_limit == "superior")
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
+ else
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
+ z = p[2];
+ found=1;
+ }
+
+ // Try to load structureZ
+ if ((found==0) && (this->GetAFDB()->TagExist(structure+"Z"))) {
+ z = this->GetAFDB()->GetDouble(structure+"Z");
+ found=2;
+ }
+
+ // Try to load structurePoint
+ if ((found==0) && (this->GetAFDB()->TagExist(structure+"Point"))) {
+ MaskImagePointType p;
+ this->GetAFDB()->GetPoint3D(structure+"Point", p);
+ z = p[2];
+ found=3;
+ }
+
+ // Try to see if it is an already computed support
+ if (found==0) {
+ if (m_ListOfSupports.find(structure) != m_ListOfSupports.end()) {
+ MaskImagePointer Structure = m_ListOfSupports[structure];
+ MaskImagePointType p;
+ if (structure_limit == "superior")
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, false, p);
+ else
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Structure, GetBackgroundValue(), 2, true, p);
+ z = p[2];
+ found=4;
+ }
+ }
+
+ // Try special case : "FindApexOfTheChest"
+ if (structure == "FindApexOfTheChest") {
+ z = FindApexOfTheChest();
+ found=5;
+ }
+ if (structure == "FindInferiorBorderOfAorticArch") {
+ z = FindInferiorBorderOfAorticArch();
+ found=6;
+ }
+ if (structure == "FindSuperiorBorderOfAorticArch") {
+ z = FindSuperiorBorderOfAorticArch();
+ found=6;
+ }
+
+ // If we find anything
+ if (found == 0) {
+ std::cerr << "ERROR : I could not find " << structure << " nor " << structure << "Z nor "
+ << structure << "Point" << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ // Apply offset
+ z += offset;
+
+ // Remove Lower or greater
+ if (station_limit == "inferior") {
+ m_Working_Support =
+ clitk::CropImageRemoveLowerThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
+ }
+ else {
+ m_Working_Support =
+ clitk::CropImageRemoveGreaterThan<MaskImageType>(m_Working_Support, 2, z, true, GetBackgroundValue());
+ }
+
+ // Check: if reference station is given, display information
+ if (GetCheckSupportFlag()) {
+ try {
+ MaskImagePointer Ref = this->GetAFDB()->template GetImage <MaskImageType>(station+"_Ref");
+ MaskImagePointType p_support;
+ MaskImagePointType p_ref;
+ if (station_limit == "superior") {
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, false, p_ref);
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, false, p_support);
+ }
+ else {
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Ref, GetBackgroundValue(), 2, true, p_ref);
+ clitk::FindExtremaPointInAGivenDirection<MaskImageType>(m_Working_Support, GetBackgroundValue(), 2, true, p_support);
+ }
+ std::ostringstream os;
+ os << "[Support] \t" << station << "\t" << station_limit << " "
+ << "Z = " << z << std::setprecision(2) << std::fixed
+ << "\tSupport = " << p_support[2]
+ << "\tRef = " << p_ref[2]
+ << "\tdiff = " << p_support[2]-p_ref[2] << "\t"
+ << structure << " " << structure_limit;
+ if (found==1) os << " (S "+file+")";
+ if (found==2) os << " (Z)";
+ if (found==3) os << " (P)";
+ if (found==4) os << " (p)";
+ if (found==5) os << " (Apex)";
+ if (found==6) os << " (AorticArch)";
+ StartNewStep(os.str());
+ } catch(clitk::ExceptionObject e) { }
+ }
+
+ // Set support
+ m_ListOfSupports[station] = m_Working_Support;
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+Support_LeftRight_S1R_S1L()
+{