diff --git a/Modules/DICOMReader/Testing/mitkDICOMFileReaderTestHelper.h b/Modules/DICOMReader/Testing/mitkDICOMFileReaderTestHelper.h index e244645640..5518633900 100644 --- a/Modules/DICOMReader/Testing/mitkDICOMFileReaderTestHelper.h +++ b/Modules/DICOMReader/Testing/mitkDICOMFileReaderTestHelper.h @@ -1,127 +1,129 @@ /*=================================================================== 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") // TODO: check that strings are actually contained } 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) { DICOMImageBlockDescriptor block = reader->GetOutput(o); const DICOMImageFrameList& outputFiles = block.GetImageFrameList(); for(DICOMImageFrameList::const_iterator iter = outputFiles.begin(); iter != outputFiles.end(); ++iter) { // check that output is part of input StringList::iterator inputPositionOfCurrentOutput = std::find( inputFiles.begin(), inputFiles.end(), (*iter)->Filename ); if (inputPositionOfCurrentOutput != inputFiles.end()) { // check that output is only part of ONE output StringList::iterator outputPositionOfCurrentOutput = std::find( allSortedInputsFiles.begin(), allSortedInputsFiles.end(), (*iter)->Filename ); if (outputPositionOfCurrentOutput == allSortedInputsFiles.end()) { // was not in list before allSortedInputsFiles.push_back( *inputPositionOfCurrentOutput ); } else { - MITK_TEST_CONDITION(false, "File '" << (*iter)->Filename << "' appears in TWO outputs. Readers are expected to use each frame only once." ) + 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 { - MITK_TEST_CONDITION(false, "File '" << (*iter)->Filename << "' appears in output, but it was never part of the input list." ) + 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 equals input list size" ) + MITK_TEST_CONDITION( allSortedInputsFiles.size() == inputFiles.size(), "Output list size (" << allSortedInputsFiles.size() << ") equals input list size (" << inputFiles.size() << ")" ) try { 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") } } }; // end test class } // namespace #endif diff --git a/Modules/DICOMReader/Testing/mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp b/Modules/DICOMReader/Testing/mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp index 564373c77d..965046ca72 100644 --- a/Modules/DICOMReader/Testing/mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp +++ b/Modules/DICOMReader/Testing/mitkDICOMITKSeriesGDCMReaderBasicsTest.cpp @@ -1,35 +1,63 @@ /*=================================================================== 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 "mitkDICOMITKSeriesGDCMReader.h" #include "mitkDICOMFileReaderTestHelper.h" +#include "mitkDICOMFilenameSorter.h" +#include "mitkDICOMTagBasedSorter.h" #include "mitkTestingMacros.h" int mitkDICOMITKSeriesGDCMReaderBasicsTest(int argc, char* argv[]) { MITK_TEST_BEGIN("mitkDICOMITKSeriesGDCMReaderBasicsTest"); mitk::DICOMITKSeriesGDCMReader::Pointer gdcmReader = mitk::DICOMITKSeriesGDCMReader::New(); - MITK_TEST_CONDITION_REQUIRED(gdcmReader.IsNotNull(), "DICOMITKSeriesGDCMReaderBasics can be instantiated."); + MITK_TEST_CONDITION_REQUIRED(gdcmReader.IsNotNull(), "DICOMITKSeriesGDCMReader can be instantiated."); mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc,argv ); + // check the Set/GetInput function mitk::DICOMFileReaderTestHelper::TestInputFilenames( gdcmReader ); + + // check that output is a good reproduction of input (no duplicates, no new elements) + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + + + // repeat test with filename based sorter in-between + mitk::DICOMFilenameSorter::Pointer filenameSorter = mitk::DICOMFilenameSorter::New(); + gdcmReader->AddSortingElement( filenameSorter ); mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + // repeat test with some more realistic sorting + gdcmReader = mitk::DICOMITKSeriesGDCMReader::New(); // this also tests destruction + mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New(); + + tagSorter->AddDistinguishingTag( std::make_pair(0x0028, 0x0010) ); // Number of Rows + tagSorter->AddDistinguishingTag( std::make_pair(0x0028, 0x0011) ); // Number of Columns + tagSorter->AddDistinguishingTag( std::make_pair(0x0028, 0x0030) ); // Pixel Spacing + tagSorter->AddDistinguishingTag( std::make_pair(0x0018, 0x1164) ); // Imager Pixel Spacing + tagSorter->AddDistinguishingTag( std::make_pair(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code) + tagSorter->AddDistinguishingTag( std::make_pair(0x0020, 0x000e) ); // Series Instance UID + tagSorter->AddDistinguishingTag( std::make_pair(0x0018, 0x0050) ); // Slice Thickness + tagSorter->AddDistinguishingTag( std::make_pair(0x0028, 0x0008) ); // Number of Frames + gdcmReader->AddSortingElement( tagSorter ); + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + + gdcmReader->PrintOutputs(std::cout); + MITK_TEST_END(); } diff --git a/Modules/DICOMReader/files.cmake b/Modules/DICOMReader/files.cmake index c04d918ae0..0a784316cc 100644 --- a/Modules/DICOMReader/files.cmake +++ b/Modules/DICOMReader/files.cmake @@ -1,11 +1,22 @@ set(H_FILES mitkDICOMFileReader.h + mitkDICOMImageFrameInfo.h mitkDICOMImageBlockDescriptor.h + mitkDICOMGDCMImageFrameInfo.h mitkDICOMITKSeriesGDCMReader.h + mitkDICOMDatasetSorter.h + mitkDICOMFilenameSorter.h + mitkDICOMEnums.h + mitkDICOMTagBasedSorter.h ) set(CPP_FILES mitkDICOMFileReader.cpp mitkDICOMImageBlockDescriptor.cpp mitkDICOMITKSeriesGDCMReader.cpp + mitkDICOMDatasetSorter.cpp + mitkDICOMFilenameSorter.cpp + mitkDICOMTagBasedSorter.cpp + mitkDICOMGDCMImageFrameInfo.cpp + mitkDICOMImageFrameInfo.cpp ) diff --git a/Modules/DICOMReader/mitkDICOMEnums.h b/Modules/DICOMReader/mitkDICOMDatasetAccess.h similarity index 51% copy from Modules/DICOMReader/mitkDICOMEnums.h copy to Modules/DICOMReader/mitkDICOMDatasetAccess.h index 618ad78dd4..bd79de6f16 100644 --- a/Modules/DICOMReader/mitkDICOMEnums.h +++ b/Modules/DICOMReader/mitkDICOMDatasetAccess.h @@ -1,38 +1,40 @@ /*=================================================================== 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 mitkDICOMEnums_h -#define mitkDICOMEnums_h +#ifndef mitkDICOMDatasetAccess_h +#define mitkDICOMDatasetAccess_h -#include "mitkDICOMImageFrameInfo.h" +#include "mitkDICOMEnums.h" + +#include "DICOMReaderExports.h" namespace mitk { - typedef std::vector StringList; - typedef std::vector BoolList; - typedef std::vector DICOMImageFrameList; +class DICOMReader_EXPORT DICOMDatasetAccess +{ + public: + + virtual std::string GetFilenameIfAvailable() const = 0; + virtual std::string GetTagValueAsString(const mitk::DICOMTag& tag) const = 0; +}; + - typedef enum - { - SpacingInPatient, /// distances are mm within a patient - SpacingAtDetector, /// distances are mm at detector surface - SpacingUnknown /// NO spacing information is present, we use (1,1) as default - } PixelSpacingInterpretation; +typedef std::vector DICOMDatasetList; } #endif diff --git a/Modules/DICOMReader/mitkDICOMFileReader.cpp b/Modules/DICOMReader/mitkDICOMDatasetSorter.cpp similarity index 63% copy from Modules/DICOMReader/mitkDICOMFileReader.cpp copy to Modules/DICOMReader/mitkDICOMDatasetSorter.cpp index 36b523b2be..3b4d353edb 100644 --- a/Modules/DICOMReader/mitkDICOMFileReader.cpp +++ b/Modules/DICOMReader/mitkDICOMDatasetSorter.cpp @@ -1,114 +1,121 @@ /*=================================================================== 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 "mitkDICOMFileReader.h" +#include "mitkDICOMDatasetSorter.h" -mitk::DICOMFileReader -::DICOMFileReader() +mitk::DICOMDatasetSorter +::DICOMDatasetSorter() :itk::LightObject() { } -mitk::DICOMFileReader -::~DICOMFileReader() +mitk::DICOMDatasetSorter +::~DICOMDatasetSorter() { } -mitk::DICOMFileReader -::DICOMFileReader(const DICOMFileReader& other ) +mitk::DICOMDatasetSorter +::DICOMDatasetSorter(const DICOMDatasetSorter& other ) :itk::LightObject() ,m_Outputs( other.m_Outputs ) // TODO copy instead of reference! { } -mitk::DICOMFileReader& -mitk::DICOMFileReader -::operator=(const DICOMFileReader& other) +mitk::DICOMDatasetSorter& +mitk::DICOMDatasetSorter +::operator=(const DICOMDatasetSorter& other) { if (this != &other) { - m_InputFilenames = other.m_InputFilenames; + m_Input = other.m_Input; m_Outputs = other.m_Outputs; // TODO copy instead of reference! } return *this; } void -mitk::DICOMFileReader -::SetInputFiles(StringList filenames) +mitk::DICOMDatasetSorter +::SetInput(DICOMDatasetList datasets) { - m_InputFilenames = filenames; + m_Input = datasets; } -const mitk::StringList& -mitk::DICOMFileReader -::GetInputFiles() const +const mitk::DICOMDatasetList& +mitk::DICOMDatasetSorter +::GetInput() const { - return m_InputFilenames; + return m_Input; } unsigned int -mitk::DICOMFileReader +mitk::DICOMDatasetSorter ::GetNumberOfOutputs() const { return m_Outputs.size(); } void -mitk::DICOMFileReader +mitk::DICOMDatasetSorter ::ClearOutputs() { m_Outputs.clear(); } void -mitk::DICOMFileReader +mitk::DICOMDatasetSorter ::SetNumberOfOutputs(unsigned int numberOfOutputs) { m_Outputs.resize(numberOfOutputs); } void -mitk::DICOMFileReader -::SetOutput(unsigned int index, const mitk::DICOMImageBlockDescriptor& output) +mitk::DICOMDatasetSorter +::SetOutput(unsigned int index, const DICOMDatasetList& output) { if (index < m_Outputs.size()) { m_Outputs[index] = output; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_Outputs.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } -const mitk::DICOMImageBlockDescriptor& -mitk::DICOMFileReader +const mitk::DICOMDatasetList& +mitk::DICOMDatasetSorter ::GetOutput(unsigned int index) const +{ + return const_cast(this)->GetOutput(index); +} + +mitk::DICOMDatasetList& +mitk::DICOMDatasetSorter +::GetOutput(unsigned int index) { if (index < m_Outputs.size()) { return m_Outputs[index]; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_Outputs.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } diff --git a/Modules/DICOMReader/mitkDICOMDatasetSorter.h b/Modules/DICOMReader/mitkDICOMDatasetSorter.h new file mode 100644 index 0000000000..f0772d99a3 --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMDatasetSorter.h @@ -0,0 +1,65 @@ +/*=================================================================== + +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 mitkDICOMDatasetSorter_h +#define mitkDICOMDatasetSorter_h + +#include "itkObjectFactory.h" +#include "mitkCommon.h" + +#include "mitkDICOMDatasetAccess.h" + +namespace mitk +{ + +class DICOMReader_EXPORT DICOMDatasetSorter : public itk::LightObject +{ + public: + + mitkClassMacro( DICOMDatasetSorter, itk::LightObject ) + + virtual DICOMTagList GetTagsOfInterest() = 0; + + void SetInput(DICOMDatasetList filenames); + const DICOMDatasetList& GetInput() const; + + virtual void Sort() = 0; + + unsigned int GetNumberOfOutputs() const; + const DICOMDatasetList& GetOutput(unsigned int index) const; + DICOMDatasetList& GetOutput(unsigned int index); + + protected: + + DICOMDatasetSorter(); + virtual ~DICOMDatasetSorter(); + + DICOMDatasetSorter(const DICOMDatasetSorter& other); + DICOMDatasetSorter& operator=(const DICOMDatasetSorter& other); + + void ClearOutputs(); + void SetNumberOfOutputs(unsigned int numberOfOutputs); + void SetOutput(unsigned int index, const DICOMDatasetList& output); + + private: + + DICOMDatasetList m_Input; + std::vector< DICOMDatasetList > m_Outputs; +}; + +} + +#endif diff --git a/Modules/DICOMReader/mitkDICOMEnums.h b/Modules/DICOMReader/mitkDICOMEnums.h index 618ad78dd4..394eb66325 100644 --- a/Modules/DICOMReader/mitkDICOMEnums.h +++ b/Modules/DICOMReader/mitkDICOMEnums.h @@ -1,38 +1,39 @@ /*=================================================================== 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 mitkDICOMEnums_h #define mitkDICOMEnums_h -#include "mitkDICOMImageFrameInfo.h" +#include +#include +#include namespace mitk { + typedef std::pair DICOMTag; typedef std::vector StringList; + typedef std::vector DICOMTagList; typedef std::vector BoolList; - typedef std::vector DICOMImageFrameList; - typedef enum { SpacingInPatient, /// distances are mm within a patient SpacingAtDetector, /// distances are mm at detector surface SpacingUnknown /// NO spacing information is present, we use (1,1) as default } PixelSpacingInterpretation; - } #endif diff --git a/Modules/DICOMReader/mitkDICOMFileReader.cpp b/Modules/DICOMReader/mitkDICOMFileReader.cpp index 36b523b2be..741efa51d7 100644 --- a/Modules/DICOMReader/mitkDICOMFileReader.cpp +++ b/Modules/DICOMReader/mitkDICOMFileReader.cpp @@ -1,114 +1,148 @@ /*=================================================================== 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 "mitkDICOMFileReader.h" mitk::DICOMFileReader ::DICOMFileReader() :itk::LightObject() { } mitk::DICOMFileReader ::~DICOMFileReader() { } mitk::DICOMFileReader ::DICOMFileReader(const DICOMFileReader& other ) :itk::LightObject() ,m_Outputs( other.m_Outputs ) // TODO copy instead of reference! { } mitk::DICOMFileReader& mitk::DICOMFileReader ::operator=(const DICOMFileReader& other) { if (this != &other) { m_InputFilenames = other.m_InputFilenames; m_Outputs = other.m_Outputs; // TODO copy instead of reference! } return *this; } void mitk::DICOMFileReader ::SetInputFiles(StringList filenames) { m_InputFilenames = filenames; } const mitk::StringList& mitk::DICOMFileReader ::GetInputFiles() const { return m_InputFilenames; } unsigned int mitk::DICOMFileReader ::GetNumberOfOutputs() const { return m_Outputs.size(); } void mitk::DICOMFileReader ::ClearOutputs() { m_Outputs.clear(); } void mitk::DICOMFileReader ::SetNumberOfOutputs(unsigned int numberOfOutputs) { m_Outputs.resize(numberOfOutputs); } void mitk::DICOMFileReader ::SetOutput(unsigned int index, const mitk::DICOMImageBlockDescriptor& output) { if (index < m_Outputs.size()) { m_Outputs[index] = output; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_Outputs.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } +void +mitk::DICOMFileReader +::PrintOutputs(std::ostream& os, bool filenameDetails) +{ + os << "---- Outputs of DICOMFilereader " << (void*)this << "----"<< std::endl; + + for (unsigned int o = 0; o < m_Outputs.size(); ++o) + { + os << "-- Output " << o << std::endl; + const DICOMImageBlockDescriptor& block = m_Outputs[o]; + const DICOMImageFrameList& frames = block.GetImageFrameList(); + os << " Number of frames: " << frames.size() << std::endl; + os << " Pixels interpolated: " << (block.GetPixelsInterpolated() ? "true" : "false") << std::endl; + os << " Pixel spacing interpretation: " << (int)block.GetPixelSpacingInterpretation() << std::endl; + os << " MITK image: " << (void*)block.GetMitkImage().GetPointer() << std::endl; + if (filenameDetails) + { + for (DICOMImageFrameList::const_iterator frameIter = frames.begin(); + frameIter != frames.end(); + ++frameIter) + { + os << " " << (*frameIter)->Filename; + if ((*frameIter)->FrameNo > 0) + { + os << ", " << (*frameIter)->FrameNo; + } + os << std::endl; + } + } + } + os << "---- End of output list ----" << std::endl; +} + + const mitk::DICOMImageBlockDescriptor& mitk::DICOMFileReader ::GetOutput(unsigned int index) const { if (index < m_Outputs.size()) { return m_Outputs[index]; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_Outputs.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } diff --git a/Modules/DICOMReader/mitkDICOMFileReader.h b/Modules/DICOMReader/mitkDICOMFileReader.h index 93a53b2c4e..657f2be15b 100644 --- a/Modules/DICOMReader/mitkDICOMFileReader.h +++ b/Modules/DICOMReader/mitkDICOMFileReader.h @@ -1,75 +1,77 @@ /*=================================================================== 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 mitkDICOMFileReader_h #define mitkDICOMFileReader_h #include "itkObjectFactory.h" #include "mitkCommon.h" #include "DICOMReaderExports.h" #include "mitkDICOMImageBlockDescriptor.h" namespace mitk { class DICOMReader_EXPORT DICOMFileReader : public itk::LightObject { public: enum LoadingConfidence { NoSupport = 0, FullSupport = 1, PartialSupport = 2, }; mitkClassMacro( DICOMFileReader, itk::LightObject ) void SetInputFiles(StringList filenames); const StringList& GetInputFiles() const; virtual void AnalyzeInputFiles() = 0; unsigned int GetNumberOfOutputs() const; const DICOMImageBlockDescriptor& GetOutput(unsigned int index) const; // void AllocateOutputImages(); virtual bool LoadImages() = 0; virtual bool CanHandleFile(const std::string& filename) = 0; + void PrintOutputs(std::ostream& os, bool filenameDetails = false); + protected: DICOMFileReader(); virtual ~DICOMFileReader(); DICOMFileReader(const DICOMFileReader& other); DICOMFileReader& operator=(const DICOMFileReader& other); void ClearOutputs(); void SetNumberOfOutputs(unsigned int numberOfOutputs); void SetOutput(unsigned int index, const DICOMImageBlockDescriptor& output); private: StringList m_InputFilenames; std::vector< DICOMImageBlockDescriptor > m_Outputs; }; } #endif diff --git a/Modules/DICOMReader/mitkDICOMFilenameSorter.cpp b/Modules/DICOMReader/mitkDICOMFilenameSorter.cpp new file mode 100644 index 0000000000..23850e66a9 --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMFilenameSorter.cpp @@ -0,0 +1,73 @@ +/*=================================================================== + +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 "mitkDICOMFilenameSorter.h" + +#include + +mitk::DICOMFilenameSorter +::DICOMFilenameSorter() +:DICOMDatasetSorter() +{ +} + +mitk::DICOMFilenameSorter +::~DICOMFilenameSorter() +{ +} + +mitk::DICOMFilenameSorter +::DICOMFilenameSorter(const DICOMFilenameSorter& other ) +:DICOMDatasetSorter(other) +{ +} + +mitk::DICOMFilenameSorter& +mitk::DICOMFilenameSorter +::operator=(const DICOMFilenameSorter& other) +{ + if (this != &other) + { + DICOMDatasetSorter::operator=(other); + } + return *this; +} + +mitk::DICOMTagList +mitk::DICOMFilenameSorter +::GetTagsOfInterest() +{ + return DICOMTagList(); +} + +bool +mitk::DICOMFilenameSorter::FilenameSort +::operator() (const mitk::DICOMDatasetAccess* left, const mitk::DICOMDatasetAccess* right) +{ + return left->GetFilenameIfAvailable().compare( right->GetFilenameIfAvailable() ) < 0 ; +} + +void +mitk::DICOMFilenameSorter +::Sort() +{ + DICOMDatasetList output = GetInput(); // copy + + std::sort( output.begin(), output.end(), FilenameSort() ); + + this->SetNumberOfOutputs(1); + this->SetOutput(0, output); +} diff --git a/Modules/DICOMReader/mitkDICOMFilenameSorter.h b/Modules/DICOMReader/mitkDICOMFilenameSorter.h new file mode 100644 index 0000000000..d80cff0c13 --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMFilenameSorter.h @@ -0,0 +1,55 @@ +/*=================================================================== + +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 mitkDICOMFilenameSorter_h +#define mitkDICOMFilenameSorter_h + +#include "mitkDICOMDatasetSorter.h" + +namespace mitk +{ + +/** + \brief sort files based on filename (last resort). +*/ +class DICOMReader_EXPORT DICOMFilenameSorter : public DICOMDatasetSorter +{ + public: + + mitkClassMacro( DICOMFilenameSorter, DICOMDatasetSorter ) + itkNewMacro( DICOMFilenameSorter ) + + virtual DICOMTagList GetTagsOfInterest(); + + virtual void Sort(); + + protected: + + struct FilenameSort + { + bool operator() (const mitk::DICOMDatasetAccess* left, const mitk::DICOMDatasetAccess* right); + }; + + DICOMFilenameSorter(); + virtual ~DICOMFilenameSorter(); + + DICOMFilenameSorter(const DICOMFilenameSorter& other); + DICOMFilenameSorter& operator=(const DICOMFilenameSorter& other); +}; + +} + +#endif diff --git a/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.cpp b/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.cpp new file mode 100644 index 0000000000..d09ccd674e --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.cpp @@ -0,0 +1,86 @@ +/*=================================================================== + + 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 "mitkDICOMGDCMImageFrameInfo.h" + +mitk::DICOMGDCMImageFrameInfo +::DICOMGDCMImageFrameInfo(const std::string& filename, unsigned int frameNo) +:itk::LightObject() +,m_FrameInfo( DICOMImageFrameInfo::New(filename, frameNo) ) +,m_TagForValue(gdcm::Scanner::TagToValue()) // empty +{ +} + +mitk::DICOMGDCMImageFrameInfo +::DICOMGDCMImageFrameInfo(DICOMImageFrameInfo::Pointer frameinfo) +:itk::LightObject() +,m_FrameInfo(frameinfo) +,m_TagForValue(gdcm::Scanner::TagToValue()) // empty +{ +} + +mitk::DICOMGDCMImageFrameInfo +::DICOMGDCMImageFrameInfo(DICOMImageFrameInfo::Pointer frameinfo, gdcm::Scanner::TagToValue const& tagToValueMapping) +:itk::LightObject() +,m_FrameInfo(frameinfo) +,m_TagForValue(tagToValueMapping) +{ +} + + +std::string +mitk::DICOMGDCMImageFrameInfo +::GetTagValueAsString(const DICOMTag& tag) const +{ + gdcm::Scanner::TagToValue::const_iterator mappedValue = m_TagForValue.find( gdcm::Tag(tag.first, tag.second) ); + + if (mappedValue != m_TagForValue.end()) + { + return mappedValue->second; + } + else + { + return std::string(""); + } +} + +std::string +mitk::DICOMGDCMImageFrameInfo +::GetFilenameIfAvailable() const +{ + if (m_FrameInfo.IsNotNull()) + { + return m_FrameInfo->Filename; + } + else + { + return ""; + } +} + +mitk::DICOMImageFrameInfo::Pointer +mitk::DICOMGDCMImageFrameInfo +::GetFrameInfo() const +{ + return m_FrameInfo; +} + +void + mitk::DICOMGDCMImageFrameInfo +::SetFrameInfo(DICOMImageFrameInfo::Pointer frameinfo) +{ + m_FrameInfo = frameinfo; +} diff --git a/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.h b/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.h new file mode 100644 index 0000000000..6bf50e5f82 --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMGDCMImageFrameInfo.h @@ -0,0 +1,59 @@ +/*=================================================================== + +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 mitkDICOMGDCMImageFrameInfo_h +#define mitkDICOMGDCMImageFrameInfo_h + +#include "mitkDICOMImageFrameInfo.h" +#include "mitkDICOMDatasetAccess.h" + +#include "gdcmScanner.h" + +namespace mitk +{ + class DICOMReader_EXPORT DICOMGDCMImageFrameInfo : public itk::LightObject, public DICOMDatasetAccess + { + public: + + mitkClassMacro(DICOMGDCMImageFrameInfo, itk::LightObject); + itkNewMacro( DICOMGDCMImageFrameInfo ); + mitkNewMacro1Param( DICOMGDCMImageFrameInfo, const std::string&); + mitkNewMacro2Param( DICOMGDCMImageFrameInfo, const std::string&, unsigned int ); + mitkNewMacro1Param( DICOMGDCMImageFrameInfo, DICOMImageFrameInfo::Pointer); + mitkNewMacro2Param( DICOMGDCMImageFrameInfo, DICOMImageFrameInfo::Pointer, gdcm::Scanner::TagToValue const&); + + virtual std::string GetTagValueAsString(const DICOMTag&) const; + + std::string GetFilenameIfAvailable() const; + + DICOMImageFrameInfo::Pointer GetFrameInfo() const; + void SetFrameInfo(DICOMImageFrameInfo::Pointer frameinfo); + + protected: + + DICOMImageFrameInfo::Pointer m_FrameInfo; + + DICOMGDCMImageFrameInfo(DICOMImageFrameInfo::Pointer frameinfo); + DICOMGDCMImageFrameInfo(DICOMImageFrameInfo::Pointer frameinfo, gdcm::Scanner::TagToValue const& tagToValueMapping); + DICOMGDCMImageFrameInfo(const std::string& filename = "", unsigned int frameNo = 0); + + gdcm::Scanner::TagToValue const& m_TagForValue; + }; + + typedef std::vector DICOMGDCMImageFrameList; +} + +#endif diff --git a/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.cpp b/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.cpp index 6ba11baea0..e11a7796bc 100644 --- a/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.cpp +++ b/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.cpp @@ -1,140 +1,247 @@ /*=================================================================== 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 "mitkDICOMITKSeriesGDCMReader.h" +#include + +#include + mitk::DICOMITKSeriesGDCMReader ::DICOMITKSeriesGDCMReader() :DICOMFileReader() ,m_FixTiltByShearing(false) ,m_Group3DplusT(false) { } mitk::DICOMITKSeriesGDCMReader ::DICOMITKSeriesGDCMReader(const DICOMITKSeriesGDCMReader& other ) :DICOMFileReader(other) ,m_FixTiltByShearing(false) ,m_Group3DplusT(false) { } mitk::DICOMITKSeriesGDCMReader ::~DICOMITKSeriesGDCMReader() { } mitk::DICOMITKSeriesGDCMReader& mitk::DICOMITKSeriesGDCMReader ::operator=(const DICOMITKSeriesGDCMReader& other) { if (this != &other) { DICOMFileReader::operator=(other); } return *this; } +mitk::DICOMGDCMImageFrameList +mitk::DICOMITKSeriesGDCMReader +::FromDICOMDatasetList(DICOMDatasetList& input) +{ + DICOMGDCMImageFrameList output; + output.reserve(input.size()); + + for(DICOMDatasetList::iterator inputIter = input.begin(); + inputIter != input.end(); + ++inputIter) + { + DICOMGDCMImageFrameInfo* gfi = dynamic_cast(*inputIter); + assert(gfi); + output.push_back(gfi); + } + + return output; +} + +mitk::DICOMDatasetList +mitk::DICOMITKSeriesGDCMReader +::ToDICOMDatasetList(DICOMGDCMImageFrameList& input) +{ + DICOMDatasetList output; + output.reserve(input.size()); + + for(DICOMGDCMImageFrameList::iterator inputIter = input.begin(); + inputIter != input.end(); + ++inputIter) + { + DICOMDatasetAccess* da = inputIter->GetPointer(); + assert(da); + output.push_back(da); + } + + return output; +} + +mitk::DICOMImageFrameList +mitk::DICOMITKSeriesGDCMReader +::ToDICOMImageFrameList(DICOMGDCMImageFrameList& input) +{ + DICOMImageFrameList output; + output.reserve(input.size()); + + for(DICOMGDCMImageFrameList::iterator inputIter = input.begin(); + inputIter != input.end(); + ++inputIter) + { + DICOMImageFrameInfo::Pointer fi = (*inputIter)->GetFrameInfo(); + assert(fi.IsNotNull()); + output.push_back(fi); + } + + return output; +} void mitk::DICOMITKSeriesGDCMReader ::AnalyzeInputFiles() { + itk::TimeProbesCollectorBase timer; + + timer.Start("Reset"); this->ClearOutputs(); + timer.Stop("Reset"); // prepare initial sorting (== list of input files) - StringList inputFilenames = this->GetInputFiles(); - DICOMImageFrameList initialFramelist; + + // scan files for sorting-relevant tags + + // TODO provide tagToValueMappings to items in initialFramelist / m_SortingResultInProgress + timer.Start("Setup scanning"); + gdcm::Scanner gdcmScanner; + for(SorterList::iterator sorterIter = m_Sorter.begin(); + sorterIter != m_Sorter.end(); + ++sorterIter) + { + assert(sorterIter->IsNotNull()); + + DICOMTagList tags = (*sorterIter)->GetTagsOfInterest(); + for(DICOMTagList::const_iterator tagIter = tags.begin(); + tagIter != tags.end(); + ++tagIter) + { + MITK_DEBUG << "Sorting uses tag " << tagIter->first << "," << tagIter->second; + gdcmScanner.AddTag( gdcm::Tag(tagIter->first, tagIter->second) ); + } + } + timer.Stop("Setup scanning"); + + timer.Start("Tag scanning"); + gdcmScanner.Scan( inputFilenames ); + timer.Stop("Tag scanning"); + + timer.Start("Setup sorting"); + DICOMGDCMImageFrameList initialFramelist; for (StringList::const_iterator inputIter = inputFilenames.begin(); inputIter != inputFilenames.end(); ++inputIter) { // TODO check DICOMness and non-multi-framedness - initialFramelist.push_back( DICOMImageFrameInfo::New(*inputIter, 0) ); + initialFramelist.push_back( DICOMGDCMImageFrameInfo::New( DICOMImageFrameInfo::New(*inputIter, 0), gdcmScanner.GetMapping(inputIter->c_str()) ) ); } + m_SortingResultInProgress.clear(); m_SortingResultInProgress.push_back( initialFramelist ); + timer.Stop("Setup sorting"); - /* - PSEUDO CODE - - // scan files for sorting-relevant tags - - gdcm::Scanner gdcmScanner; - - foreach(DICOMDataSetSorter sorter, m_Sorter) - { - TagList tags = sorter->GetTagsOfInterest(); - foreach(Tag, tags) - { - gdcmScanner.AddTag( tag ); - } - } - - // sort and split blocks as configured + // sort and split blocks as configured - DICOMImageFrameInfo nextStepSorting; // we should not modify our input list while processing it - foreach(DICOMDataSetSorter sorter, m_Sorter) - { - nextStepSorting.clear(); - - foreach(DICOMImageFrameList framelist, m_SortingResultInProgress) - { - sorter->SetInput(framelist); - sorter->Sort(); - unsigned int numberOfResultingBlocks = sorter->GetNumberOfOutputs(); - for (unsigned int b = 0; b < numberOfResultingBlocks; ++b) - { - DICOMImageFrameList blockResult = sorter->GetOutput(b); - nextStepSorting.push_back( blockResult ); - } - } - - m_SortingResultInProgress = nextStepSorting; - } - - */ + timer.Start("Sorting frames"); + SortingBlockList nextStepSorting; // we should not modify our input list while processing it + unsigned int sorterIndex = 0; + for(SorterList::iterator sorterIter = m_Sorter.begin(); + sorterIter != m_Sorter.end(); + ++sorterIndex, ++sorterIter) + { + std::stringstream ss; ss << "Sorting step " << sorterIndex; + timer.Start( ss.str().c_str() ); + nextStepSorting.clear(); + DICOMDatasetSorter::Pointer& sorter = *sorterIter; + + for(SortingBlockList::iterator blockIter = m_SortingResultInProgress.begin(); + blockIter != m_SortingResultInProgress.end(); + ++blockIter) + { + DICOMGDCMImageFrameList& gdcmInfoFrameList = *blockIter; + DICOMDatasetList datasetList = ToDICOMDatasetList( gdcmInfoFrameList ); + + sorter->SetInput(datasetList); + sorter->Sort(); + unsigned int numberOfResultingBlocks = sorter->GetNumberOfOutputs(); + for (unsigned int b = 0; b < numberOfResultingBlocks; ++b) + { + DICOMDatasetList blockResult = sorter->GetOutput(b); + DICOMGDCMImageFrameList sortedGdcmInfoFrameList = FromDICOMDatasetList(blockResult); + nextStepSorting.push_back( sortedGdcmInfoFrameList ); + } + } + + m_SortingResultInProgress = nextStepSorting; + timer.Stop( ss.str().c_str() ); + } + timer.Stop("Sorting frames"); // provide final result as output + timer.Start("Output"); this->SetNumberOfOutputs( m_SortingResultInProgress.size() ); unsigned int o = 0; for (SortingBlockList::iterator blockIter = m_SortingResultInProgress.begin(); blockIter != m_SortingResultInProgress.end(); ++o, ++blockIter) { + DICOMGDCMImageFrameList& gdcmFrameInfoList = *blockIter; + DICOMImageFrameList frameList = ToDICOMImageFrameList( gdcmFrameInfoList ); + DICOMImageBlockDescriptor block; - block.SetImageFrameList( *blockIter ); + block.SetImageFrameList( frameList ); this->SetOutput( o, block ); } + timer.Stop("Output"); + + std::cout << "---------------------------------------------------------------" << std::endl; + timer.Report( std::cout ); + std::cout << "---------------------------------------------------------------" << std::endl; } // void AllocateOutputImages(); bool mitk::DICOMITKSeriesGDCMReader ::LoadImages() { // does nothing return true; } bool mitk::DICOMITKSeriesGDCMReader ::CanHandleFile(const std::string& itkNotUsed(filename)) { return true; // can handle all } + +void +mitk::DICOMITKSeriesGDCMReader +::AddSortingElement(DICOMDatasetSorter* sorter) +{ + assert(sorter); + m_Sorter.push_back( sorter ); +} diff --git a/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.h b/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.h index 69d81798cf..96bf0f4195 100644 --- a/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.h +++ b/Modules/DICOMReader/mitkDICOMITKSeriesGDCMReader.h @@ -1,61 +1,73 @@ /*=================================================================== 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 mitkDICOMITKSeriesGDCMReader_h #define mitkDICOMITKSeriesGDCMReader_h #include "mitkDICOMFileReader.h" +#include "mitkDICOMDatasetSorter.h" + +#include "mitkDICOMGDCMImageFrameInfo.h" #include "DICOMReaderExports.h" namespace mitk { class DICOMReader_EXPORT DICOMITKSeriesGDCMReader : public DICOMFileReader { public: mitkClassMacro( DICOMITKSeriesGDCMReader, DICOMFileReader ); mitkCloneMacro( DICOMITKSeriesGDCMReader ); itkNewMacro( DICOMITKSeriesGDCMReader ); virtual void AnalyzeInputFiles(); // void AllocateOutputImages(); virtual bool LoadImages(); virtual bool CanHandleFile(const std::string& filename); + virtual void AddSortingElement(DICOMDatasetSorter* sorter); + protected: DICOMITKSeriesGDCMReader(); virtual ~DICOMITKSeriesGDCMReader(); DICOMITKSeriesGDCMReader(const DICOMITKSeriesGDCMReader& other); DICOMITKSeriesGDCMReader& operator=(const DICOMITKSeriesGDCMReader& other); + DICOMDatasetList ToDICOMDatasetList(DICOMGDCMImageFrameList& input); + DICOMGDCMImageFrameList FromDICOMDatasetList(DICOMDatasetList& input); + DICOMImageFrameList ToDICOMImageFrameList(DICOMGDCMImageFrameList& input); + private: bool m_FixTiltByShearing; bool m_Group3DplusT; - typedef std::list SortingBlockList; + typedef std::list SortingBlockList; SortingBlockList m_SortingResultInProgress; + + typedef std::list SorterList; + SorterList m_Sorter; }; } #endif diff --git a/Modules/DICOMReader/mitkDICOMImageBlockDescriptor.h b/Modules/DICOMReader/mitkDICOMImageBlockDescriptor.h index 2e01cd917b..e8fca6c1ba 100644 --- a/Modules/DICOMReader/mitkDICOMImageBlockDescriptor.h +++ b/Modules/DICOMReader/mitkDICOMImageBlockDescriptor.h @@ -1,66 +1,65 @@ /*=================================================================== 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 mitkDICOMImageBlockDescriptor_h #define mitkDICOMImageBlockDescriptor_h -#include "mitkImage.h" - #include "mitkDICOMEnums.h" +#include "mitkDICOMImageFrameInfo.h" -#include "DICOMReaderExports.h" +#include "mitkImage.h" namespace mitk { class DICOMReader_EXPORT DICOMImageBlockDescriptor { public: DICOMImageBlockDescriptor(); ~DICOMImageBlockDescriptor(); DICOMImageBlockDescriptor(const DICOMImageBlockDescriptor& other); DICOMImageBlockDescriptor& operator=(const DICOMImageBlockDescriptor& other); void SetImageFrameList(const DICOMImageFrameList& framelist); const DICOMImageFrameList& GetImageFrameList() const; void SetMitkImage(Image::Pointer image); Image::Pointer GetMitkImage() const; void SetSliceIsLoaded(unsigned int index, bool isLoaded); bool IsSliceLoaded(unsigned int index) const; bool AllSlicesAreLoaded() const; void SetPixelsInterpolated(bool pixelsAreInterpolated); bool GetPixelsInterpolated() const; void SetPixelSpacingInterpretation( PixelSpacingInterpretation interpretation ); PixelSpacingInterpretation GetPixelSpacingInterpretation() const; private: DICOMImageFrameList m_ImageFrameList; Image::Pointer m_MitkImage; BoolList m_SliceIsLoaded; bool m_PixelsInterpolated; PixelSpacingInterpretation m_PixelSpacingInterpretation; }; } #endif diff --git a/Modules/DICOMReader/mitkDICOMEnums.h b/Modules/DICOMReader/mitkDICOMImageFrameInfo.cpp similarity index 52% copy from Modules/DICOMReader/mitkDICOMEnums.h copy to Modules/DICOMReader/mitkDICOMImageFrameInfo.cpp index 618ad78dd4..b3ddcb0c92 100644 --- a/Modules/DICOMReader/mitkDICOMEnums.h +++ b/Modules/DICOMReader/mitkDICOMImageFrameInfo.cpp @@ -1,38 +1,24 @@ /*=================================================================== 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 mitkDICOMEnums_h -#define mitkDICOMEnums_h - #include "mitkDICOMImageFrameInfo.h" -namespace mitk +mitk::DICOMImageFrameInfo +::DICOMImageFrameInfo(const std::string& filename, unsigned int frameNo) +:Filename(filename) +,FrameNo(frameNo) { - typedef std::vector StringList; - typedef std::vector BoolList; - - typedef std::vector DICOMImageFrameList; - - typedef enum - { - SpacingInPatient, /// distances are mm within a patient - SpacingAtDetector, /// distances are mm at detector surface - SpacingUnknown /// NO spacing information is present, we use (1,1) as default - } PixelSpacingInterpretation; - } - -#endif diff --git a/Modules/DICOMReader/mitkDICOMImageFrameInfo.h b/Modules/DICOMReader/mitkDICOMImageFrameInfo.h index 6f58ece05d..405b5b7273 100644 --- a/Modules/DICOMReader/mitkDICOMImageFrameInfo.h +++ b/Modules/DICOMReader/mitkDICOMImageFrameInfo.h @@ -1,50 +1,48 @@ /*=================================================================== 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 mitkDICOMImageFrameInfo_h #define mitkDICOMImageFrameInfo_h #include "itkObjectFactory.h" #include "mitkCommon.h" #include "DICOMReaderExports.h" namespace mitk { class DICOMReader_EXPORT DICOMImageFrameInfo : public itk::LightObject { public: std::string Filename; unsigned int FrameNo; mitkClassMacro( DICOMImageFrameInfo, itk::LightObject ) itkNewMacro( DICOMImageFrameInfo ); mitkNewMacro1Param( DICOMImageFrameInfo, const std::string&); mitkNewMacro2Param( DICOMImageFrameInfo, const std::string&, unsigned int ); protected: - DICOMImageFrameInfo(const std::string& filename = "", unsigned int frameNo = 0) - :Filename(filename) - ,FrameNo(frameNo) - { - } + DICOMImageFrameInfo(const std::string& filename = "", unsigned int frameNo = 0); }; + + typedef std::vector DICOMImageFrameList; } #endif diff --git a/Modules/DICOMReader/mitkDICOMTagBasedSorter.cpp b/Modules/DICOMReader/mitkDICOMTagBasedSorter.cpp new file mode 100644 index 0000000000..6e5dac78cd --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMTagBasedSorter.cpp @@ -0,0 +1,147 @@ +/*=================================================================== +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 "mitkDICOMTagBasedSorter.h" + +#include + +mitk::DICOMTagBasedSorter +::DICOMTagBasedSorter() +:DICOMDatasetSorter() +{ +} + +mitk::DICOMTagBasedSorter +::~DICOMTagBasedSorter() +{ +} + +mitk::DICOMTagBasedSorter +::DICOMTagBasedSorter(const DICOMTagBasedSorter& other ) +:DICOMDatasetSorter(other) +{ +} + +mitk::DICOMTagBasedSorter& +mitk::DICOMTagBasedSorter +::operator=(const DICOMTagBasedSorter& other) +{ + if (this != &other) + { + DICOMDatasetSorter::operator=(other); + } + return *this; +} + +mitk::DICOMTagList +mitk::DICOMTagBasedSorter +::GetTagsOfInterest() +{ + DICOMTagList allTags = m_DistinguishingTags; + allTags.insert( allTags.end(), m_SortCriteria.begin(), m_SortCriteria.end() ); // append + + // TODO sort, unique + + return allTags; +} + +void +mitk::DICOMTagBasedSorter +::AddDistinguishingTag( const DICOMTag& tag ) +{ + m_DistinguishingTags.push_back(tag); +} + +void +mitk::DICOMTagBasedSorter +::AddSortCriterion( const DICOMTag& tag ) +{ + m_SortCriteria.push_back(tag); +} + +void +mitk::DICOMTagBasedSorter +::Sort() +{ + // 1. split + this->SplitGroups(); + + // 2. sort each group + this->SortGroups(); + + //std::sort( output.begin(), output.end(), FilenameSort() ); +} + +std::string +mitk::DICOMTagBasedSorter +::BuildGroupID( DICOMDatasetAccess* dataset ) +{ + // just concatenate all tag values + assert(dataset); + std::stringstream groupID; + groupID << "g"; + for (DICOMTagList::iterator tagIter = m_DistinguishingTags.begin(); + tagIter != m_DistinguishingTags.end(); + ++tagIter) + { + groupID << tagIter->first << tagIter->second; // make group/element part of the id to cover empty tags + groupID << dataset->GetTagValueAsString(*tagIter); + } + // shorten ID? + return groupID.str(); +} + +void +mitk::DICOMTagBasedSorter +::SplitGroups() +{ + DICOMDatasetList input = GetInput(); // copy + + typedef std::map GroupIDToListType; + GroupIDToListType listForGroupID; + + for (DICOMDatasetList::iterator dsIter = input.begin(); + dsIter != input.end(); + ++dsIter) + { + DICOMDatasetAccess* dataset = *dsIter; + assert(dataset); + + std::string groupID = this->BuildGroupID( dataset ); + MITK_DEBUG << "Group ID for for " << dataset->GetFilenameIfAvailable() << ": " << groupID; + listForGroupID[groupID].push_back(dataset); + } + + this->SetNumberOfOutputs(listForGroupID.size()); + unsigned int outputIndex(0); + for (GroupIDToListType::iterator groupIter = listForGroupID.begin(); + groupIter != listForGroupID.end(); + ++outputIndex, ++groupIter) + { + this->SetOutput(outputIndex, groupIter->second); + } +} + +void +mitk::DICOMTagBasedSorter +::SortGroups() +{ + // for each output + // sort by all configured tags, use secondary tags when equal or empty + // make configurable: + // - sorting order (ascending, descending) + // - sort numerically + // - ... ? +} diff --git a/Modules/DICOMReader/mitkDICOMTagBasedSorter.h b/Modules/DICOMReader/mitkDICOMTagBasedSorter.h new file mode 100644 index 0000000000..4d047c2d55 --- /dev/null +++ b/Modules/DICOMReader/mitkDICOMTagBasedSorter.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 mitkDICOMTagBasedSorter_h +#define mitkDICOMTagBasedSorter_h + +#include "mitkDICOMDatasetSorter.h" + +namespace mitk +{ + +/** + \brief sort files based on filename (last resort). +*/ +class DICOMReader_EXPORT DICOMTagBasedSorter : public DICOMDatasetSorter +{ + public: + + mitkClassMacro( DICOMTagBasedSorter, DICOMDatasetSorter ) + itkNewMacro( DICOMTagBasedSorter ) + + void AddDistinguishingTag( const DICOMTag& ); + void AddSortCriterion( const DICOMTag& ); + + virtual DICOMTagList GetTagsOfInterest(); + + virtual void Sort(); + + protected: + + DICOMTagBasedSorter(); + virtual ~DICOMTagBasedSorter(); + + DICOMTagBasedSorter(const DICOMTagBasedSorter& other); + DICOMTagBasedSorter& operator=(const DICOMTagBasedSorter& other); + + std::string BuildGroupID( DICOMDatasetAccess* dataset ); + + void SplitGroups(); + void SortGroups(); + + DICOMTagList m_DistinguishingTags; + DICOMTagList m_SortCriteria; +}; + +} + +#endif