diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h index fee60f61b9..eed0cba888 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h @@ -1,145 +1,144 @@ /*=================================================================== 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 __mitkDiffusionImage__h #define __mitkDiffusionImage__h #include "mitkImage.h" #include "itkVectorImage.h" #include "itkVectorImageToImageAdaptor.h" #include #include namespace mitk { /** * \brief this class encapsulates diffusion volumes (vectorimages not * yet supported by mitkImage) */ template class DiffusionImage : public Image { public: typedef TPixelType PixelType; typedef typename itk::VectorImage ImageType; typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; typedef itk::VectorImageToImageAdaptor< TPixelType, 3 > AdaptorType; typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType; // BValue Map // key := b-Value // value := indicesVector (containing corresponding gradient directions for a b-Value-Shell typedef std::vector< unsigned int > IndicesVector; typedef std::map< unsigned int , IndicesVector > BValueMap; mitkClassMacro( DiffusionImage, Image ) itkNewMacro(Self) - mitkCloneMacro( Self ) + //mitkCloneMacro( Self ) void AverageRedundantGradients(double precision); GradientDirectionContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions); void CorrectDKFZBrokenGradientScheme(double precision); typename ImageType::Pointer GetVectorImage() { return m_VectorImage; } void SetVectorImage(typename ImageType::Pointer image ) { this->m_VectorImage = image; } void InitializeFromVectorImage(); void SetDisplayIndexForRendering(int displayIndex); GradientDirectionContainerType::Pointer GetDirectionsWithoutMeasurementFrame() { return m_OriginalDirections; } GradientDirectionContainerType::Pointer GetDirections() { return m_Directions; } void SetDirections( GradientDirectionContainerType::Pointer directions ) { this->m_OriginalDirections = directions; ApplyMeasurementFrame(); } void SetDirections(const std::vector > directions); MeasurementFrameType GetMeasurementFrame() { return m_MeasurementFrame; } void SetMeasurementFrame( MeasurementFrameType mFrame ) { this->m_MeasurementFrame = mFrame; this->ApplyMeasurementFrame(); } bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision); int GetNumDirections(); int GetNumB0(){return m_B_ValueMap[0].size();} float GetB_Value(unsigned int i); bool IsMultiBval(); void UpdateBValueMap(); IndicesVector GetB0Indices(); itkGetMacro(B_Value, float) itkSetMacro(B_Value, float) BValueMap GetB_ValueMap(){ return m_B_ValueMap; } void AddDirectionsContainerObserver(); void RemoveDirectionsContainerObserver(); protected: DiffusionImage(); - DiffusionImage(const mitk::DiffusionImage &); virtual ~DiffusionImage(); void ApplyMeasurementFrame(); typename ImageType::Pointer m_VectorImage; float m_B_Value; MeasurementFrameType m_MeasurementFrame; GradientDirectionContainerType::Pointer m_OriginalDirections; GradientDirectionContainerType::Pointer m_Directions; int m_DisplayIndex; BValueMap m_B_ValueMap; }; /** * @brief Equal A function comparing two images for beeing equal in meta- and imagedata * * @ingroup MITKTestingAPI * * Following aspects are tested for equality: * - mitk image equal test * - gradient direction container * - measurement frame * - reference BValue * - BValue map * - itk vector image * * @param rightHandSide An image to be compared * @param leftHandSide An image to be compared * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return true, if all subsequent comparisons are true, false otherwise */ -template -bool Equal( const mitk::DiffusionImage* leftHandSide, const mitk::DiffusionImage* rightHandSide, ScalarType eps, bool verbose ); +//template +//bool Equal( const mitk::DiffusionImage* leftHandSide, const mitk::DiffusionImage* rightHandSide, ScalarType eps, bool verbose ); } // namespace mitk #include "mitkDiffusionImage.txx" #endif /* __mitkDiffusionImage__h */ diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx index 48f7cd78d2..0b3f214a04 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx @@ -1,569 +1,552 @@ /*=================================================================== 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 "itkImageRegionIterator.h" #include "itkImageRegionConstIterator.h" #include "mitkImageCast.h" #include "itkTestingComparisonImageFilter.h" #include "mitkDiffusionImage.h" #include "itkImageDuplicator.h" template mitk::DiffusionImage::DiffusionImage() : m_VectorImage(0), m_B_Value(-1.0), m_OriginalDirections(0), m_Directions(0) { MeasurementFrameType mf; for(int i=0; i<3; i++) for(int j=0; j<3; j++) mf[i][j] = 0; for(int i=0; i<3; i++) mf[i][i] = 1; m_MeasurementFrame = mf; } -template -mitk::DiffusionImage::DiffusionImage(const mitk::DiffusionImage & orig) - : mitk::Image(orig), - m_VectorImage( 0 ), - m_B_Value(orig.m_B_Value), - m_MeasurementFrame(orig.m_MeasurementFrame), - m_OriginalDirections(orig.m_OriginalDirections), - m_Directions(orig.m_Directions) -{ - - typename itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); - duplicator->SetInputImage( orig.m_VectorImage ); - duplicator->Update(); - this->SetVectorImage(duplicator->GetOutput()); - this->InitializeFromVectorImage(); -} - template mitk::DiffusionImage::~DiffusionImage() { // Remove Observer for m_Directions RemoveDirectionsContainerObserver(); } template void mitk::DiffusionImage ::InitializeFromVectorImage() { if(!m_VectorImage || !m_Directions || m_B_Value==-1.0) { MITK_INFO << "DiffusionImage could not be initialized. Set all members first!" << std::endl; return; } // find bzero index int firstZeroIndex = -1; for(GradientDirectionContainerType::ConstIterator it = m_Directions->Begin(); it != m_Directions->End(); ++it) { firstZeroIndex++; GradientDirectionType g = it.Value(); if(g[0] == 0 && g[1] == 0 && g[2] == 0 ) break; } typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); img->SetSpacing( m_VectorImage->GetSpacing() ); // Set the image spacing img->SetOrigin( m_VectorImage->GetOrigin() ); // Set the image origin img->SetDirection( m_VectorImage->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( m_VectorImage->GetLargestPossibleRegion()); img->SetBufferedRegion( m_VectorImage->GetLargestPossibleRegion() ); img->Allocate(); int vecLength = m_VectorImage->GetVectorLength(); InitializeByItk( img.GetPointer(), 1, vecLength ); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw.GoToBegin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr.GoToBegin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(firstZeroIndex)); ++itr; ++itw; } // init SetImportVolume(img->GetBufferPointer()); m_DisplayIndex = firstZeroIndex; MITK_INFO << "Diffusion-Image successfully initialized."; } template void mitk::DiffusionImage ::SetDisplayIndexForRendering(int displayIndex) { int index = displayIndex; int vecLength = m_VectorImage->GetVectorLength(); index = index > vecLength-1 ? vecLength-1 : index; if( m_DisplayIndex != index ) { typedef itk::Image ImgType; typename ImgType::Pointer img = ImgType::New(); CastToItkImage(this, img); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw.GoToBegin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr.GoToBegin(); while(!itr.IsAtEnd()) { itw.Set(itr.Get().GetElement(index)); ++itr; ++itw; } } m_DisplayIndex = index; } template bool mitk::DiffusionImage::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision) { GradientDirectionType diff = g1 - g2; GradientDirectionType diff2 = g1 + g2; return diff.two_norm() < precision || diff2.two_norm() < precision; } template void mitk::DiffusionImage::CorrectDKFZBrokenGradientScheme(double precision) { GradientDirectionContainerType::Pointer directionSet = CalcAveragedDirectionSet(precision, m_Directions); if(directionSet->size() < 7) { MITK_INFO << "Too few directions, assuming and correcting DKFZ-bogus sequence details."; double v [7][3] = {{ 0, 0, 0 }, {-0.707057, 0, 0.707057 }, { 0.707057, 0, 0.707057 }, { 0, 0.707057, 0.707057 }, { 0, 0.707057, -0.707057 }, {-0.707057, 0.707057, 0 }, { 0.707057, 0.707057, 0 } }; int i=0; for(GradientDirectionContainerType::Iterator it = m_OriginalDirections->Begin(); it != m_OriginalDirections->End(); ++it) { it.Value().set(v[i++%7]); } ApplyMeasurementFrame(); } } template mitk::DiffusionImage::GradientDirectionContainerType::Pointer mitk::DiffusionImage::CalcAveragedDirectionSet(double precision, GradientDirectionContainerType::Pointer directions) { // save old and construct new direction container GradientDirectionContainerType::Pointer newDirections = GradientDirectionContainerType::New(); // fill new direction container for(GradientDirectionContainerType::ConstIterator gdcitOld = directions->Begin(); gdcitOld != directions->End(); ++gdcitOld) { // already exists? bool found = false; for(GradientDirectionContainerType::ConstIterator gdcitNew = newDirections->Begin(); gdcitNew != newDirections->End(); ++gdcitNew) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { found = true; break; } } // if not found, add it to new container if(!found) { newDirections->push_back(gdcitOld.Value()); } } return newDirections; } template void mitk::DiffusionImage::AverageRedundantGradients(double precision) { GradientDirectionContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, m_Directions); GradientDirectionContainerType::Pointer newOriginalDirs = CalcAveragedDirectionSet(precision, m_OriginalDirections); // if sizes equal, we do not need to do anything in this function if(m_Directions->size() == newDirs->size() || m_OriginalDirections->size() == newOriginalDirs->size()) return; GradientDirectionContainerType::Pointer oldDirections = m_OriginalDirections; m_Directions = newDirs; m_OriginalDirections = newOriginalDirs; // new image typename ImageType::Pointer oldImage = m_VectorImage; m_VectorImage = ImageType::New(); m_VectorImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing m_VectorImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin m_VectorImage->SetDirection( oldImage->GetDirection() ); // Set the image direction m_VectorImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->SetVectorLength( m_Directions->size() ); m_VectorImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() ); m_VectorImage->Allocate(); // average image data that corresponds to identical directions itk::ImageRegionIterator< ImageType > newIt(m_VectorImage, m_VectorImage->GetLargestPossibleRegion()); newIt.GoToBegin(); itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion()); oldIt.GoToBegin(); // initial new value of voxel typename ImageType::PixelType newVec; newVec.SetSize(m_Directions->size()); newVec.AllocateElements(m_Directions->size()); std::vector > dirIndices; for(GradientDirectionContainerType::ConstIterator gdcitNew = m_Directions->Begin(); gdcitNew != m_Directions->End(); ++gdcitNew) { dirIndices.push_back(std::vector(0)); for(GradientDirectionContainerType::ConstIterator gdcitOld = oldDirections->Begin(); gdcitOld != oldDirections->End(); ++gdcitOld) { if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision)) { //MITK_INFO << gdcitNew.Value() << " " << gdcitOld.Value(); dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index()); } } } //int ind1 = -1; while(!newIt.IsAtEnd()) { // progress //typename ImageType::IndexType ind = newIt.GetIndex(); //ind1 = ind.m_Index[2]; // init new vector with zeros newVec.Fill(0.0); // the old voxel value with duplicates typename ImageType::PixelType oldVec = oldIt.Get(); for(unsigned int i=0; i void mitk::DiffusionImage::ApplyMeasurementFrame() { RemoveDirectionsContainerObserver(); m_Directions = GradientDirectionContainerType::New(); int c = 0; for(GradientDirectionContainerType::ConstIterator gdcit = m_OriginalDirections->Begin(); gdcit != m_OriginalDirections->End(); ++gdcit) { vnl_vector vec = gdcit.Value(); vec = vec.pre_multiply(m_MeasurementFrame); m_Directions->InsertElement(c, vec); c++; } UpdateBValueMap(); AddDirectionsContainerObserver(); } // returns number of gradients template int mitk::DiffusionImage::GetNumDirections() { int gradients = m_OriginalDirections->Size(); for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { gradients--; } return gradients; } // returns a list of indices belonging to the not diffusion weighted images template typename mitk::DiffusionImage::IndicesVector mitk::DiffusionImage::GetB0Indices() { IndicesVector indices; for (unsigned int i=0; iSize(); i++) if (GetB_Value(i)<=0) { indices.push_back(i); } return indices; } template bool mitk::DiffusionImage::IsMultiBval() { int gradients = m_OriginalDirections->Size(); for (int i=0; i0 && std::fabs(m_B_Value-GetB_Value(i))>50) return true; return false; } template void mitk::DiffusionImage::UpdateBValueMap() { m_B_ValueMap.clear(); GradientDirectionContainerType::ConstIterator gdcit; for( gdcit = this->m_Directions->Begin(); gdcit != this->m_Directions->End(); ++gdcit) m_B_ValueMap[GetB_Value(gdcit.Index())].push_back(gdcit.Index()); } template float mitk::DiffusionImage::GetB_Value(unsigned int i) { if(i > m_Directions->Size()-1) return -1; if(m_Directions->ElementAt(i).one_norm() <= 0.0) { return 0; } else { double twonorm = m_Directions->ElementAt(i).two_norm(); double bval = m_B_Value*twonorm*twonorm; if (bval<0) bval = ceil(bval - 0.5); else bval = floor(bval + 0.5); return bval; } } template void mitk::DiffusionImage::SetDirections(const std::vector > directions) { m_OriginalDirections = GradientDirectionContainerType::New(); for(unsigned int i=0; iInsertElement( i, directions[i].GetVnlVector() ); } this->ApplyMeasurementFrame(); } template void mitk::DiffusionImage::AddDirectionsContainerObserver() { // Add Modified Observer to invoke an UpdateBValueList by modifieng the DirectionsContainer (m_Directions) typedef DiffusionImage< TPixelType > Self; typedef itk::SimpleMemberCommand< Self > DCCommand ; typename DCCommand::Pointer command = DCCommand::New(); command->SetCallbackFunction(this, &Self::UpdateBValueMap); } template void mitk::DiffusionImage::RemoveDirectionsContainerObserver() { if(m_Directions){ m_Directions->RemoveAllObservers(); } } -template +/*template bool mitk::Equal(const mitk::DiffusionImage* rightHandSide, const mitk::DiffusionImage* leftHandSide, ScalarType eps, bool verbose) { // Fast testing area MITK_INFO << "[( DiffusionImage )] EQUAL METHOD."; bool returnValue = true; if( rightHandSide == NULL ) { if(verbose) MITK_INFO << "[( DiffusionImage )] rightHandSide is NULL."; return false; } if( leftHandSide == NULL ) { if(verbose) MITK_INFO << "[( DiffusionImage )] leftHandSide is NULL."; return false; } if(leftHandSide->IsMultiBval() != rightHandSide->IsMultiBval()) { if(verbose) MITK_INFO << "[( DiffusionImage )] IsMultiBval properie is not Equal."; return false; } if(leftHandSide->GetNumB0() != rightHandSide->GetNumB0()) { if(verbose) MITK_INFO << "[( DiffusionImage )] Number of B0Values is not Equal."; return false; } if(leftHandSide->GetB_Value() != rightHandSide->GetB_Value()) { if(verbose) MITK_INFO << "[( DiffusionImage )] Reference BValue is not Equal."; return false; } if(leftHandSide->GetMeasurementFrame() != rightHandSide->GetMeasurementFrame()) { if(verbose) MITK_INFO << "[( DiffusionImage )] MeasurementFrame is not Equal."; return false; } if(leftHandSide->GetDirections()->Size() != rightHandSide->GetDirections()->Size()) { if(verbose) MITK_INFO << "[( DiffusionImage )] GradientDirectionContainer size is not Equal."; return false; } if(leftHandSide->GetB_ValueMap().size() != rightHandSide->GetB_ValueMap().size()) { if(verbose) MITK_INFO << "[( DiffusionImage )] BValue Map: Size is not Equal."; return false; } // Slow testing area if(mitk::Equal(static_cast(rightHandSide),static_cast(leftHandSide),eps,verbose) == false) { if(verbose) MITK_INFO << "[( DiffusionImage )] Base-Class (mitk::Image) is not Equal."; return false; } typename itk::Testing::ComparisonImageFilter::Pointer EqualFilter = itk::Testing::ComparisonImageFilter::New(); EqualFilter->SetInput(rightHandSide->GetVectorImage()); EqualFilter->SetInput(leftHandSide->GetVectorImage()); EqualFilter->Update(); if(EqualFilter->GetNumberOfPixelsWithDifferences() != 0) { if(verbose) MITK_INFO << "[( DiffusionImage )] Capsulated itk::VectorImage is not Equal."; return false; } if(!std::equal(leftHandSide->GetDirections()->Begin(),leftHandSide->GetDirections()->End(),rightHandSide->GetDirections()->Begin())) { if(verbose) MITK_INFO << "[( DiffusionImage )] GradientDirections are not Equal."; return false; } if(!std::equal(leftHandSide->GetB0Indices().begin(), leftHandSide->GetB0Indices().end(), rightHandSide->GetB0Indices().begin())) { if(verbose) MITK_INFO << "[( DiffusionImage )] Number of B0Values is not Equal."; return false; } std::map >::const_iterator rhsBValueMapIterator = rightHandSide->GetB_ValueMap().begin(); std::map >::const_iterator lhsBValueMapIterator = leftHandSide->GetB_ValueMap().begin(); std::map >::const_iterator lhsBValueMapIteratorEnd = leftHandSide->GetB_ValueMap().end(); for(;lhsBValueMapIterator != lhsBValueMapIteratorEnd;) { if(lhsBValueMapIterator->first != rhsBValueMapIterator->first) { if(verbose) MITK_INFO << "[( DiffusionImage )] BValue Map: lhsKey " << lhsBValueMapIterator->first << " != rhsKey " << rhsBValueMapIterator->first << " is not Equal."; return false; } if(lhsBValueMapIterator->second.size() != rhsBValueMapIterator->second.size()) { if(verbose) MITK_INFO << "[( DiffusionImage )] BValue Map: Indices vector size is not Equal. (Key: " << lhsBValueMapIterator->first <<")"; return false; } if(!std::equal(lhsBValueMapIterator->second.begin(),lhsBValueMapIterator->second.end(), rhsBValueMapIterator->second.begin())) { if(verbose) MITK_INFO << "[( DiffusionImage )] BValue Map: Indices are not Equal. (Key: " << lhsBValueMapIterator->first <<")"; return false; } rhsBValueMapIterator++; lhsBValueMapIterator++; } return returnValue; -} +}*/ diff --git a/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake b/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake index 140722ceaa..75728a9751 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake +++ b/Modules/DiffusionImaging/DiffusionCore/Testing/files.cmake @@ -1,11 +1,11 @@ set(MODULE_TESTS mitkFactoryRegistrationTest.cpp - mitkDiffusionImageEqualTest.cpp + #mitkDiffusionImageEqualTest.cpp ) set(MODULE_CUSTOM_TESTS mitkPyramidImageRegistrationMethodTest.cpp mitkDWHeadMotionCorrectionTest.cpp mitkImageReconstructionTest.cpp )