diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.cpp new file mode 100644 index 0000000000..b166ffabd5 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.cpp @@ -0,0 +1,324 @@ +/*=================================================================== + +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. + +===================================================================*/ +/*========================================================================= + +Program: Tensor ToolKit - TTK +Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $ +Language: C++ +Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $ +Version: $Revision: 68 $ + +Copyright (c) INRIA 2010. All rights reserved. +See LICENSE.txt for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef _itk_MultiShellAdcAverageReconstructionImageFilter_cpp_ +#define _itk_MultiShellAdcAverageReconstructionImageFilter_cpp_ +#endif + +#define _USE_MATH_DEFINES + +#include "itkMultiShellAdcAverageReconstructionImageFilter.h" +#include +#include +#include "mitkDiffusionFunctionCollection.h" + +namespace itk +{ + +template +MultiShellAdcAverageReconstructionImageFilter +::MultiShellAdcAverageReconstructionImageFilter() +{ + this->SetNumberOfRequiredInputs( 1 ); + // this->SetNumberOfThreads(1); +} + +template +void MultiShellAdcAverageReconstructionImageFilter +::BeforeThreadedGenerateData() +{ + + // test whether BvalueMap contains all necessary information + if(m_BValueMap.size() == 0) + { + itkWarningMacro(<< "No BValueMap given: create one using GradientDirectionContainer"); + + GradientDirectionContainerType::ConstIterator gdcit; + for( gdcit = m_OriginalGradientDirections->Begin(); gdcit != m_OriginalGradientDirections->End(); ++gdcit) + { + double bValueKey = int(((m_BValue * gdcit.Value().two_norm() * gdcit.Value().two_norm())+7.5)/10)*10; + m_BValueMap[bValueKey].push_back(gdcit.Index()); + } + } + + //# BValueMap contains no bZero --> itkException + if(m_BValueMap.find(0.0) == m_BValueMap.end()) + { + MITK_INFO << "No ReferenceSignal (BZeroImages) found!"; + itkExceptionMacro(<< "No ReferenceSignal (BZeroImages) found!"); + } + + // [allDirectionsContainer] Gradient DirectionContainer containing all unique directions + m_allDirectionsIndicies = mitk::gradients::GetAllUniqueDirections(m_BValueMap, m_OriginalGradientDirections); + // [sizeAllDirections] size of GradientContainer cointaining all unique directions + m_allDirectionsSize = m_allDirectionsIndicies.size(); + + m_TargetGradientDirections = mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(m_BValueMap,m_OriginalGradientDirections); + + + for(BValueMap::const_iterator it = m_BValueMap.begin();it != m_BValueMap.end(); it++) + { + if((*it).first == 0.0) continue; + // if any #ShellDirection < 15 --> itkException (No interpolation possible) + if((*it).second.size() < 15){ + MITK_INFO << "Abort: No interpolation possible Shell-" << (*it).first << " has less than 15 directions."; + itkExceptionMacro(<<"No interpolation possible"); + } + } + m_ShellInterpolationMatrixVector.reserve(m_BValueMap.size()-1); + + // for each shell + BValueMap::const_iterator it = m_BValueMap.begin(); + + it++; //skip bZeroIndices + + for(;it != m_BValueMap.end();it++) + { + //- calculate maxShOrder + const IndicesVector currentShell = it->second; + unsigned int SHMaxOrder = 12; + while( ((SHMaxOrder+1)*(SHMaxOrder+2)/2) > currentShell.size()) + { + SHMaxOrder -= 2 ; + } + //- get TragetSHBasis using allDirectionsContainer + vnl_matrix sphericalCoordinates; + sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(m_allDirectionsIndicies, m_OriginalGradientDirections); + vnl_matrix TargetSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder); + //MITK_INFO << "TargetSHBasis " << TargetSHBasis.rows() << " x " << TargetSHBasis.cols(); + //- get ShellSHBasis using currentShellDirections + sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(currentShell, m_OriginalGradientDirections); + vnl_matrix ShellSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder); + //MITK_INFO << "ShellSHBasis " << ShellSHBasis.rows() << " x " << ShellSHBasis.cols(); + //- calculate interpolationSHBasis [TargetSHBasis * ShellSHBasis^-1] + vnl_matrix_inverse invShellSHBasis(ShellSHBasis); + vnl_matrix shellInterpolationMatrix = TargetSHBasis * invShellSHBasis.pinverse(); + //MITK_INFO << "shellInterpolationMatrix " << shellInterpolationMatrix.rows() << " x " << shellInterpolationMatrix.cols(); + //- save interpolationSHBasis + m_ShellInterpolationMatrixVector.push_back(shellInterpolationMatrix); + + } + + m_WeightsVector.reserve(m_BValueMap.size()-1); + BValueMap::const_iterator itt = m_BValueMap.begin(); + itt++; // skip ReferenceImages + //- calculate Weights [Weigthing = shell_size / max_shell_size] + unsigned int maxShellSize = 0; + for(;itt != m_BValueMap.end(); itt++){ + if(itt->second.size() > maxShellSize) + maxShellSize = itt->second.size(); + } + itt = m_BValueMap.begin(); + itt++; // skip ReferenceImages + for(;itt != m_BValueMap.end(); itt++){ + m_WeightsVector.push_back(itt->second.size() / (double)maxShellSize); + MITK_INFO << m_WeightsVector.back(); + } + + + // initialize output image + typename OutputImageType::Pointer outImage = static_cast(ProcessObject::GetOutput(0)); + //outImage = OutputImageType::New(); + outImage->SetSpacing( this->GetInput()->GetSpacing() ); + outImage->SetOrigin( this->GetInput()->GetOrigin() ); + outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction using bZeroDirection+AllDirectionsContainer + outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion()); + outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() ); + outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() ); + outImage->SetVectorLength( 1+m_allDirectionsSize ); // size of 1(bzeroValue) + AllDirectionsContainer + outImage->Allocate(); + + BValueMap::iterator ittt = m_BValueMap.begin(); + ittt++; // skip bZeroImages corresponding to 0-bValue + m_TargetBValue = 0; + while(ittt!=m_BValueMap.end()) + { + m_TargetBValue += ittt->first; + ittt++; + } + m_TargetBValue /= (double)(m_BValueMap.size()-1); + + + MITK_INFO << "Input:" << std::endl << std::endl + << " GradientDirections: " << m_OriginalGradientDirections->Size() << std::endl + << " Shells: " << (m_BValueMap.size() - 1) << std::endl + << " ReferenceImages: " << m_BValueMap.at(0.0).size() << std::endl; + + MITK_INFO << "Output:" << std::endl << std::endl + << " OutImageVectorLength: " << outImage->GetVectorLength() << std::endl + << " TargetDirections: " << m_allDirectionsSize << std::endl + << " TargetBValue: " << m_TargetBValue << std::endl + << std::endl; + +} + +template +void +MultiShellAdcAverageReconstructionImageFilter +::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType /*threadId*/) +{ + + // Get input gradient image pointer + typename InputImageType::Pointer inputImage = static_cast< InputImageType * >(ProcessObject::GetInput(0)); + // ImageRegionIterator for the input image + ImageRegionIterator< InputImageType > iit(inputImage, outputRegionForThread); + iit.GoToBegin(); + + // Get output gradient image pointer + typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(ProcessObject::GetOutput(0)); + // ImageRegionIterator for the output image + ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); + oit.GoToBegin(); + + // calculate target bZero-Value [b0_t] + const IndicesVector BZeroIndices = m_BValueMap[0.0]; + double BZeroAverage = 0.0; + + // create empty nxm SignalMatrix containing n->signals/directions (in case of interpolation ~ sizeAllDirections otherwise the size of any shell) for m->shells + vnl_matrix SignalMatrix(m_allDirectionsSize, m_BValueMap.size()-1); + // create nx1 targetSignalVector + vnl_vector SignalVector(m_allDirectionsSize); + + + // ** walking over each Voxel + while(!iit.IsAtEnd()) + { + InputPixelType b = iit.Get(); + BZeroAverage=0.0; + for(unsigned int i = 0 ; i < BZeroIndices.size(); i++){ + //MITK_INFO << "BValues("<second; + vnl_vector InterpVector(currentShell.size()); + + // - get raw Signal for currente shell + for(unsigned int i = 0 ; i < currentShell.size(); i++) + InterpVector.put(i,b[currentShell[i]]); + //MITK_INFO << "InputVector(RAWSIGNAL:"<< shellIndex <<")"; + //MITK_INFO << InterpVector ; + //- normalization of the raw Signal + S_S0Normalization(InterpVector, BZeroAverage); + //MITK_INFO << "InputVector(NORMALIZED:"<< shellIndex <<")"; + //MITK_INFO << InterpVector ; + //- interpolate the Signal if necessary using corresponding interpolationSHBasis + + SignalVector = m_ShellInterpolationMatrixVector.at(shellIndex) * InterpVector; + + //MITK_INFO << "SignalVector(NORMALIZED:"<< shellIndex <<")"; + //MITK_INFO << SignalVector ; + + // - ADC calculation for the signalVector + calculateAdcFromSignal(SignalVector, shellIterator->first); + //MITK_INFO << "SignalVector(SIGNaL->ADC:"<< shellIndex <<")"; + //MITK_INFO << SignalVector ; + + //- weight the signal + SignalVector *= m_WeightsVector.at(shellIndex); + + //- save the (interpolated) ShellSignalVector as the ith column in the SignalMatrix + SignalMatrix.set_column(shellIndex, SignalVector); + + shellIterator++; + shellIndex++; + + } + // ADC averaging Sum(ADC)/n + for(unsigned int i = 0 ; i < SignalMatrix.rows(); i++) + SignalVector.put(i,SignalMatrix.get_row(i).sum()); + SignalVector/= (double)(m_BValueMap.size()-1); + //MITK_INFO << "SignalVector(AVERAGEDADC)"; + //MITK_INFO << SignalVector ; + + // recalculate signal from ADC + calculateSignalFromAdc(SignalVector, m_TargetBValue, BZeroAverage); + //MITK_INFO << "SignalVector(ADC->SIGNAL)"; + //MITK_INFO << SignalVector ; + + for(unsigned int i = 1 ; i < out.Size(); i ++) + out.SetElement(i,SignalVector.get(i-1)); + + //MITK_INFO << "NewSignal: " << out; + //MITK_INFO << "-------------"; + oit.Set(out); + ++oit; + ++iit; + } +} +template +void MultiShellAdcAverageReconstructionImageFilter +::S_S0Normalization( vnl_vector & vec, const double & S0 ) +{ + for(unsigned int i = 0; i < vec.size(); i++){ + vec[i] /= S0; + if(vec[i]>1.0) vec[i] = 1; + if(vec[i]<0.0) vec[i] = 0; + } +} + +template +void MultiShellAdcAverageReconstructionImageFilter +::calculateAdcFromSignal( vnl_vector & vec, const double & bValue) +{ + for(unsigned int i = 0; i < vec.size(); i++) + vec[i] = log(vec[i])/-bValue; +} + +template +void MultiShellAdcAverageReconstructionImageFilter +::calculateSignalFromAdc(vnl_vector & vec, const double & bValue, const double & referenceSignal) +{ + for(unsigned int i = 0 ; i < vec.size(); i++){ + //MITK_INFO << vec[i]; + //MITK_INFO << bValue; + //MITK_INFO << referenceSignal; + vec[i] = referenceSignal * exp((-bValue) * vec[i]); + } +} + +} // end of namespace diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.h new file mode 100644 index 0000000000..030c651fb8 --- /dev/null +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.h @@ -0,0 +1,117 @@ +/*=================================================================== + +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 _itk_MultiShellAdcAverageReconstructionImageFilter_h_ +#define _itk_MultiShellAdcAverageReconstructionImageFilter_h_ + +#include +#include +#include + +namespace itk +{ + +/** +* \brief Select subset of the input vectors equally distributed over the sphere using an iterative electrostatic repulsion strategy. */ + + template + class MultiShellAdcAverageReconstructionImageFilter + : public ImageToImageFilter, itk::VectorImage > + { + + public: + + typedef MultiShellAdcAverageReconstructionImageFilter Self; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef ImageToImageFilter< itk::VectorImage, itk::VectorImage > Superclass; + typedef typename Superclass::OutputImageRegionType OutputImageRegionType; + + /** Method for creation through the object factory. */ + itkNewMacro(Self) + + /** Runtime information support. */ + itkTypeMacro(MultiShellAdcAverageReconstructionImageFilter, ImageToImageFilter) + + typedef TInputScalarType InputScalarType; + typedef itk::VectorImage InputImageType; + typedef typename InputImageType::PixelType InputPixelType; + + typedef TOutputScalarType OutputScalarType; + typedef itk::VectorImage OutputImageType; + typedef typename OutputImageType::PixelType OutputPixelType; + + typedef OutputScalarType BaselineScalarType; + typedef BaselineScalarType BaselinePixelType; + typedef typename itk::Image BaselineImageType; + + typedef vnl_vector_fixed< double, 3 > GradientDirectionType; + typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; + + typedef std::vector IndicesVector; + typedef std::map BValueMap; + + itkGetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer) + itkSetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer) + + itkGetMacro(TargetGradientDirections, GradientDirectionContainerType::Pointer) + itkGetMacro(TargetBValue, float) + + itkGetMacro(BValue,float) + itkSetMacro(BValue,float) + inline void SetOriginalBValueMap(BValueMap inp){m_BValueMap = inp;} + + protected: + MultiShellAdcAverageReconstructionImageFilter(); + ~MultiShellAdcAverageReconstructionImageFilter() {} + + void BeforeThreadedGenerateData(); + void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType NumberOfThreads ); + void S_S0Normalization( vnl_vector & vec, const double & S0 ); + void calculateAdcFromSignal( vnl_vector & vec, const double & bValue); + void calculateSignalFromAdc( vnl_vector & vec, const double & bValue, const double & referenceSignal); + + + + GradientDirectionContainerType::Pointer m_TargetGradientDirections; ///< container for the subsampled output gradient directions + GradientDirectionContainerType::Pointer m_OriginalGradientDirections; ///< input gradient directions + + BValueMap m_BValueMap; + double m_BValue; + + double m_TargetBValue; + + std::vector m_WeightsVector; + + std::vector > m_ShellInterpolationMatrixVector; + std::vector m_bZeroIndicesSplitVectors; + + IndicesVector m_allDirectionsIndicies; + + unsigned int m_allDirectionsSize; + + }; + + +} // end of namespace + + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkMultiShellAdcAverageReconstructionImageFilter.cpp" +#endif + + +#endif diff --git a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx index afb1972fad..4778589dae 100644 --- a/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx +++ b/Modules/DiffusionImaging/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.txx @@ -1,430 +1,430 @@ /*=================================================================== 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" template mitk::DiffusionImage::DiffusionImage() : m_VectorImage(0), m_Directions(0), m_OriginalDirections(0), m_B_Value(-1.0), m_VectorImageAdaptor(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() { // 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 = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); 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 = itw.Begin(); itk::ImageRegionConstIterator itr (m_VectorImage, m_VectorImage->GetLargestPossibleRegion() ); itr = itr.Begin(); 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++; } UpdateBValueList(); 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 number of not diffusion weighted images template int mitk::DiffusionImage::GetNumB0() { int b0 = 0; for (int i=0; iSize(); i++) if (GetB_Value(i)<=0) { b0++; } return b0; } // returns a list of indices belonging to the not diffusion weighted images template typename mitk::DiffusionImage::IndicesVector mitk::DiffusionImage::GetB0Indices() { IndicesVector indices; for (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::UpdateBValueList() { m_B_ValueMap.clear(); GradientDirectionContainerType::ConstIterator gdcit; for( gdcit = this->m_Directions->Begin(); gdcit != this->m_Directions->End(); ++gdcit) { float currentBvalue = std::floor(GetB_Value(gdcit.Index())); - double rounded = int((currentBvalue+7.5)/10)*10; + double rounded = int((currentBvalue+7.5)/100)*100; m_B_ValueMap[rounded].push_back(gdcit.Index()); } /* BValueMap::iterator it = m_B_ValueMap.begin(); for(;it != m_B_ValueMap.end(); it++) { MITK_INFO << it->first << " : " << it->second.size(); } */ } template float mitk::DiffusionImage::GetB_Value(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(); return m_B_Value*twonorm*twonorm ; } } template void mitk::DiffusionImage::SetDirections(const std::vector > directions) { m_OriginalDirections = GradientDirectionContainerType::New(); for(unsigned int i=0; iInsertElement( i, directions[i].Get_vnl_vector() ); } 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::UpdateBValueList); } template void mitk::DiffusionImage::RemoveDirectionsContainerObserver() { if(m_Directions){ m_Directions->RemoveAllObservers(); } } diff --git a/Modules/DiffusionImaging/DiffusionCore/files.cmake b/Modules/DiffusionImaging/DiffusionCore/files.cmake index 07866a8d47..44d1bfa51a 100644 --- a/Modules/DiffusionImaging/DiffusionCore/files.cmake +++ b/Modules/DiffusionImaging/DiffusionCore/files.cmake @@ -1,116 +1,117 @@ set(CPP_FILES # DicomImport DicomImport/mitkDicomDiffusionImageReader.cpp # DicomImport/mitkGroupDiffusionHeadersFilter.cpp DicomImport/mitkDicomDiffusionImageHeaderReader.cpp DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp # DataStructures IODataStructures/mitkDiffusionCoreObjectFactory.cpp # DataStructures -> DWI IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSource.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageReader.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriter.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageIOFactory.cpp IODataStructures/DiffusionWeightedImages/mitkNrrdDiffusionImageWriterFactory.cpp IODataStructures/DiffusionWeightedImages/mitkDiffusionImageSerializer.cpp # DataStructures -> QBall IODataStructures/QBallImages/mitkQBallImageSource.cpp IODataStructures/QBallImages/mitkNrrdQBallImageReader.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriter.cpp IODataStructures/QBallImages/mitkNrrdQBallImageIOFactory.cpp IODataStructures/QBallImages/mitkNrrdQBallImageWriterFactory.cpp IODataStructures/QBallImages/mitkQBallImage.cpp IODataStructures/QBallImages/mitkQBallImageSerializer.cpp # DataStructures -> Tensor IODataStructures/TensorImages/mitkTensorImageSource.cpp IODataStructures/TensorImages/mitkNrrdTensorImageReader.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp IODataStructures/TensorImages/mitkNrrdTensorImageIOFactory.cpp IODataStructures/TensorImages/mitkNrrdTensorImageWriterFactory.cpp IODataStructures/TensorImages/mitkTensorImage.cpp IODataStructures/TensorImages/mitkTensorImageSerializer.cpp # Rendering Rendering/vtkMaskedProgrammableGlyphFilter.cpp Rendering/mitkCompositeMapper.cpp Rendering/mitkVectorImageVtkGlyphMapper3D.cpp Rendering/vtkOdfSource.cxx Rendering/vtkThickPlane.cxx Rendering/mitkOdfNormalizationMethodProperty.cpp Rendering/mitkOdfScaleByProperty.cpp Rendering/mitkPlanarFigureMapper3D.cpp # Algorithms Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp # Function Collection mitkDiffusionFunctionCollection.cpp ) set(H_FILES # function Collection mitkDiffusionFunctionCollection.h # Rendering Rendering/mitkDiffusionImageMapper.h Rendering/mitkOdfVtkMapper2D.h Rendering/mitkPlanarFigureMapper3D.h # Reconstruction Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h Algorithms/Reconstruction/itkPointShell.h Algorithms/Reconstruction/itkOrientationDistributionFunction.h Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h + Algorithms/Reconstruction/itkMultiShellAdcAverageReconstructionImageFilter.h # IO Datastructures IODataStructures/DiffusionWeightedImages/mitkDiffusionImage.h # Algorithms Algorithms/itkDiffusionQballGeneralizedFaImageFilter.h Algorithms/itkDiffusionQballPrepareVisualizationImageFilter.h Algorithms/itkTensorDerivedMeasurementsFilter.h Algorithms/itkBrainMaskExtractionImageFilter.h Algorithms/itkB0ImageExtractionImageFilter.h Algorithms/itkB0ImageExtractionToSeparateImageFilter.h Algorithms/itkTensorImageToDiffusionImageFilter.h Algorithms/itkTensorToL2NormImageFilter.h Algorithms/itkGaussianInterpolateImageFunction.h Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h Algorithms/itkCartesianToPolarVectorImageFilter.h Algorithms/itkPolarToCartesianVectorImageFilter.h Algorithms/itkDistanceMapFilter.h Algorithms/itkProjectionFilter.h Algorithms/itkResidualImageFilter.h Algorithms/itkExtractChannelFromRgbaImageFilter.h Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h Algorithms/itkMergeDiffusionImagesFilter.h Algorithms/itkDwiPhantomGenerationFilter.h Algorithms/itkFiniteDiffOdfMaximaExtractionFilter.h Algorithms/itkMrtrixPeakImageConverter.h Algorithms/itkFslPeakImageConverter.h Algorithms/itkShCoefficientImageImporter.h Algorithms/itkOdfMaximaExtractionFilter.h Algorithms/itkResampleDwiImageFilter.h ) set( TOOL_FILES ) diff --git a/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.cpp b/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.cpp index 9e9ba9054f..783fe353e6 100644 --- a/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.cpp @@ -1,93 +1,249 @@ /*=================================================================== 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 "mitkDiffusionFunctionCollection.h" #include #include "mitkVector.h" // for Windows #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // Namespace ::SH #include #include #include -// Namespace ::vnl_function + +// Namespace ::Gradients +#include "itkVectorContainer.h" #include "vnl/vnl_vector.h" //------------------------- SH-function ------------------------------------ double mitk::sh::factorial(int number) { - if(number <= 1) return 1; - double result = 1.0; - for(int i=1; i<=number; i++) - result *= i; - return result; + if(number <= 1) return 1; + double result = 1.0; + for(int i=1; i<=number; i++) + result *= i; + return result; } void mitk::sh::Cart2Sph(double x, double y, double z, double *cart) { - double phi, th, rad; - rad = sqrt(x*x+y*y+z*z); - if( rad < mitk::eps ) - { - th = M_PI/2; - phi = M_PI/2; - } - else - { - th = acos(z/rad); - phi = atan2(y, x); - } - cart[0] = phi; - cart[1] = th; - cart[2] = rad; + double phi, th, rad; + rad = sqrt(x*x+y*y+z*z); + if( rad < mitk::eps ) + { + th = M_PI/2; + phi = M_PI/2; + } + else + { + th = acos(z/rad); + phi = atan2(y, x); + } + cart[0] = phi; + cart[1] = th; + cart[2] = rad; } double mitk::sh::legendre0(int l) { - if( l%2 != 0 ) - { - return 0; - } - else - { - double prod1 = 1.0; - for(int i=1;i mitk::gradients::GetAllUniqueDirections(const std::map > & refBValueMap, GradientDirectionContainerType *refGradientsContainer ) +{ + + IndiciesVector directioncontainer; + BValueMap::const_iterator mapIterator = refBValueMap.begin(); + + if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) + mapIterator++; //skip bzero Values + + for( ; mapIterator != refBValueMap.end(); mapIterator++){ + + IndiciesVector currentShell = mapIterator->second; + + while(currentShell.size()>0) + { + unsigned int wntIndex = currentShell.back(); + currentShell.pop_back(); + + IndiciesVector::iterator containerIt = directioncontainer.begin(); + bool directionExist = false; + while(containerIt != directioncontainer.end()) + { + if (fabs(dot(refGradientsContainer->ElementAt(*containerIt), refGradientsContainer->ElementAt(wntIndex))) > 0.9998) + { + directionExist = true; + break; + } + containerIt++; + } + if(!directionExist) + { + directioncontainer.push_back(wntIndex); + } + } + } + + return directioncontainer; +} + + +bool mitk::gradients::CheckForDifferingShellDirections(const std::map > & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer) +{ + BValueMap::const_iterator mapIterator = refBValueMap.begin(); + + if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) + mapIterator++; //skip bzero Values + + for( ; mapIterator != refBValueMap.end(); mapIterator++){ + + BValueMap::const_iterator mapIterator_2 = refBValueMap.begin(); + if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) + mapIterator_2++; //skip bzero Values + + for( ; mapIterator_2 != refBValueMap.end(); mapIterator_2++){ + + if(mapIterator_2 == mapIterator) continue; + + IndiciesVector currentShell = mapIterator->second; + IndiciesVector testShell = mapIterator_2->second; + for (unsigned int i = 0; i< currentShell.size(); i++) + if (fabs(dot(refGradientsContainer->ElementAt(currentShell[i]), refGradientsContainer->ElementAt(testShell[i]))) <= 0.9998) { return true; } + + } + } + return false; +} + + +template +double mitk::gradients::dot (vnl_vector_fixed< type ,3> const& v1, vnl_vector_fixed< type ,3 > const& v2 ) +{ + double result = (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (v1.two_norm() * v2.two_norm()); + return result ; +} + +vnl_matrix mitk::gradients::ComputeSphericalFromCartesian(const IndiciesVector & refShell, GradientDirectionContainerType::Pointer refGradientsContainer) +{ + + vnl_matrix Q(3, refShell.size()); + + for(unsigned int i = 0; i < refShell.size(); i++) + { + double x = refGradientsContainer->ElementAt(refShell[i]).normalize().get(0); + double y = refGradientsContainer->ElementAt(refShell[i]).normalize().get(1); + double z = refGradientsContainer->ElementAt(refShell[i]).normalize().get(2); + double cart[3]; + mitk::sh::Cart2Sph(x,y,z,cart); + Q(0,i) = cart[0]; + Q(1,i) = cart[1]; + Q(2,i) = cart[2]; + } + return Q; +} + +vnl_matrix mitk::gradients::ComputeSphericalHarmonicsBasis(const vnl_matrix & QBallReference, const unsigned int & LOrder) +{ + vnl_matrix SHBasisOutput(QBallReference.cols(), (LOrder+1)*(LOrder+2)*0.5); + for(unsigned int i=0; i< SHBasisOutput.rows(); i++) + for(int k = 0; k <= LOrder; k += 2) + for(int m =- k; m <= k; m++) + { + int j = ( k * k + k + 2 ) / 2 + m - 1; + double phi = QBallReference(0,i); + double th = QBallReference(1,i); + SHBasisOutput(i,j) = mitk::sh::Yj(m,k,th,phi); + } + return SHBasisOutput; +} + +mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer( + const mitk::gradients::BValueMap & bValueMap, + mitk::gradients::GradientDirectionContainerType::Pointer origninalGradentcontainer) +{ + mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New(); + BValueMap::const_iterator mapIterator = bValueMap.begin(); + + if(bValueMap.find(0) != bValueMap.end() && bValueMap.size() > 1){ + mapIterator++; //skip bzero Values + vnl_vector_fixed vec; + vec.fill(0.0); + directioncontainer->push_back(vec); + } + + for( ; mapIterator != bValueMap.end(); mapIterator++){ + + IndiciesVector currentShell = mapIterator->second; + + while(currentShell.size()>0) + { + unsigned int wntIndex = currentShell.back(); + currentShell.pop_back(); + + mitk::gradients::GradientDirectionContainerType::Iterator containerIt = directioncontainer->Begin(); + bool directionExist = false; + while(containerIt != directioncontainer->End()) + { + if (fabs(dot(containerIt.Value(), origninalGradentcontainer->ElementAt(wntIndex))) > 0.9998) + { + directionExist = true; + break; + } + containerIt++; + } + if(!directionExist) + { + directioncontainer->push_back(origninalGradentcontainer->ElementAt(wntIndex).normalize()); + } + } + } + + return directioncontainer; +} diff --git a/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.h b/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.h index 8267c5cc9b..ffe98944ad 100644 --- a/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.h +++ b/Modules/DiffusionImaging/DiffusionCore/mitkDiffusionFunctionCollection.h @@ -1,39 +1,64 @@ /*=================================================================== 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 __mitkDiffusionFunctionCollection_h_ #define __mitkDiffusionFunctionCollection_h_ #include "DiffusionCoreExports.h" - +#include "vector.h" +#include "map.h" +#include "vnl/vnl_vector.h" +#include "vnl/vnl_vector_fixed.h" +#include "itkVectorContainer.h" namespace mitk{ class DiffusionCore_EXPORT sh { public: -static double factorial(int number); -static void Cart2Sph(double x, double y, double z, double* cart); -static double legendre0(int l); -static double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart); -static double Yj(int m, int k, double theta, double phi); + static double factorial(int number); + static void Cart2Sph(double x, double y, double z, double* cart); + static double legendre0(int l); + static double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart); + static double Yj(int m, int k, double theta, double phi); +}; + +class DiffusionCore_EXPORT gradients +{ +private: + typedef std::vector IndiciesVector; + typedef std::map BValueMap; + typedef itk::VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > > GradientDirectionContainerType; + +public: + static std::vector GetAllUniqueDirections(const std::map > & refBValueMap, GradientDirectionContainerType *refGradientsContainer ); + + static bool CheckForDifferingShellDirections(const std::map > & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer); + static vnl_matrix ComputeSphericalHarmonicsBasis(const vnl_matrix & QBallReference, const unsigned int & LOrder); + static vnl_matrix ComputeSphericalFromCartesian(const IndiciesVector & refShell, GradientDirectionContainerType::Pointer refGradientsContainer); + static mitk::gradients::GradientDirectionContainerType::Pointer CreateNormalizedUniqueGradientDirectionContainer(const BValueMap &bValueMap, mitk::gradients::GradientDirectionContainerType::Pointer origninalGradentcontainer); + + + template + static double dot (vnl_vector_fixed< type ,3> const& v1, vnl_vector_fixed< type ,3 > const& v2 ); }; + } #endif //__mitkDiffusionFunctionCollection_h_ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp index 87054f15a6..36b853feb7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp @@ -1,595 +1,636 @@ /*=================================================================== 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. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include #include +#include // mitk includes #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include #include const std::string QmitkPreprocessingView::VIEW_ID = "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; QmitkPreprocessingView::QmitkPreprocessingView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_DiffusionImage(NULL) { } QmitkPreprocessingView::QmitkPreprocessingView(const QmitkPreprocessingView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); } } void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkPreprocessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) ); + connect( (QObject*)(m_Controls->m_AdcAverage), SIGNAL(clicked()), this, SLOT(DoAdcAverage()) ); + } } +void QmitkPreprocessingView::DoAdcAverage() +{ + if (m_DiffusionImage.IsNull()) + return; + + typedef mitk::DiffusionImage DiffusionImageType; + typedef itk::MultiShellAdcAverageReconstructionImageFilter FilterType; + typedef DiffusionImageType::BValueMap BValueMap; + + BValueMap originalShellMap = m_DiffusionImage->GetB_ValueMap(); + + GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); + + FilterType::Pointer filter = FilterType::New(); + filter->SetInput(m_DiffusionImage->GetVectorImage()); + filter->SetOriginalGradientDirections(gradientContainer); + filter->SetOriginalBValueMap(originalShellMap); + filter->SetBValue(m_DiffusionImage->GetB_Value()); + filter->Update(); + + DiffusionImageType::Pointer image = DiffusionImageType::New(); + image->SetVectorImage( filter->GetOutput() ); + image->SetB_Value( filter->GetTargetBValue() ); + //image->SetOriginalDirections( filter->GetTargetGradientDirections() ); + image->SetDirections( filter->GetTargetGradientDirections() ); + //image->SetMeasurementFrame( m_DiffusionImage->GetMeasurementFrame() ); + image->InitializeFromVectorImage(); + + mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); + imageNode->SetData( image ); + QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); + + imageNode->SetName((name+"_averaged").toStdString().c_str()); + GetDefaultDataStorage()->Add(imageNode); + +} + + void QmitkPreprocessingView::OnSelectionChanged( std::vector nodes ) { bool foundDwiVolume = false; m_DiffusionImage = NULL; m_SelectedDiffusionNodes.clear(); // iterate selection for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast*>(node->GetData()) ) { foundDwiVolume = true; m_DiffusionImage = dynamic_cast*>(node->GetData()); m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_SelectedDiffusionNodes.push_back(node); } } m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume); m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume); m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume); - + m_Controls->m_AdcAverage->setEnabled(foundDwiVolume); foreach(QCheckBox * box, m_ReduceGradientCheckboxes) { m_Controls->m_ReductionFrame->layout()->removeWidget(box); delete box; } foreach(QSpinBox * box, m_ReduceGradientSpinboxes) { m_Controls->m_ReductionFrame->layout()->removeWidget(box); delete box; } m_ReduceGradientCheckboxes.clear(); m_ReduceGradientSpinboxes.clear(); if (foundDwiVolume) { m_Controls->m_InputData->setTitle("Input Data"); vnl_matrix_fixed< double, 3, 3 > mf = m_DiffusionImage->GetMeasurementFrame(); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } typedef mitk::DiffusionImage::BValueMap BValueMap; typedef mitk::DiffusionImage::BValueMap::iterator BValueMapIterator; BValueMap bValMap = m_DiffusionImage->GetB_ValueMap(); BValueMapIterator it = bValMap.begin(); m_Controls->m_BvalueTable->clear(); m_Controls->m_BvalueTable->setRowCount(bValMap.size() ); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_BvalueTable->setHorizontalHeaderLabels(headerList); QCheckBox* checkBox; QSpinBox* spinBox; int i = 0 ; for(;it != bValMap.end(); it++) { m_Controls->m_BvalueTable->setItem(i,0,new QTableWidgetItem(QString::number(it->first))); m_Controls->m_BvalueTable->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size()))); // Reduce Gradients GUI adaption if(it->first != 0 && bValMap.size() > 1){ checkBox = new QCheckBox(QString::number(it->first) + " with " + QString::number(it->second.size()) + " directions"); checkBox->setEnabled(true); checkBox->setChecked(true); checkBox->setCheckable(true); m_ReduceGradientCheckboxes.push_back(checkBox); m_Controls->m_ReductionFrame->layout()->addWidget(checkBox); spinBox = new QSpinBox(); spinBox->setValue(std::ceil((float)it->second.size()/2)); spinBox->setMaximum(it->second.size()); spinBox->setMinimum(0); m_ReduceGradientSpinboxes.push_back(spinBox); m_Controls->m_ReductionFrame->layout()->addWidget(spinBox); } i++; } } else { for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } m_Controls->m_BvalueTable->clear(); m_Controls->m_BvalueTable->setRowCount(1); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_BvalueTable->setHorizontalHeaderLabels(headerList); m_Controls->m_BvalueTable->setItem(0,0,new QTableWidgetItem("-")); m_Controls->m_BvalueTable->setItem(0,1,new QTableWidgetItem("-")); m_Controls->m_DiffusionImageLabel->setText("mandatory"); m_Controls->m_InputData->setTitle("Please Select Input Data"); } } void QmitkPreprocessingView::Activated() { QmitkFunctionality::Activated(); } void QmitkPreprocessingView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); for (int j=0; jSize(); j++) if (gradientContainer->at(j)[0]<0) gradientContainer->at(j) = -gradientContainer->at(j); m_DiffusionImage->SetDirections(gradientContainer); } void QmitkPreprocessingView::DoApplyMesurementFrame() { if (m_DiffusionImage.IsNull()) return; vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) return; mf[r][c] = item->text().toDouble(); } m_DiffusionImage->SetMeasurementFrame(mf); } void QmitkPreprocessingView::DoShowGradientDirections() { if (m_DiffusionImage.IsNull()) return; int maxIndex = 0; int maxSize = m_DiffusionImage->GetDimension(0); if (maxSizeGetDimension(1)) { maxSize = m_DiffusionImage->GetDimension(1); maxIndex = 1; } if (maxSizeGetDimension(2)) { maxSize = m_DiffusionImage->GetDimension(2); maxIndex = 2; } mitk::Point3D origin = m_DiffusionImage->GetGeometry()->GetOrigin(); mitk::PointSet::Pointer originSet = mitk::PointSet::New(); typedef mitk::DiffusionImage::BValueMap BValueMap; typedef mitk::DiffusionImage::BValueMap::iterator BValueMapIterator; BValueMap bValMap = m_DiffusionImage->GetB_ValueMap(); GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); mitk::Geometry3D::Pointer geometry = m_DiffusionImage->GetGeometry(); int shellCount = 1; for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it) { mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (int j=0; jsecond.size(); j++) { mitk::Point3D ip; vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]); if (v.magnitude()>mitk::eps) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2; pointset->InsertPoint(j, ip); } else if (originSet->IsEmpty()) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2; originSet->InsertPoint(j, ip); } } if (it->firstSetData(pointset); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); name += "_Shell_"; name += QString::number(it->first); node->SetName(name.toStdString().c_str()); node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); int b0 = shellCount%2; int b1 = 0; int b2 = 0; if (shellCount>4) b2 = 1; if (shellCount%4 >= 2) b1 = 1; node->SetProperty("color", mitk::ColorProperty::New(b2, b1, b0)); GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); shellCount++; } // add origin to datastorage mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(originSet); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); name += "_Origin"; node->SetName(name.toStdString().c_str()); node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); node->SetProperty("color", mitk::ColorProperty::New(1,1,1)); GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); } void QmitkPreprocessingView::DoReduceGradientDirections() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage DiffusionImageType; typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef DiffusionImageType::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; BValueMap originalShellMap = m_DiffusionImage->GetB_ValueMap(); std::vector newNumGradientDirections; int shellCounter = 0; foreach(QCheckBox * box , m_ReduceGradientCheckboxes) { if(box->isChecked()) { double BValue = (box->text().split(' ')).at(0).toDouble(); shellSlectionMap[BValue] = originalShellMap[BValue]; newNumGradientDirections.push_back(m_ReduceGradientSpinboxes.at(shellCounter)->value()); } shellCounter++; } if (newNumGradientDirections.empty()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(m_DiffusionImage->GetVectorImage()); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(newNumGradientDirections); filter->SetOriginalBValueMap(originalShellMap); filter->SetShellSelectionBValueMap(shellSlectionMap); filter->Update(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(m_DiffusionImage->GetB_Value()); image->SetDirections(filter->GetGradientDirections()); image->SetMeasurementFrame(m_DiffusionImage->GetMeasurementFrame()); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); foreach(QSpinBox* box, m_ReduceGradientSpinboxes) { name += "_"; name += QString::number(box->value()); } imageNode->SetName(name.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::MergeDwis() { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; if (m_SelectedDiffusionNodes.size()<2) return; typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); for (int i=0; i* >( m_SelectedDiffusionNodes.at(i)->GetData() ); if ( dwi.IsNotNull() ) { imageContainer.push_back(dwi->GetVectorImage()); gradientListContainer.push_back(dwi->GetDirections()); bValueContainer.push_back(dwi->GetB_Value()); if (i>0) { name += "+"; name += m_SelectedDiffusionNodes.at(i)->GetName().c_str(); } } } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(filter->GetB_Value()); image->SetDirections(filter->GetOutputGradients()); image->SetMeasurementFrame(mf); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); imageNode->SetName(name.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { // typedefs typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; // check number of selected objects, return if empty int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0_ALL")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::AverageGradients() { int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); vols->AverageRedundantGradients(m_Controls->m_Blur->value()); ++itemiter; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h index 7fa2503fce..0e25d361f8 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.h @@ -1,109 +1,110 @@ /*=================================================================== 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 _QMITKPREPROCESSINGVIEW_H_INCLUDED #define _QMITKPREPROCESSINGVIEW_H_INCLUDED #include #include #include "ui_QmitkPreprocessingViewControls.h" #include "mitkDiffusionImage.h" typedef short DiffusionPixelType; struct PrpSelListener; /*! * \ingroup org_mitk_gui_qt_preprocessing_internal * * \brief QmitkPreprocessingView * * Document your class here. * * \sa QmitkFunctionality */ class QmitkPreprocessingView : public QmitkFunctionality { friend struct PrpSelListener; // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; typedef vnl_vector_fixed< double, 3 > GradientDirectionType; typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; QmitkPreprocessingView(); QmitkPreprocessingView(const QmitkPreprocessingView& other); virtual ~QmitkPreprocessingView(); virtual void CreateQtPartControl(QWidget *parent); /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); /// \brief Called when the functionality is activated virtual void Activated(); virtual void Deactivated(); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); static const int nrconvkernels; protected slots: void AverageGradients(); void ExtractB0(); void MergeDwis(); void DoApplyMesurementFrame(); void DoReduceGradientDirections(); void DoShowGradientDirections(); void DoHalfSphereGradientDirections(); + void DoAdcAverage(); protected: /** Called by ExtractB0 if check-box activated, extracts all b0 images without averaging */ void DoExtractBOWithoutAveraging(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkPreprocessingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name); mitk::DiffusionImage::Pointer m_DiffusionImage; std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes; QList m_ReduceGradientCheckboxes; QList m_ReduceGradientSpinboxes; }; #endif // _QMITKPREPROCESSINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui index ee3586448e..5b4cb3ef19 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui @@ -1,567 +1,562 @@ QmitkPreprocessingViewControls 0 0 892 - 1080 + 1114 0 0 false QmitkPreprocessingViewControls true Please Select Input Data Raw DWI: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true 0 0 Info 0 0 Qt::ScrollBarAsNeeded Qt::ScrollBarAlwaysOff true 100 true false true b-Value Number of gradients Qt::Horizontal 40 20 false Generate pointset displaying the gradient vectors (applied measurement frame). Show gradients Non diffusion weighted image 0 30 Average and extract all images that were acquired without diffusion weighting. true false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Extract B0 Create a 3D+t data set containing all b0 images as timesteps Extract all B0 images without averaging Modify DWI QFrame::NoFrame QFrame::Raised - - 0 - - - 0 - - - 0 - - + 0 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. 6 2.000000000000000 0.000100000000000 0.001000000000000 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Merge radius false Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them by taking all directions within a certain radius into account. Average redundant gradients + + + + false + + + <html><head/><body><p>Create a new Diffusion Weighted Image (DWI) using an ADC average over all q-shells.</p></body></html> + + + ADC Average (Multi-Shell) + + + Qt::Horizontal QFrame::NoFrame QFrame::Raised - - 0 - - - 0 - - - 0 - - + 0 9 Specify desired number of gradients per shell: false Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere using an iterative energy repulsion strategy. Reduce number of gradients Qt::Horizontal false Sometimes the gradient directions are not located on one half sphere. Mirror gradients to half sphere Merge selected images false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Merge selected DWIs 0 0 Measurment frame Qt::Horizontal 40 20 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column false Apply new measurement frame Qt::Vertical 20 40