diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp index 7ab9f2ec1b..6164793663 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp @@ -1,459 +1,483 @@ /*=================================================================== 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 "mitkNrrdTensorImageReader.h" #include "itkImageFileReader.h" #include "itkImageRegionIterator.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include #include "mitkITKImageImport.h" #include "mitkImageDataItem.h" namespace mitk { void NrrdTensorImageReader ::GenerateData() { if ( m_FileName == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!"); } else { try { const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, NULL ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } try { - MITK_INFO << "Trying to load dti as nifti ..."; std::string fname3 = "temp_dti.nii"; itksys::SystemTools::CopyAFile(m_FileName.c_str(), fname3.c_str()); - typedef itk::Image ImageType; + typedef itk::VectorImage ImageType; itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(fname3); reader->Update(); - itksys::SystemTools::RemoveFile(fname3.c_str()); - ImageType::Pointer img = reader->GetOutput(); - itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); - - itk::ImageRegion< 3 > region; - region.SetSize(0,size[0]); - region.SetSize(1,size[1]); - region.SetSize(2,size[2]); - itk::Vector spacing; - spacing[0] = img->GetSpacing()[0]; - spacing[1] = img->GetSpacing()[1]; - spacing[2] = img->GetSpacing()[2]; - itk::Point origin; - origin[0] = img->GetOrigin()[0]; - origin[1] = img->GetOrigin()[1]; - origin[2] = img->GetOrigin()[2]; - itk::Matrix direction; - direction[0][0] = img->GetDirection()[0][0]; - direction[1][0] = img->GetDirection()[1][0]; - direction[2][0] = img->GetDirection()[2][0]; - direction[0][1] = img->GetDirection()[0][1]; - direction[1][1] = img->GetDirection()[1][1]; - direction[2][1] = img->GetDirection()[2][1]; - direction[0][2] = img->GetDirection()[0][2]; - direction[1][2] = img->GetDirection()[1][2]; - direction[2][2] = img->GetDirection()[2][2]; typedef itk::Image,3> VecImgType; - typedef VecImgType::PixelType FixPixType; VecImgType::Pointer vecImg = VecImgType::New(); - vecImg->SetSpacing( spacing ); - vecImg->SetOrigin( origin ); - vecImg->SetDirection( direction ); - vecImg->SetRegions( region ); + vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing + vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin + vecImg->SetDirection( img->GetDirection() ); // Set the image direction + vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot = ot.Begin(); - while (!ot.IsAtEnd()) - { - itk::DiffusionTensor3D tensor; - ImageType::IndexType idx; - idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; + itk::ImageRegionIterator it (img, img->GetLargestPossibleRegion() ); + it = it.Begin(); - if (size[3]==6) + typedef ImageType::PixelType VarPixType; + typedef VecImgType::PixelType FixPixType; + int numComponents = img->GetNumberOfComponentsPerPixel(); + + if (numComponents==6) + { + MITK_INFO << "Trying to load dti as 6-comp nifti ..."; + while (!it.IsAtEnd()) { - for (int te=0; teGetPixel(idx)); - } + VarPixType vec = it.Get(); + FixPixType fixVec(vec.GetDataPointer()); + + itk::DiffusionTensor3D tensor; + tensor.SetElement(0, vec.GetElement(0)); + tensor.SetElement(1, vec.GetElement(1)); + tensor.SetElement(2, vec.GetElement(2)); + tensor.SetElement(3, vec.GetElement(3)); + tensor.SetElement(4, vec.GetElement(4)); + tensor.SetElement(5, vec.GetElement(5)); + + fixVec = tensor; + + ot.Set(fixVec); + ++ot; + ++it; } - else if (size[3]==9) + } + else if(numComponents==9) + { + MITK_INFO << "Trying to load dti as 9-comp nifti ..."; + while (!it.IsAtEnd()) { - idx[3] = 0; - tensor.SetElement(0, img->GetPixel(idx)); - idx[3] = 1; - tensor.SetElement(1, img->GetPixel(idx)); - idx[3] = 2; - tensor.SetElement(2, img->GetPixel(idx)); - idx[3] = 4; - tensor.SetElement(3, img->GetPixel(idx)); - idx[3] = 5; - tensor.SetElement(4, img->GetPixel(idx)); - idx[3] = 8; - tensor.SetElement(5, img->GetPixel(idx)); + VarPixType vec = it.Get(); + itk::DiffusionTensor3D tensor; + tensor.SetElement(0, vec.GetElement(0)); + tensor.SetElement(1, vec.GetElement(1)); + tensor.SetElement(2, vec.GetElement(2)); + tensor.SetElement(3, vec.GetElement(4)); + tensor.SetElement(4, vec.GetElement(5)); + tensor.SetElement(5, vec.GetElement(8)); + + FixPixType fixVec(tensor); + ot.Set(fixVec); + ++ot; + ++it; } - else - throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!"); + } + else if (numComponents==1) + { + MITK_INFO << "Trying to load dti as 4D nifti ..."; + typedef itk::Image ImageType; + itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); + typedef itk::ImageFileReader FileReaderType; + FileReaderType::Pointer reader = FileReaderType::New(); + reader->SetImageIO(io); + reader->SetFileName(this->m_FileName); + reader->Update(); + ImageType::Pointer img = reader->GetOutput(); + + itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); + + while (!ot.IsAtEnd()) + { + itk::DiffusionTensor3D tensor; + ImageType::IndexType idx; + idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; + + if (size[3]==6) + { + for (int te=0; teGetPixel(idx)); + } + } + else if (size[3]==9) + { + idx[3] = 0; + tensor.SetElement(0, img->GetPixel(idx)); + idx[3] = 1; + tensor.SetElement(1, img->GetPixel(idx)); + idx[3] = 2; + tensor.SetElement(2, img->GetPixel(idx)); + idx[3] = 4; + tensor.SetElement(3, img->GetPixel(idx)); + idx[3] = 5; + tensor.SetElement(4, img->GetPixel(idx)); + idx[3] = 8; + tensor.SetElement(5, img->GetPixel(idx)); + } + else + throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!"); - FixPixType fixVec(tensor); - ot.Set(fixVec); - ++ot; + FixPixType fixVec(tensor); + ot.Set(fixVec); + ++ot; + } } this->GetOutput()->InitializeByItk(vecImg.GetPointer()); this->GetOutput()->SetVolume(vecImg->GetBufferPointer()); } catch(...) { MITK_INFO << "Trying to load dti as nrrd ..."; typedef itk::VectorImage ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(this->m_FileName); reader->Update(); ImageType::Pointer img = reader->GetOutput(); typedef itk::Image,3> VecImgType; VecImgType::Pointer vecImg = VecImgType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot = ot.Begin(); itk::ImageRegionIterator it (img, img->GetLargestPossibleRegion() ); it = it.Begin(); typedef ImageType::PixelType VarPixType; typedef VecImgType::PixelType FixPixType; int numComponents = img->GetNumberOfComponentsPerPixel(); itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary(); std::vector imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; bool readFrame = false; double xx, xy, xz, yx, yy, yz, zx, zy, zz; MeasurementFrameType measFrame; measFrame.SetIdentity(); MeasurementFrameType measFrameTransp; measFrameTransp.SetIdentity(); for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData (imgMetaDictionary, *itKey, metaString); if (itKey->find("measurement frame") != std::string::npos) { sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); if (xx>10e-10 || xy>10e-10 || xz>10e-10 || yx>10e-10 || yy>10e-10 || yz>10e-10 || zx>10e-10 || zy>10e-10 || zz>10e-10 ) { readFrame = true; measFrame(0,0) = xx; measFrame(0,1) = xy; measFrame(0,2) = xz; measFrame(1,0) = yx; measFrame(1,1) = yy; measFrame(1,2) = yz; measFrame(2,0) = zx; measFrame(2,1) = zy; measFrame(2,2) = zz; measFrameTransp = measFrame.GetTranspose(); } } } if (numComponents==6) { while (!it.IsAtEnd()) { // T'=RTR' VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); if(readFrame) { itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(3)); tensor.SetElement(4, vec.GetElement(4)); tensor.SetElement(5, vec.GetElement(5)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); fixVec = tensor; } ot.Set(fixVec); ++ot; ++it; } } else if(numComponents==9) { while (!it.IsAtEnd()) { VarPixType vec = it.Get(); itk::DiffusionTensor3D tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(4)); tensor.SetElement(4, vec.GetElement(5)); tensor.SetElement(5, vec.GetElement(8)); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; ++it; } } else if (numComponents==1) { typedef itk::Image ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(this->m_FileName); reader->Update(); ImageType::Pointer img = reader->GetOutput(); itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); MITK_INFO << size; while (!ot.IsAtEnd()) { itk::DiffusionTensor3D tensor; ImageType::IndexType idx; idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; if (size[3]==6) { for (int te=0; teGetPixel(idx)); } - - // idx[3] = 0; - // tensor.SetElement(0, img->GetPixel(idx)); - // idx[3] = 1; - // tensor.SetElement(1, img->GetPixel(idx)); - // idx[3] = 3; - // tensor.SetElement(2, img->GetPixel(idx)); - // idx[3] = 2; - // tensor.SetElement(3, img->GetPixel(idx)); - // idx[3] = 4; - // tensor.SetElement(4, img->GetPixel(idx)); - // idx[3] = 5; - // tensor.SetElement(5, img->GetPixel(idx)); } else if (size[3]==9) { idx[3] = 0; tensor.SetElement(0, img->GetPixel(idx)); idx[3] = 1; tensor.SetElement(1, img->GetPixel(idx)); idx[3] = 2; tensor.SetElement(2, img->GetPixel(idx)); idx[3] = 4; tensor.SetElement(3, img->GetPixel(idx)); idx[3] = 5; tensor.SetElement(4, img->GetPixel(idx)); idx[3] = 8; tensor.SetElement(5, img->GetPixel(idx)); } else throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!"); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; } } else { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Image has wrong number of pixel components!"); } this->GetOutput()->InitializeByItk(vecImg.GetPointer()); this->GetOutput()->SetVolume(vecImg->GetBufferPointer()); } try { setlocale(LC_ALL, currLocale.c_str()); } catch(...) { MITK_INFO << "Could not reset locale " << currLocale; } } catch(std::exception& e) { throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested DTI file!"); } } } void NrrdTensorImageReader::GenerateOutputInformation() { } const char* NrrdTensorImageReader ::GetFileName() const { return m_FileName.c_str(); } void NrrdTensorImageReader ::SetFileName(const char* aFileName) { m_FileName = aFileName; } const char* NrrdTensorImageReader ::GetFilePrefix() const { return m_FilePrefix.c_str(); } void NrrdTensorImageReader ::SetFilePrefix(const char* aFilePrefix) { m_FilePrefix = aFilePrefix; } const char* NrrdTensorImageReader ::GetFilePattern() const { return m_FilePattern.c_str(); } void NrrdTensorImageReader ::SetFilePattern(const char* aFilePattern) { m_FilePattern = aFilePattern; } bool NrrdTensorImageReader ::CanReadFile(const std::string filename, const std::string /*filePrefix*/, const std::string /*filePattern*/) { // First check the extension if( filename == "" ) { return false; } std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename); ext = itksys::SystemTools::LowerCase(ext); if (ext == ".hdti" || ext == ".dti") { return true; } return false; } itk::DiffusionTensor3D NrrdTensorImageReader ::ConvertMatrixTypeToFixedArrayType(const itk::DiffusionTensor3D::Superclass::MatrixType & matrix) { /* | 0 1 2 | * | X 3 4 | * | X X 5 | */ itk::DiffusionTensor3D arr; arr.SetElement(0,matrix(0,0)); arr.SetElement(1,matrix(0,1)); arr.SetElement(2,matrix(0,2)); arr.SetElement(3,matrix(1,3)); arr.SetElement(4,matrix(1,4)); arr.SetElement(5,matrix(2,5)); return arr; } } //namespace MITK diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp index bbf4f2acbd..28603a7c36 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp @@ -1,389 +1,363 @@ /*=================================================================== 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 __itkEvaluateDirectionImagesFilter_cpp #define __itkEvaluateDirectionImagesFilter_cpp #include "itkEvaluateDirectionImagesFilter.h" #include #include #include #include #define _USE_MATH_DEFINES #include namespace itk { template< class PixelType > EvaluateDirectionImagesFilter< PixelType > ::EvaluateDirectionImagesFilter(): m_ImageSet(NULL), m_ReferenceImageSet(NULL), m_IgnoreMissingDirections(false), m_Eps(0.0001) { - this->SetNumberOfOutputs(2); + this->SetNumberOfIndexedOutputs(2); } template< class PixelType > void EvaluateDirectionImagesFilter< PixelType >::GenerateData() { if (m_ImageSet.IsNull() || m_ReferenceImageSet.IsNull()) return; DirectionImageContainerType::Pointer set1 = DirectionImageContainerType::New(); DirectionImageContainerType::Pointer set2 = DirectionImageContainerType::New(); for (int i=0; iSize(); i++) { typename itk::ImageDuplicator< DirectionImageType >::Pointer duplicator = itk::ImageDuplicator< DirectionImageType >::New(); duplicator->SetInputImage( m_ImageSet->GetElement(i) ); duplicator->Update(); set1->InsertElement(i, dynamic_cast(duplicator->GetOutput())); } for (int i=0; iSize(); i++) { typename itk::ImageDuplicator< DirectionImageType >::Pointer duplicator = itk::ImageDuplicator< DirectionImageType >::New(); duplicator->SetInputImage( m_ReferenceImageSet->GetElement(i) ); duplicator->Update(); set2->InsertElement(i, dynamic_cast(duplicator->GetOutput())); } m_ImageSet = set1; m_ReferenceImageSet = set2; // angular error image typename OutputImageType::Pointer outputImage = OutputImageType::New(); outputImage->SetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() ); outputImage->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() ); outputImage->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() ); outputImage->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() ); outputImage->Allocate(); outputImage->FillBuffer(0.0); this->SetNthOutput(0, outputImage); // length error image outputImage = OutputImageType::New(); outputImage->SetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() ); outputImage->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() ); outputImage->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() ); outputImage->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() ); outputImage->Allocate(); outputImage->FillBuffer(0.0); this->SetNthOutput(1, outputImage); if (m_MaskImage.IsNull()) { m_MaskImage = UCharImageType::New(); m_MaskImage->SetOrigin( outputImage->GetOrigin() ); m_MaskImage->SetRegions( outputImage->GetLargestPossibleRegion() ); m_MaskImage->SetSpacing( outputImage->GetSpacing() ); m_MaskImage->SetDirection( outputImage->GetDirection() ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } m_MeanAngularError = 0.0; m_MedianAngularError = 0; m_MaxAngularError = 0.0; m_MinAngularError = itk::NumericTraits::max(); m_VarAngularError = 0.0; m_AngularErrorVector.clear(); m_MeanLengthError = 0.0; m_MedianLengthError = 0; m_MaxLengthError = 0.0; m_MinLengthError = itk::NumericTraits::max(); m_VarLengthError = 0.0; m_LengthErrorVector.clear(); if (m_ImageSet.IsNull() || m_ReferenceImageSet.IsNull()) return; outputImage = static_cast< OutputImageType* >(this->ProcessObject::GetOutput(0)); typename OutputImageType::Pointer outputImage2 = static_cast< OutputImageType* >(this->ProcessObject::GetOutput(1)); ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion()); ImageRegionIterator< OutputImageType > oit2(outputImage2, outputImage2->GetLargestPossibleRegion()); ImageRegionIterator< UCharImageType > mit(m_MaskImage, m_MaskImage->GetLargestPossibleRegion()); - int numImages = m_ImageSet->Size(); + int numTestImages = m_ImageSet->Size(); int numReferenceImages = m_ReferenceImageSet->Size(); - - // fill missing directions with zeros - if (numImages>numReferenceImages) - { - DirectionType zeroDir; zeroDir.Fill(0.0); - for (int i=0; iSetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() ); - img->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() ); - img->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() ); - img->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() ); - img->Allocate(); - img->FillBuffer(zeroDir); - m_ReferenceImageSet->InsertElement(m_ReferenceImageSet->Size(), img); - } - numReferenceImages = numImages; - } - else if (numReferenceImages>numImages) - { - DirectionType zeroDir; zeroDir.Fill(0.0); - for (int i=0; iSetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() ); - img->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() ); - img->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() ); - img->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() ); - img->Allocate(); - img->FillBuffer(zeroDir); - m_ImageSet->InsertElement(m_ImageSet->Size(), img); - } - numImages = numReferenceImages; - } - int numDirections = numReferenceImages; + int maxNumDirections = std::max(numReferenceImages, numTestImages); // matrix containing the angular error between the directions - vnl_matrix< float > diffM; diffM.set_size(numDirections, numDirections); + vnl_matrix< float > diffM; diffM.set_size(maxNumDirections, maxNumDirections); boost::progress_display disp(outputImage->GetLargestPossibleRegion().GetSize()[0]*outputImage->GetLargestPossibleRegion().GetSize()[1]*outputImage->GetLargestPossibleRegion().GetSize()[2]); while( !oit.IsAtEnd() ) { ++disp; if( mit.Get()!=1 ) { ++oit; ++oit2; ++mit; continue; } typename OutputImageType::IndexType index = oit.GetIndex(); float maxAngularError = 1.0; diffM.fill(10); // initialize with invalid error value // get number of valid directions (length > 0) int numRefDirs = 0; int numTestDirs = 0; std::vector< vnl_vector_fixed< PixelType, 3 > > testDirs; std::vector< vnl_vector_fixed< PixelType, 3 > > refDirs; - for (int i=0; i refDir = m_ReferenceImageSet->GetElement(i)->GetPixel(index).GetVnlVector(); if (refDir.magnitude() > m_Eps ) { refDir.normalize(); refDirs.push_back(refDir); numRefDirs++; } + } + for (int i=0; i testDir = m_ImageSet->GetElement(i)->GetPixel(index).GetVnlVector(); if (testDir.magnitude() > m_Eps ) { testDir.normalize(); testDirs.push_back(testDir); numTestDirs++; } } // i: index of reference direction // j: index of test direction - for (int i=0; i refDir; if (i testDir; if (j1.0) diffM[i][j] = 1.0; } } float angularError = 0.0; float lengthError = 0.0; int counter = 0; vnl_matrix< float > diffM_copy = diffM; - for (int k=0; k small error) - for (int i=0; ierror && diffM[i][j]<2) // found valid error entry + if (diffM[i][j]>error && diffM[i][j]<2) // found valid error entry { error = diffM[i][j]; a = i; b = j; missingDir = false; } else if (diffM[i][j]<0 && error<0) // found missing direction { a = i; b = j; missingDir = true; } } - if (a<0 || b<0 || m_IgnoreMissingDirections && missingDir) + if (a<0 || b<0 || (m_IgnoreMissingDirections && missingDir)) continue; // no more directions found if (a>=numRefDirs && b>=numTestDirs) { MITK_INFO << "ERROR: missing test and reference direction. should not be possible. check code."; continue; } // remove processed directions from error matrix diffM.set_row(a, 10.0); diffM.set_column(b, 10.0); if (a>=numRefDirs) // missing reference direction (find next closest) { for (int i=0; ierror) { error = diffM_copy[i][b]; a = i; } } else if (b>=numTestDirs) // missing test direction (find next closest) { for (int i=0; ierror) { error = diffM_copy[a][i]; b = i; } } - float refLength = m_ReferenceImageSet->GetElement(a)->GetPixel(index).GetVnlVector().magnitude(); - float testLength = m_ImageSet->GetElement(b)->GetPixel(index).GetVnlVector().magnitude(); + float refLength = 0; + float testLength = 1; if (a>=numRefDirs || b>=numTestDirs || error<0) error = 0; + else + { + refLength = m_ReferenceImageSet->GetElement(a)->GetPixel(index).GetVnlVector().magnitude(); + testLength = m_ImageSet->GetElement(b)->GetPixel(index).GetVnlVector().magnitude(); + } m_LengthErrorVector.push_back( fabs(refLength-testLength) ); m_AngularErrorVector.push_back( acos(error)*180.0/M_PI ); m_MeanAngularError += m_AngularErrorVector.back(); m_MeanLengthError += m_LengthErrorVector.back(); angularError += m_AngularErrorVector.back(); lengthError += m_LengthErrorVector.back(); counter++; } if (counter>0) { lengthError /= counter; angularError /= counter; } oit2.Set(lengthError); oit.Set(angularError); ++oit; ++oit2; ++mit; } std::sort( m_AngularErrorVector.begin(), m_AngularErrorVector.end() ); m_MeanAngularError /= m_AngularErrorVector.size(); // mean - for (int i=0; im_MaxAngularError ) m_MaxAngularError = m_AngularErrorVector.at(i); if ( m_AngularErrorVector.at(i)1) { m_VarAngularError /= (m_AngularErrorVector.size()-1); // variance // median if (m_AngularErrorVector.size()%2 == 0) m_MedianAngularError = 0.5*( m_AngularErrorVector.at( m_AngularErrorVector.size()/2 ) + m_AngularErrorVector.at( m_AngularErrorVector.size()/2+1 ) ); else m_MedianAngularError = m_AngularErrorVector.at( (m_AngularErrorVector.size()+1)/2 ) ; } std::sort( m_LengthErrorVector.begin(), m_LengthErrorVector.end() ); m_MeanLengthError /= m_LengthErrorVector.size(); // mean - for (int i=0; im_MaxLengthError ) m_MaxLengthError = m_LengthErrorVector.at(i); if ( m_LengthErrorVector.at(i)1) { m_VarLengthError /= (m_LengthErrorVector.size()-1); // variance // median if (m_LengthErrorVector.size()%2 == 0) m_MedianLengthError = 0.5*( m_LengthErrorVector.at( m_LengthErrorVector.size()/2 ) + m_LengthErrorVector.at( m_LengthErrorVector.size()/2+1 ) ); else m_MedianLengthError = m_LengthErrorVector.at( (m_LengthErrorVector.size()+1)/2 ) ; } } } #endif // __itkEvaluateDirectionImagesFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp index a24e174713..e2857935cd 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToVectorImageFilter.cpp @@ -1,836 +1,832 @@ #include "itkTractsToVectorImageFilter.h" // VTK #include #include #include // ITK #include #include // misc #define _USE_MATH_DEFINES #include #include namespace itk{ static bool CompareVectorLengths(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); } template< class PixelType > TractsToVectorImageFilter< PixelType >::TractsToVectorImageFilter(): m_AngularThreshold(0.7), m_MaskImage(NULL), m_NumDirectionsImage(NULL), m_NormalizeVectors(false), m_Epsilon(0.999), m_UseWorkingCopy(true), m_MaxNumDirections(3), m_UseTrilinearInterpolation(false), m_Thres(0.5) { this->SetNumberOfRequiredOutputs(1); } template< class PixelType > TractsToVectorImageFilter< PixelType >::~TractsToVectorImageFilter() { } template< class PixelType > vnl_vector_fixed TractsToVectorImageFilter< PixelType >::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > itk::Point TractsToVectorImageFilter< PixelType >::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } template< class PixelType > void TractsToVectorImageFilter< PixelType >::GenerateData() { mitk::Geometry3D::Pointer geometry = m_FiberBundle->GetGeometry(); // calculate new image parameters itk::Vector spacing; itk::Point origin; itk::Matrix direction; ImageRegion<3> imageRegion; if (!m_MaskImage.IsNull()) { spacing = m_MaskImage->GetSpacing(); imageRegion = m_MaskImage->GetLargestPossibleRegion(); origin = m_MaskImage->GetOrigin(); direction = m_MaskImage->GetDirection(); } else { spacing = geometry->GetSpacing(); origin = geometry->GetOrigin(); mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds(); origin[0] += bounds.GetElement(0); origin[1] += bounds.GetElement(2); origin[2] += bounds.GetElement(4); for (int i=0; i<3; i++) for (int j=0; j<3; j++) direction[j][i] = geometry->GetMatrixColumn(i)[j]; imageRegion.SetSize(0, geometry->GetExtent(0)); imageRegion.SetSize(1, geometry->GetExtent(1)); imageRegion.SetSize(2, geometry->GetExtent(2)); m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } OutputImageType::RegionType::SizeType outImageSize = imageRegion.GetSize(); m_OutImageSpacing = m_MaskImage->GetSpacing(); m_ClusteredDirectionsContainer = ContainerType::New(); // initialize crossings image m_CrossingsImage = ItkUcharImgType::New(); m_CrossingsImage->SetSpacing( spacing ); m_CrossingsImage->SetOrigin( origin ); m_CrossingsImage->SetDirection( direction ); m_CrossingsImage->SetRegions( imageRegion ); m_CrossingsImage->Allocate(); m_CrossingsImage->FillBuffer(0); // initialize num directions image m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); // resample fiber bundle float minSpacing = 1; if(m_OutImageSpacing[0]GetDeepCopy(); // resample fiber bundle for sufficient voxel coverage - m_FiberBundle->ResampleFibers(minSpacing/10); + m_FiberBundle->ResampleFibers(minSpacing/3); // iterate over all fibers vtkSmartPointer fiberPolyData = m_FiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); int numFibers = m_FiberBundle->GetNumFibers(); itk::TimeProbe clock; m_DirectionsContainer = ContainerType::New(); if (m_UseTrilinearInterpolation) MITK_INFO << "Generating directions from tractogram (trilinear interpolation)"; else MITK_INFO << "Generating directions from tractogram"; boost::progress_display disp(numFibers); for( int i=0; iGetNextCell ( numPoints, points ); if (numPoints<2) continue; itk::Index<3> index; index.Fill(0); itk::ContinuousIndex contIndex; vnl_vector_fixed dir, wDir; itk::Point worldPos; vnl_vector v; for( int j=0; jGetPoint(points[j]); worldPos = GetItkPoint(temp); v = GetVnlVector(temp); dir = GetVnlVector(fiberPolyData->GetPoint(points[j+1]))-v; dir.normalize(); m_MaskImage->TransformPhysicalPointToIndex(worldPos, index); m_MaskImage->TransformPhysicalPointToContinuousIndex(worldPos, contIndex); if (m_MaskImage->GetPixel(index)==0) continue; if (!m_UseTrilinearInterpolation) { if (index[0] < 0 || index[0] >= outImageSize[0]) continue; if (index[1] < 0 || index[1] >= outImageSize[1]) continue; if (index[2] < 0 || index[2] >= outImageSize[2]) continue; int idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]); DirectionContainerType::Pointer dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, dir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), dir); } else { dirCont->InsertElement(0, dir); m_DirectionsContainer->InsertElement(idx, dirCont); } continue; } float frac_x = contIndex[0] - index[0]; float frac_y = contIndex[1] - index[1]; float frac_z = contIndex[2] - index[2]; if (frac_x<0) { index[0] -= 1; frac_x += 1; } if (frac_y<0) { index[1] -= 1; frac_y += 1; } if (frac_z<0) { index[2] -= 1; frac_z += 1; } frac_x = 1-frac_x; frac_y = 1-frac_y; frac_z = 1-frac_z; // int coordinates inside image? if (index[0] < 0 || index[0] >= outImageSize[0]-1) continue; if (index[1] < 0 || index[1] >= outImageSize[1]-1) continue; if (index[2] < 0 || index[2] >= outImageSize[2]-1) continue; DirectionContainerType::Pointer dirCont; int idx; wDir = dir; float weight = ( frac_x)*( frac_y)*( frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2] ); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = ( frac_x)*(1-frac_y)*( frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0] + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2] ); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = ( frac_x)*( frac_y)*(1-frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0] + outImageSize[0]*(index[1] + outImageSize[1]*index[2]+outImageSize[1]); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = ( frac_x)*(1-frac_y)*(1-frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0] + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2]+outImageSize[1]); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = (1-frac_x)*( frac_y)*( frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0]+1 + outImageSize[0]*(index[1] + outImageSize[1]*index[2] ); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = (1-frac_x)*( frac_y)*(1-frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0]+1 + outImageSize[0]*(index[1] + outImageSize[1]*index[2]+outImageSize[1]); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = (1-frac_x)*(1-frac_y)*( frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0]+1 + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2] ); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } wDir = dir; weight = (1-frac_x)*(1-frac_y)*(1-frac_z); if (weight>m_Thres) { wDir *= weight; idx = index[0]+1 + outImageSize[0]*(index[1]+1+ outImageSize[1]*index[2]+outImageSize[1]); dirCont = DirectionContainerType::New(); if (m_DirectionsContainer->IndexExists(idx)) { dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull()) { dirCont = DirectionContainerType::New(); dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } else dirCont->InsertElement(dirCont->Size(), wDir); } else { dirCont->InsertElement(0, wDir); m_DirectionsContainer->InsertElement(idx, dirCont); } } } clock.Stop(); } vtkSmartPointer m_VtkCellArray = vtkSmartPointer::New(); vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); itk::ImageRegionIterator dirIt(m_NumDirectionsImage, m_NumDirectionsImage->GetLargestPossibleRegion()); itk::ImageRegionIterator crossIt(m_CrossingsImage, m_CrossingsImage->GetLargestPossibleRegion()); m_DirectionImageContainer = DirectionImageContainerType::New(); int maxNumDirections = 0; MITK_INFO << "Clustering directions"; boost::progress_display disp2(outImageSize[0]*outImageSize[1]*outImageSize[2]); for(crossIt.GoToBegin(); !crossIt.IsAtEnd(); ++crossIt) { ++disp2; OutputImageType::IndexType index = crossIt.GetIndex(); int idx = index[0]+(index[1]+index[2]*outImageSize[1])*outImageSize[0]; if (!m_DirectionsContainer->IndexExists(idx)) { ++dirIt; continue; } DirectionContainerType::Pointer dirCont = m_DirectionsContainer->GetElement(idx); if (dirCont.IsNull() || index[0] < 0 || index[0] >= outImageSize[0] || index[1] < 0 || index[1] >= outImageSize[1] || index[2] < 0 || index[2] >= outImageSize[2]) { ++dirIt; continue; } std::vector< DirectionType > directions; for (int i=0; iSize(); i++) if (dirCont->ElementAt(i).magnitude()>0.0001) directions.push_back(dirCont->ElementAt(i)); if (!directions.empty()) directions = FastClustering(directions); std::sort( directions.begin(), directions.end(), CompareVectorLengths ); if ( directions.size() > maxNumDirections ) { for (int i=maxNumDirections; iSetSpacing( spacing ); directionImage->SetOrigin( origin ); directionImage->SetDirection( direction ); directionImage->SetRegions( imageRegion ); directionImage->Allocate(); Vector< float, 3 > nullVec; nullVec.Fill(0.0); directionImage->FillBuffer(nullVec); m_DirectionImageContainer->InsertElement(i, directionImage); } maxNumDirections = std::min((int)directions.size(), m_MaxNumDirections); } int numDir = directions.size(); if (numDir>m_MaxNumDirections) numDir = m_MaxNumDirections; for (int i=0; i container = vtkSmartPointer::New(); itk::ContinuousIndex center; center[0] = index[0]; center[1] = index[1]; center[2] = index[2]; itk::Point worldCenter; m_MaskImage->TransformContinuousIndexToPhysicalPoint( center, worldCenter ); - - // workaround ********************************************* - //DirectionType dir = m_MaskImage->GetDirection()*directions.at(i); DirectionType dir = directions.at(i); - // workaround ********************************************* // set direction image pixel ItkDirectionImageType::Pointer directionImage = m_DirectionImageContainer->GetElement(i); Vector< float, 3 > pixel; pixel.SetElement(0, dir[0]); pixel.SetElement(1, dir[1]); pixel.SetElement(2, dir[2]); directionImage->SetPixel(index, pixel); // add direction to vector field (with spacing compensation) itk::Point worldStart; worldStart[0] = worldCenter[0]-dir[0]/2*minSpacing; worldStart[1] = worldCenter[1]-dir[1]/2*minSpacing; worldStart[2] = worldCenter[2]-dir[2]/2*minSpacing; vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer()); container->GetPointIds()->InsertNextId(id); itk::Point worldEnd; worldEnd[0] = worldCenter[0]+dir[0]/2*minSpacing; worldEnd[1] = worldCenter[1]+dir[1]/2*minSpacing; worldEnd[2] = worldCenter[2]+dir[2]/2*minSpacing; id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer()); container->GetPointIds()->InsertNextId(id); m_VtkCellArray->InsertNextCell(container); } dirIt.Set(numDir); ++dirIt; } vtkSmartPointer directionsPolyData = vtkSmartPointer::New(); directionsPolyData->SetPoints(m_VtkPoints); directionsPolyData->SetLines(m_VtkCellArray); m_OutputFiberBundle = mitk::FiberBundleX::New(directionsPolyData); } template< class PixelType > std::vector< vnl_vector_fixed< double, 3 > > TractsToVectorImageFilter< PixelType >::FastClustering(std::vector< vnl_vector_fixed< double, 3 > >& inDirs) { std::vector< vnl_vector_fixed< double, 3 > > outDirs; if (inDirs.empty()) return outDirs; vnl_vector_fixed< double, 3 > oldMean, currentMean, workingMean; std::vector< vnl_vector_fixed< double, 3 > > normalizedDirs; std::vector< int > touched; for (int i=0; i0.0001) { counter = 0; oldMean = currentMean; workingMean = oldMean; workingMean.normalize(); currentMean.fill(0.0); for (int i=0; i=m_AngularThreshold) { currentMean += inDirs[i]; touched[i] = 1; counter++; } else if (-angle>=m_AngularThreshold) { currentMean -= inDirs[i]; touched[i] = 1; counter++; } } } // found stable mean if (counter>0) { currentMean /= counter; float mag = currentMean.magnitude(); if (mag>0) { if (mag>max) max = mag; outDirs.push_back(currentMean); } } // find next unused seed free = false; for (int i=0; i0) for (int i=0; i std::vector< vnl_vector_fixed< double, 3 > > TractsToVectorImageFilter< PixelType >::Clustering(std::vector< vnl_vector_fixed< double, 3 > >& inDirs) { std::vector< vnl_vector_fixed< double, 3 > > outDirs; if (inDirs.empty()) return outDirs; vnl_vector_fixed< double, 3 > oldMean, currentMean, workingMean; std::vector< vnl_vector_fixed< double, 3 > > normalizedDirs; std::vector< int > touched; for (int i=0; i0.0001) { counter = 0; oldMean = currentMean; workingMean = oldMean; workingMean.normalize(); currentMean.fill(0.0); for (int i=0; i=m_AngularThreshold) { currentMean += inDirs[i]; counter++; } else if (-angle>=m_AngularThreshold) { currentMean -= inDirs[i]; counter++; } } } // found stable mean if (counter>0) { bool add = true; vnl_vector_fixed< double, 3 > normMean = currentMean; normMean.normalize(); for (int i=0; i dir = outDirs[i]; dir.normalize(); if ((normMean-dir).magnitude()<=0.0001) { add = false; break; } } currentMean /= counter; if (add) { float mag = currentMean.magnitude(); if (mag>0) { if (mag>max) max = mag; outDirs.push_back(currentMean); } } } } if (m_NormalizeVectors) for (int i=0; i0) for (int i=0; i TractsToVectorImageFilter< PixelType >::DirectionContainerType::Pointer TractsToVectorImageFilter< PixelType >::MeanShiftClustering(DirectionContainerType::Pointer dirCont) { DirectionContainerType::Pointer container = DirectionContainerType::New(); float max = 0; for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) { vnl_vector_fixed mean = ClusterStep(dirCont, it.Value()); if (mean.is_zero()) continue; bool addMean = true; for (DirectionContainerType::ConstIterator it2 = container->Begin(); it2!=container->End(); ++it2) { vnl_vector_fixed dir = it2.Value(); float angle = fabs(dot_product(mean, dir)/(mean.magnitude()*dir.magnitude())); if (angle>=m_Epsilon) { addMean = false; break; } } if (addMean) { if (m_NormalizeVectors) mean.normalize(); else if (mean.magnitude()>max) max = mean.magnitude(); container->InsertElement(container->Size(), mean); } } // max normalize voxel directions if (max>0 && !m_NormalizeVectors) for (int i=0; iSize(); i++) container->ElementAt(i) /= max; if (container->Size()Size()) return MeanShiftClustering(container); else return container; } template< class PixelType > vnl_vector_fixed TractsToVectorImageFilter< PixelType >::ClusterStep(DirectionContainerType::Pointer dirCont, vnl_vector_fixed currentMean) { vnl_vector_fixed newMean; newMean.fill(0); for (DirectionContainerType::ConstIterator it = dirCont->Begin(); it!=dirCont->End(); ++it) { vnl_vector_fixed dir = it.Value(); float angle = dot_product(currentMean, dir)/(currentMean.magnitude()*dir.magnitude()); if (angle>=m_AngularThreshold) newMean += dir; else if (-angle>=m_AngularThreshold) newMean -= dir; } if (fabs(dot_product(currentMean, newMean)/(currentMean.magnitude()*newMean.magnitude()))>=m_Epsilon || newMean.is_zero()) return newMean; else return ClusterStep(dirCont, newMean); } } diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt b/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt index 0e1e716e8b..a855f907cc 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt +++ b/Modules/DiffusionImaging/FiberTracking/Testing/CMakeLists.txt @@ -1,7 +1,9 @@ MITK_CREATE_MODULE_TESTS() mitkAddCustomModuleTest(mitkFiberBundleXReaderWriterTest mitkFiberBundleXReaderWriterTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib) #mitkAddCustomModuleTest(mitkGibbsTrackingTest mitkGibbsTrackingTest ${MITK_DATA_DIR}/DiffusionImaging/qBallImage.qbi ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/gibbsTrackingParameters.gtp ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib) #mitkAddCustomModuleTest(mitkFiberBundleXTest mitkFiberBundleXTest ${MITK_DATA_DIR}/DiffusionImaging/fiberBundleX.fib) mitkAddCustomModuleTest(mitkStreamlineTrackingTest mitkStreamlineTrackingTest ${MITK_DATA_DIR}/DiffusionImaging/tensorImage.dti ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/streamlineTractogram.fib) mitkAddCustomModuleTest(mitkPeakExtractionTest mitkPeakExtractionTest ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_SHCoeffs.nrrd ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_VectorField.fib) +mitkAddCustomModuleTest(mitkPeakExtractionTest mitkPeakExtractionTest ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_SHCoeffs.nrrd ${MITK_DATA_DIR}/DiffusionImaging/diffusionImageMask.nrrd ${MITK_DATA_DIR}/DiffusionImaging/qBallImage_VectorField.fib) +mitkAddCustomModuleTest(mitkLocalFiberPlausibilityTest mitkLocalFiberPlausibilityTest ${MITK_DATA_DIR}/DiffusionImaging/streamlineTractogram.fib ${MITK_DATA_DIR}/DiffusionImaging/LDFP_GT_DIRECTION_0.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_GT_DIRECTION_1.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_ERROR_IMAGE.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_NUM_DIRECTIONS.nrrd ${MITK_DATA_DIR}/DiffusionImaging/LDFP_VECTOR_FIELD.fib) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake b/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake index e4f646dbf1..8c1ff91dd6 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/Testing/files.cmake @@ -1,9 +1,10 @@ SET(MODULE_CUSTOM_TESTS mitkFiberBundleXReaderWriterTest.cpp mitkFiberBundleXTest.cpp mitkGibbsTrackingTest.cpp mitkStreamlineTrackingTest.cpp mitkPeakExtractionTest.cpp + mitkLocalFiberPlausibilityTest.cpp ) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp new file mode 100755 index 0000000000..c052ba2009 --- /dev/null +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkLocalFiberPlausibilityTest.cpp @@ -0,0 +1,149 @@ +/*=================================================================== + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +using namespace std; + +int mitkLocalFiberPlausibilityTest(int argc, char* argv[]) +{ + MITK_TEST_BEGIN("mitkLocalFiberPlausibilityTest"); + MITK_TEST_CONDITION_REQUIRED(argc==7,"check for input data") + + string fibFile = argv[1]; + vector< string > referenceImages; referenceImages.push_back(argv[2]); referenceImages.push_back(argv[3]); + string LDFP_ERROR_IMAGE = argv[4]; + string LDFP_NUM_DIRECTIONS = argv[5]; + string LDFP_VECTOR_FIELD = argv[6]; + + float angularThreshold = 25; + bool ignore = false; + + try + { + RegisterDiffusionCoreObjectFactory(); + RegisterFiberTrackingObjectFactory(); + + typedef itk::Image ItkUcharImgType; + typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; + typedef itk::VectorContainer< int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; + typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; + + // load fiber bundle + mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); + + // load reference directions + ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); + for (int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); + typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; + CasterType::Pointer caster = CasterType::New(); + caster->SetInput(img); + caster->Update(); + ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); + referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); + } + catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } + } + + ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); + ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); + itkMaskImage->SetSpacing( dirImg->GetSpacing() ); + itkMaskImage->SetOrigin( dirImg->GetOrigin() ); + itkMaskImage->SetDirection( dirImg->GetDirection() ); + itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->Allocate(); + itkMaskImage->FillBuffer(1); + + // extract directions from fiber bundle + itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); + fOdfFilter->SetFiberBundle(inputTractogram); + fOdfFilter->SetMaskImage(itkMaskImage); + fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); + fOdfFilter->SetNormalizeVectors(true); + fOdfFilter->SetUseWorkingCopy(false); + fOdfFilter->Update(); + ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); + + // evaluate directions + EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); + evaluationFilter->SetImageSet(directionImageContainer); + evaluationFilter->SetReferenceImageSet(referenceImageContainer); + evaluationFilter->SetMaskImage(itkMaskImage); + evaluationFilter->SetIgnoreMissingDirections(ignore); + evaluationFilter->Update(); + + EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); + ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); + mitk::FiberBundleX::Pointer testDirections = fOdfFilter->GetOutputFiberBundle(); + + mitk::Image::Pointer mitkAngularErrorImage = mitk::Image::New(); + mitkAngularErrorImage->InitializeByItk( angularErrorImage.GetPointer() ); + mitkAngularErrorImage->SetVolume( angularErrorImage->GetBufferPointer() ); + + mitk::Image::Pointer mitkNumDirImage = mitk::Image::New(); + mitkNumDirImage->InitializeByItk( numDirImage.GetPointer() ); + mitkNumDirImage->SetVolume( numDirImage->GetBufferPointer() ); + + mitk::Image::Pointer gtAngularErrorImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_ERROR_IMAGE)->GetData()); + mitk::Image::Pointer gtNumTestDirImage = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_NUM_DIRECTIONS)->GetData()); + mitk::FiberBundleX::Pointer gtTestDirections = dynamic_cast(mitk::IOUtil::LoadDataNode(LDFP_VECTOR_FIELD)->GetData()); + + MITK_TEST_CONDITION_REQUIRED(testDirections->Equals(gtTestDirections), "Check if vector fields are equal."); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtAngularErrorImage, mitkAngularErrorImage, 0.0001, true), "Check if error images are equal."); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(gtNumTestDirImage, mitkNumDirImage, 0.0001, true), "Check if num direction images are equal."); + } + catch (itk::ExceptionObject e) + { + MITK_INFO << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_INFO << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_INFO << "ERROR!?!"; + return EXIT_FAILURE; + } + MITK_TEST_END(); +} diff --git a/Modules/DiffusionImaging/MiniApps/TractometerAngularErrorTool.cpp b/Modules/DiffusionImaging/MiniApps/TractometerAngularErrorTool.cpp index 294bb67ea9..a42916d2e4 100755 --- a/Modules/DiffusionImaging/MiniApps/TractometerAngularErrorTool.cpp +++ b/Modules/DiffusionImaging/MiniApps/TractometerAngularErrorTool.cpp @@ -1,263 +1,302 @@ /*=================================================================== 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 "MiniAppManager.h" #include #include #include #include #include #include #include #include #include "ctkCommandLineParser.h" #include #include #include #include #include #include #include +#include #define _USE_MATH_DEFINES #include int TractometerAngularErrorTool(int argc, char* argv[]) { ctkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", ctkCommandLineParser::String, "input tractogram (.fib, vtk ascii file format)", us::Any(), false); parser.addArgument("reference", "r", ctkCommandLineParser::StringList, "reference direction images", us::Any(), false); parser.addArgument("out", "o", ctkCommandLineParser::String, "output root", us::Any(), false); - parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image"); + parser.addArgument("mask", "m", ctkCommandLineParser::StringList, "mask images"); parser.addArgument("athresh", "a", ctkCommandLineParser::Float, "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true); parser.addArgument("verbose", "v", ctkCommandLineParser::Bool, "output optional and intermediate calculation results"); parser.addArgument("ignore", "n", ctkCommandLineParser::Bool, "don't increase error for missing or too many directions"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; ctkCommandLineParser::StringContainerType referenceImages = us::any_cast(parsedArgs["reference"]); + ctkCommandLineParser::StringContainerType maskImages; + if (parsedArgs.count("mask")) + maskImages = us::any_cast(parsedArgs["mask"]); string fibFile = us::any_cast(parsedArgs["input"]); - string maskImage(""); - if (parsedArgs.count("mask")) - maskImage = us::any_cast(parsedArgs["mask"]); - float angularThreshold = 25; if (parsedArgs.count("athresh")) angularThreshold = us::any_cast(parsedArgs["athresh"]); string outRoot = us::any_cast(parsedArgs["out"]); bool verbose = false; if (parsedArgs.count("verbose")) verbose = us::any_cast(parsedArgs["verbose"]); bool ignore = false; if (parsedArgs.count("ignore")) ignore = us::any_cast(parsedArgs["ignore"]); try { RegisterDiffusionCoreObjectFactory(); RegisterFiberTrackingObjectFactory(); typedef itk::Image ItkUcharImgType; typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; typedef itk::VectorContainer< int, ItkDirectionImage3DType::Pointer > ItkDirectionImageContainerType; typedef itk::EvaluateDirectionImagesFilter< float > EvaluationFilterType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(fibFile)->GetData()); // load reference directions ItkDirectionImageContainerType::Pointer referenceImageContainer = ItkDirectionImageContainerType::New(); for (int i=0; i(mitk::IOUtil::LoadDataNode(referenceImages.at(i))->GetData()); typedef mitk::ImageToItk< ItkDirectionImage3DType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); ItkDirectionImage3DType::Pointer itkImg = caster->GetOutput(); referenceImageContainer->InsertElement(referenceImageContainer->Size(),itkImg); } catch(...){ MITK_INFO << "could not load: " << referenceImages.at(i); } } - // load/create mask image ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); - if (maskImage.compare("")==0) - { - ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); - itkMaskImage->SetSpacing( dirImg->GetSpacing() ); - itkMaskImage->SetOrigin( dirImg->GetOrigin() ); - itkMaskImage->SetDirection( dirImg->GetDirection() ); - itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); - itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); - itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); - itkMaskImage->Allocate(); - itkMaskImage->FillBuffer(1); - } - else - { - mitk::Image::Pointer mitkMaskImage = dynamic_cast(mitk::IOUtil::LoadDataNode(maskImage)->GetData()); - mitk::CastToItkImage(mitkMaskImage, itkMaskImage); - } - + ItkDirectionImage3DType::Pointer dirImg = referenceImageContainer->GetElement(0); + itkMaskImage->SetSpacing( dirImg->GetSpacing() ); + itkMaskImage->SetOrigin( dirImg->GetOrigin() ); + itkMaskImage->SetDirection( dirImg->GetDirection() ); + itkMaskImage->SetLargestPossibleRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->SetBufferedRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->SetRequestedRegion( dirImg->GetLargestPossibleRegion() ); + itkMaskImage->Allocate(); + itkMaskImage->FillBuffer(1); // extract directions from fiber bundle itk::TractsToVectorImageFilter::Pointer fOdfFilter = itk::TractsToVectorImageFilter::New(); fOdfFilter->SetFiberBundle(inputTractogram); fOdfFilter->SetMaskImage(itkMaskImage); fOdfFilter->SetAngularThreshold(cos(angularThreshold*M_PI/180)); fOdfFilter->SetNormalizeVectors(true); fOdfFilter->SetUseWorkingCopy(false); fOdfFilter->Update(); ItkDirectionImageContainerType::Pointer directionImageContainer = fOdfFilter->GetDirectionImageContainer(); if (verbose) { // write vector field mitk::FiberBundleX::Pointer directions = fOdfFilter->GetOutputFiberBundle(); mitk::CoreObjectFactory::FileWriterList fileWriters = mitk::CoreObjectFactory::GetInstance()->GetFileWriters(); for (mitk::CoreObjectFactory::FileWriterList::iterator it = fileWriters.begin() ; it != fileWriters.end() ; ++it) { if ( (*it)->CanWriteBaseDataType(directions.GetPointer()) ) { string outfilename = outRoot; outfilename.append("_VECTOR_FIELD.fib"); (*it)->SetFileName( outfilename.c_str() ); (*it)->DoWrite( directions.GetPointer() ); } } // write direction images for (int i=0; iSize(); i++) { itk::TractsToVectorImageFilter::ItkDirectionImageType::Pointer itkImg = directionImageContainer->GetElement(i); typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter::ItkDirectionImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_DIRECTION_"); outfilename.append(boost::lexical_cast(i)); outfilename.append(".nrrd"); MITK_INFO << "writing " << outfilename; writer->SetFileName(outfilename.c_str()); writer->SetInput(itkImg); writer->Update(); } // write num direction image { ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage(); typedef itk::ImageFileWriter< ItkUcharImgType > WriterType; WriterType::Pointer writer = WriterType::New(); string outfilename = outRoot; outfilename.append("_NUM_DIRECTIONS.nrrd"); MITK_INFO << "writing " << outfilename; writer->SetFileName(outfilename.c_str()); writer->SetInput(numDirImage); writer->Update(); } } - // evaluate directions - EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); - evaluationFilter->SetImageSet(directionImageContainer); - evaluationFilter->SetReferenceImageSet(referenceImageContainer); - evaluationFilter->SetMaskImage(itkMaskImage); - evaluationFilter->SetIgnoreMissingDirections(ignore); - evaluationFilter->Update(); + string logFile = outRoot; + logFile.append("_ANGULAR_ERROR.csv"); + ofstream file; + file.open (logFile.c_str()); - if (verbose) + if (maskImages.size()>0) { - EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); - typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; - WriterType::Pointer writer = WriterType::New(); + for (int i=0; i(mitk::IOUtil::LoadDataNode(maskImages.at(i))->GetData()); + mitk::CastToItkImage(mitkMaskImage, itkMaskImage); + + // evaluate directions + EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); + evaluationFilter->SetImageSet(directionImageContainer); + evaluationFilter->SetReferenceImageSet(referenceImageContainer); + evaluationFilter->SetMaskImage(itkMaskImage); + evaluationFilter->SetIgnoreMissingDirections(ignore); + evaluationFilter->Update(); + + if (verbose) + { + EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); + typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; + WriterType::Pointer writer = WriterType::New(); + + string outfilename = outRoot; + outfilename.append("_ERROR_IMAGE.nrrd"); + + MITK_INFO << "writing " << outfilename; + writer->SetFileName(outfilename.c_str()); + writer->SetInput(angularErrorImage); + writer->Update(); + } + + string sens = itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(fibFile)); + sens.append(","); - string outfilename = outRoot; - outfilename.append("_ERROR_IMAGE.nrrd"); + sens.append(itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(maskImages.at(i)))); + sens.append(","); - MITK_INFO << "writing " << outfilename; - writer->SetFileName(outfilename.c_str()); - writer->SetInput(angularErrorImage); - writer->Update(); + sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); + sens.append(","); + + sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); + sens.append(","); + + sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); + sens.append(","); + + sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); + sens.append(","); + + sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); + sens.append(";\n"); + file << sens; + } } + else + { + // evaluate directions + EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New(); + evaluationFilter->SetImageSet(directionImageContainer); + evaluationFilter->SetReferenceImageSet(referenceImageContainer); + evaluationFilter->SetMaskImage(itkMaskImage); + evaluationFilter->SetIgnoreMissingDirections(ignore); + evaluationFilter->Update(); + + if (verbose) + { + EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0); + typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType; + WriterType::Pointer writer = WriterType::New(); - string logFile = outRoot; - logFile.append("_ANGULAR_ERROR.csv"); + string outfilename = outRoot; + outfilename.append("_ERROR_IMAGE.nrrd"); - ofstream file; - file.open (logFile.c_str()); + MITK_INFO << "writing " << outfilename; + writer->SetFileName(outfilename.c_str()); + writer->SetInput(angularErrorImage); + writer->Update(); + } - string sens = "Mean:"; - sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); - sens.append(";\n"); + string sens = itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(fibFile)); + sens.append(","); - sens.append("Median:"); - sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); - sens.append(";\n"); + sens.append("FULL"); + sens.append(","); - sens.append("Maximum:"); - sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); - sens.append(";\n"); + sens.append(boost::lexical_cast(evaluationFilter->GetMeanAngularError())); + sens.append(","); - sens.append("Minimum:"); - sens.append(","); - sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); - sens.append(";\n"); + sens.append(boost::lexical_cast(evaluationFilter->GetMedianAngularError())); + sens.append(","); - sens.append("STDEV:"); - sens.append(","); - sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); - sens.append(";\n"); + sens.append(boost::lexical_cast(evaluationFilter->GetMaxAngularError())); + sens.append(","); - file << sens; + sens.append(boost::lexical_cast(evaluationFilter->GetMinAngularError())); + sens.append(","); + sens.append(boost::lexical_cast(std::sqrt(evaluationFilter->GetVarAngularError()))); + sens.append(";\n"); + file << sens; + } file.close(); MITK_INFO << "DONE"; } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(TractometerAngularErrorTool); diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp index 8e309d4abd..e1ba64bee3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkOdfMaximaExtractionView.cpp @@ -1,776 +1,779 @@ /*=================================================================== 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. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include #include // Blueberry #include #include // Qmitk #include "QmitkOdfMaximaExtractionView.h" // MITK #include #include #include #include #include #include // ITK #include #include #include #include #include #include #include // Qt #include const std::string QmitkOdfMaximaExtractionView::VIEW_ID = "org.mitk.views.odfmaximaextractionview"; using namespace mitk; QmitkOdfMaximaExtractionView::QmitkOdfMaximaExtractionView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { } // Destructor QmitkOdfMaximaExtractionView::~QmitkOdfMaximaExtractionView() { } void QmitkOdfMaximaExtractionView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkOdfMaximaExtractionViewControls; m_Controls->setupUi( parent ); connect((QObject*) m_Controls->m_StartTensor, SIGNAL(clicked()), (QObject*) this, SLOT(StartTensor())); connect((QObject*) m_Controls->m_StartFiniteDiff, SIGNAL(clicked()), (QObject*) this, SLOT(StartFiniteDiff())); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_ImportPeaks, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertPeaks())); connect((QObject*) m_Controls->m_ImportShCoeffs, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertShCoeffs())); } } void QmitkOdfMaximaExtractionView::UpdateGui() { m_Controls->m_GenerateImageButton->setEnabled(false); m_Controls->m_StartFiniteDiff->setEnabled(false); m_Controls->m_StartTensor->setEnabled(false); m_Controls->m_CoeffImageFrame->setEnabled(false); if (!m_ImageNodes.empty() || !m_TensorImageNodes.empty()) { m_Controls->m_InputData->setTitle("Input Data"); if (!m_TensorImageNodes.empty()) { m_Controls->m_DwiFibLabel->setText(m_TensorImageNodes.front()->GetName().c_str()); m_Controls->m_StartTensor->setEnabled(true); } else { m_Controls->m_DwiFibLabel->setText(m_ImageNodes.front()->GetName().c_str()); m_Controls->m_StartFiniteDiff->setEnabled(true); m_Controls->m_GenerateImageButton->setEnabled(true); m_Controls->m_CoeffImageFrame->setEnabled(true); m_Controls->m_ShOrderBox->setEnabled(true); m_Controls->m_MaxNumPeaksBox->setEnabled(true); m_Controls->m_PeakThresholdBox->setEnabled(true); m_Controls->m_AbsoluteThresholdBox->setEnabled(true); } } else m_Controls->m_DwiFibLabel->setText("mandatory"); if (m_ImageNodes.empty()) { m_Controls->m_ImportPeaks->setEnabled(false); m_Controls->m_ImportShCoeffs->setEnabled(false); } else { m_Controls->m_ImportPeaks->setEnabled(true); m_Controls->m_ImportShCoeffs->setEnabled(true); } if (!m_BinaryImageNodes.empty()) { m_Controls->m_MaskLabel->setText(m_BinaryImageNodes.front()->GetName().c_str()); } else { m_Controls->m_MaskLabel->setText("optional"); } } template void QmitkOdfMaximaExtractionView::TemplatedConvertShCoeffs(mitk::Image* mitkImg) { typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType; typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); typename FilterType::Pointer filter = FilterType::New(); switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: filter->SetToolkit(FilterType::FSL); break; case 1: filter->SetToolkit(FilterType::MRTRIX); break; default: filter->SetToolkit(FilterType::FSL); } filter->SetInputImage(caster->GetOutput()); filter->GenerateData(); typename FilterType::QballImageType::Pointer itkQbi = filter->GetQballImage(); typename FilterType::CoefficientImageType::Pointer itkCi = filter->GetCoefficientImage(); { mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkCi.GetPointer() ); img->SetVolume( itkCi->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); node->SetName("_ShCoefficientImage"); node->SetVisibility(false); GetDataStorage()->Add(node); } { mitk::QBallImage::Pointer img = mitk::QBallImage::New(); img->InitializeByItk( itkQbi.GetPointer() ); img->SetVolume( itkQbi->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); node->SetName("_QballImage"); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::ConvertShCoeffs() { if (m_ImageNodes.empty()) return; mitk::Image::Pointer mitkImg = dynamic_cast(m_ImageNodes.at(0)->GetData()); if (mitkImg->GetDimension()!=4) { MITK_INFO << "wrong image type (need 4 dimensions)"; return; } int nrCoeffs = mitkImg->GetLargestPossibleRegion().GetSize()[3]; // solve bx² + cx + d = 0 = shOrder² + 2*shOrder + 2-2*neededCoeffs; int c=3, d=2-2*nrCoeffs; double D = c*c-4*d; int shOrder; if (D>0) { shOrder = (-c+sqrt(D))/2.0; if (shOrder<0) shOrder = (-c-sqrt(D))/2.0; } else if (D==0) shOrder = -c/2.0; MITK_INFO << "using SH-order " << shOrder; switch (shOrder) { + case 2: + TemplatedConvertShCoeffs<2>(mitkImg); + break; case 4: TemplatedConvertShCoeffs<4>(mitkImg); break; case 6: TemplatedConvertShCoeffs<6>(mitkImg); break; case 8: TemplatedConvertShCoeffs<8>(mitkImg); break; case 10: TemplatedConvertShCoeffs<10>(mitkImg); break; case 12: TemplatedConvertShCoeffs<12>(mitkImg); break; default: MITK_INFO << "SH-order " << shOrder << " not supported"; } } void QmitkOdfMaximaExtractionView::ConvertPeaks() { if (m_ImageNodes.empty()) return; switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: { typedef itk::Image< float, 4 > ItkImageType; typedef itk::FslPeakImageConverter< float > FilterType; FilterType::Pointer filter = FilterType::New(); FilterType::InputType::Pointer inputVec = FilterType::InputType::New(); mitk::Geometry3D::Pointer geom; for (int i=0; i(m_ImageNodes.at(i)->GetData()); geom = mitkImg->GetGeometry(); typedef mitk::ImageToItk< FilterType::InputImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); FilterType::InputImageType::Pointer itkImg = caster->GetOutput(); inputVec->InsertElement(inputVec->Size(), itkImg); } filter->SetInputImages(inputVec); filter->GenerateData(); mitk::Vector3D outImageSpacing = geom->GetSpacing(); float maxSpacing = 1; if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2]) maxSpacing = outImageSpacing[0]; else if (outImageSpacing[1] > outImageSpacing[2]) maxSpacing = outImageSpacing[1]; else maxSpacing = outImageSpacing[2]; mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle(); // directions->SetGeometry(geom); DataNode::Pointer node = DataNode::New(); node->SetData(directions); node->SetName("_VectorField"); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); typedef FilterType::DirectionImageContainerType DirectionImageContainerType; DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(i)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } break; } case 1: { typedef itk::Image< float, 4 > ItkImageType; typedef itk::MrtrixPeakImageConverter< float > FilterType; FilterType::Pointer filter = FilterType::New(); // cast to itk mitk::Image::Pointer mitkImg = dynamic_cast(m_ImageNodes.at(0)->GetData()); mitk::Geometry3D::Pointer geom = mitkImg->GetGeometry(); typedef mitk::ImageToItk< FilterType::InputImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImg); caster->Update(); FilterType::InputImageType::Pointer itkImg = caster->GetOutput(); filter->SetInputImage(itkImg); filter->GenerateData(); mitk::Vector3D outImageSpacing = geom->GetSpacing(); float maxSpacing = 1; if(outImageSpacing[0]>outImageSpacing[1] && outImageSpacing[0]>outImageSpacing[2]) maxSpacing = outImageSpacing[0]; else if (outImageSpacing[1] > outImageSpacing[2]) maxSpacing = outImageSpacing[1]; else maxSpacing = outImageSpacing[2]; mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle(); //directions->SetGeometry(geom); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(maxSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } typedef FilterType::DirectionImageContainerType DirectionImageContainerType; DirectionImageContainerType::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { ItkDirectionImage3DType::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } break; } } } void QmitkOdfMaximaExtractionView::GenerateImage() { if (!m_ImageNodes.empty()) GenerateDataFromDwi(); } void QmitkOdfMaximaExtractionView::StartTensor() { if (m_TensorImageNodes.empty()) return; typedef itk::DiffusionTensorPrincipalDirectionImageFilter< float, float > MaximaExtractionFilterType; MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); mitk::Geometry3D::Pointer geometry; try{ TensorImage::Pointer img = dynamic_cast(m_TensorImageNodes.at(0)->GetData()); ItkTensorImage::Pointer itkImage = ItkTensorImage::New(); CastToItkImage(img, itkImage); filter->SetInput(itkImage); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Tensor Principal Direction Extraction due to Image has wrong pixel type.", QMessageBox::Ok ); return; //throw e; } if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } if (m_Controls->m_NormalizationBox->currentIndex()==0) filter->SetNormalizeVectors(false); filter->Update(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { MaximaExtractionFilterType::OutputImageType::Pointer itkImg = filter->GetOutput(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_PrincipalDirection"; node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_TensorImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } template void QmitkOdfMaximaExtractionView::StartMaximaExtraction() { typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType; typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); switch (m_Controls->m_ToolkitBox->currentIndex()) { case 0: filter->SetToolkit(MaximaExtractionFilterType::FSL); break; case 1: filter->SetToolkit(MaximaExtractionFilterType::MRTRIX); break; default: filter->SetToolkit(MaximaExtractionFilterType::FSL); } mitk::Geometry3D::Pointer geometry; try{ Image::Pointer img = dynamic_cast(m_ImageNodes.at(0)->GetData()); typedef ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType; typename CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); filter->SetInput(caster->GetOutput()); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); QMessageBox::warning( NULL, "Wrong pixel type", "Could not perform Finite Differences Extraction due to Image has wrong pixel type.", QMessageBox::Ok ); return; //throw; } filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThreshold->value()*M_PI/180)); filter->SetClusteringThreshold(cos((float)m_Controls->m_ClusteringAngleBox->value()*M_PI/180)); filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value()); filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value()); filter->SetAbsolutePeakThreshold(m_Controls->m_AbsoluteThresholdBox->value()); if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } switch (m_Controls->m_NormalizationBox->currentIndex()) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } filter->Update(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { typedef typename MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer; typename ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { typename MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); node->SetVisibility(false); GetDataStorage()->Add(node); } } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node2 = DataNode::New(); node2->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node2->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node2); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::StartFiniteDiff() { if (m_ImageNodes.empty()) return; switch (m_Controls->m_ShOrderBox->currentIndex()) { case 0: StartMaximaExtraction<2>(); break; case 1: StartMaximaExtraction<4>(); break; case 2: StartMaximaExtraction<6>(); break; case 3: StartMaximaExtraction<8>(); break; case 4: StartMaximaExtraction<10>(); break; case 5: StartMaximaExtraction<12>(); break; } } void QmitkOdfMaximaExtractionView::GenerateDataFromDwi() { typedef itk::OdfMaximaExtractionFilter< float > MaximaExtractionFilterType; MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New(); mitk::Geometry3D::Pointer geometry; if (!m_ImageNodes.empty()) { try{ Image::Pointer img = dynamic_cast(m_ImageNodes.at(0)->GetData()); typedef ImageToItk< MaximaExtractionFilterType::CoefficientImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(img); caster->Update(); filter->SetShCoeffImage(caster->GetOutput()); geometry = img->GetGeometry(); } catch(itk::ExceptionObject &e) { MITK_INFO << "wrong image type: " << e.what(); return; } } else return; filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value()); filter->SetPeakThreshold(m_Controls->m_PeakThresholdBox->value()); if (!m_BinaryImageNodes.empty()) { ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New(); Image::Pointer mitkMaskImg = dynamic_cast(m_BinaryImageNodes.at(0)->GetData()); CastToItkImage(mitkMaskImg, itkMaskImage); filter->SetMaskImage(itkMaskImage); } switch (m_Controls->m_NormalizationBox->currentIndex()) { case 0: filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM); break; case 1: filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM); break; case 2: filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM); break; } filter->GenerateData(); ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage(); if (m_Controls->m_OutputDirectionImagesBox->isChecked()) { typedef MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer; ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer(); for (int i=0; iSize(); i++) { MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk( itkImg.GetPointer() ); img->SetVolume( itkImg->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(img); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_Direction"; name += QString::number(i+1); node->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node); } } if (m_Controls->m_OutputNumDirectionsBox->isChecked()) { mitk::Image::Pointer image2 = mitk::Image::New(); image2->InitializeByItk( numDirImage.GetPointer() ); image2->SetVolume( numDirImage->GetBufferPointer() ); DataNode::Pointer node = DataNode::New(); node->SetData(image2); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_NumDirections"; node->SetName(name.toStdString().c_str()); GetDataStorage()->Add(node); } if (m_Controls->m_OutputVectorFieldBox->isChecked()) { mitk::Vector3D outImageSpacing = geometry->GetSpacing(); float minSpacing = 1; if(outImageSpacing[0]GetOutputFiberBundle(); // directions->SetGeometry(geometry); DataNode::Pointer node = DataNode::New(); node->SetData(directions); QString name(m_ImageNodes.at(0)->GetName().c_str()); name += "_VectorField"; node->SetName(name.toStdString().c_str()); node->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(minSpacing)); node->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(false)); GetDataStorage()->Add(node); } } void QmitkOdfMaximaExtractionView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkOdfMaximaExtractionView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkOdfMaximaExtractionView::OnSelectionChanged( std::vector nodes ) { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_DwiFibLabel->setText("mandatory"); m_Controls->m_MaskLabel->setText("optional"); m_BinaryImageNodes.clear(); m_ImageNodes.clear(); m_TensorImageNodes.clear(); // iterate all selected objects, adjust warning visibility for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_TensorImageNodes.push_back(node); } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) m_BinaryImageNodes.push_back(node); else m_ImageNodes.push_back(node); } } UpdateGui(); }