diff --git a/Modules/Core/Common/include/itkAnatomicalOrientation.h b/Modules/Core/Common/include/itkAnatomicalOrientation.h index bb977d5382e..581d10fa7ab 100644 --- a/Modules/Core/Common/include/itkAnatomicalOrientation.h +++ b/Modules/Core/Common/include/itkAnatomicalOrientation.h @@ -92,6 +92,7 @@ class ITKCommon_EXPORT AnatomicalOrientation { INVALID = 0, + RIP = m_OrientationValue, @@ -247,6 +248,7 @@ class ITKCommon_EXPORT AnatomicalOrientation { INVALID = 0, + RIP = m_OrientationValue, @@ -416,11 +418,10 @@ class ITKCommon_EXPORT AnatomicalOrientation * * @param legacyOrientation */ - AnatomicalOrientation(LegacyOrientationType legacyOrientation) -# ifdef ITK_FUTURE_LEGACY_REMOVE - [deprecated("Use the AnatomicalOrientation::FromEnum type instead.")] +# ifdef ITK_LEGACY_REMOVE + [[deprecated("Use the AnatomicalOrientation::FromEnum type instead.")]] # endif - ; + AnatomicalOrientation(LegacyOrientationType legacyOrientation); #endif AnatomicalOrientation(FromEnum orientation); @@ -429,12 +430,28 @@ class ITKCommon_EXPORT AnatomicalOrientation : m_Value(DirectionCosinesToOrientation(d)) {} - explicit AnatomicalOrientation(std::string str); - operator ToEnum() const { return m_Value; } std::string - GetAsString() const; + GetAsToStringEncoding() const; + + std::string + GetAsFromStringEncoding() const; + + static AnatomicalOrientation + CreateFromToStringEncoding(std::string str); + + static AnatomicalOrientation + CreateFromFromStringEncoding(std::string str); + + /** An involution to convert between "to" and "from" single charactor encoding strings. + * + * For example the string "RAS" is converted to "LPI" and vice versa. + * + * + * */ + static std::string + ConvertStringEncoding(std::string str); DirectionType GetAsDirection() const @@ -475,7 +492,7 @@ class ITKCommon_EXPORT AnatomicalOrientation static bool SameOrientationAxes(CoordinateEnum a, CoordinateEnum b) { - const unsigned int AxisField = 0xE; // b1110, mask lowest bit + const unsigned int AxisField = 0xE; // b1110, mask the lowest bit return (static_cast(a) & AxisField) == (static_cast(b) & AxisField); } @@ -493,8 +510,6 @@ class ITKCommon_EXPORT AnatomicalOrientation private: // Private methods to create the maps, these will only be called once. - static std::map - CreateCodeToString(); /** \brief Return the global instance of the map from orientation enum to strings. * diff --git a/Modules/Core/Common/src/itkAnatomicalOrientation.cxx b/Modules/Core/Common/src/itkAnatomicalOrientation.cxx index 7588243e005..071edcdd59b 100644 --- a/Modules/Core/Common/src/itkAnatomicalOrientation.cxx +++ b/Modules/Core/Common/src/itkAnatomicalOrientation.cxx @@ -40,20 +40,6 @@ AnatomicalOrientation::AnatomicalOrientation(CoordinateEnum primary, CoordinateE } } -AnatomicalOrientation::AnatomicalOrientation(std::string str) - : m_Value(ToEnum::INVALID) -{ - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - - const std::map & stringToCode = GetStringToCode(); - auto iter = stringToCode.find(str); - if (iter != stringToCode.end()) - { - m_Value = iter->second; - } -} - - #ifndef ITK_FUTURE_LEGACY_REMOVE AnatomicalOrientation::AnatomicalOrientation(LegacyOrientationType legacyOrientation) : AnatomicalOrientation(SpatialOrientationAdapter::ToDirectionCosines(legacyOrientation)) @@ -68,7 +54,7 @@ AnatomicalOrientation::AnatomicalOrientation(AnatomicalOrientation::FromEnum fro std::string -AnatomicalOrientation::GetAsString() const +AnatomicalOrientation::GetAsToStringEncoding() const { // a lambda function to convert a CoordinateEnum to a char @@ -101,6 +87,52 @@ AnatomicalOrientation::GetAsString() const } +std::string +AnatomicalOrientation::GetAsFromStringEncoding() const +{ + return ConvertStringEncoding(GetAsToStringEncoding()); +} + + +AnatomicalOrientation +AnatomicalOrientation::CreateFromToStringEncoding(std::string str) +{ + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + + const std::map & stringToCode = GetStringToCode(); + auto iter = stringToCode.find(str); + if (iter == stringToCode.end()) + { + return AnatomicalOrientation(ToEnum::INVALID); + } + return AnatomicalOrientation(iter->second); +} + +AnatomicalOrientation +AnatomicalOrientation::CreateFromFromStringEncoding(std::string str) +{ + return AnatomicalOrientation::CreateFromToStringEncoding(ConvertStringEncoding(str)); +} + + +std::string +AnatomicalOrientation::ConvertStringEncoding(std::string str) +{ + const std::map flipmap = { { 'R', 'L' }, { 'L', 'R' }, { 'A', 'P' }, { 'P', 'A' }, + { 'S', 'I' }, { 'I', 'S' }, { 'X', 'X' } }; + + for (auto & c : str) + { + auto it = flipmap.find(toupper(c)); + if (it != flipmap.end()) + { + c = it->second; + } + } + return str; +} + + AnatomicalOrientation::CoordinateEnum AnatomicalOrientation::GetCoordinateTerm(CoordinateMajornessTermsEnum cmt) const { @@ -111,7 +143,23 @@ AnatomicalOrientation::GetCoordinateTerm(CoordinateMajornessTermsEnum cmt) const const std::map & AnatomicalOrientation::GetCodeToString() { - static const std::map codeToString = CreateCodeToString(); + auto createCodeToString = []() -> std::map { + std::map orientToString; + + for (auto code : { ToEnum::RIP, ToEnum::LIP, ToEnum::RSP, ToEnum::LSP, ToEnum::RIA, ToEnum::LIA, ToEnum::RSA, + ToEnum::LSA, ToEnum::IRP, ToEnum::ILP, ToEnum::SRP, ToEnum::SLP, ToEnum::IRA, ToEnum::ILA, + ToEnum::SRA, ToEnum::SLA, ToEnum::RPI, ToEnum::LPI, ToEnum::RAI, ToEnum::LAI, ToEnum::RPS, + ToEnum::LPS, ToEnum::RAS, ToEnum::LAS, ToEnum::PRI, ToEnum::PLI, ToEnum::ARI, ToEnum::ALI, + ToEnum::PRS, ToEnum::PLS, ToEnum::ARS, ToEnum::ALS, ToEnum::IPR, ToEnum::SPR, ToEnum::IAR, + ToEnum::SAR, ToEnum::IPL, ToEnum::SPL, ToEnum::IAL, ToEnum::SAL, ToEnum::PIR, ToEnum::PSR, + ToEnum::AIR, ToEnum::ASR, ToEnum::PIL, ToEnum::PSL, ToEnum::AIL, ToEnum::ASL, ToEnum::INVALID }) + { + orientToString[code] = AnatomicalOrientation(code).GetAsToStringEncoding(); + } + + return orientToString; + }; + static const std::map codeToString = createCodeToString(); return codeToString; } @@ -135,67 +183,6 @@ AnatomicalOrientation::GetStringToCode() } -std::map -AnatomicalOrientation::CreateCodeToString() -{ - std::map orientToString; - auto helperAddCode = [&orientToString](std::string str, ToEnum code) { orientToString[code] = std::move(str); }; - - // Map between axis string labels and SpatialOrientation - helperAddCode("RIP", ToEnum::RIP); - helperAddCode("LIP", ToEnum::LIP); - helperAddCode("RSP", ToEnum::RSP); - helperAddCode("LSP", ToEnum::LSP); - helperAddCode("RIA", ToEnum::RIA); - helperAddCode("LIA", ToEnum::LIA); - helperAddCode("RSA", ToEnum::RSA); - helperAddCode("LSA", ToEnum::LSA); - helperAddCode("IRP", ToEnum::IRP); - helperAddCode("ILP", ToEnum::ILP); - helperAddCode("SRP", ToEnum::SRP); - helperAddCode("SLP", ToEnum::SLP); - helperAddCode("IRA", ToEnum::IRA); - helperAddCode("ILA", ToEnum::ILA); - helperAddCode("SRA", ToEnum::SRA); - helperAddCode("SLA", ToEnum::SLA); - helperAddCode("RPI", ToEnum::RPI); - helperAddCode("LPI", ToEnum::LPI); - helperAddCode("RAI", ToEnum::RAI); - helperAddCode("LAI", ToEnum::LAI); - helperAddCode("RPS", ToEnum::RPS); - helperAddCode("LPS", ToEnum::LPS); - helperAddCode("RAS", ToEnum::RAS); - helperAddCode("LAS", ToEnum::LAS); - helperAddCode("PRI", ToEnum::PRI); - helperAddCode("PLI", ToEnum::PLI); - helperAddCode("ARI", ToEnum::ARI); - helperAddCode("ALI", ToEnum::ALI); - helperAddCode("PRS", ToEnum::PRS); - helperAddCode("PLS", ToEnum::PLS); - helperAddCode("ARS", ToEnum::ARS); - helperAddCode("ALS", ToEnum::ALS); - helperAddCode("IPR", ToEnum::IPR); - helperAddCode("SPR", ToEnum::SPR); - helperAddCode("IAR", ToEnum::IAR); - helperAddCode("SAR", ToEnum::SAR); - helperAddCode("IPL", ToEnum::IPL); - helperAddCode("SPL", ToEnum::SPL); - helperAddCode("IAL", ToEnum::IAL); - helperAddCode("SAL", ToEnum::SAL); - helperAddCode("PIR", ToEnum::PIR); - helperAddCode("PSR", ToEnum::PSR); - helperAddCode("AIR", ToEnum::AIR); - helperAddCode("ASR", ToEnum::ASR); - helperAddCode("PIL", ToEnum::PIL); - helperAddCode("PSL", ToEnum::PSL); - helperAddCode("AIL", ToEnum::AIL); - helperAddCode("ASL", ToEnum::ASL); - helperAddCode("INVALID", ToEnum::INVALID); - - return orientToString; -} - - typename AnatomicalOrientation::ToEnum AnatomicalOrientation::DirectionCosinesToOrientation(const DirectionType & dir) { @@ -322,15 +309,14 @@ operator<<(std::ostream & out, typename AnatomicalOrientation::CoordinateEnum va std::ostream & operator<<(std::ostream & out, typename AnatomicalOrientation::ToEnum value) { - - auto iter = AnatomicalOrientation::GetCodeToString().find(value); - if (iter == AnatomicalOrientation::GetCodeToString().end()) - { - return (out << "invalid"); - } - return (out << iter->second); + return (out << AnatomicalOrientation(value).GetAsToStringEncoding()); } +std::ostream & +operator<<(std::ostream & out, typename AnatomicalOrientation::FromEnum value) +{ + return (out << AnatomicalOrientation(value).GetAsFromStringEncoding()); +} std::ostream & operator<<(std::ostream & out, const AnatomicalOrientation & orientation) diff --git a/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx b/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx index 2be4f52f812..1e5fdd6f09f 100644 --- a/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx +++ b/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx @@ -35,7 +35,7 @@ TEST(AnatomicalOrientation, ConstructionAndValues) AnatomicalOrientation do1(OE::LPS); - EXPECT_EQ("LPS", do1.GetAsString()); + EXPECT_EQ("LPS", do1.GetAsToStringEncoding()); EXPECT_EQ(CE::RightToLeft, do1.GetPrimaryTerm()); EXPECT_EQ(CE::AnteriorToPosterior, do1.GetSecondaryTerm()); EXPECT_EQ(CE::InferiorToSuperior, do1.GetTertiaryTerm()); @@ -45,9 +45,9 @@ TEST(AnatomicalOrientation, ConstructionAndValues) EXPECT_EQ(d, do1.GetAsDirection()); - do1 = AnatomicalOrientation("RAS"); + do1 = AnatomicalOrientation::CreateFromToStringEncoding("RAS"); - EXPECT_EQ("RAS", do1.GetAsString()); + EXPECT_EQ("RAS", do1.GetAsToStringEncoding()); EXPECT_EQ(CE::LeftToRight, do1.GetPrimaryTerm()); EXPECT_EQ(CE::PosteriorToAnterior, do1.GetSecondaryTerm()); EXPECT_EQ(CE::InferiorToSuperior, do1.GetTertiaryTerm()); @@ -60,9 +60,9 @@ TEST(AnatomicalOrientation, ConstructionAndValues) EXPECT_EQ(d, do1.GetAsDirection()); - do1 = AnatomicalOrientation("rai"); + do1 = AnatomicalOrientation::CreateFromToStringEncoding("rai"); - EXPECT_EQ("RAI", do1.GetAsString()); + EXPECT_EQ("RAI", do1.GetAsToStringEncoding()); EXPECT_EQ(CE::LeftToRight, do1.GetPrimaryTerm()); EXPECT_EQ(CE::PosteriorToAnterior, do1.GetSecondaryTerm()); EXPECT_EQ(CE::SuperiorToInferior, do1.GetTertiaryTerm()); @@ -71,7 +71,7 @@ TEST(AnatomicalOrientation, ConstructionAndValues) do1 = AnatomicalOrientation(OE::PIR); - EXPECT_EQ("PIR", do1.GetAsString()); + EXPECT_EQ("PIR", do1.GetAsToStringEncoding()); EXPECT_EQ(CE::AnteriorToPosterior, do1.GetPrimaryTerm()); EXPECT_EQ(CE::SuperiorToInferior, do1.GetSecondaryTerm()); EXPECT_EQ(CE::LeftToRight, do1.GetTertiaryTerm()); @@ -85,7 +85,7 @@ TEST(AnatomicalOrientation, ConstructionAndValues) AnatomicalOrientation do2(d); - EXPECT_EQ("PIR", do2.GetAsString()); + EXPECT_EQ("PIR", do2.GetAsToStringEncoding()); EXPECT_EQ(CE::AnteriorToPosterior, do2.GetPrimaryTerm()); EXPECT_EQ(CE::SuperiorToInferior, do2.GetSecondaryTerm()); EXPECT_EQ(CE::LeftToRight, do2.GetTertiaryTerm()); @@ -93,8 +93,8 @@ TEST(AnatomicalOrientation, ConstructionAndValues) EXPECT_EQ(d, do2.GetAsDirection()); - AnatomicalOrientation do3("something invalid"); - EXPECT_EQ("INVALID", do3.GetAsString()); + AnatomicalOrientation do3 = AnatomicalOrientation::CreateFromToStringEncoding("something invalid"); + EXPECT_EQ("INVALID", do3.GetAsToStringEncoding()); EXPECT_EQ(CE::UNKNOWN, do3.GetPrimaryTerm()); EXPECT_EQ(CE::UNKNOWN, do3.GetSecondaryTerm()); EXPECT_EQ(CE::UNKNOWN, do3.GetTertiaryTerm()); @@ -222,7 +222,7 @@ TEST(AntomicalOrientation, ToFromEnumInteroperability) EXPECT_EQ(itk_rai, itk::AnatomicalOrientation(OE::LPS)); EXPECT_EQ(itk_rai.GetAsOrientation(), OE::LPS); - EXPECT_EQ(itk_rai.GetAsString(), "LPS"); + EXPECT_EQ(itk_rai.GetAsToStringEncoding(), "LPS"); const std::array expected_terms = { { CE::RightToLeft, CE::AnteriorToPosterior, CE::InferiorToSuperior } }; EXPECT_EQ(itk_rai.GetTerms(), expected_terms); } @@ -244,6 +244,6 @@ TEST(AnatomicalOrientation, LegacyInteroperability) itk::AnatomicalOrientation itk_rai(SOE::ITK_COORDINATE_ORIENTATION_RAI); EXPECT_EQ(itk_rai, OE::LPS); EXPECT_EQ(itk_rai.GetAsOrientation(), OE::LPS); - EXPECT_EQ(itk_rai.GetAsString(), "LPS"); + EXPECT_EQ(itk_rai.GetAsToStringEncoding(), "LPS"); } #endif diff --git a/Modules/IO/ImageBase/test/itkReadWriteImageWithDictionaryTest.cxx b/Modules/IO/ImageBase/test/itkReadWriteImageWithDictionaryTest.cxx index 1fb9369e409..91308882284 100644 --- a/Modules/IO/ImageBase/test/itkReadWriteImageWithDictionaryTest.cxx +++ b/Modules/IO/ImageBase/test/itkReadWriteImageWithDictionaryTest.cxx @@ -47,7 +47,7 @@ itkReadWriteImageWithDictionaryTest(int argc, char * argv[]) inputImage->Allocate(); inputImage->FillBuffer(0); - inputImage->SetDirection(itk::AnatomicalOrientation("LSA").GetAsDirection()); + inputImage->SetDirection(itk::AnatomicalOrientation::CreateFromToStringEncoding("LSA").GetAsDirection()); // Add some metadata in the dictionary itk::MetaDataDictionary & inputDictionary = inputImage->GetMetaDataDictionary(); diff --git a/Modules/IO/NIFTI/test/itkNiftiReadAnalyzeTest.cxx b/Modules/IO/NIFTI/test/itkNiftiReadAnalyzeTest.cxx index d8f9b69a272..1431e4f8903 100644 --- a/Modules/IO/NIFTI/test/itkNiftiReadAnalyzeTest.cxx +++ b/Modules/IO/NIFTI/test/itkNiftiReadAnalyzeTest.cxx @@ -184,11 +184,11 @@ itkNiftiAnalyzeContentsAndCoordinatesTest(char * { std::string hdrName(argv[1]); hdrName += "/littleEndian_"; - hdrName += expected_code.GetAsString(); + hdrName += expected_code.GetAsToStringEncoding(); hdrName += ".hdr"; std::string imgName(argv[1]); imgName += "/littleEndian_"; - imgName += expected_code.GetAsString(); + imgName += expected_code.GetAsToStringEncoding(); imgName += ".img"; // hack the header to have proper orientation code @@ -253,8 +253,8 @@ itkNiftiAnalyzeContentsAndCoordinatesTest(char * if (orientation_code != expected_code) { std::cerr << "Analyze orientation " << static_cast(hist_orient_code) << std::endl; - std::cerr << "expected orientation " << expected_code.GetAsString() << " but found " - << orientation_code.GetAsString() << std::endl; + std::cerr << "expected orientation " << expected_code.GetAsToStringEncoding() << " but found " + << orientation_code.GetAsToStringEncoding() << std::endl; return EXIT_FAILURE; } @@ -264,7 +264,7 @@ itkNiftiAnalyzeContentsAndCoordinatesTest(char * << "negative x step:" << (flip_x ? "true" : "false") << std::endl << "Origin :" << img->GetOrigin() << std::endl << "Spacing :" << img->GetSpacing() << std::endl - << "Code :" << orientation_code.GetAsString() << std::endl + << "Code :" << orientation_code.GetAsToStringEncoding() << std::endl << "Direction:" << img->GetDirection() << std::endl; return EXIT_SUCCESS;