diff --git a/Examples/mitkdump/mitkdump.cpp b/Examples/mitkdump/mitkdump.cpp index 07047f5c02..a352a5eb74 100644 --- a/Examples/mitkdump/mitkdump.cpp +++ b/Examples/mitkdump/mitkdump.cpp @@ -1,61 +1,75 @@ /*=================================================================== 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 "mitkClassicDICOMSeriesReader.h" +#include "mitkDICOMFileReaderSelector.h" using mitk::DICOMTag; int main(int argc, char* argv[]) { mitk::StringList inputFiles; for (int a = 1; a < argc; ++a) { inputFiles.push_back( std::string(argv[a]) ); } // ----------------- Configure reader ------------------- + mitk::DICOMFileReaderSelector::Pointer configSelector = mitk::DICOMFileReaderSelector::New(); + configSelector->LoadBuiltIn3DConfigs(); // a set of compiled in ressources with standard configurations that work well + configSelector->SetInputFiles( inputFiles ); + mitk::DICOMFileReader::Pointer reader = configSelector->GetFirstReaderWithMinimumNumberOfOutputImages(); + if (reader.IsNull()) + { + MITK_ERROR << "Could not configure any DICOM reader.. Exiting..."; + return EXIT_FAILURE; + } - // DOES fix tilt when detected - // DOES group 3D blocks into 3D+t if possible - mitk::ClassicDICOMSeriesReader::Pointer gdcmReader = mitk::ClassicDICOMSeriesReader::New(); + MITK_INFO << "---- Best reader configuration -----------------"; + reader->PrintConfiguration( std::cout ); + MITK_INFO << "-------------------------------------------"; // ----------------- Load ------------------- - gdcmReader->SetInputFiles( inputFiles ); + reader->SetInputFiles( inputFiles ); MITK_INFO << "Analyzing " << inputFiles.size() << " files ..."; - gdcmReader->AnalyzeInputFiles(); - //gdcmReader->PrintOutputs(std::cout, false); + reader->AnalyzeInputFiles(); + reader->PrintOutputs(std::cout, false); + + return EXIT_SUCCESS; + MITK_INFO << "Loading " << inputFiles.size() << " files ..."; - gdcmReader->LoadImages(); + reader->LoadImages(); - unsigned int numberOfOutputs = gdcmReader->GetNumberOfOutputs(); + unsigned int numberOfOutputs = reader->GetNumberOfOutputs(); for (unsigned int o = 0; o < numberOfOutputs; ++o) { - const mitk::DICOMImageBlockDescriptor block = gdcmReader->GetOutput(o); + const mitk::DICOMImageBlockDescriptor block = reader->GetOutput(o); const mitk::DICOMImageFrameList& outputFiles = block.GetImageFrameList(); mitk::Image::Pointer mitkImage = block.GetMitkImage(); MITK_INFO << "-------------------------------------------"; MITK_INFO << "Output " << o << " at " << (void*) mitkImage.GetPointer(); MITK_INFO << " Number of files: " << outputFiles.size(); if (mitkImage.IsNotNull()) { MITK_INFO << " Dimensions: " << mitkImage->GetDimension(0) << " " << mitkImage->GetDimension(1) << " " << mitkImage->GetDimension(2); } } + + return EXIT_SUCCESS; } diff --git a/Modules/DICOMReader/Resources/configurations/3D/acquisitionnumberfirst.xml b/Modules/DICOMReader/Resources/configurations/3D/acquisitionnumberfirst.xml new file mode 100644 index 0000000000..f4ac880eca --- /dev/null +++ b/Modules/DICOMReader/Resources/configurations/3D/acquisitionnumberfirst.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/Modules/DICOMReader/Resources/configurations/3D/classicreader.xml b/Modules/DICOMReader/Resources/configurations/3D/classicreader.xml new file mode 100644 index 0000000000..744e62ed67 --- /dev/null +++ b/Modules/DICOMReader/Resources/configurations/3D/classicreader.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/Modules/DICOMReader/Resources/configurations/3DnT/classicreader.xml b/Modules/DICOMReader/Resources/configurations/3DnT/classicreader.xml new file mode 100644 index 0000000000..4bb181dda8 --- /dev/null +++ b/Modules/DICOMReader/Resources/configurations/3DnT/classicreader.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/Modules/DICOMReader/files.cmake b/Modules/DICOMReader/files.cmake index e299c6a353..575e796447 100644 --- a/Modules/DICOMReader/files.cmake +++ b/Modules/DICOMReader/files.cmake @@ -1,41 +1,50 @@ set(H_FILES mitkDICOMFileReader.h mitkDICOMImageFrameInfo.h mitkDICOMImageBlockDescriptor.h mitkDICOMGDCMImageFrameInfo.h mitkDICOMITKSeriesGDCMReader.h mitkDICOMDatasetSorter.h mitkDICOMFilenameSorter.h mitkDICOMEnums.h mitkDICOMTagBasedSorter.h mitkDICOMSortCriterion.h mitkDICOMSortByTag.h mitkEquiDistantBlocksSorter.h mitkSortByImagePositionPatient.h mitkClassicDICOMSeriesReader.h mitkThreeDnTDICOMSeriesReader.h mitkDICOMTag.h mitkDICOMReaderConfigurator.h + mitkDICOMFileReaderSelector.h ) set(CPP_FILES mitkDICOMFileReader.cpp mitkDICOMImageBlockDescriptor.cpp mitkDICOMITKSeriesGDCMReader.cpp mitkDICOMDatasetSorter.cpp mitkDICOMFilenameSorter.cpp mitkDICOMTagBasedSorter.cpp mitkDICOMGDCMImageFrameInfo.cpp mitkDICOMImageFrameInfo.cpp mitkDICOMSortCriterion.cpp mitkDICOMSortByTag.cpp mitkITKDICOMSeriesReaderHelper.cpp mitkEquiDistantBlocksSorter.cpp mitkSortByImagePositionPatient.cpp mitkGantryTiltInformation.cpp mitkClassicDICOMSeriesReader.cpp mitkThreeDnTDICOMSeriesReader.cpp mitkDICOMTag.cpp mitkDICOMEnums.cpp mitkDICOMReaderConfigurator.cpp + mitkDICOMFileReaderSelector.cpp +) + +set(RESOURCE_FILES + configurations/3D/acquisitionnumberfirst.xml + configurations/3D/classicreader.xml + + configurations/3DnT/classicreader.xml ) diff --git a/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp b/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp new file mode 100644 index 0000000000..a53b1fde8a --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp @@ -0,0 +1,183 @@ +/*=================================================================== + +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 "mitkDICOMReaderConfigurator.h" + +#include "mitkModuleContext.h" + +#include +#include +#include +#include + +mitk::DICOMFileReaderSelector +::DICOMFileReaderSelector() +{ +} + +mitk::DICOMFileReaderSelector +::~DICOMFileReaderSelector() +{ +} + +void +mitk::DICOMFileReaderSelector +::AddConfigsFromResources(const std::string& path) +{ + std::vector configs = GetModuleContext()->GetModule()->FindResources(path, "*.xml", false); + + for (std::vector::iterator iter = configs.begin(); + iter != configs.end(); + ++iter) + { + ModuleResource& resource = *iter; + if (resource.IsValid()) + { + ModuleResourceStream stream(resource); + + // read all into string s + std::string s; + + stream.seekg(0, std::ios::end); + s.reserve(stream.tellg()); + stream.seekg(0, std::ios::beg); + + s.assign((std::istreambuf_iterator(stream)), + std::istreambuf_iterator()); + + //MITK_INFO << "------------ One resource with content\n" << s << "\n------- end -------"; + this->AddConfig(s); + } + } +} + +void +mitk::DICOMFileReaderSelector +::LoadBuiltIn3DConfigs() +{ + this->AddConfigsFromResources("configurations/3D"); +} + +void +mitk::DICOMFileReaderSelector +::LoadBuiltIn3DnTConfigs() +{ + this->AddConfigsFromResources("configurations/3DnT"); +} + +void +mitk::DICOMFileReaderSelector +::AddConfig(const std::string& xmlDescription) +{ + DICOMReaderConfigurator::Pointer configurator = DICOMReaderConfigurator::New(); + DICOMFileReader::Pointer reader = configurator->CreateFromUTF8ConfigString(xmlDescription); + + if (reader.IsNotNull()) + { + m_Readers.push_back( reader ); + m_PossibleConfigurations.push_back(xmlDescription); + } + else + { + std::stringstream ss; + ss << "Could not parse reader configuration. Ignoring it."; + throw std::invalid_argument( ss.str() ); + } +} + +void +mitk::DICOMFileReaderSelector +::AddConfigFile(const std::string& filename) +{ + std::ifstream file(filename.c_str()); + std::string s; + + file.seekg(0, std::ios::end); + s.reserve(file.tellg()); + file.seekg(0, std::ios::beg); + + s.assign((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + + this->AddConfig(s); +} + +void +mitk::DICOMFileReaderSelector +::SetInputFiles(StringList filenames) +{ + m_InputFilenames = filenames; +} + +const mitk::StringList& +mitk::DICOMFileReaderSelector +::GetInputFiles() const +{ + return m_InputFilenames; +} + +mitk::DICOMFileReader::Pointer +mitk::DICOMFileReaderSelector +::GetFirstReaderWithMinimumNumberOfOutputImages() +{ + ReaderList workingCandidates; + + // let all readers analyze the file set + unsigned int readerIndex(0); + for (ReaderList::iterator rIter = m_Readers.begin(); + rIter != m_Readers.end(); + ++readerIndex, ++rIter) + { + (*rIter)->SetInputFiles( m_InputFilenames ); + try + { + (*rIter)->AnalyzeInputFiles(); + workingCandidates.push_back( *rIter ); + MITK_INFO << "Reader " << readerIndex << " suggests " << (*rIter)->GetNumberOfOutputs() << " 3D blocks"; + } + catch (std::exception& e) + { + MITK_ERROR << "Reader " << readerIndex << " threw exception during file analysis, ignoring this reader. Exception: " << e.what(); + } + catch (...) + { + MITK_ERROR << "Reader " << readerIndex << " threw unknown exception during file analysis, ignoring this reader."; + } + } + + DICOMFileReader::Pointer bestReader; + + unsigned int minimumNumberOfOutputs = std::numeric_limits::max(); + readerIndex = 0; + unsigned int bestReaderIndex(0); + // select the reader with the minimum number of mitk::Images as output + for (ReaderList::iterator rIter = workingCandidates.begin(); + rIter != workingCandidates.end(); + ++readerIndex, ++rIter) + { + if ( (*rIter)->GetNumberOfOutputs() < minimumNumberOfOutputs ) + { + minimumNumberOfOutputs = (*rIter)->GetNumberOfOutputs(); + bestReader = *rIter; + bestReaderIndex = readerIndex; + } + } + + MITK_INFO << "Decided for reader #" << bestReaderIndex; + + return bestReader; +} diff --git a/Modules/DICOMReader/mitkDICOMFileReaderSelector.h b/Modules/DICOMReader/mitkDICOMFileReaderSelector.h new file mode 100644 index 0000000000..0b3533ef4d --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMFileReaderSelector.h @@ -0,0 +1,61 @@ +/*=================================================================== + +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 mitkDICOMFileReaderSelector_h +#define mitkDICOMFileReaderSelector_h + +#include "mitkDICOMFileReader.h" + +namespace mitk +{ + +class DICOMReader_EXPORT DICOMFileReaderSelector : public itk::LightObject +{ + public: + + mitkClassMacro( DICOMFileReaderSelector, itk::LightObject ) + itkNewMacro( DICOMFileReaderSelector ) + + void AddConfig(const std::string& xmlDescription); + void AddConfigFile(const std::string& filename); + + void LoadBuiltIn3DConfigs(); + void LoadBuiltIn3DnTConfigs(); + + void SetInputFiles(StringList filenames); + const StringList& GetInputFiles() const; + + DICOMFileReader::Pointer GetFirstReaderWithMinimumNumberOfOutputImages(); + + protected: + + DICOMFileReaderSelector(); + virtual ~DICOMFileReaderSelector(); + + void AddConfigsFromResources(const std::string& path); + + private: + + StringList m_PossibleConfigurations; + StringList m_InputFilenames; + typedef std::list ReaderList; + ReaderList m_Readers; + + }; + +} // namespace + +#endif // mitkDICOMFileReaderSelector_h