diff --git a/Modules/DICOMReader/test/CMakeLists.txt b/Modules/DICOMReader/test/CMakeLists.txt index 559920cb95..c29e224fc8 100644 --- a/Modules/DICOMReader/test/CMakeLists.txt +++ b/Modules/DICOMReader/test/CMakeLists.txt @@ -1,10 +1,12 @@ MITK_CREATE_MODULE_TESTS() file(GLOB_RECURSE tinyCTSlices ${MITK_DATA_DIR}/TinyCTAbdomen/1??) +file(GLOB_RECURSE sloppyDICOMfiles ${MITK_DATA_DIR}/SloppyDICOMFiles/1*) -#foreach(f ${tinyCTSlices}) +#foreach(f ${sloppyDICOMfiles}) # message(" ${f}") #endforeach() mitkAddCustomModuleTest(mitkDICOMFileReaderTest_Basics mitkDICOMFileReaderTest ${tinyCTSlices}) mitkAddCustomModuleTest(mitkDICOMITKSeriesGDCMReaderBasicsTest_Basics mitkDICOMITKSeriesGDCMReaderBasicsTest ${tinyCTSlices}) +mitkAddCustomModuleTest(mitkDICOMSimpleVolumeImportTest mitkDICOMSimpleVolumeImportTest ${sloppyDICOMfiles}) diff --git a/Modules/DICOMReader/test/files.cmake b/Modules/DICOMReader/test/files.cmake index 94f0d1df07..255fd1fe7f 100644 --- a/Modules/DICOMReader/test/files.cmake +++ b/Modules/DICOMReader/test/files.cmake @@ -1,16 +1,17 @@ set(MODULE_TESTS mitkDICOMReaderConfiguratorTest.cpp mitkDICOMDCMTKTagScannerTest.cpp + mitkDICOMSimpleVolumeImportTest.cpp mitkDICOMTagPathTest.cpp mitkDICOMPropertyTest.cpp ) set(MODULE_CUSTOM_TESTS mitkDICOMFileReaderTest.cpp mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp ) set(CPP_FILES mitkDICOMNullFileReader.cpp mitkDICOMFilenameSorter.cpp ) diff --git a/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h b/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h index 2e1f966c2c..b0dd8d72e6 100644 --- a/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h +++ b/Modules/DICOMReader/test/mitkDICOMFileReaderTestHelper.h @@ -1,176 +1,188 @@ /*=================================================================== 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. ===================================================================*/ #ifndef mitkDICOMFileReaderTestHelper_h #define mitkDICOMFileReaderTestHelper_h #include "mitkDICOMFileReader.h" #include "mitkDICOMEnums.h" #include "mitkTestingMacros.h" namespace mitk { class DICOMFileReaderTestHelper { public: static StringList& GetInputFilenames() { static StringList inputs; return inputs; } static void SetTestInputFilenames(int argc, char* argv[]) { mitk::StringList inputFiles; for (int a = 1; a < argc; ++a) { inputFiles.push_back( argv[a] ); } GetInputFilenames() = inputFiles; } static void SetTestInputFilenames(const StringList& filenames) { GetInputFilenames() = filenames; } static void TestInputFilenames(DICOMFileReader* reader) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); const StringList& inputFilesReturned = reader->GetInputFiles(); MITK_TEST_CONDITION( inputFilesReturned.size() == inputFiles.size(), "Input file list is received") MITK_TEST_CONDITION( reader->GetNumberOfOutputs() == 0, "No outputs without analysis") } static void TestOutputsContainInputs(DICOMFileReader* reader) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); reader->AnalyzeInputFiles(); StringList allSortedInputsFiles; unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); for (unsigned int o = 0; o < numberOfOutputs; ++o) { const DICOMImageBlockDescriptor block = reader->GetOutput(o); const DICOMImageFrameList& outputFiles = block.GetImageFrameList(); for(auto iter = outputFiles.cbegin(); iter != outputFiles.cend(); ++iter) { // check that output is part of input auto inputPositionOfCurrentOutput = std::find( inputFiles.cbegin(), inputFiles.cend(), (*iter)->Filename ); if (inputPositionOfCurrentOutput != inputFiles.cend()) { // check that output is only part of ONE output auto outputPositionOfCurrentOutput = std::find( allSortedInputsFiles.cbegin(), allSortedInputsFiles.cend(), (*iter)->Filename ); if (outputPositionOfCurrentOutput == allSortedInputsFiles.cend()) { // was not in list before allSortedInputsFiles.push_back( *inputPositionOfCurrentOutput ); } else { reader->PrintOutputs(std::cout); MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in TWO outputs. Readers are expected to use each frame only once." ) } } else { reader->PrintOutputs(std::cout); MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in output, but it was never part of the input list." ) } } } MITK_TEST_CONDITION( allSortedInputsFiles.size() == inputFiles.size(), "Output list size (" << allSortedInputsFiles.size() << ") equals input list size (" << inputFiles.size() << ")" ) try { const DICOMImageBlockDescriptor block = reader->GetOutput( inputFiles.size() ); MITK_TEST_CONDITION(false, "Invalid indices for GetOutput() should throw exception") } catch( std::invalid_argument& ) { MITK_TEST_CONDITION(true, "Invalid indices for GetOutput() should throw exception") } } static void TestMitkImagesAreLoaded( DICOMFileReader* reader, const DICOMFileReader::AdditionalTagsMapType& requestedTags, const std::unordered_map& expectedProperties ) { StringList inputFiles = GetInputFilenames(); reader->SetInputFiles( inputFiles ); reader->AnalyzeInputFiles(); reader->LoadImages(); unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); for (unsigned int o = 0; o < numberOfOutputs; ++o) { const DICOMImageBlockDescriptor block = reader->GetOutput(o); const DICOMImageFrameList& outputFiles = block.GetImageFrameList(); const mitk::Image::Pointer mitkImage = block.GetMitkImage(); for ( auto iter = requestedTags.cbegin(); iter != requestedTags.cend(); ++iter) { mitk::BaseProperty* property = mitkImage->GetProperty( iter->second.c_str() ).GetPointer(); MITK_TEST_CONDITION( property != nullptr, "Requested Tag is available as Property in Image" ); if (property) { MITK_INFO << iter->first.ToStr() << " / " << property->GetNameOfClass(); auto expectfinding = expectedProperties.find(iter->second); if (expectfinding != expectedProperties.end()) { MITK_TEST_CONDITION(std::string(property->GetNameOfClass()) == expectfinding->second, "Property type is as expected"); } } } MITK_DEBUG << "-------------------------------------------"; MITK_DEBUG << "Output " << o << " at " << (void*) mitkImage.GetPointer(); MITK_DEBUG << " Number of files: " << outputFiles.size(); MITK_DEBUG << " Dimensions: " << mitkImage->GetDimension(0) << " " << mitkImage->GetDimension(1) << " " << mitkImage->GetDimension(2); } } +static void TestSingleBlockIsRead( DICOMFileReader* reader ) +{ + StringList inputFiles = GetInputFilenames(); + reader->SetInputFiles( inputFiles ); + reader->AnalyzeInputFiles(); + reader->LoadImages(); + + unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); + + MITK_TEST_CONDITION_REQUIRED( numberOfOutputs == 1, "Single block is read from input files."); +} + static mitk::BaseProperty::Pointer DummyTagToPropertyFunctor( const mitk::StringLookupTable& ) { return mitk::BaseProperty::Pointer(); } }; // end test class } // namespace #endif diff --git a/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp b/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp new file mode 100644 index 0000000000..bcf2ee91fa --- /dev/null +++ b/Modules/DICOMReader/test/mitkDICOMSimpleVolumeImportTest.cpp @@ -0,0 +1,108 @@ +/*=================================================================== + +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 "mitkDICOMFileReaderSelector.h" +#include "mitkDICOMFileReaderTestHelper.h" + +#include +#include +#include +#include +#include +#include + +#include "mitkImageToItk.h" +#include "itkImageRegionConstIteratorWithIndex.h" + +#include "mitkTestingMacros.h" + +/** + \brief Verify single block reading of SimpleDICOMvolumeImport for sloppily tagged data. +*/ +int mitkDICOMSimpleVolumeImportTest(int argc, char* argv[]) +{ + typedef mitk::DICOMFileReaderSelector::ReaderList ReaderList; + typedef itk::Image< short, 3 > ImageType; + typedef itk::ImageRegionConstIteratorWithIndex< ImageType > IteratorType; + + MITK_TEST_BEGIN("mitkDICOMSimpleVolumeImportTest"); + + us::ModuleResource resource = + us::ModuleRegistry::GetModule("MitkDICOMReader")->GetResource("configurations/3D/simpleinstancenumber_soft.xml"); + + std::string descr; + if ( resource.IsValid() ) + { + us::ModuleResourceStream stream(resource); + + stream.seekg(0, std::ios::end); + descr.reserve(stream.tellg()); + stream.seekg(0, std::ios::beg); + + descr.assign((std::istreambuf_iterator(stream)), + std::istreambuf_iterator()); + } + mitk::DICOMFileReaderSelector::Pointer readerSelector = mitk::DICOMFileReaderSelector::New(); + + readerSelector->AddConfig( descr ); + ReaderList readers = readerSelector->GetAllConfiguredReaders(); + + mitk::DICOMFileReader::Pointer simpleReader; + for ( ReaderList::const_iterator it = readers.begin(); it != readers.end(); ++it ) + { + mitk::DICOMFileReader::Pointer reader = *it; + std::string configLabel = reader->GetConfigurationLabel(); + if ( configLabel == "Instance Number, non-consecutive, simple import" ) + { + simpleReader = reader; + } + } + + MITK_TEST_CONDITION_REQUIRED( simpleReader.IsNotNull(), "DICOMFileReaderSelector is able to create simple reader from XML"); + + mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc,argv ); + + mitk::DICOMFileReaderTestHelper::TestInputFilenames( simpleReader ); + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( simpleReader ); + mitk::DICOMFileReaderTestHelper::TestSingleBlockIsRead( simpleReader ); + + const mitk::DICOMImageBlockDescriptor block = simpleReader->GetOutput( 0 ); + const mitk::DICOMImageFrameList& outputFiles = block.GetImageFrameList(); + const mitk::Image::Pointer mitkImage = block.GetMitkImage(); + + ImageType::Pointer itkImage = mitk::ImageToItkImage( mitkImage ); + + IteratorType it( itkImage, itkImage->GetLargestPossibleRegion() ); + bool success = true; + while ( !it.IsAtEnd() ) + { + ImageType::PixelType val = it.Get(); + ImageType::IndexType ind = it.GetIndex(); + + if ( !val == ind[2] ) + { + success = false; + break; + } + + ++it; + } + + MITK_TEST_CONDITION( success, "Single block image composed as expected."); + + MITK_TEST_END(); +} +