diff --git a/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp b/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp index 771a6ab4e9..8390b79d90 100644 --- a/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp +++ b/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp @@ -1,460 +1,458 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include #define BOOST_DATE_TIME_NO_LIB //Prevent unnecessary/unwanted auto link in this compilation when activating boost libraries in the MITK superbuild //It is necessary because BOOST_ALL_DYN_LINK overwrites BOOST_DATE_TIME_NO_LIB #if defined(BOOST_ALL_DYN_LINK) #undef BOOST_ALL_DYN_LINK #endif #include #include "mitkITKDICOMSeriesReaderHelper.h" #include "mitkITKDICOMSeriesReaderHelper.txx" #include "mitkDICOMGDCMTagScanner.h" #include "mitkArbitraryTimeGeometry.h" #include "dcvrda.h" const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::AcquisitionDateTag = mitk::DICOMTag( 0x0008, 0x0022 ); const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::AcquisitionTimeTag = mitk::DICOMTag( 0x0008, 0x0032 ); const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::TriggerTimeTag = mitk::DICOMTag( 0x0018, 0x1060 ); #define switch3DCase( IOType, T ) \ case IOType: \ return LoadDICOMByITK( filenames, correctTilt, tiltInfo, io ); bool mitk::ITKDICOMSeriesReaderHelper::CanHandleFile( const std::string& filename ) { MITK_DEBUG << "ITKDICOMSeriesReaderHelper::CanHandleFile " << filename; itk::GDCMImageIO::Pointer tester = itk::GDCMImageIO::New(); return tester->CanReadFile( filename.c_str() ); } mitk::Image::Pointer mitk::ITKDICOMSeriesReaderHelper::Load( const StringContainer& filenames, bool correctTilt, const GantryTiltInformation& tiltInfo ) { if ( filenames.empty() ) { MITK_DEBUG << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic."; return nullptr; // this is not actually an error but the result is very simple } typedef itk::GDCMImageIO DcmIoType; DcmIoType::Pointer io = DcmIoType::New(); try { if ( io->CanReadFile( filenames.front().c_str() ) ) { io->SetFileName( filenames.front().c_str() ); io->ReadImageInformation(); if ( io->GetPixelType() == itk::ImageIOBase::SCALAR ) { switch ( io->GetComponentType() ) { switch3DCase(DcmIoType::UCHAR, unsigned char) switch3DCase(DcmIoType::CHAR, char) switch3DCase( DcmIoType::USHORT, unsigned short) switch3DCase(DcmIoType::SHORT, short) switch3DCase(DcmIoType::UINT, unsigned int) switch3DCase(DcmIoType::INT, int) switch3DCase( DcmIoType::ULONG, long unsigned int) switch3DCase(DcmIoType::LONG, long int) switch3DCase(DcmIoType::FLOAT, float) switch3DCase(DcmIoType::DOUBLE, double) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } else if ( io->GetPixelType() == itk::ImageIOBase::RGB ) { switch ( io->GetComponentType() ) { switch3DCase(DcmIoType::UCHAR, itk::RGBPixel) switch3DCase( DcmIoType::CHAR, itk::RGBPixel) switch3DCase(DcmIoType::USHORT, itk::RGBPixel) switch3DCase(DcmIoType::SHORT, itk::RGBPixel) switch3DCase( DcmIoType::UINT, itk::RGBPixel) switch3DCase(DcmIoType::INT, itk::RGBPixel) switch3DCase(DcmIoType::ULONG, itk::RGBPixel) switch3DCase(DcmIoType::LONG, itk::RGBPixel) switch3DCase( DcmIoType::FLOAT, itk::RGBPixel) switch3DCase(DcmIoType::DOUBLE, itk::RGBPixel) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } MITK_ERROR << "Unsupported DICOM pixel type"; return nullptr; } } catch ( const itk::MemoryAllocationError& e ) { MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what(); } catch ( const std::exception& e ) { MITK_ERROR << "Error encountered when loading DICOM series:" << e.what(); } catch ( ... ) { MITK_ERROR << "Unspecified error encountered when loading DICOM series."; } return nullptr; } #define switch3DnTCase( IOType, T ) \ case IOType: \ return LoadDICOMByITK3DnT( filenamesLists, correctTilt, tiltInfo, io ); mitk::Image::Pointer mitk::ITKDICOMSeriesReaderHelper::Load3DnT( const StringContainerList& filenamesLists, bool correctTilt, const GantryTiltInformation& tiltInfo ) { if ( filenamesLists.empty() || filenamesLists.front().empty() ) { MITK_DEBUG << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic."; return nullptr; // this is not actually an error but the result is very simple } typedef itk::GDCMImageIO DcmIoType; DcmIoType::Pointer io = DcmIoType::New(); try { if ( io->CanReadFile( filenamesLists.front().front().c_str() ) ) { io->SetFileName( filenamesLists.front().front().c_str() ); io->ReadImageInformation(); if ( io->GetPixelType() == itk::ImageIOBase::SCALAR ) { switch ( io->GetComponentType() ) { switch3DnTCase(DcmIoType::UCHAR, unsigned char) switch3DnTCase(DcmIoType::CHAR, char) switch3DnTCase(DcmIoType::USHORT, unsigned short) switch3DnTCase( DcmIoType::SHORT, short) switch3DnTCase(DcmIoType::UINT, unsigned int) switch3DnTCase(DcmIoType::INT, int) switch3DnTCase(DcmIoType::ULONG, long unsigned int) switch3DnTCase(DcmIoType::LONG, long int) switch3DnTCase(DcmIoType::FLOAT, float) switch3DnTCase(DcmIoType::DOUBLE, double) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } else if ( io->GetPixelType() == itk::ImageIOBase::RGB ) { switch ( io->GetComponentType() ) { switch3DnTCase(DcmIoType::UCHAR, itk::RGBPixel) switch3DnTCase(DcmIoType::CHAR, itk::RGBPixel) switch3DnTCase( DcmIoType::USHORT, itk::RGBPixel) switch3DnTCase(DcmIoType::SHORT, itk::RGBPixel) switch3DnTCase(DcmIoType::UINT, itk::RGBPixel) switch3DnTCase( DcmIoType::INT, itk::RGBPixel) switch3DnTCase(DcmIoType::ULONG, itk::RGBPixel) switch3DnTCase(DcmIoType::LONG, itk::RGBPixel) switch3DnTCase( DcmIoType::FLOAT, itk::RGBPixel) switch3DnTCase(DcmIoType::DOUBLE, itk::RGBPixel) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } MITK_ERROR << "Unsupported DICOM pixel type"; return nullptr; } } catch ( const itk::MemoryAllocationError& e ) { MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what(); } catch ( const std::exception& e ) { MITK_ERROR << "Error encountered when loading DICOM series:" << e.what(); } catch ( ... ) { MITK_ERROR << "Unspecified error encountered when loading DICOM series."; } return nullptr; } bool ConvertDICOMDateTimeString( const std::string& dateString, const std::string& timeString, OFDateTime& time ) { OFString content( timeString.c_str() ); if ( !dateString.empty() ) { content = OFString( dateString.c_str() ).append( content ); } else { // This is a workaround for DICOM data that has an AquisitionTime but no AquisitionDate. // In this case, we use the current date. That's not really nice, but is absolutely OK // as we're only interested in the time anyways... OFString currentDate; DcmDate::getCurrentDate( currentDate ); content = currentDate.append( content ); } const OFCondition result = DcmDateTime::getOFDateTimeFromString( content, time ); return result.good(); } boost::posix_time::ptime ConvertOFDateTimeToPTime( const OFDateTime& time ) { const boost::gregorian::date boostDate( time.getDate().getYear(), time.getDate().getMonth(), time.getDate().getDay() ); const boost::posix_time::time_duration boostTime = boost::posix_time::hours( time.getTime().getHour() ) + boost::posix_time::minutes( time.getTime().getMinute() ) + boost::posix_time::seconds( time.getTime().getSecond() ) + boost::posix_time::milliseconds( time.getTime().getMilliSecond() ); boost::posix_time::ptime result( boostDate, boostTime ); return result; } OFDateTime GetLowerDateTime( const OFDateTime& time1, const OFDateTime& time2 ) { OFDateTime result = time1; if ( ( time2.getDate() < time1.getDate() ) || ( ( time2.getDate() == time1.getDate() ) && ( time2.getTime() < time1.getTime() ) ) ) { result = time2; } return result; } OFDateTime GetUpperDateTime( const OFDateTime& time1, const OFDateTime& time2 ) { OFDateTime result = time1; if ( ( time2.getDate() > time1.getDate() ) || ( ( time2.getDate() == time1.getDate() ) && ( time2.getTime() > time1.getTime() ) ) ) { result = time2; } return result; } double ComputeMiliSecDuration( const OFDateTime& start, const OFDateTime& stop ) { const boost::posix_time::ptime startTime = ConvertOFDateTimeToPTime( start ); const boost::posix_time::ptime stopTime = ConvertOFDateTimeToPTime( stop ); ::boost::posix_time::time_duration duration = stopTime - startTime; return duration.total_milliseconds(); } bool mitk::ITKDICOMSeriesReaderHelper::ExtractDateTimeBoundsAndTriggerOfTimeStep( const StringContainer& filenamesOfTimeStep, DateTimeBounds& bounds, TimeBounds& triggerBounds) { DICOMGDCMTagScanner::Pointer filescanner = DICOMGDCMTagScanner::New(); filescanner->SetInputFiles(filenamesOfTimeStep); filescanner->AddTag(AcquisitionDateTag); filescanner->AddTag(AcquisitionTimeTag); filescanner->AddTag(TriggerTimeTag); filescanner->Scan(); const DICOMDatasetAccessingImageFrameList frameList = filescanner->GetFrameInfoList(); bool result = false; bool firstAq = true; bool firstTr = true; triggerBounds = TimeBounds(0.0); for (DICOMDatasetAccessingImageFrameList::const_iterator pos = frameList.cbegin(); pos != frameList.cend(); ++pos) { const std::string aqDateStr = (*pos)->GetTagValueAsString(AcquisitionDateTag).value; const std::string aqTimeStr = (*pos)->GetTagValueAsString(AcquisitionTimeTag).value; const std::string triggerTimeStr = (*pos)->GetTagValueAsString(TriggerTimeTag).value; OFDateTime aqDateTime; const bool convertAqResult = ConvertDICOMDateTimeString(aqDateStr, aqTimeStr, aqDateTime); OFBool convertTriggerResult; mitk::ScalarType triggerTime = OFStandard::atof(triggerTimeStr.c_str(), &convertTriggerResult); if (convertAqResult) { if (firstAq) { bounds[0] = aqDateTime; bounds[1] = aqDateTime; firstAq = false; } else { bounds[0] = GetLowerDateTime(bounds[0], aqDateTime); bounds[1] = GetUpperDateTime(bounds[1], aqDateTime); } result = true; } if (convertTriggerResult) { if (firstTr) { triggerBounds[0] = triggerTime; triggerBounds[1] = triggerTime; firstTr = false; } else { triggerBounds[0] = std::min(triggerBounds[0], triggerTime); triggerBounds[1] = std::max(triggerBounds[1], triggerTime); } result = true; } } return result; }; bool mitk::ITKDICOMSeriesReaderHelper::ExtractTimeBoundsOfTimeStep( const StringContainer& filenamesOfTimeStep, TimeBounds& bounds, const OFDateTime& baselineDateTime ) { DateTimeBounds aqDTBounds; TimeBounds triggerBounds; bool result = ExtractDateTimeBoundsAndTriggerOfTimeStep(filenamesOfTimeStep, aqDTBounds, triggerBounds); mitk::ScalarType lowerBound = ComputeMiliSecDuration( baselineDateTime, aqDTBounds[0] ); mitk::ScalarType upperBound = ComputeMiliSecDuration( baselineDateTime, aqDTBounds[1] ); if ( lowerBound < mitk::eps || upperBound < mitk::eps ) { lowerBound = triggerBounds[0]; upperBound = triggerBounds[1]; } bounds[0] = lowerBound; bounds[1] = upperBound; return result; }; mitk::ITKDICOMSeriesReaderHelper::TimeBoundsList mitk::ITKDICOMSeriesReaderHelper::ExtractTimeBoundsOfTimeSteps( const StringContainerList& filenamesOfTimeSteps ) { TimeBoundsList result; OFDateTime baseLine; - bool baseLineSet = false; // extract the timebounds DateTimeBounds baselineDateTimeBounds; TimeBounds triggerBounds; StringContainerList::const_iterator pos = filenamesOfTimeSteps.cbegin(); ExtractDateTimeBoundsAndTriggerOfTimeStep(*pos, baselineDateTimeBounds, triggerBounds); baseLine = baselineDateTimeBounds[0]; - baseLineSet = true; // timebounds for baseline is 0 TimeBounds bounds( 0.0 ); result.push_back( bounds ); // iterate over the remaining timesteps for ( ++pos; pos != filenamesOfTimeSteps.cend(); ++pos ) { TimeBounds bounds( 0.0 ); TimeBounds dateTimeBounds; // extract the timebounds relative to the baseline if ( ExtractTimeBoundsOfTimeStep( *pos, dateTimeBounds, baseLine ) ) { bounds[0] = dateTimeBounds[0]; bounds[1] = dateTimeBounds[1]; } result.push_back( bounds ); } return result; }; mitk::TimeGeometry::Pointer mitk::ITKDICOMSeriesReaderHelper::GenerateTimeGeometry( const BaseGeometry* templateGeometry, const TimeBoundsList& boundsList ) { TimeGeometry::Pointer timeGeometry; double check = 0.0; const auto boundListSize = boundsList.size(); for ( std::size_t pos = 0; pos < boundListSize; ++pos ) { check += boundsList[pos][0]; check += boundsList[pos][1]; } if ( check < mitk::eps ) { // if all bounds are zero we assume that the bounds could not be correctly determined // and as a fallback generate a time geometry in the old mitk style ProportionalTimeGeometry::Pointer newTimeGeometry = ProportionalTimeGeometry::New(); newTimeGeometry->Initialize( templateGeometry, boundListSize ); timeGeometry = newTimeGeometry.GetPointer(); } else { ArbitraryTimeGeometry::Pointer newTimeGeometry = ArbitraryTimeGeometry::New(); newTimeGeometry->ClearAllGeometries(); newTimeGeometry->ReserveSpaceForGeometries( boundListSize ); for ( std::size_t pos = 0; pos < boundListSize; ++pos ) { TimeBounds bounds = boundsList[pos]; if ( pos + 1 < boundListSize ) { //Currently we do not explicitly support "gaps" in the time coverage //thus we set the max time bound of a time step to the min time bound //of its successor. bounds[1] = boundsList[pos + 1][0]; } newTimeGeometry->AppendNewTimeStepClone(templateGeometry, bounds[0], bounds[1]); } timeGeometry = newTimeGeometry.GetPointer(); } return timeGeometry; }; diff --git a/Modules/DICOMReader/test/mitkDICOMTagPathTest.cpp b/Modules/DICOMReader/test/mitkDICOMTagPathTest.cpp index 937f1f6c66..57c993fcad 100644 --- a/Modules/DICOMReader/test/mitkDICOMTagPathTest.cpp +++ b/Modules/DICOMReader/test/mitkDICOMTagPathTest.cpp @@ -1,240 +1,240 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDICOMTagPath.h" #include "mitkTestFixture.h" #include "mitkTestingMacros.h" #include class mitkDICOMTagPathTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkDICOMTagPathTestSuite); MITK_TEST(DICOMTagPathToPropertyRegEx); MITK_TEST(DICOMTagPathToPersistenceKeyRegEx); MITK_TEST(DICOMTagPathToPersistenceKeyTemplate); MITK_TEST(DICOMTagPathToPersistenceNameTemplate); MITK_TEST(DICOMTagPathToDCMTKSearchPath); MITK_TEST(PropertyNameToDICOMTagPath); MITK_TEST(DICOMTagPathToPropertyName); MITK_TEST(ExecutePropertyRegEx); CPPUNIT_TEST_SUITE_END(); private: mitk::DICOMTagPath simplePath; mitk::DICOMTagPath deepPath; mitk::DICOMTagPath deepPath_withAnyElement; mitk::DICOMTagPath deepPath_withAnySelection; mitk::DICOMTagPath deepPath_withSelection; mitk::DICOMTagPath verydeepPath; mitk::DICOMTagPath emptyPath; public: void setUp() override { simplePath.AddElement(0x0010, 0x0011); deepPath.AddElement(0x0010, 0x0011); deepPath.AddElement(0x0020, 0x0022); deepPath.AddElement(0x003A, 0x0033); deepPath_withAnyElement.AddElement(0x0010, 0x0011); deepPath_withAnyElement.AddAnyElement(); deepPath_withAnyElement.AddElement(0x003a, 0x003f); deepPath_withAnySelection.AddElement(0x0010, 0x0011); deepPath_withAnySelection.AddAnySelection(0x002B, 0x002E); deepPath_withAnySelection.AddElement(0x0030, 0x0033); deepPath_withSelection.AddElement(0x0010, 0x0011); deepPath_withSelection.AddSelection(0x0020, 0x0022, 6); deepPath_withSelection.AddElement(0x003b, 0x003e); verydeepPath.AddAnySelection(0x0010, 0x0011); verydeepPath.AddAnyElement(); verydeepPath.AddElement(0x0030, 0x0033); verydeepPath.AddSelection(0x004c, 0x004d, 4); verydeepPath.AddElement(0x0050, 0x0055); } void tearDown() override { } void DICOMTagPathToPropertyRegEx() { std::string result = mitk::DICOMTagPathToPropertyRegEx(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011)'", std::string("DICOM\\.0010\\.0011"), result); result = mitk::DICOMTagPathToPropertyRegEx(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011).(0020,0022).(003A,0033)'", std::string("DICOM\\.0010\\.0011\\.0020\\.0022\\.(003a|003A)\\.0033"), result); result = mitk::DICOMTagPathToPropertyRegEx(deepPath_withAnyElement); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011).*.(003a,003f)'", std::string("DICOM\\.0010\\.0011\\.([A-Fa-f\\d]{4})\\.([A-Fa-f\\d]{4})\\.(003a|003A)\\.(003f|003F)"), result); result = mitk::DICOMTagPathToPropertyRegEx(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011).(002B,002E)[*].(0030,0033)'", std::string("DICOM\\.0010\\.0011\\.(002b|002B)\\.(002e|002E)\\.\\[(\\d*)\\]\\.0030\\.0033"), result); result = mitk::DICOMTagPathToPropertyRegEx(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011).(0020,0022)[6].(003b,003e)'", std::string("DICOM\\.0010\\.0011\\.0020\\.0022\\.\\[6\\]\\.(003b|003B)\\.(003e|003E)"), result); result = mitk::DICOMTagPathToPropertyRegEx(verydeepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyRegEx() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", std::string("DICOM\\.0010\\.0011\\.\\[(\\d*)\\]\\.([A-Fa-f\\d]{4})\\.([A-Fa-f\\d]{4})\\.0030\\.0033\\.(004c|004C)\\.(004d|004D)\\.\\[4\\]\\.0050\\.0055"), result); } void DICOMTagPathToPersistenceKeyRegEx() { std::string result = mitk::DICOMTagPathToPersistenceKeyRegEx(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011)'", std::string("DICOM_0010_0011"), result); result = mitk::DICOMTagPathToPersistenceKeyRegEx(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011).(0020,0022).(003A,0033)'", std::string("DICOM_0010_0011_0020_0022_(003a|003A)_0033"), result); result = mitk::DICOMTagPathToPersistenceKeyRegEx(deepPath_withAnyElement); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011).*.(003a,003f)'", std::string("DICOM_0010_0011_([A-Fa-f\\d]{4})_([A-Fa-f\\d]{4})_(003a|003A)_(003f|003F)"), result); result = mitk::DICOMTagPathToPersistenceKeyRegEx(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011).(002B,002E)[*].(0030,0033)'", std::string("DICOM_0010_0011_(002b|002B)_(002e|002E)_\\[(\\d*)\\]_0030_0033"), result); result = mitk::DICOMTagPathToPersistenceKeyRegEx(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011).(0020,0022)[6].(003b,003e)'", std::string("DICOM_0010_0011_0020_0022_\\[6\\]_(003b|003B)_(003e|003E)"), result); result = mitk::DICOMTagPathToPersistenceKeyRegEx(verydeepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyRegEx() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", std::string("DICOM_0010_0011_\\[(\\d*)\\]_([A-Fa-f\\d]{4})_([A-Fa-f\\d]{4})_0030_0033_(004c|004C)_(004d|004D)_\\[4\\]_0050_0055"), result); } void DICOMTagPathToPersistenceKeyTemplate() { std::string result = mitk::DICOMTagPathToPersistenceKeyTemplate(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011)'", std::string("DICOM_0010_0011"), result); result = mitk::DICOMTagPathToPersistenceKeyTemplate(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011).(0020,0022).(003A,0033)'", std::string("DICOM_0010_0011_0020_0022_003A_0033"), result); result = mitk::DICOMTagPathToPersistenceKeyTemplate(deepPath_withAnyElement); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011).*.(003a,003f)'", std::string("DICOM_0010_0011_$1_$2_003A_003F"), result); result = mitk::DICOMTagPathToPersistenceKeyTemplate(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011).(002B,002E)[*].(0030,0033)'", std::string("DICOM_0010_0011_002B_002E_[$1]_0030_0033"), result); result = mitk::DICOMTagPathToPersistenceKeyTemplate(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011).(0020,0022)[6].(003b,003e)'", std::string("DICOM_0010_0011_0020_0022_[6]_003B_003E"), result); result = mitk::DICOMTagPathToPersistenceKeyTemplate(verydeepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceKeyTemplate() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", std::string("DICOM_0010_0011_[$1]_$2_$3_0030_0033_004C_004D_[4]_0050_0055"), result); } void DICOMTagPathToPersistenceNameTemplate() { std::string result = mitk::DICOMTagPathToPersistenceNameTemplate(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011)'", std::string("DICOM.0010.0011"), result); result = mitk::DICOMTagPathToPersistenceNameTemplate(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011).(0020,0022).(003A,0033)'", std::string("DICOM.0010.0011.0020.0022.003A.0033"), result); result = mitk::DICOMTagPathToPersistenceNameTemplate(deepPath_withAnyElement); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011).*.(003a,003f)'", std::string("DICOM.0010.0011.$1.$2.003A.003F"), result); result = mitk::DICOMTagPathToPersistenceNameTemplate(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011).(002B,002E)[*].(0030,0033)'", std::string("DICOM.0010.0011.002B.002E.[$1].0030.0033"), result); result = mitk::DICOMTagPathToPersistenceNameTemplate(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011).(0020,0022)[6].(003b,003e)'", std::string("DICOM.0010.0011.0020.0022.[6].003B.003E"), result); result = mitk::DICOMTagPathToPersistenceNameTemplate(verydeepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPersistenceNameTemplate() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", std::string("DICOM.0010.0011.[$1].$2.$3.0030.0033.004C.004D.[4].0050.0055"), result); } void DICOMTagPathToDCMTKSearchPath() { std::string result = mitk::DICOMTagPathToDCMTKSearchPath(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToDCMTKSearchPath() with '(0010,0011)'", std::string("(0010,0011)"), result); result = mitk::DICOMTagPathToDCMTKSearchPath(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToDCMTKSearchPath() with '(0010,0011).(0020,0022).(003A,0033)'", std::string("(0010,0011).(0020,0022).(003A,0033)"), result); CPPUNIT_ASSERT_THROW(mitk::DICOMTagPathToDCMTKSearchPath(deepPath_withAnyElement), mitk::Exception); result = mitk::DICOMTagPathToDCMTKSearchPath(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToDCMTKSearchPath() with '(0010,0011).(002B,002E)[*].(0030,0033)'", std::string("(0010,0011).(002B,002E)[*].(0030,0033)"), result); result = mitk::DICOMTagPathToDCMTKSearchPath(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToDCMTKSearchPath() with '(0010,0011).(0020,0022)[6].(003b,003e)'", std::string("(0010,0011).(0020,0022)[6].(003B,003E)"), result); CPPUNIT_ASSERT_THROW(mitk::DICOMTagPathToDCMTKSearchPath(verydeepPath), mitk::Exception); } void PropertyNameToDICOMTagPath() { mitk::DICOMTagPath result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011)'", simplePath, result); result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011.0020.0022.003A.0033"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011).(0020,0022).(003A,0033)'", deepPath, result); result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011.*.003a.003f"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011).*.(003a,003f)'", deepPath_withAnyElement, result); result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011.002B.002E.[*].0030.0033"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011).(002B,002E)[*].(0030,0033)'", deepPath_withAnySelection, result); result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011.0020.0022.[6].003b.003e"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011).(0020,0022)[6].(003b,003e)'", deepPath_withSelection, result); result = mitk::PropertyNameToDICOMTagPath("DICOM.0010.0011.[*].*.0030.0033.004c.004d.[4].0050.0055"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", verydeepPath, result); result = mitk::PropertyNameToDICOMTagPath("WRONG.0010.0011.0020.0022.0030.0033"); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing PropertyNameToDICOMTagPath() with wrong path", emptyPath, result); } void DICOMTagPathToPropertyName() { std::string result = mitk::DICOMTagPathToPropertyName(simplePath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011)'", result, std::string("DICOM.0010.0011")); result = mitk::DICOMTagPathToPropertyName(deepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011).(0020,0022).(003A,0033)'", result, std::string("DICOM.0010.0011.0020.0022.003A.0033")); result = mitk::DICOMTagPathToPropertyName(deepPath_withAnyElement); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011).*.(003a,003f)'", result, std::string("DICOM.0010.0011.*.003A.003F")); result = mitk::DICOMTagPathToPropertyName(deepPath_withAnySelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011).(002B,002E)[*].(0030,0033)'", result, std::string("DICOM.0010.0011.002B.002E.[*].0030.0033")); result = mitk::DICOMTagPathToPropertyName(deepPath_withSelection); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011).(0020,0022)[6].(003b,003e)'", result, std::string("DICOM.0010.0011.0020.0022.[6].003B.003E")); result = mitk::DICOMTagPathToPropertyName(verydeepPath); CPPUNIT_ASSERT_EQUAL_MESSAGE("Testing DICOMTagPathToPropertyName() with '(0010,0011)[*].*.(0030,0033).(004c,004d)[4].(0050,0055)'", result, std::string("DICOM.0010.0011.[*].*.0030.0033.004C.004D.[4].0050.0055")); } void ExecutePropertyRegEx() { std::regex regEx(mitk::DICOMTagPathToPropertyRegEx(simplePath)); std::string result = mitk::DICOMTagPathToPropertyName(simplePath); CPPUNIT_ASSERT(std::regex_match(result, regEx)); regEx = std::regex(mitk::DICOMTagPathToPropertyRegEx(deepPath)); result = mitk::DICOMTagPathToPropertyName(deepPath); CPPUNIT_ASSERT(std::regex_match(result, regEx)); regEx = std::regex(mitk::DICOMTagPathToPropertyRegEx(deepPath_withAnyElement)); result = mitk::DICOMTagPathToPropertyName(deepPath_withAnyElement); - int position = result.find("*"); + auto position = result.find("*"); if (std::string::npos != position) { result.replace(position, 1, "1234.ABCD"); CPPUNIT_ASSERT(std::regex_match(result, regEx)); } regEx = std::regex(mitk::DICOMTagPathToPropertyRegEx(deepPath_withAnySelection)); result = mitk::DICOMTagPathToPropertyName(deepPath_withAnySelection); position = result.find("[*]"); if (std::string::npos != position) { result.replace(position, 3, "[10]"); CPPUNIT_ASSERT(std::regex_match(result, regEx)); } regEx = std::regex(mitk::DICOMTagPathToPropertyRegEx(deepPath_withSelection)); result = mitk::DICOMTagPathToPropertyName(deepPath_withSelection); CPPUNIT_ASSERT(std::regex_match(result, regEx)); regEx = std::regex(mitk::DICOMTagPathToPropertyRegEx(verydeepPath)); result = mitk::DICOMTagPathToPropertyName(verydeepPath); position = result.find("[*]"); if (std::string::npos != position) { result.replace(position, 3, "[1]"); position = result.find("*"); if (std::string::npos != position) { result.replace(position, 1, "abcd.1234"); CPPUNIT_ASSERT(std::regex_match(result, regEx)); } } } }; MITK_TEST_SUITE_REGISTRATION(mitkDICOMTagPath) diff --git a/Modules/DICOMReaderServices/src/mitkClassicDICOMSeriesReaderService.cpp b/Modules/DICOMReaderServices/src/mitkClassicDICOMSeriesReaderService.cpp index b8d137c7d5..8d70e81130 100644 --- a/Modules/DICOMReaderServices/src/mitkClassicDICOMSeriesReaderService.cpp +++ b/Modules/DICOMReaderServices/src/mitkClassicDICOMSeriesReaderService.cpp @@ -1,41 +1,41 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkClassicDICOMSeriesReaderService.h" #include namespace mitk { ClassicDICOMSeriesReaderService::ClassicDICOMSeriesReaderService() : BaseDICOMReaderService("MITK DICOM Reader v2 (classic config)") { this->RegisterService(); } - DICOMFileReader::Pointer ClassicDICOMSeriesReaderService::GetReader(const mitk::StringList& relevantFiles) const + DICOMFileReader::Pointer ClassicDICOMSeriesReaderService::GetReader(const mitk::StringList&) const { mitk::ClassicDICOMSeriesReader::Pointer reader = mitk::ClassicDICOMSeriesReader::New(); return reader.GetPointer(); }; ClassicDICOMSeriesReaderService* ClassicDICOMSeriesReaderService::Clone() const { return new ClassicDICOMSeriesReaderService(*this); } }