diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h index 3a2c95f769..10e2d15222 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h @@ -1,230 +1,232 @@ /*=================================================================== 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_TensorReconstructionWithEigenvalueCorrectionFilter_h_ #define _itk_TensorReconstructionWithEigenvalueCorrectionFilter_h_ #include "itkImageToImageFilter.h" #include #include #include #include namespace itk { template class TensorReconstructionWithEigenvalueCorrectionFilter : public ImageToImageFilter< itk::Image< TDiffusionPixelType, 3 >, itk::Image,3> > { public: typedef itk::VectorImage ImageType; typedef TensorReconstructionWithEigenvalueCorrectionFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< Image< TDiffusionPixelType, 3>, Image< DiffusionTensor3D< TTensorPixelType >, 3 > > Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(TensorReconstructionWithEigenvalueCorrectionFilter, ImageToImageFilter) + typedef typename itk::Image,3> OutputType; typedef TDiffusionPixelType GradientPixelType; typedef DiffusionTensor3D< TTensorPixelType > TensorPixelType; typedef Image< TensorPixelType, 3 > TensorImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; /** An alternative typedef defining one (of the many) gradient images. * It will be assumed that the vectorImage has the same dimension as the * Reference image and a vector length parameter of \c n (number of * gradient directions) */ typedef VectorImage< GradientPixelType, 3 > GradientImagesType; typedef typename GradientImagesType::PixelType GradientVectorType; /** Holds each magnetic field gradient used to acquire one DWImage */ typedef vnl_vector_fixed< double, 3 > GradientDirectionType; /** Container to hold gradient directions of the 'n' DW measurements */ typedef VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType; /** Another set method to add a gradient directions and its corresponding * image. The image here is a VectorImage. The user is expected to pass the * gradient directions in a container. The ith element of the container * corresponds to the gradient direction of the ith component image the * VectorImage. For the baseline image, a vector of all zeros * should be set. */ void SetGradientImage( GradientDirectionContainerType *, const GradientImagesType *image); + itkSetMacro( BValue, TTensorPixelType) /** Set the b0 threshold */ itkSetMacro( B0Threshold, double) /** Get the pseudeInverse that was calculated in the process of tensor estimation */ itkGetMacro(PseudoInverse, vnl_matrix) /** FIXME: added by Sebastian Wirkert due to compile error otherwise. */ itkGetMacro(CorrectedDiffusionVolumes, ImageType::Pointer) /** Outputs the design matrix that was calculated in the process of tensor estimation */ itkGetMacro(H, vnl_matrix) /** Outputs the normalized b-vector */ itkGetMacro(BVec, vnl_vector) /** Outputs the mask created by thresholding the B0 weighted volume*/ itkGetMacro(B0Mask, vnl_vector) /** Returns the dwi image volumes with smoothed voxels on positions were there were negative eigenvalues in the tensir*/ ImageType::Pointer GetGradientImagePointer() { return m_GradientImagePointer; } /** Get the mask image*/ itk::Image::Pointer GetMask() { return m_MaskImage; } protected: TensorReconstructionWithEigenvalueCorrectionFilter(); ~TensorReconstructionWithEigenvalueCorrectionFilter() {} void GenerateData(); typedef enum { GradientIsInASingleImage = 1, GradientIsInManyImages, Else } GradientImageTypeEnumeration; private: double CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size, itk::Image ::Pointer mask,typename GradientImagesType::Pointer corrected_diffusion_temp); /** Calculates the attenuation for a voxel*/ void CalculateAttenuation(vnl_vector org_data, vnl_vector &atten,int nof,int numberb0); /** Correct the diffusion data set for voxels that contain negative eigenvalues in the tensor*/ void CorrectDiffusionImage(int nof,int numberb0,itk::Size<3> size,typename GradientImagesType::Pointer corrected_diffusion,itk::Image::Pointer mask,vnl_vector< double> pixel_max,vnl_vector< double> pixel_min); /** Calculte a tensor iamge from a diffusion data set*/ void GenerateTensorImage(int nof,int numberb0,itk::Size<3> size,itk::VectorImage::Pointer corrected_diffusion,itk::Image::Pointer mask,double what_mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg ); //void DeepCopyTensorImage(itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg, itk::Image< itk::DiffusionTensor3D, 3 >::Pointer temp_tensorImg); //void DeepCopyDiffusionImage(itk::VectorImage::Pointer corrected_diffusion, itk::VectorImage::Pointer corrected_diffusion_temp,int nof); void TurnMask( itk::Size<3> size, itk::Image::Pointer mask, double previous_mask, double set_mask); double CheckNegatives ( itk::Size<3> size, itk::Image::Pointer mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg ); /** Gradient image was specified in a single image or in multiple images */ GradientImageTypeEnumeration m_GradientImageTypeEnumeration; /** Number of gradient measurements */ unsigned int m_NumberOfGradientDirections; /** container to hold gradient directions */ GradientDirectionContainerType::Pointer m_GradientDirectionContainer; /** b-value */ TTensorPixelType m_BValue; /** Number of baseline images */ unsigned int m_NumberOfBaselineImages; ImageType::Pointer m_CorrectedDiffusionVolumes; double m_B0Threshold; /** decodes what is to be done with every single voxel */ itk::Image::Pointer m_MaskImage; /** Pseudoinverse calculated in the process of calculating a tensor */ vnl_matrix m_PseudoInverse; /** design matrix */ vnl_matrix m_H; /** normalized b-vector */ vnl_vector m_BVec; /** m_B0Mask indicates whether a volume identified by an index is B0-weighted or not */ vnl_vector m_B0Mask; /** volumes of the diffusion data set */ typename GradientImagesType::Pointer m_GradientImagePointer; }; } // end of namespace #ifndef ITK_MANUAL_INSTANTIATION #include "itkTensorReconstructionWithEigenvalueCorrectionFilter.txx" #endif #endif diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx index 00f12b04e9..582b7ae4b9 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx @@ -1,1098 +1,994 @@ /*=================================================================== 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_TensorReconstructionWithEigenvalueCorrectionFilter_txx_ -#define _itk_TensorReconstructionWithEigenvalueCorrectioFiltern_txx_ +#define _itk_TensorReconstructionWithEigenvalueCorrectionFilter_txx_ #endif #include "itkImageRegionConstIterator.h" #include #include "itkImageFileWriter.h" #include "itkImage.h" #include "itkImageRegionIterator.h" - - namespace itk { +template +TensorReconstructionWithEigenvalueCorrectionFilter +::TensorReconstructionWithEigenvalueCorrectionFilter() +{ + m_B0Threshold = 50.0; +} - template - TensorReconstructionWithEigenvalueCorrectionFilter - ::TensorReconstructionWithEigenvalueCorrectionFilter() - { - m_B0Threshold = 50.0; - } - - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::GenerateData () - { +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::GenerateData () +{ - m_GradientImagePointer = static_cast< GradientImagesType * >( - this->ProcessObject::GetInput(0) ); + m_GradientImagePointer = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) ); - typename GradientImagesType::SizeType size = m_GradientImagePointer->GetLargestPossibleRegion().GetSize(); + typename GradientImagesType::SizeType size = m_GradientImagePointer->GetLargestPossibleRegion().GetSize(); - // number of volumes - int nof = m_GradientDirectionContainer->Size(); + // number of volumes + int nof = m_GradientDirectionContainer->Size(); - // determine the number of b-zero values - int numberb0=0; - for(int i=0; i vec = m_GradientDirectionContainer->ElementAt(i); + // due to roundings, the values are not always exactly zero + if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.0001&& vec[1]>-0.0001 && vec[2]>-0.0001) { - vnl_vector_fixed vec = m_GradientDirectionContainer->ElementAt(i); - - // due to roundings, the values are not always exactly zero - if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.0001&& vec[1]>-0.0001 && vec[2]>-0.0001) - { - numberb0++; - } + numberb0++; } + } - // Matrix to store all diffusion encoding gradients - vnl_matrix directions(nof-numberb0,3); + // Matrix to store all diffusion encoding gradients + vnl_matrix directions(nof-numberb0,3); - m_B0Mask.set_size(nof); + m_B0Mask.set_size(nof); - int cnt=0; - for(int i=0; i vec = m_GradientDirectionContainer->ElementAt(i); + int cnt=0; + for(int i=0; i vec = m_GradientDirectionContainer->ElementAt(i); - if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.0001&& vec[1]>-0.0001 && vec[2]>-0.0001) - { - // the diffusion encoding gradient is approximately zero, wo we are dealing with a non-diffusion weighted volume - m_B0Mask[i]=1; - } - else - { - // dealing with a diffusion weighted volume - m_B0Mask[i]=0; + if(vec[0]<0.0001 && vec[1]<0.0001 && vec[2]<0.0001 && vec[0]>-0.0001&& vec[1]>-0.0001 && vec[2]>-0.0001) + { + // the diffusion encoding gradient is approximately zero, wo we are dealing with a non-diffusion weighted volume + m_B0Mask[i]=1; + } + else + { + // dealing with a diffusion weighted volume + m_B0Mask[i]=0; - // set the diffusion encoding gradient to the directions matrix - directions[cnt][0] = vec[0]; - directions[cnt][1] = vec[1]; - directions[cnt][2] = vec[2]; + // set the diffusion encoding gradient to the directions matrix + directions[cnt][0] = vec[0]; + directions[cnt][1] = vec[1]; + directions[cnt][2] = vec[2]; - cnt++; - } + cnt++; } + } - // looking for maximal norm among gradients. - // The norm is calculated with use of spectral radius theorem- based on determination of eigenvalue. + // looking for maximal norm among gradients. + // The norm is calculated with use of spectral radius theorem- based on determination of eigenvalue. - vnl_matrix dirsTimesDirsTrans = directions*directions.transpose(); + vnl_matrix dirsTimesDirsTrans = directions*directions.transpose(); - vnl_vector< double> diagonal(nof-numberb0); - vnl_vector< double> b_vec(nof-numberb0); - vnl_vector< double> temporary(3); + vnl_vector< double> diagonal(nof-numberb0); + vnl_vector< double> b_vec(nof-numberb0); + vnl_vector< double> temporary(3); - for (int i=0;i H(nof-numberb0, 6); - vnl_matrix H_org(nof-numberb0, 6); - vnl_vector pre_tensor(9); + // Calculation of so called design matrix that is used to obtain expected signal. - //H is matrix that containes covariances for directions. It is stored twice because its original value is needed later - // while H is changed + vnl_matrix H(nof-numberb0, 6); + vnl_matrix H_org(nof-numberb0, 6); + vnl_vector pre_tensor(9); - int etbt[6] = { 0, 4, 8, 1, 5, 2 };// tensor order + //H is matrix that contains covariances for directions. It is stored twice because its original value is needed later + // while H is changed - for (int i = 0; i < nof-numberb0; i++) + int etbt[6] = { 0, 4, 8, 1, 5, 2 };// tensor order + + for (int i = 0; i < nof-numberb0; i++) + { + for (int j = 0; j < 3; j++) { - for (int j = 0; j < 3; j++) - { - temporary[j] = -directions[i][j]; - } - for (int j = 0; j < 3; j++) - { - for (int k = 0; k < 3; k++) - { - pre_tensor[k + 3 * j] = temporary[k] * directions[i][j]; - } - } - for (int j = 0; j < 6; j++) - { - H[i][j] = pre_tensor[etbt[j]]; - } - for (int j = 0; j < 3; j++) + temporary[j] = -directions[i][j]; + } + for (int j = 0; j < 3; j++) + { + for (int k = 0; k < 3; k++) { - H[i][3 + j] *= 2.0; + pre_tensor[k + 3 * j] = temporary[k] * directions[i][j]; } } + for (int j = 0; j < 6; j++) + { + H[i][j] = pre_tensor[etbt[j]]; + } + for (int j = 0; j < 3; j++) + { + H[i][3 + j] *= 2.0; + } + } - H_org=H; + H_org=H; - // calculation of inverse matrix by means of pseudoinverse + // calculation of inverse matrix by means of pseudoinverse - vnl_matrix inputtopseudoinverse=H.transpose()*H; - vnl_symmetric_eigensystem eig( inputtopseudoinverse); - vnl_matrix pseudoInverse = eig.pinverse()*H.transpose(); + vnl_matrix inputtopseudoinverse=H.transpose()*H; + vnl_symmetric_eigensystem eig( inputtopseudoinverse); + vnl_matrix pseudoInverse = eig.pinverse()*H.transpose(); - typedef itk::Image MaskImageType; - MaskImageType::Pointer mask = MaskImageType::New(); - mask->SetRegions(m_GradientImagePointer->GetLargestPossibleRegion().GetSize()); - mask->SetSpacing(m_GradientImagePointer->GetSpacing()); - mask->SetOrigin(m_GradientImagePointer->GetOrigin()); - mask->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction - mask->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - mask->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - mask->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - mask->Allocate(); + typedef itk::Image MaskImageType; + MaskImageType::Pointer mask = MaskImageType::New(); + mask->SetRegions(m_GradientImagePointer->GetLargestPossibleRegion().GetSize()); + mask->SetSpacing(m_GradientImagePointer->GetSpacing()); + mask->SetOrigin(m_GradientImagePointer->GetOrigin()); + mask->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction + mask->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + mask->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + mask->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + mask->Allocate(); - // Image thresholding: For every voxel mean B0 image is calculated and then voxels of mean B0 less than the - // treshold on the B0 image proviced by the userare excluded from the dataset with use of defined mask image. - // 1 in mask voxel means that B0 > assumed treshold. + // Image thresholding: For every voxel mean B0 image is calculated and then voxels of mean B0 less than the + // treshold on the B0 image proviced by the userare excluded from the dataset with use of defined mask image. + // 1 in mask voxel means that B0 > assumed treshold. - int mask_cnt=0; - for(unsigned int x=0;x ix = {{x,y,z}}; - + double mean_b=0.0; + itk::Index<3> ix = {{x,y,z}}; - GradientVectorType pixel = m_GradientImagePointer->GetPixel(ix); - for (int i=0;i m_B0Threshold) - { - mask->SetPixel(ix, 1); - mask_cnt++; - } - else + GradientVectorType pixel = m_GradientImagePointer->GetPixel(ix); + for (int i=0;iSetPixel(ix, 0); + mean_b = mean_b + pixel[i]; } - } - } - } - - //14.10.2013 - /* - - //create a copy of the original image- it is then used in pre-processing methods - - m_CorrectedDiffusionVolumes = ImageType::New(); - m_CorrectedDiffusionVolumes->SetRegions(size); - m_CorrectedDiffusionVolumes->SetSpacing(m_GradientImagePointer->GetSpacing()); - m_CorrectedDiffusionVolumes->SetOrigin(m_GradientImagePointer->GetOrigin()); - m_CorrectedDiffusionVolumes->SetVectorLength(nof); - m_CorrectedDiffusionVolumes->Allocate(); - - - - for ( int x=0;x m_B0Threshold) { - itk::Index<3> ix = {{x,y,z}}; - - GradientVectorType p = m_GradientImagePointer->GetPixel(ix); - - m_CorrectedDiffusionVolumes->SetPixel(ix,p); - + mask->SetPixel(ix, 1); + mask_cnt++; } + else + mask->SetPixel(ix, 0); } } + } - */ - - - - //Sometimes the gradient voxels may contain negative values ( even if B0 voxel is > = 50 ). This must be corrected by smoothing DWI - //Smoothing is done by aproximation of negative voxel value by its correct ( positive) 27-th neighborhood. - - - // typename TensorImageType::Pointer someimg; - // someimg = TensorImageType::New(); - - - - double mask_val=0.0; - vnl_vector org_vec(nof); + double mask_val=0.0; + vnl_vector org_vec(nof); - int counter_corrected =0; + int counter_corrected =0; - for (unsigned int x=0;x ix = {x,y,z}; + itk::Index<3> ix = {x,y,z}; - mask_val = mask->GetPixel(ix); + mask_val = mask->GetPixel(ix); - //14.10.2013 - //GradientVectorType pixel2 = m_CorrectedDiffusionVolumes->GetPixel(ix); + GradientVectorType pixel2 = m_GradientImagePointer->GetPixel(ix); - GradientVectorType pixel2 = m_GradientImagePointer->GetPixel(ix); - - for (int i=0;i0) + if(mask_val >0) + { + for( int f=0;fSetPixel(ix, pixel2); - m_GradientImagePointer->SetPixel(ix, pixel2); + for (int i=0;iSetPixel(ix, pixel2); - } } } } + } + typename TensorImageType::Pointer tensorImg; + tensorImg = TensorImageType::New(); + tensorImg->SetSpacing( m_GradientImagePointer->GetSpacing() ); // Set the image spacing + tensorImg->SetOrigin( m_GradientImagePointer->GetOrigin() ); // Set the image origin + tensorImg->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction + tensorImg->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + tensorImg->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + tensorImg->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); + tensorImg->Allocate(); + //Declaration of vectors that contains too high or too low atenuation for each gradient. Attenuation is only calculated for + //non B0 images so nof-numberb0. + vnl_vector< double> pixel_max(nof-numberb0); + vnl_vector< double> pixel_min(nof-numberb0); + // to high and to low attenuation is calculated with use of highest allowed =5 and lowest allowed =0.01 diffusion coefficient - typename TensorImageType::Pointer tensorImg; - tensorImg = TensorImageType::New(); - tensorImg->SetSpacing( m_GradientImagePointer->GetSpacing() ); // Set the image spacing - tensorImg->SetOrigin( m_GradientImagePointer->GetOrigin() ); // Set the image origin - tensorImg->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction - tensorImg->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - tensorImg->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - tensorImg->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() ); - tensorImg->Allocate(); - - //Declaration of vectors that contains too high or too low atenuation for each gradient. Attenuation is only calculated for - //non B0 images so nof-numberb0. + for (int i=0;i pixel_max(nof-numberb0); - vnl_vector< double> pixel_min(nof-numberb0); + m_PseudoInverse = pseudoInverse; + m_H = H_org; + m_BVec=b_vec; - // to high and to low attenuation is calculated with use of highest allowed =5 and lowest allowed =0.01 diffusion coefficient + // in preprocessing we are dealing with 3 types of voxels: voxels excluded = 0 in mask, voxels correct =1 and voxels under correction + //= 2. During pre processing most of voxels should be switched from 2 to 1. - for (int i=0;i outputIterator(tensorImg, tensorImg->GetLargestPossibleRegion()); + outputIterator.GoToBegin(); + while(!outputIterator.IsAtEnd()) + { + TensorPixelType tens = outputIterator.Get(); - // Generation of final pre-processed tensor image that might be used as an input for FWE method - //14.10.2013 - //GenerateTensorImage(nof,numberb0,size,m_CorrectedDiffusionVolumes,mask,what_mask,tensorImg); - GenerateTensorImage(nof,numberb0,size,m_GradientImagePointer,mask,what_mask,tensorImg); + tens/= 1000.0; - m_MaskImage = mask; + outputIterator.Set(tens); + ++outputIterator; + } - this->SetNthOutput(0, tensorImg); + this->SetNthOutput(0, tensorImg); +} - } +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::SetGradientImage( GradientDirectionContainerType *gradientDirection, + const GradientImagesType *gradientImage ) +{ - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::SetGradientImage( GradientDirectionContainerType *gradientDirection, - const GradientImagesType *gradientImage ) + if( m_GradientImageTypeEnumeration == GradientIsInManyImages ) { + itkExceptionMacro( << "Cannot call both methods:" + << "AddGradientImage and SetGradientImage. Please call only one of them."); + } - if( m_GradientImageTypeEnumeration == GradientIsInManyImages ) - { - itkExceptionMacro( << "Cannot call both methods:" - << "AddGradientImage and SetGradientImage. Please call only one of them."); - } - - this->m_GradientDirectionContainer = gradientDirection; - + this->m_GradientDirectionContainer = gradientDirection; - unsigned int numImages = gradientDirection->Size(); - this->m_NumberOfBaselineImages = 0; - this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages; + unsigned int numImages = gradientDirection->Size(); + this->m_NumberOfBaselineImages = 0; - // ensure that the gradient image we received has as many components as - // the number of gradient directions - if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + this->m_NumberOfGradientDirections ) - { - itkExceptionMacro( << this->m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages - << "baselines = " << this->m_NumberOfGradientDirections + this->m_NumberOfBaselineImages - << " directions specified but image has " << gradientImage->GetVectorLength() - << " components."); - } + this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages; - this->ProcessObject::SetNthInput( 0, - const_cast< GradientImagesType* >(gradientImage) ); - m_GradientImageTypeEnumeration = GradientIsInASingleImage; + // ensure that the gradient image we received has as many components as + // the number of gradient directions + if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + this->m_NumberOfGradientDirections ) + { + itkExceptionMacro( << this->m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages + << "baselines = " << this->m_NumberOfGradientDirections + this->m_NumberOfBaselineImages + << " directions specified but image has " << gradientImage->GetVectorLength() + << " components."); } - template - double - TensorReconstructionWithEigenvalueCorrectionFilter - ::CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size, itk::Image::Pointer mask, typename GradientImagesType::Pointer corrected_diffusion_temp) - { - // method is used for finding a new value for the voxel with use of its 27 neighborhood. To perform such a smoothing correct voxels are - // counted an arithmetical mean is calculated and stored as a new value for the voxel. If there is no proper neigborhood voxel is turned - // to the value of 0. + this->ProcessObject::SetNthInput( 0, + const_cast< GradientImagesType* >(gradientImage) ); + m_GradientImageTypeEnumeration = GradientIsInASingleImage; +} + +template +double +TensorReconstructionWithEigenvalueCorrectionFilter +::CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size, itk::Image::Pointer mask, typename GradientImagesType::Pointer corrected_diffusion_temp) +{ + // method is used for finding a new value for the voxel with use of its 27 neighborhood. To perform such a smoothing correct voxels are + // counted an arithmetical mean is calculated and stored as a new value for the voxel. If there is no proper neigborhood voxel is turned + // to the value of 0. - // Definition of neighbourhood avoiding crossing the image boundaries - int x_max=size[0]-1; - int y_max=size[1]-1; - int z_max=size[2]-1; + // Definition of neighbourhood avoiding crossing the image boundaries + int x_max=size[0]-1; + int y_max=size[1]-1; + int z_max=size[2]-1; - double back_x=std::max(0,x-1); - double back_y=std::max(0,y-1); - double back_z=std::max(0,z-1); + double back_x=std::max(0,x-1); + double back_y=std::max(0,y-1); + double back_z=std::max(0,z-1); - double forth_x=std::min((x+1),x_max); - double forth_y=std::min((y+1),y_max); - double forth_z=std::min((z+1),z_max); + double forth_x=std::min((x+1),x_max); + double forth_y=std::min((y+1),y_max); + double forth_z=std::min((z+1),z_max); - double tempsum=0; - double temp_number=0; + double tempsum=0; + double temp_number=0; - for(int i=back_x; i<=forth_x; i++) + for(int i=back_x; i<=forth_x; i++) + { + for (int j=back_y; j<=forth_y; j++) { - for (int j=back_y; j<=forth_y; j++) + for (int k=back_z; k<=forth_z; k++) { - for (int k=back_z; k<=forth_z; k++) - { - itk::Index<3> ix = {i,j,k}; + itk::Index<3> ix = {i,j,k}; - GradientVectorType p = corrected_diffusion_temp->GetPixel(ix); + GradientVectorType p = corrected_diffusion_temp->GetPixel(ix); - if (p[f] > 0.0 )// taking only positive values and counting them + if (p[f] > 0.0 )// taking only positive values and counting them + { + if(!(i==x && j==y && k== z)) { - if(!(i==x && j==y && k== z)) - { - tempsum=tempsum+p[f]; - temp_number++; - } - + tempsum=tempsum+p[f]; + temp_number++; } - - } } } + } - //getting back to the original position of the voxel + //getting back to the original position of the voxel - itk::Index<3> ix = {x,y,z}; + itk::Index<3> ix = {x,y,z}; - if (temp_number <= 0.0) - { - tempsum=0; - mask->SetPixel(ix,0); - } - else - { - tempsum=tempsum/temp_number; + if (temp_number <= 0.0) + { + tempsum=0; + mask->SetPixel(ix,0); + } + else + { + tempsum=tempsum/temp_number; - } + } - return tempsum;// smoothed value of voxel - } + return tempsum;// smoothed value of voxel +} - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::CalculateAttenuation(vnl_vector org_data,vnl_vector &atten,int nof, int numberb0) - { - double mean_b=0.0; +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::CalculateAttenuation(vnl_vector org_data,vnl_vector &atten,int nof, int numberb0) +{ + double mean_b=0.0; - for (int i=0;i0) { - if(m_B0Mask[i]>0) - { - double o_d=org_data[i]; - mean_b=mean_b+org_data[i]; - } - + double o_d=org_data[i]; + mean_b=mean_b+org_data[i]; } - mean_b=mean_b/numberb0; - int cnt=0; - for (int i=0;i - double - TensorReconstructionWithEigenvalueCorrectionFilter - ::CheckNegatives ( itk::Size<3> size, itk::Image::Pointer mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg ) - { +template +double +TensorReconstructionWithEigenvalueCorrectionFilter +::CheckNegatives ( itk::Size<3> size, itk::Image::Pointer mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg ) +{ + + // The method was created to simplif the flow of negative eigenvalue correction process. The method itself just return the number + // of voxels (tensors) with negative eigenvalues. Then if the voxel was previously bad ( mask=2 ) but it is not bad anymore mask is + //changed to 1. - // The method was created to simplif the flow of negative eigenvalue correction process. The method itself just return the number - // of voxels (tensors) with negative eigenvalues. Then if the voxel was previously bad ( mask=2 ) but it is not bad anymore mask is - //changed to 1. + // declaration of important structures and variables + double badvoxels=0; + double pixel=0; + itk::DiffusionTensor3D ten; + vnl_matrix temp_tensor(3,3); + vnl_vector eigen_vals(3); + vnl_vector tensor (6); - // declaration of important structures and variables - double badvoxels=0; - double pixel=0; - itk::DiffusionTensor3D ten; - vnl_matrix temp_tensor(3,3); - vnl_vector eigen_vals(3); - vnl_vector tensor (6); + // for every pixel from the image + for (unsigned int x=0;x ix = {x,y,z}; + pixel = mask->GetPixel(ix); + // but only if previously marked as bad one-negative eigen value - itk::Index<3> ix = {x,y,z}; - pixel = mask->GetPixel(ix); + if(pixel > 1) + { - // but only if previously marked as bad one-negative eigen value + ten = tensorImg->GetPixel(ix); - if(pixel > 1) - { + // changing order from tensor structure in MITK into vnl structure 3x3 symmetric tensor matrix - ten = tensorImg->GetPixel(ix); + tensor[0] = ten(0,0); + tensor[3] = ten(0,1); + tensor[5] = ten(0,2); + tensor[1] = ten(1,1); + tensor[4] = ten(1,2); + tensor[2] = ten(2,2); - // changing order from tensor structure in MITK into vnl structure 3x3 symmetric tensor matrix + temp_tensor[0][0]= tensor[0]; temp_tensor[1][0]= tensor[3]; temp_tensor[2][0]= tensor[5]; + temp_tensor[0][1]= tensor[3]; temp_tensor[1][1]= tensor[1]; temp_tensor[2][1]= tensor[4]; + temp_tensor[0][2]= tensor[5]; temp_tensor[1][2]= tensor[4]; temp_tensor[2][2]= tensor[2]; - tensor[0] = ten(0,0); - tensor[3] = ten(0,1); - tensor[5] = ten(0,2); - tensor[1] = ten(1,1); - tensor[4] = ten(1,2); - tensor[2] = ten(2,2); + //checking negativity of tensor eigenvalues - temp_tensor[0][0]= tensor[0]; temp_tensor[1][0]= tensor[3]; temp_tensor[2][0]= tensor[5]; - temp_tensor[0][1]= tensor[3]; temp_tensor[1][1]= tensor[1]; temp_tensor[2][1]= tensor[4]; - temp_tensor[0][2]= tensor[5]; temp_tensor[1][2]= tensor[4]; temp_tensor[2][2]= tensor[2]; + vnl_symmetric_eigensystem eigen_tensor(temp_tensor); - //checking negativity of tensor eigenvalues - vnl_symmetric_eigensystem eigen_tensor(temp_tensor); + eigen_vals[0]=eigen_tensor.get_eigenvalue(0); + eigen_vals[1]=eigen_tensor.get_eigenvalue(1); + eigen_vals[2]=eigen_tensor.get_eigenvalue(2); + //comparison to 0.01 instead of 0 was proposed by O.Pasternak - eigen_vals[0]=eigen_tensor.get_eigenvalue(0); - eigen_vals[1]=eigen_tensor.get_eigenvalue(1); - eigen_vals[2]=eigen_tensor.get_eigenvalue(2); + if( eigen_vals[0]>0.01 && eigen_vals[1]>0.01 && eigen_vals[2]>0.01) + { + mask->SetPixel(ix,1); - //comparison to 0.01 instead of 0 was proposed by O.Pasternak + } + else + { + badvoxels++; + } - if( eigen_vals[0]>0.01 && eigen_vals[1]>0.01 && eigen_vals[2]>0.01) - { - mask->SetPixel(ix,1); + } - } - else - { - badvoxels++; - } + } + } + } - } + double ret = badvoxels; - } - } - } + return ret; - double ret = badvoxels; +} - return ret; - } +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::CorrectDiffusionImage(int nof,int numberb0,itk::Size<3> size, typename GradientImagesType::Pointer corrected_diffusion,itk::Image::Pointer mask,vnl_vector< double> pixel_max,vnl_vector< double> pixel_min) +{ + // in this method the voxels that has tensor negative eigenvalues are smoothed. Smoothing is done on DWI image.For the voxel + //detected as bad one, B0 image is smoothed obligatory. All other gradient images are smoothed only when value of attenuation + //is out of declared bounds for too high or too low attenuation. + // declaration of important variables + vnl_vector org_data(nof); + vnl_vector atten(nof-numberb0); + double cnt_atten=0; - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::CorrectDiffusionImage(int nof,int numberb0,itk::Size<3> size, typename GradientImagesType::Pointer corrected_diffusion,itk::Image::Pointer mask,vnl_vector< double> pixel_max,vnl_vector< double> pixel_min) + for (unsigned int z=0;z org_data(nof); - vnl_vector atten(nof-numberb0); - double cnt_atten=0; - - for (unsigned int z=0;z ix = {x, y, z}; - for (unsigned int y=0;y ix = {x, y, z}; + if(mask->GetPixel(ix) > 1.0) + { + GradientVectorType pt = corrected_diffusion->GetPixel(ix); - if(mask->GetPixel(ix) > 1.0) + for (int i=0;iGetPixel(ix); - - for (int i=0;i0) { - if(m_B0Mask[i]>0) - { - mean_b=mean_b+org_data[i]; - } + mean_b=mean_b+org_data[i]; + } - } - mean_b=mean_b/numberb0; - int cnt=0; - for (int i=0;i pixel_max[cnt_atten]) { - int x_max=size[0]-1; - int y_max=size[1]-1; - int z_max=size[2]-1; + int x_max=size[0]-1; + int y_max=size[1]-1; + int z_max=size[2]-1; - double back_x=std::max(0,(int)x-1); - double back_y=std::max(0,(int)y-1); - double back_z=std::max(0,(int)z-1); + double back_x=std::max(0,(int)x-1); + double back_y=std::max(0,(int)y-1); + double back_z=std::max(0,(int)z-1); - double forth_x=std::min(((int)x+1),x_max); - double forth_y=std::min(((int)y+1),y_max); - double forth_z=std::min(((int)z+1),z_max); + double forth_x=std::min(((int)x+1),x_max); + double forth_y=std::min(((int)y+1),y_max); + double forth_z=std::min(((int)z+1),z_max); - double tempsum=0; - double temp_number=0; + double tempsum=0; + double temp_number=0; - for(unsigned int i=back_x; i<=forth_x; i++) + for(unsigned int i=back_x; i<=forth_x; i++) + { + for (unsigned int j=back_y; j<=forth_y; j++) { - for (unsigned int j=back_y; j<=forth_y; j++) + for (unsigned int k=back_z; k<=forth_z; k++) { - for (unsigned int k=back_z; k<=forth_z; k++) - { - itk::Index<3> ix = {i,j,k}; + itk::Index<3> ix = {i,j,k}; - GradientVectorType p = corrected_diffusion->GetPixel(ix); + GradientVectorType p = corrected_diffusion->GetPixel(ix); - //double test= p[f]; + //double test= p[f]; - if (p[f] > 0.0 )// taking only positive values and counting them + if (p[f] > 0.0 )// taking only positive values and counting them + { + if(!(i==x && j==y && k== z)) { - if(!(i==x && j==y && k== z)) - { - tempsum=tempsum+p[f]; - temp_number++; - } - + tempsum=tempsum+p[f]; + temp_number++; } - } + + } } + } - //getting back to the original position of the voxel + //getting back to the original position of the voxel - itk::Index<3> ix = {x,y,z}; + itk::Index<3> ix = {x,y,z}; - if (temp_number <= 0.0) - { - tempsum=0; - mask->SetPixel(ix,0); - } - else - { - tempsum=tempsum/temp_number; + if (temp_number <= 0.0) + { + tempsum=0; + mask->SetPixel(ix,0); + } + else + { + tempsum=tempsum/temp_number; - } + } - org_data[f] = tempsum; + org_data[f] = tempsum; } cnt_atten++; - } - //smoothing B0 - if(m_B0Mask[f]==1) - { + } + //smoothing B0 + if(m_B0Mask[f]==1) + { - int x_max=size[0] - 1; - int y_max=size[1] - 1; - int z_max=size[2] - 1; + int x_max=size[0] - 1; + int y_max=size[1] - 1; + int z_max=size[2] - 1; - double back_x=std::max(0,(int)x-1); - double back_y=std::max(0,(int)y-1); - double back_z=std::max(0,(int)z-1); + double back_x=std::max(0,(int)x-1); + double back_y=std::max(0,(int)y-1); + double back_z=std::max(0,(int)z-1); - double forth_x=std::min(((int)x+1),x_max); - double forth_y=std::min(((int)y+1),y_max); - double forth_z=std::min(((int)z+1),z_max); + double forth_x=std::min(((int)x+1),x_max); + double forth_y=std::min(((int)y+1),y_max); + double forth_z=std::min(((int)z+1),z_max); - double tempsum=0; - double temp_number=0; + double tempsum=0; + double temp_number=0; - for(unsigned int i=back_x; i<=forth_x; i++) + for(unsigned int i=back_x; i<=forth_x; i++) + { + for (unsigned int j=back_y; j<=forth_y; j++) + { + for (unsigned int k=back_z; k<=forth_z; k++) { - for (unsigned int j=back_y; j<=forth_y; j++) - { - for (unsigned int k=back_z; k<=forth_z; k++) - { - itk::Index<3> ix = {i,j,k}; + itk::Index<3> ix = {i,j,k}; - GradientVectorType p = corrected_diffusion->GetPixel(ix); - - //double test= p[f]; - - if (p[f] > 0.0 )// taking only positive values and counting them - { - if(!(i==x && j==y && k== z)) - { - tempsum=tempsum+p[f]; - temp_number++; - } - - } + GradientVectorType p = corrected_diffusion->GetPixel(ix); + //double test= p[f]; + if (p[f] > 0.0 )// taking only positive values and counting them + { + if(!(i==x && j==y && k== z)) + { + tempsum=tempsum+p[f]; + temp_number++; } - } - } - //getting back to the original position of the voxel + } - itk::Index<3> ix = {x,y,z}; - if (temp_number <= 0.0) - { - tempsum=0; - mask->SetPixel(ix,0); } - else - { - tempsum=tempsum/temp_number; + } + } - } + //getting back to the original position of the voxel - org_data[f] = tempsum; + itk::Index<3> ix = {x,y,z}; + if (temp_number <= 0.0) + { + tempsum=0; + mask->SetPixel(ix,0); } + else + { + tempsum=tempsum/temp_number; + } - } + org_data[f] = tempsum; - for (int i=0;iSetPixel(ix, pt); } - else - { - GradientVectorType pt = corrected_diffusion->GetPixel(ix); - corrected_diffusion->SetPixel(ix, pt); + for (int i=0;iSetPixel(ix, pt); + + } + else + { + GradientVectorType pt = corrected_diffusion->GetPixel(ix); + corrected_diffusion->SetPixel(ix, pt); + } } } + } - } +} - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::GenerateTensorImage(int nof,int numberb0,itk::Size<3> size,itk::VectorImage::Pointer corrected_diffusion,itk::Image::Pointer mask,double what_mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg) - { - // in this method the whole tensor image is updated with a tensors for defined voxels ( defined by a value of mask); +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::GenerateTensorImage(int nof,int numberb0,itk::Size<3> size,itk::VectorImage::Pointer corrected_diffusion,itk::Image::Pointer mask,double what_mask, typename itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg) +{ + // in this method the whole tensor image is updated with a tensors for defined voxels ( defined by a value of mask); - itk::Index<3> ix; - vnl_vector org_data(nof); - vnl_vector atten(nof-numberb0); - vnl_vector tensor(6); - itk::DiffusionTensor3D ten; - double mask_val=0; + itk::Index<3> ix; + itk::Index<3> idx; + idx.Fill(5); - for (unsigned int x=0;x org_data(nof); + vnl_vector atten(nof-numberb0); + vnl_vector tensor(6); + itk::DiffusionTensor3D ten; + double mask_val=0; - for (unsigned int y=0;yGetPixel(ix); - //Tensors are calculated only for voxels above theshold for B0 image. + ix[0] = x; ix[1] = y; ix[2] = z; - if( mask_val > 0.0 ) - { + mask_val= mask->GetPixel(ix); - // calculation of attenuation with use of gradient image and and mean B0 image - GradientVectorType pt = corrected_diffusion->GetPixel(ix); + //Tensors are calculated only for voxels above theshold for B0 image. - for (int i=0;i 0.0 ) + { - double mean_b=0.0; + // calculation of attenuation with use of gradient image and and mean B0 image + GradientVectorType pt = corrected_diffusion->GetPixel(ix); - for (int i=0;i0) - { - mean_b=mean_b+org_data[i]; - } + for (int i=0;i0) + { + mean_b=mean_b+org_data[i]; + } + } + mean_b=mean_b/numberb0; + int cnt=0; + for (int i=0;iSetPixel(ix, ten); + // Calculation of tensor with use of previously calculated inverse of design matrix and attenuation + tensor = m_PseudoInverse*atten; + ten(0,0) = tensor[0]; + ten(0,1) = tensor[3]; + ten(0,2) = tensor[5]; + ten(1,1) = tensor[1]; + ten(1,2) = tensor[4]; + ten(2,2) = tensor[2]; + tensorImg->SetPixel(ix, ten); - } - // for voxels with mask value 0 - tensor is simply 0 ( outside brain value) - else if (mask_val < 1.0) - { - ten(0,0) = 0; - ten(0,1) = 0; - ten(0,2) = 0; - ten(1,1) = 0; - ten(1,2) = 0; - ten(2,2) = 0; - tensorImg->SetPixel(ix, ten); - } - } } - } - - + // for voxels with mask value 0 - tensor is simply 0 ( outside brain value) + else if (mask_val < 1.0) + { - }// end of Generate Tensor + ten(0,0) = 0; + ten(0,1) = 0; + ten(0,2) = 0; + ten(1,1) = 0; + ten(1,2) = 0; + ten(2,2) = 0; + tensorImg->SetPixel(ix, ten); + } + if (ix == idx) + { + for (int ll = 0; ll < 6 ; ll++) + std::cout << tensor[ll] << "," << std::endl; + } - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::TurnMask( itk::Size<3> size, itk::Image::Pointer mask, double previous_mask, double set_mask) - { - // The method changes voxels in the mask that poses a certain value with other value. - itk::Index<3> ix; - double temp_mask_value=0; - for(unsigned int x=0;xGetPixel(ix); - if(temp_mask_value>previous_mask) - { - mask->SetPixel(ix,set_mask); - } - } } } } - /* +}// end of Generate Tensor - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::DeepCopyDiffusionImage(itk::VectorImage::Pointer corrected_diffusion, itk::VectorImage::Pointer corrected_diffusion_temp,int nof) - { - corrected_diffusion_temp->SetSpacing(corrected_diffusion->GetSpacing()); - corrected_diffusion_temp->SetOrigin(corrected_diffusion->GetOrigin()); - corrected_diffusion_temp->SetVectorLength(nof); - corrected_diffusion_temp->SetRegions(corrected_diffusion->GetLargestPossibleRegion()); - corrected_diffusion_temp->Allocate(); - itk::ImageRegionConstIterator inputIterator(corrected_diffusion, corrected_diffusion->GetLargestPossibleRegion()); - itk::ImageRegionIterator outputIterator(corrected_diffusion_temp, corrected_diffusion_temp->GetLargestPossibleRegion()); +template +void +TensorReconstructionWithEigenvalueCorrectionFilter +::TurnMask( itk::Size<3> size, itk::Image::Pointer mask, double previous_mask, double set_mask) +{ + // The method changes voxels in the mask that poses a certain value with other value. - inputIterator.GoToBegin(); - outputIterator.GoToBegin(); + itk::Index<3> ix; + double temp_mask_value=0; - while(!inputIterator.IsAtEnd()) - { - outputIterator.Set(inputIterator.Get()); - ++inputIterator; - ++outputIterator; - } - } - - template - void - TensorReconstructionWithEigenvalueCorrectionFilter - ::DeepCopyTensorImage(itk::Image< itk::DiffusionTensor3D, 3 >::Pointer tensorImg, itk::Image< itk::DiffusionTensor3D, 3 >::Pointer temp_tensorImg) + for(unsigned int x=0;xSetSpacing(tensorImg->GetSpacing()); - temp_tensorImg->SetOrigin(tensorImg->GetOrigin()); - temp_tensorImg->SetRegions(tensorImg->GetLargestPossibleRegion()); - temp_tensorImg->Allocate(); - - itk::ImageRegionConstIterator inputIterator(tensorImg, tensorImg->GetLargestPossibleRegion()); - itk::ImageRegionIterator outputIterator(temp_tensorImg, temp_tensorImg->GetLargestPossibleRegion()); - - inputIterator.GoToBegin(); - outputIterator.GoToBegin(); - - while(!inputIterator.IsAtEnd()) + for(unsigned int y=0;yGetPixel(ix); + + if(temp_mask_value>previous_mask) + { + mask->SetPixel(ix,set_mask); + } } + } } - - - */ - - +} } // end of namespace diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui index ef12cfca5d..cd7b9890cc 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkTensorReconstructionViewControls.ui @@ -1,562 +1,562 @@ QmitkTensorReconstructionViewControls 0 0 380 1019 0 0 true QmitkTensorReconstructionViewControls Please Select Input Data: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Raw DWI/DTI: Tensor reconstruction and colormap visualization Advanced Settings false QFrame::StyledPanel QFrame::Raised 9 9 9 9 QFrame::NoFrame QFrame::Raised 0 0 0 0 B0 Threshold false 10000 Only influences WLS reconstruction Ignore voxels with negative eigenvalues 0 - Weighted Linear Least Squares + ITK Linear Least Squares With correction for negative eigenvalues false Select raw DWI! Start Reconstruction Estimate Diffusion Weighted Image from Tensors QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 6 0 0 0 0 how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" how fuzzy the confidence boundary should be. By default, confidence boundary is perfectly sharp (float); default: "0" B-Value false #Gradient Directions 3 12 42 92 162 252 362 492 642 812 1002 10000 100 1000 false Estimates the original diffusion weighted image based on a reconstructed tensor image. Estimate DWI based on Tensor Image Estimate Q-Ball Image from Tensors false Calculate ODF value as tensor value in the according direction Start QBI Estimation Estimate Residuals false false false percentages of error 1 Per volume 200 300 Per slice outliers per slice QFrame::NoFrame QFrame::Raised 0 0 0 0 300 400 QFrame::NoFrame QFrame::Raised 0 0 0 0 20 255 Volume: .., Slice:.. false Calculate the residual from a dti and a dwi image Residual Image Calculation QmitkResidualAnalysisWidget QWidget
QmitkResidualAnalysisWidget.h
1
QmitkResidualViewWidget QGraphicsView
QmitkResidualViewWidget.h