diff --git a/Core/Code/TestingHelper/mitkTestingMacros.h b/Core/Code/TestingHelper/mitkTestingMacros.h index a7d4ac8e7b..002e9743c8 100644 --- a/Core/Code/TestingHelper/mitkTestingMacros.h +++ b/Core/Code/TestingHelper/mitkTestingMacros.h @@ -1,378 +1,377 @@ /*=================================================================== 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 mitkTestingMacros_h #define mitkTestingMacros_h #include #include #include #include #include #include #include #include namespace mitk { /** @brief Indicate a failed test. */ class TestFailedException : public std::exception { public: TestFailedException() {} }; } /** * @brief Output some text without generating a terminating newline. Include * * @ingroup MITKTestingAPI */ #define MITK_TEST_OUTPUT_NO_ENDL(x) \ std::cout x ; /** * @brief Output some text. * * @ingroup MITKTestingAPI */ #define MITK_TEST_OUTPUT(x) \ MITK_TEST_OUTPUT_NO_ENDL(x << "\n") /** * @brief Do some general test preparations. Must be called first in the * main test function. * * @deprecatedSince{2013_09} Use MITK_TEST_SUITE_REGISTRATION instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_BEGIN(testName) \ std::string mitkTestName(#testName); \ mitk::TestManager::GetInstance()->Initialize(); \ try { /** * @brief Fail and finish test with message MSG * * @deprecatedSince{2013_09} Use CPPUNIT_FAIL instead * @ingroup MITKTestingAPI */ #define MITK_TEST_FAILED_MSG(MSG) \ MITK_TEST_OUTPUT(MSG) \ throw mitk::TestFailedException(); /** * @brief Must be called last in the main test function. * * @deprecatedSince{2013_09} Use MITK_TEST_SUITE_REGISTRATION instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_END() \ } catch (mitk::TestFailedException ex) { \ MITK_TEST_OUTPUT(<< "Further test execution skipped.") \ mitk::TestManager::GetInstance()->TestFailed(); \ } catch (std::exception ex) { \ MITK_TEST_OUTPUT(<< "std::exception occured " << ex.what()) \ mitk::TestManager::GetInstance()->TestFailed(); \ } \ if (mitk::TestManager::GetInstance()->NumberOfFailedTests() > 0) { \ MITK_TEST_OUTPUT(<< mitkTestName << ": [DONE FAILED] , subtests passed: " << \ mitk::TestManager::GetInstance()->NumberOfPassedTests() << " failed: " << \ mitk::TestManager::GetInstance()->NumberOfFailedTests() ) \ return EXIT_FAILURE; \ } else { \ MITK_TEST_OUTPUT(<< mitkTestName << ": " \ << mitk::TestManager::GetInstance()->NumberOfPassedTests() \ << " tests [DONE PASSED]") \ return EXIT_SUCCESS; \ } \ /** * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT or CPPUNIT_ASSERT_MESSAGE instead. */ #define MITK_TEST_CONDITION(COND,MSG) \ MITK_TEST_OUTPUT_NO_ENDL(<< MSG) \ if ( ! (COND) ) { \ mitk::TestManager::GetInstance()->TestFailed(); \ MITK_TEST_OUTPUT(<< " [FAILED]\n" << "In " << __FILE__ \ << ", line " << __LINE__ \ << ": " #COND " : [FAILED]") \ } else { \ MITK_TEST_OUTPUT(<< " [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT or CPPUNIT_ASSERT_MESSAGE instead. */ #define MITK_TEST_CONDITION_REQUIRED(COND,MSG) \ MITK_TEST_OUTPUT_NO_ENDL(<< MSG) \ if ( ! (COND) ) { \ MITK_TEST_FAILED_MSG(<< " [FAILED]\n" << " +--> in " << __FILE__ \ << ", line " << __LINE__ \ << ", expression is false: \"" #COND "\"") \ } else { \ MITK_TEST_OUTPUT(<< " [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * \brief Begin block which should be checked for exceptions * * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT_THROW instead. * @ingroup MITKTestingAPI * * This macro, together with MITK_TEST_FOR_EXCEPTION_END, can be used * to test whether a code block throws an expected exception. The test FAILS if the * exception is NOT thrown. A simple example: * MITK_TEST_FOR_EXCEPTION_BEGIN(itk::ImageFileReaderException) typedef itk::ImageFileReader< itk::Image > ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName("/tmp/not-existing"); reader->Update(); MITK_TEST_FOR_EXCEPTION_END(itk::ImageFileReaderException) * */ #define MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ try { /** * @deprecatedSince{2013_09} */ #define MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) \ mitk::TestManager::GetInstance()->TestFailed(); \ MITK_TEST_OUTPUT( << "Expected an '" << #EXCEPTIONCLASS << "' exception. [FAILED]") \ } \ catch (EXCEPTIONCLASS) { \ MITK_TEST_OUTPUT( << "Caught an expected '" << #EXCEPTIONCLASS \ << "' exception. [PASSED]") \ mitk::TestManager::GetInstance()->TestPassed(); \ } /** * @brief Simplified version of MITK_TEST_FOR_EXCEPTION_BEGIN / END for * a single statement * * @deprecatedSince{2013_09} Use CPPUNIT_ASSERT_THROW instead. * @ingroup MITKTestingAPI */ #define MITK_TEST_FOR_EXCEPTION(EXCEPTIONCLASS, STATEMENT) \ MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS) \ STATEMENT ; \ MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS) /** * @brief Testing macro to test if two objects are equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * Feel free to implement mitk::Equal for your own datatype or purpose. * * @deprecatedSince{2013_09} Use MITK_ASSERT_EQUAL instead. * * @param OBJ1 First object. * @param OBJ2 Second object. * @param MSG Message to appear with the test. */ #define MITK_TEST_EQUAL(OBJ1,OBJ2,MSG) \ MITK_TEST_CONDITION_REQUIRED( mitk::Equal(OBJ1, OBJ2, mitk::eps, true)==true, MSG) /** * @brief Testing macro to test if two objects are equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * Feel free to implement mitk::Equal for your own datatype or purpose. * * @param EXPECTED First object. * @param ACTUAL Second object. * @param MSG Message to appear with the test. */ #define MITK_ASSERT_EQUAL(EXPECTED, ACTUAL, MSG) \ CPPUNIT_ASSERT_MESSAGE(MSG, mitk::Equal(EXPECTED, ACTUAL, mitk::eps, true)) /** * @brief Testing macro to test if two objects are not equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * * @deprecatedSince{2013_09} Use MITK_ASSERT_NOT_EQUAL instead. * * @param OBJ1 First object. * @param OBJ2 Second object. * @param MSG Message to appear with the test. * * \sa MITK_TEST_EQUAL */ #define MITK_TEST_NOT_EQUAL(OBJ1,OBJ2,MSG) \ MITK_TEST_CONDITION_REQUIRED( mitk::Equal(OBJ1, OBJ2, mitk::eps, true)==false, MSG) /** * @brief Testing macro to test if two objects are not equal. * * @ingroup MITKTestingAPI * * This macro uses mitk::eps and the corresponding mitk::Equal methods for all * comparisons and will give verbose output on the dashboard/console. * * @param OBJ1 First object. * @param OBJ2 Second object. * @param MSG Message to appear with the test. * * \sa MITK_ASSERT_EQUAL */ #define MITK_ASSERT_NOT_EQUAL(OBJ1, OBJ2, MSG) \ CPPUNIT_ASSERT_MESSAGE(MSG, !mitk::Equal(OBJ1, OBJ2, mitk::eps, true)) /** * @brief Registers the given test suite. * * @ingroup MITKTestingAPI * * @param TESTSUITE_NAME The name of the test suite class, without "TestSuite" * at the end. */ #define MITK_TEST_SUITE_REGISTRATION(TESTSUITE_NAME) \ int TESTSUITE_NAME ## Test(int /*argc*/, char* /*argv*/[]) \ { \ CppUnit::TextUi::TestRunner runner; \ runner.addTest(TESTSUITE_NAME ## TestSuite::suite()); \ runner.run(); \ return EXIT_SUCCESS; \ } /** * @brief Adds a test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases. * The macro internally just calls the CPPUNIT_TEST macro. * * @param TESTMETHOD The name of the member funtion test. */ #define MITK_TEST(TESTMETHOD) CPPUNIT_TEST(TESTMETHOD) /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need custom parameters. * * @param TESTMETHOD The name of the member function test. * @param ARGS A std::vector object containing test parameter. * * @note Use the macro MITK_PARAMETERIZED_TEST only if you know what * you are doing. If you are not sure, use MITK_TEST instead. */ #define MITK_PARAMETERIZED_TEST(TESTMETHOD, ARGS) \ { \ std::string testName = #TESTMETHOD; \ for (std::size_t i = 0; i < ARGS.size(); ++i) \ { \ testName += "_" + ARGS[i]; \ } \ CPPUNIT_TEST_SUITE_ADD_TEST( \ ( new mitk::TestCaller( \ context.getTestNameFor(testName), \ &TestFixtureType::TESTMETHOD, \ context.makeFixture(), args ) ) ); \ } /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need parameters from the command line. * * @warning Use the macro MITK_PARAMETERIZED_CMD_LINE_TEST only * if you know what you are doing. If you are not sure, use * MITK_TEST instead. MITK_PARAMETERIZED_CMD_LINE_TEST is meant * for migrating from ctest to CppUnit. If you implement new * tests, the MITK_TEST macro will be sufficient. * * @param TESTMETHOD The name of the member function test. */ #define MITK_PARAMETERIZED_CMD_LINE_TEST(TESTMETHOD) \ CPPUNIT_TEST_SUITE_ADD_TEST( \ ( new mitk::TestCaller( \ context.getTestNameFor( #TESTMETHOD), \ &TestFixtureType::TESTMETHOD, \ context.makeFixture() ) ) ); /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need one custom parameter. * * @param TESTMETHOD The name of the member function test. * @param arg1 A custom string parameter being passed to the fixture. * * @note Use the macro MITK_PARAMETERIZED_TEST_1 only if you know what * you are doing. If you are not sure, use MITK_TEST instead. * * @see MITK_PARAMETERIZED_TEST */ #define MITK_PARAMETERIZED_TEST_1(TESTMETHOD, arg1) \ { \ std::vector args; \ args.push_back(arg1); \ MITK_PARAMETERIZED_TEST(TESTMETHOD, args) \ } /** * @brief Adds a parameterized test to the current test suite. * * @ingroup MITKTestingAPI * * Use this macro after the CPPUNIT_TEST_SUITE() macro to add test cases * which need two custom parameter. * * @param TESTMETHOD The name of the member function test. * @param arg1 A custom string parameter being passed to the fixture. * * @note Use the macro MITK_PARAMETERIZED_TEST_2 only if you know what * you are doing. If you are not sure, use MITK_TEST instead. * * @see MITK_PARAMETERIZED_TEST */ #define MITK_PARAMETERIZED_TEST_2(TESTMETHOD, arg1, arg2) \ { \ std::vector args; \ args.push_back(arg1); \ args.push_back(arg2); \ MITK_PARAMETERIZED_TEST(TESTMETHOD, args) \ } - #endif diff --git a/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp b/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp index a02c473b58..88a8a8ca00 100644 --- a/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp +++ b/Modules/DICOMReader/mitkDICOMFileReaderSelector.cpp @@ -1,260 +1,259 @@ /*=================================================================== 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 "mitkDICOMGDCMTagScanner.h" #include #include #include #include #include mitk::DICOMFileReaderSelector ::DICOMFileReaderSelector() { } mitk::DICOMFileReaderSelector ::~DICOMFileReaderSelector() { } std::list mitk::DICOMFileReaderSelector ::GetAllConfiguredReaders() const { return m_Readers; } void mitk::DICOMFileReaderSelector ::AddConfigsFromResources(const std::string& path) { std::vector configs = us::GetModuleContext()->GetModule()->FindResources(path, "*.xml", false); for (std::vector::iterator iter = configs.begin(); iter != configs.end(); ++iter) { us::ModuleResource& resource = *iter; if (resource.IsValid()) { us::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()); this->AddConfig(s); } } } void mitk::DICOMFileReaderSelector ::AddConfigFromResource(us::ModuleResource& resource) { if (resource.IsValid()) { us::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()); this->AddConfig(s); } } void mitk::DICOMFileReaderSelector ::AddConfigFromResource(const std::string& resourcename) { us::ModuleResource r = us::GetModuleContext()->GetModule()->GetResource(resourcename); this->AddConfigFromResource(r); } void mitk::DICOMFileReaderSelector ::AddFileReaderCanditate(DICOMFileReader::Pointer reader) { if (reader.IsNotNull()) { m_Readers.push_back( reader ); } } void mitk::DICOMFileReaderSelector ::LoadBuiltIn3DConfigs() { //this->AddConfigsFromResources("configurations/3D"); // in this order of preference... this->AddConfigFromResource("configurations/3D/instancenumber.xml"); this->AddConfigFromResource("configurations/3D/slicelocation.xml"); this->AddConfigFromResource("configurations/3D/imageposition.xml"); this->AddConfigFromResource("configurations/3D/imageposition_byacquisition.xml"); //this->AddConfigFromResource("configurations/3D/imagetime.xml"); // no sense in this one? want to see a real-world example first this->AddConfigFromResource("configurations/3D/classicreader.xml"); // currently is 3D+t actually } 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; // do the tag scanning externally and just ONCE DICOMGDCMTagScanner::Pointer gdcmScanner = DICOMGDCMTagScanner::New(); gdcmScanner->SetInputFiles( m_InputFilenames ); // let all readers analyze the file set for (ReaderList::iterator rIter = m_Readers.begin(); rIter != m_Readers.end(); ++rIter) { gdcmScanner->AddTags( (*rIter)->GetTagsOfInterest() ); } gdcmScanner->Scan(); // 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 ); (*rIter)->SetTagCache( gdcmScanner.GetPointer() ); try { (*rIter)->AnalyzeInputFiles(); workingCandidates.push_back( *rIter ); MITK_INFO << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") suggests " << (*rIter)->GetNumberOfOutputs() << " 3D blocks"; if ((*rIter)->GetNumberOfOutputs() == 1) { MITK_DEBUG << "Early out with reader #" << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << "), less than 1 block is not possible"; return *rIter; } } catch (std::exception& e) { MITK_ERROR << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") threw exception during file analysis, ignoring this reader. Exception: " << e.what(); } catch (...) { MITK_ERROR << "Reader " << readerIndex << " (" << (*rIter)->GetConfigurationLabel() << ") 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) { unsigned int thisReadersNumberOfOutputs = (*rIter)->GetNumberOfOutputs(); if ( thisReadersNumberOfOutputs > 0 // we don't count readers that don't actually produce output && thisReadersNumberOfOutputs < minimumNumberOfOutputs ) { minimumNumberOfOutputs = (*rIter)->GetNumberOfOutputs(); bestReader = *rIter; bestReaderIndex = readerIndex; } } MITK_DEBUG << "Decided for reader #" << bestReaderIndex << " (" << bestReader->GetConfigurationLabel() << ")"; MITK_DEBUG << m_PossibleConfigurations[bestReaderIndex]; return bestReader; } diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp new file mode 100644 index 0000000000..8e684800ce --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp @@ -0,0 +1,245 @@ +/*=================================================================== + +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 "mitkDiffusionDICOMFileReader.h" + +#include "mitkDiffusionDICOMFileReaderHelper.h" + +#include "mitkDiffusionHeaderSiemensDICOMFileReader.h" +#include "mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h" +#include "mitkDiffusionHeaderGEDICOMFileReader.h" + +static void PerformHeaderAnalysis( mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType headers ) +{ + unsigned int images = headers.size(); + + unsigned int unweighted_images = 0; + unsigned int weighted_images = 0; + + mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType::const_iterator c_iter = headers.begin(); + while( c_iter != headers.end() ) + { + const mitk::DiffusionImageDICOMHeaderInformation h = *c_iter; + if( h.baseline ) unweighted_images++; + if( h.b_value > 0 ) weighted_images++; + + ++c_iter; + } + + MITK_INFO << " :: Analyzed volumes " << images << "\n" + << " :: \t"<< unweighted_images << " b = 0" << "\n" + << " :: \t"<< weighted_images << " b > 0"; +} + +mitk::DiffusionDICOMFileReader::DiffusionDICOMFileReader() +{ + +} + +mitk::DiffusionDICOMFileReader::~DiffusionDICOMFileReader() +{ + +} + +bool mitk::DiffusionDICOMFileReader +::LoadImages() +{ + // prepare data reading + DiffusionDICOMFileReaderHelper helper; + DiffusionDICOMFileReaderHelper::VolumeFileNamesContainer filenames; + + const size_t number_of_outputs = this->GetNumberOfOutputs(); + + for( size_t idx = 0; idx < number_of_outputs; idx++ ) + { + DICOMImageFrameList flist = this->GetOutput(idx).GetImageFrameList(); + + std::vector< std::string > FileNamesPerVolume; + + DICOMImageFrameList::const_iterator cIt = flist.begin(); + while( cIt != flist.end() ) + { + FileNamesPerVolume.push_back( (*cIt)->Filename ); + ++cIt; + } + + filenames.push_back( FileNamesPerVolume ); + } + + // TODO : only prototyping to test loading of diffusion images + // we need some solution for the different types + typedef mitk::DiffusionImage DiffusionImageType; + DiffusionImageType::Pointer output_image = DiffusionImageType::New(); + + DiffusionImageType::GradientDirectionContainerType::Pointer directions = + DiffusionImageType::GradientDirectionContainerType::New(); + + + double max_bvalue = 0; + for( size_t idx = 0; idx < number_of_outputs; idx++ ) + { + DiffusionImageDICOMHeaderInformation header = this->m_RetrievedHeader.at(idx); + + if( max_bvalue < header.b_value ) + max_bvalue = header.b_value; + } + + // normalize the retrieved gradient directions according to the set b-value (maximal one) + for( size_t idx = 0; idx < number_of_outputs; idx++ ) + { + DiffusionImageDICOMHeaderInformation header = this->m_RetrievedHeader.at(idx); + DiffusionImageType::GradientDirectionType grad = header.g_vector; + + grad.normalize(); + grad *= sqrt( header.b_value / max_bvalue ); + + directions->push_back( grad ); + } + + bool is_mosaic_file = false; + // FIXME : criterion for testing MOSAIC + /* { + is_mosaic_file = true; + }*/ + + // initialize the output image + output_image->SetDirections( directions ); + output_image->SetB_Value( max_bvalue ); + if( is_mosaic_file ) + { + + mitk::MosaicDescriptor mdesc; + // FIXME : will come from the header information + mdesc.nimages = 50; + + output_image->SetVectorImage( helper.LoadMosaicToVector( filenames, mdesc ) ); + + } + else + { + output_image->SetVectorImage( helper.LoadToVector( filenames ) ); + } + output_image->InitializeFromVectorImage(); + output_image->UpdateBValueMap(); + + // reduce the number of outputs to 1 as we will produce a single image + this->SetNumberOfOutputs(1); + + // set the image to output + DICOMImageBlockDescriptor& block = this->InternalGetOutput(0); + block.SetMitkImage( (mitk::Image::Pointer) output_image ); + +} + +void mitk::DiffusionDICOMFileReader +::AnalyzeInputFiles() +{ + Superclass::AnalyzeInputFiles(); + + // collect output from superclass + size_t number_of_outputs = this->GetNumberOfOutputs(); + + if(number_of_outputs == 0) + { + MITK_ERROR << "Failed to parse input, retrieved 0 outputs from SeriesGDCMReader "; + } + + DICOMImageBlockDescriptor block_0 = this->GetOutput(0); + + MITK_INFO << "Retrieved " << number_of_outputs << "outputs."; + + // collect vendor ID from the first output, first image + StringList inputFilename; + DICOMImageFrameInfo::Pointer frame_0 = block_0.GetImageFrameList().at(0); + inputFilename.push_back( frame_0->Filename ); + + gdcm::Scanner gdcmScanner; + + gdcm::Tag t_vendor(0x008, 0x0070); + gdcm::Tag t_imagetype(0x008, 0x008); + + // add DICOM Tag for vendor + gdcmScanner.AddTag( t_vendor ); + // add DICOM Tag for image type + gdcmScanner.AddTag( t_imagetype ); + gdcmScanner.Scan( inputFilename ); + + // retrieve both vendor and image type + std::string vendor = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_vendor ); + std::string image_type = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_imagetype ); + MITK_INFO << "Got vendor: " << vendor << " image type " << image_type; + + + mitk::DiffusionHeaderDICOMFileReader::Pointer header_reader; + + // parse vendor tag + if( vendor.find("SIEMENS") != std::string::npos ) + { + if( image_type.find("MOSAIC") != std::string::npos ) + { + header_reader = mitk::DiffusionHeaderSiemensMosaicDICOMFileReader::New(); + } + else + { + header_reader = mitk::DiffusionHeaderSiemensDICOMFileReader::New(); + } + + } + else if( vendor.find("GE") != std::string::npos ) + { + header_reader = mitk::DiffusionHeaderGEDICOMFileReader::New(); + } + else if( vendor.find("PHILIPS") != std::string::npos ) + { + + } + else + { + // unknown vendor + } + + if( header_reader.IsNull() ) + { + MITK_ERROR << "No header reader for given vendor. "; + return; + } + + bool canread = false; + for( size_t idx; idx < number_of_outputs; idx++ ) + { + DICOMImageFrameInfo::Pointer frame = this->GetOutput( idx ).GetImageFrameList().at(0); + canread = header_reader->ReadDiffusionHeader(frame->Filename); + } + + // collect the information + m_RetrievedHeader = header_reader->GetHeaderInformation(); + + // TODO : Analyze outputs + header information, i.e. for the loading confidence + MITK_INFO << "----- Diffusion DICOM Analysis Report ---- "; + + PerformHeaderAnalysis( m_RetrievedHeader ); + + MITK_INFO << "==========================================="; + +} + + +bool mitk::DiffusionDICOMFileReader +::CanHandleFile(const std::string &filename) +{ + +} + diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h new file mode 100644 index 0000000000..5ed962aa3c --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h @@ -0,0 +1,53 @@ +/*=================================================================== + +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 MITKDIFFUSIONDICOMFILEREADER_H +#define MITKDIFFUSIONDICOMFILEREADER_H + +#include "DiffusionCoreExports.h" + +#include "mitkDICOMITKSeriesGDCMReader.h" +#include "mitkDiffusionHeaderDICOMFileReader.h" + +namespace mitk +{ + +class DiffusionCore_EXPORT DiffusionDICOMFileReader + : public DICOMITKSeriesGDCMReader +{ +public: + + mitkClassMacro( DiffusionDICOMFileReader, DICOMITKSeriesGDCMReader ) + mitkCloneMacro( DiffusionDICOMFileReader ) + + itkNewMacro( DiffusionDICOMFileReader ) + + virtual void AnalyzeInputFiles(); + + virtual bool LoadImages(); + + virtual bool CanHandleFile(const std::string &filename); + +protected: + DiffusionDICOMFileReader(); + virtual ~DiffusionDICOMFileReader(); + + mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType m_RetrievedHeader; +}; + +} + +#endif // MITKDIFFUSIONDICOMFILEREADER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReaderHelper.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReaderHelper.h new file mode 100644 index 0000000000..f49742c62f --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReaderHelper.h @@ -0,0 +1,241 @@ +#ifndef MITKDIFFUSIONDICOMFILEREADERHELPER_H +#define MITKDIFFUSIONDICOMFILEREADERHELPER_H + +#include "mitkDiffusionImage.h" + +#include "itkImageSeriesReader.h" +#include "itkVectorImage.h" + +#include "itkImageRegionIteratorWithIndex.h" + +namespace mitk +{ + +/** + * @brief The MosaicDescriptor struct is a help struct holding the necessary information for + * loading a mosaic DICOM file into an MITK file with correct geometry information + */ +struct MosaicDescriptor +{ + unsigned int nimages; + + itk::ImageBase<3>::SpacingType spacing; + itk::ImageBase<3>::DirectionType direction; + float origin[3]; +}; + +class DiffusionDICOMFileReaderHelper +{ +public: + typedef std::vector< std::string > StringContainer; + + typedef std::vector< StringContainer > VolumeFileNamesContainer; + + + + template< typename PixelType, unsigned int VecImageDimension> + typename itk::VectorImage< PixelType, VecImageDimension >::Pointer LoadToVector( + const VolumeFileNamesContainer& filenames + //const itk::ImageBase<3>::RegionType requestedRegion + ) + { + typedef itk::Image< PixelType, 3> InputImageType; + typedef itk::ImageSeriesReader< InputImageType > SeriesReaderType; + + typename SeriesReaderType::Pointer probe_reader = SeriesReaderType::New(); + probe_reader->SetFileNames( filenames.at(0) ); + probe_reader->GenerateOutputInformation(); + const itk::ImageBase<3>::RegionType requestedRegion = probe_reader->GetOutput()->GetLargestPossibleRegion(); + + MITK_INFO << " --- Probe reader : \n" << + " Retrieved LPR " << requestedRegion; + + typedef itk::VectorImage< PixelType, 3 > VectorImageType; + + typename VectorImageType::Pointer output_image = VectorImageType::New(); + output_image->SetNumberOfComponentsPerPixel( filenames.size() ); + output_image->SetSpacing( probe_reader->GetOutput()->GetSpacing() ); + output_image->SetOrigin( probe_reader->GetOutput()->GetOrigin() ); + output_image->SetDirection( probe_reader->GetOutput()->GetDirection() ); + output_image->SetLargestPossibleRegion( probe_reader->GetOutput()->GetLargestPossibleRegion() ); + output_image->SetBufferedRegion( requestedRegion ); + output_image->Allocate(); + + itk::ImageRegionIterator< VectorImageType > vecIter( + output_image, requestedRegion ); + + VolumeFileNamesContainer::const_iterator volumesFileNamesIter = filenames.begin(); + + // iterate over the given volumes + unsigned int component = 0; + while( volumesFileNamesIter != filenames.end() ) + { + + MITK_INFO << " ======== Loading volume " << component+1 << " of " << filenames.size(); + + typename SeriesReaderType::Pointer volume_reader = SeriesReaderType::New(); + volume_reader->SetFileNames( *volumesFileNamesIter ); + + try + { + volume_reader->UpdateLargestPossibleRegion(); + } + catch( const itk::ExceptionObject &e) + { + mitkThrow() << " ITK Series reader failed : "<< e.what(); + } + + itk::ImageRegionConstIterator< InputImageType > iRCIter ( + volume_reader->GetOutput(), + volume_reader->GetOutput()->GetLargestPossibleRegion() ); + + // transfer to vector image + iRCIter.GoToBegin(); + vecIter.GoToBegin(); + + + + while( !iRCIter.IsAtEnd() ) + { + typename VectorImageType::PixelType vector_pixel = vecIter.Get(); + vector_pixel.SetElement( component, iRCIter.Get() ); + vecIter.Set( vector_pixel ); + + ++vecIter; + ++iRCIter; + } + + ++volumesFileNamesIter; + component++; + } + + return output_image; + + } + + + /** + * Create the vector image for the resulting diffusion image from a mosaic DICOM image set, + * The method needs to be provided with the MosaicDescriptor struct to be able to compute the + * correct index and to set the geometry information of the image itself. + */ + template< typename PixelType, unsigned int VecImageDimension> + typename itk::VectorImage< PixelType, VecImageDimension >::Pointer LoadMosaicToVector( + const VolumeFileNamesContainer& filenames, + MosaicDescriptor mosaicInfo ) + { + typedef itk::Image< PixelType, 3> MosaicImageType; + typedef itk::ImageFileReader< MosaicImageType > SingleImageReaderType; + + // generate output + typedef itk::VectorImage< PixelType, 3 > VectorImageType; + + VolumeFileNamesContainer::const_iterator volumesFileNamesIter = filenames.begin(); + + // probe the first file to retrieve the size of the 2d image + // we need this information to compute the index relation between mosaic and resulting 3d position + // but we need it only once + typename SingleImageReaderType::Pointer mosaic_probe = SingleImageReaderType::New(); + mosaic_probe->SetFileName( (*volumesFileNamesIter).at(0) ); + try + { + mosaic_probe->UpdateLargestPossibleRegion(); + } + catch( const itk::ExceptionObject &e) + { + mitkThrow() << " ITK Image file reader failed : "<< e.what(); + } + + typename MosaicImageType::RegionType mosaic_lpr = mosaic_probe->GetOutput()->GetLargestPossibleRegion(); + MITK_INFO << " == MOSAIC: " << mosaic_lpr; + + itk::ImageBase<3>::SizeValueType images_per_row = ceil( sqrt( mosaicInfo.nimages ) ); + + itk::ImageBase<3>::RegionType requestedRegion; + requestedRegion.SetSize( 0, mosaic_lpr.GetSize()[0]/images_per_row); + requestedRegion.SetSize( 1, mosaic_lpr.GetSize()[1]/images_per_row); + requestedRegion.SetSize( 2, mosaicInfo.nimages); + + typename VectorImageType::Pointer output_image = VectorImageType::New(); + output_image->SetNumberOfComponentsPerPixel( filenames.size() ); + /* + FIXME!!! The struct currently does not provide the geometry information + the loading works as required + output_image->SetSpacing( mosaicInfo.spacing ); + output_image->SetOrigin( mosaicInfo.origin ); + output_image->SetDirection( mosaicInfo.direction );*/ + output_image->SetLargestPossibleRegion( requestedRegion ); + output_image->SetBufferedRegion( requestedRegion ); + output_image->Allocate(); + + itk::ImageRegionIteratorWithIndex< VectorImageType > vecIter( + output_image, requestedRegion ); + + // hold the image sizes in an extra variable ( used very often ) + typename MosaicImageType::SizeValueType dx = requestedRegion.GetSize()[0]; + typename MosaicImageType::SizeValueType dy = requestedRegion.GetSize()[1]; + + // iterate over the given volumes + unsigned int component = 0; + while( volumesFileNamesIter != filenames.end() ) + { + + MITK_INFO << " ======== Loading volume " << component+1 << " of " << filenames.size(); + + typename SingleImageReaderType::Pointer mosaic_reader = SingleImageReaderType::New(); + mosaic_reader->SetFileName( (*volumesFileNamesIter).at(0) ); + + try + { + mosaic_reader->UpdateLargestPossibleRegion(); + } + catch( const itk::ExceptionObject &e) + { + mitkThrow() << " ITK Image file reader failed : "<< e.what(); + } + + typename MosaicImageType::Pointer current_mosaic = mosaic_reader->GetOutput(); + + vecIter.GoToBegin(); + while( !vecIter.IsAtEnd() ) + { + typename VectorImageType::PixelType vector_pixel = vecIter.Get(); + typename VectorImageType::IndexType threeD_index = vecIter.GetIndex(); + + typename MosaicImageType::IndexType mosaic_index; + + mosaic_index[2] = 1; + + // first find the corresponding tile in the mosaic + // this is defined by the z-position of the vector (3D) image iterator + // in x : z_index % #images_in_grid + // in y : z_index / #images_in_grid + // + // the remaining is just computing the correct position in the mosaic, done by + // --------- index of (0,0,z) ----- + --- current 2d position --- + mosaic_index[0] = (threeD_index[2] % images_per_row) * dx + threeD_index[0]; + mosaic_index[1] = (threeD_index[2] / images_per_row) * dy + threeD_index[1]; + + typename MosaicImageType::PixelType mosaic_pixel = current_mosaic->GetPixel( mosaic_index ); + + vector_pixel.SetElement( component, mosaic_pixel ); + vecIter.Set( vector_pixel ); + + ++vecIter; + } + + ++volumesFileNamesIter; + component++; + + } + + return output_image; + + } + +}; + + +} + +#endif // MITKDIFFUSIONDICOMFILEREADERHELPER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp new file mode 100644 index 0000000000..5b0ec021ae --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp @@ -0,0 +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 "mitkDiffusionHeaderDICOMFileReader.h" + +mitk::DiffusionHeaderDICOMFileReader +::DiffusionHeaderDICOMFileReader() +{ + +} + +mitk::DiffusionHeaderDICOMFileReader +::~DiffusionHeaderDICOMFileReader() +{ + +} + +mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType +mitk::DiffusionHeaderDICOMFileReader +::GetHeaderInformation() +{ + if( m_HeaderInformationList.size() < 1 ) + { + MITK_WARN << "No information retrieved yet. Call AnalyzeInputFiles first!"; + } + + return m_HeaderInformationList; +} diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h new file mode 100644 index 0000000000..b890d15e94 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h @@ -0,0 +1,132 @@ +/*=================================================================== + +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 MITKDIFFUSIONHEADERFILEREADER_H +#define MITKDIFFUSIONHEADERFILEREADER_H + +#include + +#include +#include "mitkDiffusionImage.h" + +#include "gdcmScanner.h" +#include "gdcmReader.h" + +namespace mitk +{ + +/** + * @brief The DiffusionImageHeaderInformation struct + */ +struct DiffusionImageDICOMHeaderInformation +{ + DiffusionImageDICOMHeaderInformation() + : b_value(0), + baseline(false), + isotropic(false) + { + g_vector.fill(0); + } + + void Print() + { + MITK_INFO << " DiffusionImageHeaderInformation : \n" + << " : b value : " << b_value << "\n" + << " : gradient : " << g_vector << "\n" + << " : isotropic : " << isotropic << "\n --- \n"; + } + + unsigned int b_value; + vnl_vector_fixed< double, 3> g_vector; + bool baseline; + bool isotropic; +}; + +struct DiffusionImageMosaicDICOMHeaderInformation + : public DiffusionImageDICOMHeaderInformation +{ + unsigned long n_images; + bool slicenormalup; +}; + + + +/** + * @class DiffusionHeaderDICOMFileReader + * + * @brief Abstract class for all vendor specific diffusion file header reader + * + * To provide a diffusion header reader for a new vendor, reimplement the \sa ReadDiffusionHeader method. + */ +class DiffusionCore_EXPORT DiffusionHeaderDICOMFileReader + : public itk::LightObject +{ +public: + + typedef std::vector< DiffusionImageDICOMHeaderInformation > DICOMHeaderListType; + + mitkClassMacro( DiffusionHeaderDICOMFileReader, itk::LightObject ) + itkSimpleNewMacro( Self ) + + /** + * @brief IsDiffusionHeader Parse the given dicom file and collect the special diffusion image information + * @return + */ + virtual bool ReadDiffusionHeader( std::string ){ return false; } + + DICOMHeaderListType GetHeaderInformation(); + +protected: + DiffusionHeaderDICOMFileReader(); + + virtual ~DiffusionHeaderDICOMFileReader(); + + DICOMHeaderListType m_HeaderInformationList; +}; + +/** + * @brief Retrieve the value of a gdcm tag to the given string + * + * @param tag the gdcm::Tag to be search for + * @param dataset a gdcm::DataSet to look into + * @param target a string to store the value of the given tag if found + * @param verbose make some output + * + * @return true if a string was found, false otherwise + */ +static bool RevealBinaryTag(const gdcm::Tag tag, const gdcm::DataSet& dataset, std::string& target, bool verbose = true) +{ + if( dataset.FindDataElement( tag ) ) + { + if(verbose) MITK_INFO << "Found tag " << tag.PrintAsPipeSeparatedString(); + + const gdcm::DataElement& de = dataset.GetDataElement( tag ); + target = std::string( de.GetByteValue()->GetPointer(), + de.GetByteValue()->GetLength() ); + return true; + + } + else + { + if(verbose) MITK_INFO << "Could not find tag " << tag.PrintAsPipeSeparatedString(); + return false; + } +} + + +} // end namespace mitk + +#endif // MITKDIFFUSIONHEADERFILEREADER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.cpp b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.cpp new file mode 100644 index 0000000000..04f552619e --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.cpp @@ -0,0 +1,101 @@ +#include "mitkDiffusionHeaderGEDICOMFileReader.h" + +mitk::DiffusionHeaderGEDICOMFileReader +::DiffusionHeaderGEDICOMFileReader() +{ + +} + +mitk::DiffusionHeaderGEDICOMFileReader +::~DiffusionHeaderGEDICOMFileReader() +{ + +} + +bool mitk::DiffusionHeaderGEDICOMFileReader +::ReadDiffusionHeader(std::string filename) +{ + + gdcm::Reader gdcmReader; + gdcmReader.SetFileName( filename.c_str() ); + + gdcmReader.Read(); + + gdcm::Tag ge_bvalue_tag( 0x0043, 0x1039 ); + gdcm::Tag ge_gradient_x( 0x0019, 0x10bb ); + gdcm::Tag ge_gradient_y( 0x0019, 0x10bc ); + gdcm::Tag ge_gradient_z( 0x0019, 0x10bd ); + + bool success = true; + DiffusionImageDICOMHeaderInformation header_info; + + std::string ge_tagvalue_string; + char* pEnd; + + // start with b-value + success = RevealBinaryTag( ge_bvalue_tag, gdcmReader.GetFile().GetDataSet(), ge_tagvalue_string ); + // b value stored in the first bytes + // typical example: "1000\8\0\0" for bvalue=1000 + // "40\8\0\0" for bvalue=40 + // so we need to cut off the last 6 elements + const char* bval_string = ge_tagvalue_string.substr(0,ge_tagvalue_string.length()-6).c_str(); + header_info.b_value = static_cast(strtod( bval_string, &pEnd )); + + // now retrieve the gradient direction + if(success && + RevealBinaryTag( ge_gradient_x, gdcmReader.GetFile().GetDataSet(), ge_tagvalue_string ) ) + { + header_info.g_vector[0] = strtod( ge_tagvalue_string.c_str(), &pEnd ); + } + else + { + success = false; + } + + if( success && + RevealBinaryTag( ge_gradient_y, gdcmReader.GetFile().GetDataSet(), ge_tagvalue_string ) ) + { + header_info.g_vector[1] = strtod( ge_tagvalue_string.c_str(), &pEnd ); + } + else + { + success = false; + } + + if( success && + RevealBinaryTag( ge_gradient_z, gdcmReader.GetFile().GetDataSet(), ge_tagvalue_string ) ) + { + header_info.g_vector[2] = strtod( ge_tagvalue_string.c_str(), &pEnd ); + } + else + { + success = false; + } + + if( success ) + { + // Fix for (0,0,0) direction in IVIM datasets + if( header_info.b_value > 0 && + header_info.g_vector.two_norm() < vnl_math::eps ) + { + header_info.g_vector.fill(1); + header_info.g_vector.normalize(); + header_info.isotropic = true; + } + + // mark baseline + if( header_info.b_value == 0 ) + header_info.baseline = true; + + this->m_HeaderInformationList.push_back( header_info ); + + header_info.Print(); + } + + return success; + + + +} + + diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.h new file mode 100644 index 0000000000..0e0e23eac9 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderGEDICOMFileReader.h @@ -0,0 +1,28 @@ +#ifndef MITKDIFFUSIONHEADERGEDICOMFILEREADER_H +#define MITKDIFFUSIONHEADERGEDICOMFILEREADER_H + +#include "DiffusionCoreExports.h" +#include "mitkDiffusionHeaderDICOMFileReader.h" + +namespace mitk +{ + +class DiffusionCore_EXPORT DiffusionHeaderGEDICOMFileReader + : public DiffusionHeaderDICOMFileReader +{ +public: + + mitkClassMacro( DiffusionHeaderGEDICOMFileReader, DiffusionHeaderDICOMFileReader ) + itkNewMacro( Self ) + + virtual bool ReadDiffusionHeader(std::string filename); + +protected: + DiffusionHeaderGEDICOMFileReader(); + + virtual ~DiffusionHeaderGEDICOMFileReader(); +}; + +} + +#endif // MITKDIFFUSIONHEADERGEDICOMFILEREADER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileHelper.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileHelper.h new file mode 100644 index 0000000000..ce6039571f --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileHelper.h @@ -0,0 +1,72 @@ +#ifndef MITKDIFFUSIONHEADERSIEMENSDICOMFILEHELPER_H +#define MITKDIFFUSIONHEADERSIEMENSDICOMFILEHELPER_H + + +enum SiemensDiffusionHeaderType { + SIEMENS_CSA1 = 0, + SIEMENS_CSA2 +}; + +static SiemensDiffusionHeaderType GetHeaderType( std::string header ) +{ + // The CSA2 format begins with the string ‘SV10’, the CSA1 format does not. + if( header.find("SV10") != std::string::npos ) + { + return SIEMENS_CSA2; + } + else + { + return SIEMENS_CSA1; + } +} + +struct Siemens_Header_Format +{ + Siemens_Header_Format( size_t nlen, + size_t vm, + size_t vr, + size_t syngodt, + size_t nitems ) + : NameLength( nlen ), + Delimiter( "\0" ), + VM( vm ), + VR( vr ), + Syngodt( syngodt ), + NumItems( nitems ) + { + + } + + size_t NameLength; + std::string Delimiter; + size_t VM; + size_t VR; + size_t Syngodt; + size_t NumItems; +}; + +static bool ParseInputString( std::string input, std::vector& values, Siemens_Header_Format format_specs ) +{ + + // TODO : Compute offset based on the format_specs, where does the 84 come from??? + int offset = 84; + int vm = *(input.c_str() + format_specs.NameLength ); + + for (int k = 0; k < vm; k++) + { + int itemLength = *(input.c_str() + offset + 4); + + int strideSize = static_cast (ceil(static_cast(itemLength)/4) * 4); + std::string valueString = input.substr( offset+16, itemLength ); + + double value = atof( valueString.c_str() ); + values.push_back( value ); + + offset += 16+strideSize; + } + + return true; +} + + +#endif // MITKDIFFUSIONHEADERSIEMENSDICOMFILEHELPER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp new file mode 100644 index 0000000000..6ff039be65 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp @@ -0,0 +1,143 @@ +/*=================================================================== + +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 "mitkDiffusionHeaderSiemensDICOMFileReader.h" + +#include "gdcmScanner.h" +#include "gdcmReader.h" + + +/** + * @brief Extract b value from the siemens diffusion tag + */ +bool mitk::DiffusionHeaderSiemensDICOMFileReader +::ExtractSiemensDiffusionTagInformation( std::string tag_value, mitk::DiffusionImageDICOMHeaderInformation& values) +{ + SiemensDiffusionHeaderType hformat = GetHeaderType( tag_value ); + Siemens_Header_Format specs = this->m_SiemensFormatsCollection.at( hformat ); + + MITK_DEBUG << " Header format: " << hformat; + MITK_DEBUG << " :: Retrieving b value. "; + + std::string::size_type tag_position = + tag_value.find( "B_value", 0 ); + + if( tag_position == std::string::npos ) + { + MITK_ERROR << "No b value information found. "; + return false; + } + + std::string value_string = tag_value.substr( tag_position, tag_value.size() - tag_position + 1 ); + + std::vector value_array; + if( ParseInputString(value_string, value_array, specs) ) + { + values.b_value = value_array.at(0); + } + + // search for GradientDirectionInformation if the bvalue is not null + if( values.b_value > 0 ) + { + std::string::size_type tag_position = tag_value.find( "DiffusionGradientDirection", 0 ); + // Possibly it is a IVIM dataset, i.e. the gradient direction is not relevant + // and possibly either not set or set to zero + if( tag_position == std::string::npos ) + { + MITK_WARN << "No gradient direction information, but non-zero b-value. Possibly an IVIM dataset. " << "\n" + << "Setting gradient to (1,1,1)."; + + values.isotropic = true; + values.g_vector.fill(1); + return false; + } + + value_array.clear(); + std::string gradient_direction_str = tag_value.substr( tag_position, tag_value.size() - tag_position + 1 ); + + if( ParseInputString(gradient_direction_str, value_array, specs) ) + { + if( value_array.size() != 3 ) + { + MITK_ERROR << " Retrieved gradient information of length " << value_array.size(); + return false; + } + + for( unsigned int i=0; iExtractSiemensDiffusionTagInformation( siemens_diffusionheader_str, values ); + + m_HeaderInformationList.push_back( values ); + } + + +} diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h new file mode 100644 index 0000000000..53c7d5b456 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h @@ -0,0 +1,49 @@ +/*=================================================================== + +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 MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H +#define MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H + +#include "DiffusionCoreExports.h" + +#include "mitkDiffusionHeaderDICOMFileReader.h" +#include "mitkDiffusionHeaderSiemensDICOMFileHelper.h" + +namespace mitk +{ + +class DiffusionCore_EXPORT DiffusionHeaderSiemensDICOMFileReader + : public DiffusionHeaderDICOMFileReader +{ +public: + + mitkClassMacro( DiffusionHeaderSiemensDICOMFileReader, DiffusionHeaderDICOMFileReader ) + itkNewMacro( Self ) + + virtual bool ReadDiffusionHeader(std::string filename); + +protected: + DiffusionHeaderSiemensDICOMFileReader(); + + ~DiffusionHeaderSiemensDICOMFileReader(); + + bool ExtractSiemensDiffusionTagInformation( std::string tag_value, mitk::DiffusionImageDICOMHeaderInformation& values ); + + std::vector< Siemens_Header_Format > m_SiemensFormatsCollection; +}; + +} +#endif // MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.cpp b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.cpp new file mode 100644 index 0000000000..bf775da920 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.cpp @@ -0,0 +1,79 @@ +#include "mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h" + +mitk::DiffusionHeaderSiemensMosaicDICOMFileReader::DiffusionHeaderSiemensMosaicDICOMFileReader() + : DiffusionHeaderSiemensDICOMFileReader() +{ + +} + +mitk::DiffusionHeaderSiemensMosaicDICOMFileReader +::~DiffusionHeaderSiemensMosaicDICOMFileReader() +{ + +} + +bool mitk::DiffusionHeaderSiemensMosaicDICOMFileReader +::ReadDiffusionHeader(std::string filename) +{ + gdcm::Reader gdcmReader; + gdcmReader.SetFileName( filename.c_str() ); + + gdcmReader.Read(); + + MITK_INFO << " -- Analyzing: " << filename; + + const gdcm::DataSet& dataset = gdcmReader.GetFile().GetDataSet(); + + const gdcm::Tag t_sie_diffusion( 0x0029,0x1010 ); + std::string siemens_diffusionheader_str; + if( RevealBinaryTag( t_sie_diffusion, dataset, siemens_diffusionheader_str ) ) + { + mitk::DiffusionImageMosaicDICOMHeaderInformation header_values; + + this->ExtractSiemensDiffusionTagInformation( siemens_diffusionheader_str, header_values ); + + //MITK_INFO << siemens_diffusionheader_str; + + SiemensDiffusionHeaderType hformat = GetHeaderType( siemens_diffusionheader_str ); + Siemens_Header_Format specs = this->m_SiemensFormatsCollection.at( hformat ); + + double n_images = 0; + std::string::size_type tag_position = siemens_diffusionheader_str.find( "NumberOfImagesInMosaic", 0 ); + if( tag_position != std::string::npos ) + { + std::vector value_array; + ParseInputString( siemens_diffusionheader_str.substr( tag_position, siemens_diffusionheader_str.size() - tag_position + 1 ), + value_array, + specs + ); + + header_values.n_images = value_array[0]; + } + + tag_position = siemens_diffusionheader_str.find("SliceNormalVector", 0); + if( tag_position != std::string::npos ) + { + std::vector value_array; + ParseInputString( siemens_diffusionheader_str.substr( tag_position, siemens_diffusionheader_str.size() - tag_position + 1 ), + value_array, + specs + ); + + MITK_DEBUG << "SliceNormal"; + for( unsigned int i=0; i 2 ) + { + header_values.slicenormalup = (value_array[2] > 0); + } + + } + + m_HeaderInformationList.push_back( header_values ); + + } + +} diff --git a/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h new file mode 100644 index 0000000000..ebed47c4e1 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h @@ -0,0 +1,43 @@ +/*=================================================================== + +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 MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H +#define MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H + +#include "mitkDiffusionHeaderSiemensDICOMFileReader.h" + +namespace mitk +{ + +class DiffusionHeaderSiemensMosaicDICOMFileReader + : public DiffusionHeaderSiemensDICOMFileReader +{ +public: + mitkClassMacro( DiffusionHeaderSiemensMosaicDICOMFileReader, + DiffusionHeaderSiemensDICOMFileReader ) + itkNewMacro( Self ) + + virtual bool ReadDiffusionHeader(std::string filename); + +protected: + DiffusionHeaderSiemensMosaicDICOMFileReader(); + + virtual ~DiffusionHeaderSiemensMosaicDICOMFileReader(); +}; + +} + +#endif // MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake b/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake index 53141cf060..06e8aedcfb 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake @@ -1,10 +1,12 @@ set(MODULE_TESTS mitkFactoryRegistrationTest.cpp ) set(MODULE_CUSTOM_TESTS mitkPyramidImageRegistrationMethodTest.cpp mitkDWHeadMotionCorrectionTest.cpp mitkImageReconstructionTest.cpp + mitkDiffusionDICOMFileReaderTest.cpp + ) diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp new file mode 100644 index 0000000000..442d2b82fa --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp @@ -0,0 +1,119 @@ +/*=================================================================== + +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 "mitkDiffusionDICOMFileReader.h" +#include "mitkDiffusionDICOMFileReaderTestHelper.h" +#include "mitkDICOMTagBasedSorter.h" +#include "mitkDICOMSortByTag.h" + +#include "mitkNrrdDiffusionImageWriter.h" + +#include "mitkTestingMacros.h" + +using mitk::DICOMTag; + +int mitkDiffusionDICOMFileReaderTest(int argc, char* argv[]) +{ + MITK_TEST_BEGIN("mitkDiffusionDICOMFileReaderTest"); + + mitk::DiffusionDICOMFileReader::Pointer gdcmReader = mitk::DiffusionDICOMFileReader::New(); + MITK_TEST_CONDITION_REQUIRED(gdcmReader.IsNotNull(), "DICOMITKSeriesGDCMReader can be instantiated."); + + std::string output_filename = "/tmp/dicom_out.dwi"; + if( argc > 3) + { + mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc-1,argv ); + output_filename = std::string( argv[argc-1] ); + } + else + { + mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc,argv ); + } + + // check the Set/GetInput function + mitk::DICOMFileReaderTestHelper::TestInputFilenames( gdcmReader ); + MITK_INFO << "Test input filenanems"; + + // check that output is a good reproduction of input (no duplicates, no new elements) + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + MITK_INFO << "Test output"; + + // repeat test with some more realistic sorting + gdcmReader = mitk::DiffusionDICOMFileReader::New(); // this also tests destruction + mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New(); + + // Use tags as in Qmitk + // all the things that split by tag in DicomSeriesReader + tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0010) ); // Number of Rows + tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0011) ); // Number of Columns + tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0030) ); // Pixel Spacing + tagSorter->AddDistinguishingTag( DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing + tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code) + // TODO handle as real vectors! cluster with configurable errors! + tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x000e) ); // Series Instance UID + tagSorter->AddDistinguishingTag( DICOMTag(0x0018, 0x0050) ); // Slice Thickness + tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0008) ); // Number of Frames + tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID + + // gdcmReader->AddSortingElement( tagSorter ); + //mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + + mitk::DICOMSortCriterion::ConstPointer sorting = + mitk::DICOMSortByTag::New( DICOMTag(0x0020, 0x0013), // instance number + mitk::DICOMSortByTag::New( DICOMTag(0x0020, 0x0012), // aqcuisition number + mitk::DICOMSortByTag::New( DICOMTag(0x0008, 0x0032), // aqcuisition time + mitk::DICOMSortByTag::New( DICOMTag(0x0018, 0x1060), // trigger time + mitk::DICOMSortByTag::New( DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly) + ).GetPointer() + ).GetPointer() + ).GetPointer() + ).GetPointer() + ).GetPointer(); + tagSorter->SetSortCriterion( sorting ); + + MITK_INFO << "Created sort"; + + gdcmReader->AddSortingElement( tagSorter ); + mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader ); + + MITK_INFO << "Created sort"; + + //gdcmReader->PrintOutputs(std::cout, true); + + // really load images + //mitk::DICOMFileReaderTestHelper::TestMitkImagesAreLoaded( gdcmReader ); + gdcmReader->LoadImages(); + + mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage(); + + mitk::DiffusionImage::Pointer d_img = static_cast*>( loaded_image.GetPointer() ); + + mitk::NrrdDiffusionImageWriter::Pointer writer = + mitk::NrrdDiffusionImageWriter::New(); + writer->SetFileName( output_filename.c_str() ); + writer->SetInput(d_img ); + + try + { + writer->Update(); + } + catch( const itk::ExceptionObject& e) + { + MITK_TEST_FAILED_MSG( << "Writer failed : " << e.what() ); + } + + MITK_TEST_END(); +} diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h new file mode 100644 index 0000000000..9453ba312d --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h @@ -0,0 +1,153 @@ +/*=================================================================== + +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 mitkDiffusionDICOMFileReaderTestHelper_h +#define mitkDiffusionDICOMFileReaderTestHelper_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) + { + const 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 + { + 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) +{ + 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(); + mitk::Image::Pointer mitkImage = block.GetMitkImage(); + + MITK_INFO << "-------------------------------------------"; + MITK_INFO << "Output " << o << " at " << (void*) mitkImage.GetPointer(); + MITK_INFO << " Number of files: " << outputFiles.size(); + MITK_INFO << " Dimensions: " << mitkImage->GetDimension(0) << " " << mitkImage->GetDimension(1) << " " << mitkImage->GetDimension(2); + } +} + + +}; // end test class + +} // namespace + +#endif diff --git a/Modules/DiffusionImaging/DiffusionCore/files.cmake b/Modules/DiffusionImaging/DiffusionCore/files.cmake index ac90de0f2d..dc82108281 100644 --- a/Modules/DiffusionImaging/DiffusionCore/files.cmake +++ b/Modules/DiffusionImaging/DiffusionCore/files.cmake @@ -1,129 +1,114 @@ set(CPP_FILES # DicomImport DicomImport/mitkDicomDiffusionImageReader.cpp # DicomImport/mitkGroupDiffusionHeadersFilter.cpp DicomImport/mitkDicomDiffusionImageHeaderReader.cpp DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp - # DataStructures -> DWI - IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp - IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp - IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp + DicomImport/mitkDiffusionDICOMFileReader.cpp + DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp + DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp + DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.cpp + DicomImport/mitkDiffusionHeaderGEDICOMFileReader.cpp - IODataStructures/DiffusionWeightedImages/mitkImageToDiffusionImageSource.cpp - IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.cpp - - # DataStructures -> QBall - IODataStructures/QBallImages/mitkQBallImageSource.cpp - IODataStructures/QBallImages/mitkQBallImage.cpp - - # DataStructures -> Tensor - IODataStructures/TensorImages/mitkTensorImage.cpp - - #IODataStructures/mitkRegistrationObject.cpp - - # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp Algorithms/itkDwiGradientLengthCorrectionFilter.cpp # Registration Algorithms & Co. Algorithms/Registration/mitkRegistrationWrapper.cpp Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp # MultishellProcessing Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.cpp Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.cpp Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.cpp # Function Collection mitkDiffusionFunctionCollection.cpp ) set(H_FILES # function Collection mitkDiffusionFunctionCollection.h # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkOdfVtkMapper2D.h # Reconstruction Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h Algorithms/Reconstruction/itkPointShell.h Algorithms/Reconstruction/itkOrientationDistributionFunction.h Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h # MultishellProcessing Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.h Algorithms/Reconstruction/MultishellProcessing/itkDWIVoxelFunctor.h Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.h Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.h Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.h Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.h - # IO Datastructures - IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h - # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkB0ImageExtractionToSeparateImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkResidualImageFilter.h Algorithms/itkExtractChannelFromRgbaImageFilter.h Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h Algorithms/itkMergeDiffusionImagesFilter.h Algorithms/itkDwiPhantomGenerationFilter.h Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h Algorithms/itkMrtrixPeakImageConverter.h Algorithms/itkFslPeakImageConverter.h Algorithms/itkShCoefficientImageImporter.h Algorithms/itkShCoefficientImageExporter.h Algorithms/itkOdfMaximaExtractionFilter.h Algorithms/itkResampleDwiImageFilter.h Algorithms/itkDwiGradientLengthCorrectionFilter.h Algorithms/itkAdcImageFilter.h Algorithms/itkSplitDWImageFilter.h Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.h Algorithms/mitkDiffusionImageToDiffusionImageFilter.h Algorithms/itkNonLocalMeansDenoisingFilter.h Algorithms/itkVectorImageToImageFilter.h ) set( TOOL_FILES )