diff --git a/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp index c24a218dc1..d5dfca06cf 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,644 +1,645 @@ /*=================================================================== 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 "itkTractsToDWIImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk { TractsToDWIImageFilter::TractsToDWIImageFilter() : m_CircleDummy(false) , m_VolumeAccuracy(1) , m_Upsampling(1) , m_NumberOfRepetitions(1) , m_EnforcePureFiberVoxels(true) { m_Spacing.Fill(2.5); m_Origin.Fill(0.0); m_DirectionMatrix.SetIdentity(); m_ImageRegion.SetSize(0, 10); m_ImageRegion.SetSize(1, 10); m_ImageRegion.SetSize(2, 10); } TractsToDWIImageFilter::~TractsToDWIImageFilter() { } std::vector< TractsToDWIImageFilter::DoubleDwiType::Pointer > TractsToDWIImageFilter::AddKspaceArtifacts( std::vector< DoubleDwiType::Pointer >& images ) { // create slice object SliceType::Pointer slice = SliceType::New(); ImageRegion<2> region; region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); slice->SetLargestPossibleRegion( region ); slice->SetBufferedRegion( region ); slice->SetRequestedRegion( region ); slice->Allocate(); boost::progress_display disp(images.size()*images[0]->GetVectorLength()*images[0]->GetLargestPossibleRegion().GetSize(2)); std::vector< DoubleDwiType::Pointer > outImages; for (int i=0; iSetSpacing( m_Spacing ); newImage->SetOrigin( m_Origin ); newImage->SetDirection( m_DirectionMatrix ); newImage->SetLargestPossibleRegion( m_ImageRegion ); newImage->SetBufferedRegion( m_ImageRegion ); newImage->SetRequestedRegion( m_ImageRegion ); newImage->SetVectorLength( image->GetVectorLength() ); newImage->Allocate(); DiffusionSignalModel* signalModel; if (iGetVectorLength(); g++) for (int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { ++disp; // extract slice from channel g for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; SliceType::PixelType pix2D = image->GetPixel(index3D)[g]; slice->SetPixel(index2D, pix2D); } // fourier transform slice itk::FFTRealToComplexConjugateImageFilter< SliceType::PixelType, 2 >::Pointer fft = itk::FFTRealToComplexConjugateImageFilter< SliceType::PixelType, 2 >::New(); fft->SetInput(slice); fft->Update(); ComplexSliceType::Pointer fSlice = fft->GetOutput(); fSlice = RearrangeSlice(fSlice); // add artifacts for (int a=0; aSetRelaxationT2(signalModel->GetRelaxationT2()); fSlice = m_KspaceArtifacts.at(a)->AddArtifact(fSlice); } // save k-space slice of s0 image if (g==0) for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; double kpix = sqrt(fSlice->GetPixel(index2D).real()*fSlice->GetPixel(index2D).real()+fSlice->GetPixel(index2D).imag()*fSlice->GetPixel(index2D).imag()); m_KspaceImage->SetPixel(index3D, kpix); } // inverse fourier transform slice SliceType::Pointer newSlice; itk::FFTComplexConjugateToRealImageFilter< SliceType::PixelType, 2 >::Pointer ifft = itk::FFTComplexConjugateToRealImageFilter< SliceType::PixelType, 2 >::New(); ifft->SetInput(fSlice); ifft->Update(); newSlice = ifft->GetOutput(); // put slice back into channel g for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; DoubleDwiType::PixelType pix3D = newImage->GetPixel(index3D); SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; pix3D[g] = newSlice->GetPixel(index2D); newImage->SetPixel(index3D, pix3D); } } outImages.push_back(newImage); } return outImages; } TractsToDWIImageFilter::ComplexSliceType::Pointer TractsToDWIImageFilter::RearrangeSlice(ComplexSliceType::Pointer slice) { ImageRegion<2> region = slice->GetLargestPossibleRegion(); ComplexSliceType::Pointer rearrangedSlice = ComplexSliceType::New(); rearrangedSlice->SetLargestPossibleRegion( region ); rearrangedSlice->SetBufferedRegion( region ); rearrangedSlice->SetRequestedRegion( region ); rearrangedSlice->Allocate(); int xHalf = region.GetSize(0)/2; int yHalf = region.GetSize(1)/2; for (int y=0; y pix = slice->GetPixel(idx); if( idx[0] < xHalf ) idx[0] = idx[0] + xHalf; else idx[0] = idx[0] - xHalf; if( idx[1] < yHalf ) idx[1] = idx[1] + yHalf; else idx[1] = idx[1] - yHalf; rearrangedSlice->SetPixel(idx, pix); } return rearrangedSlice; } void TractsToDWIImageFilter::GenerateData() { // check input data if (m_FiberBundle.IsNull()) itkExceptionMacro("Input fiber bundle is NULL!"); int numFibers = m_FiberBundle->GetNumFibers(); if (numFibers<=0) itkExceptionMacro("Input fiber bundle contains no fibers!"); if (m_FiberModels.empty()) itkExceptionMacro("No diffusion model for fiber compartments defined!"); if (m_NonFiberModels.empty()) itkExceptionMacro("No diffusion model for non-fiber compartments defined!"); // determine k-space undersampling for (int i=0; i*>(m_KspaceArtifacts.at(i)) ) m_Upsampling = dynamic_cast*>(m_KspaceArtifacts.at(i))->GetKspaceCropping(); if (m_Upsampling<=1) m_Upsampling = 1; if (m_TissueMask.IsNotNull()) { // use input tissue mask m_Spacing = m_TissueMask->GetSpacing(); m_Origin = m_TissueMask->GetOrigin(); m_DirectionMatrix = m_TissueMask->GetDirection(); m_ImageRegion = m_TissueMask->GetLargestPossibleRegion(); if (m_Upsampling>1) { ImageRegion<3> region = m_ImageRegion; region.SetSize(0, m_ImageRegion.GetSize(0)*m_Upsampling); region.SetSize(1, m_ImageRegion.GetSize(1)*m_Upsampling); mitk::Vector3D spacing = m_Spacing; spacing[0] /= m_Upsampling; spacing[1] /= m_Upsampling; itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); rescaler->SetInput(0,m_TissueMask); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetOutputParametersFromImage(m_TissueMask); resampler->SetSize(region.GetSize()); resampler->SetOutputSpacing(spacing); resampler->Update(); m_TissueMask = resampler->GetOutput(); } MITK_INFO << "Using tissue mask"; } // initialize output dwi image OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( m_Spacing ); outImage->SetOrigin( m_Origin ); outImage->SetDirection( m_DirectionMatrix ); outImage->SetLargestPossibleRegion( m_ImageRegion ); outImage->SetBufferedRegion( m_ImageRegion ); outImage->SetRequestedRegion( m_ImageRegion ); outImage->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); outImage->Allocate(); OutputImageType::PixelType temp; temp.SetSize(m_FiberModels[0]->GetNumGradients()); temp.Fill(0.0); outImage->FillBuffer(temp); // is input slize size a power of two? int x=2; int y=2; while (x " << x; m_ImageRegion.SetSize(0, x); } if (y!=m_ImageRegion.GetSize(1)) { MITK_INFO << "Adjusting image height: " << m_ImageRegion.GetSize(1) << " --> " << y; m_ImageRegion.SetSize(1, y); } // initialize k-space image m_KspaceImage = ItkDoubleImgType::New(); m_KspaceImage->SetSpacing( m_Spacing ); m_KspaceImage->SetOrigin( m_Origin ); m_KspaceImage->SetDirection( m_DirectionMatrix ); m_KspaceImage->SetLargestPossibleRegion( m_ImageRegion ); m_KspaceImage->SetBufferedRegion( m_ImageRegion ); m_KspaceImage->SetRequestedRegion( m_ImageRegion ); m_KspaceImage->Allocate(); m_KspaceImage->FillBuffer(0); // apply undersampling to image parameters m_UpsampledSpacing = m_Spacing; m_UpsampledImageRegion = m_ImageRegion; m_UpsampledSpacing[0] /= m_Upsampling; m_UpsampledSpacing[1] /= m_Upsampling; m_UpsampledImageRegion.SetSize(0, m_ImageRegion.GetSize()[0]*m_Upsampling); m_UpsampledImageRegion.SetSize(1, m_ImageRegion.GetSize()[1]*m_Upsampling); // everything from here on is using the upsampled image parameters!!! if (m_TissueMask.IsNull()) { m_TissueMask = ItkUcharImgType::New(); m_TissueMask->SetSpacing( m_UpsampledSpacing ); m_TissueMask->SetOrigin( m_Origin ); m_TissueMask->SetDirection( m_DirectionMatrix ); m_TissueMask->SetLargestPossibleRegion( m_UpsampledImageRegion ); m_TissueMask->SetBufferedRegion( m_UpsampledImageRegion ); m_TissueMask->SetRequestedRegion( m_UpsampledImageRegion ); m_TissueMask->Allocate(); m_TissueMask->FillBuffer(1); } // resample fiber bundle for sufficient voxel coverage float minSpacing = 1; if(m_UpsampledSpacing[0]GetFiberSampling()<=0 || 10/m_FiberBundle->GetFiberSampling()>minSpacing*0.5/m_VolumeAccuracy) { fiberBundle = m_FiberBundle->GetDeepCopy(); fiberBundle->ResampleFibers(minSpacing*0.5/m_VolumeAccuracy); } // generate double images to wokr with because we don't want to lose precision // we use a separate image for each compartment model std::vector< DoubleDwiType::Pointer > compartments; for (int i=0; iSetSpacing( m_UpsampledSpacing ); doubleDwi->SetOrigin( m_Origin ); doubleDwi->SetDirection( m_DirectionMatrix ); doubleDwi->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleDwi->SetBufferedRegion( m_UpsampledImageRegion ); doubleDwi->SetRequestedRegion( m_UpsampledImageRegion ); doubleDwi->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_FiberModels[0]->GetNumGradients()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); compartments.push_back(doubleDwi); } if (m_CircleDummy) { for (int i=0; iGetNumGradients()); pix.Fill(1); DoubleDwiType::Pointer doubleDwi = compartments.at(i); ImageRegion<3> region = doubleDwi->GetLargestPossibleRegion(); ImageRegionIterator it(doubleDwi, region); while(!it.IsAtEnd()) { DoubleDwiType::IndexType index = it.GetIndex(); double t = region.GetSize(0)/2; double d1 = index[0]-t+0.5; t = region.GetSize(1)/2; double d2 = index[1]-t+0.5; if (sqrt(d1*d1+d2*d2)<20*m_Upsampling) it.Set(pix); ++it; } } } else { vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); MITK_INFO << "Generating signal of " << m_FiberModels.size() << " fiber compartments"; double maxFiberDensity = 0; boost::progress_display disp(numFibers); for( int i=0; iGetNextCell ( numPoints, points ); if (numPoints<2) continue; for( int j=0; jGetPoint(points[j]); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(points[j+1]))-v; else dir = v-GetItkVector(fiberPolyData->GetPoint(points[j-1])); itk::Index<3> idx; itk::ContinuousIndex contIndex; m_TissueMask->TransformPhysicalPointToIndex(vertex, idx); m_TissueMask->TransformPhysicalPointToContinuousIndex(vertex, contIndex); double frac_x = contIndex[0] - idx[0]; double frac_y = contIndex[1] - idx[1]; double frac_z = contIndex[2] - idx[2]; if (frac_x<0) { idx[0] -= 1; frac_x += 1; } if (frac_y<0) { idx[1] -= 1; frac_y += 1; } if (frac_z<0) { idx[2] -= 1; frac_z += 1; } // use trilinear interpolation itk::Index<3> newIdx; for (int x=0; x<2; x++) { frac_x = 1-frac_x; for (int y=0; y<2; y++) { frac_y = 1-frac_y; for (int z=0; z<2; z++) { frac_z = 1-frac_z; newIdx[0] = idx[0]+x; newIdx[1] = idx[1]+y; newIdx[2] = idx[2]+z; double frac = frac_x*frac_y*frac_z; // is position valid? if (!m_TissueMask->GetLargestPossibleRegion().IsInside(newIdx) || m_TissueMask->GetPixel(newIdx)<=0) continue; // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); doubleDwi->SetPixel(newIdx, doubleDwi->GetPixel(newIdx) + frac*m_FiberModels[k]->SimulateMeasurement()); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(newIdx); if (pix[0]>maxFiberDensity) maxFiberDensity = pix[0]; } } } } } } MITK_INFO << "Generating signal of " << m_NonFiberModels.size() << " non-fiber compartments"; boost::progress_display disp2(m_NonFiberModels.size()*compartments.at(0)->GetLargestPossibleRegion().GetNumberOfPixels()); for (int i=0; i it(doubleDwi, doubleDwi->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { ++disp2; DoubleDwiType::IndexType index = it.GetIndex(); if (m_TissueMask->GetLargestPossibleRegion().IsInside(index) && m_TissueMask->GetPixel(index)>0) doubleDwi->SetPixel(index, doubleDwi->GetPixel(index) + m_NonFiberModels[i]->SimulateMeasurement()); ++it; } } MITK_INFO << "Adjusting compartment signal intensities according to volume fraction"; ImageRegionIterator it3(m_TissueMask, m_TissueMask->GetLargestPossibleRegion()); boost::progress_display disp3(m_TissueMask->GetLargestPossibleRegion().GetNumberOfPixels()); while(!it3.IsAtEnd()) { ++disp3; DoubleDwiType::IndexType index = it3.GetIndex(); if (it3.Get()>0) { // compartment weights are calculated according to fiber density double w = compartments.at(0)->GetPixel(index)[0]/maxFiberDensity; if (m_EnforcePureFiberVoxels && w>0) w = 1; // adjust fiber signal for (int i=0; iGetPixel(index); if (pix[0]>0) pix /= pix[0]; pix *= w/m_FiberModels.size(); doubleDwi->SetPixel(index, pix); } // adjust non-fiber signal for (int i=0; iGetPixel(index); if (pix[0]>0) pix /= pix[0]; pix *= (1-w)/m_NonFiberModels.size(); doubleDwi->SetPixel(index, pix); } } ++it3; } } // do k-space stuff double maxValue = 0; double usedS = 1; if (!m_KspaceArtifacts.empty()) MITK_INFO << "Generating k-space artifacts"; else MITK_INFO << "Generating k-space image"; compartments = AddKspaceArtifacts(compartments); // we are now working with the low resolution images again!!! for (int i=0; i it(doubleDwi, doubleDwi->GetLargestPossibleRegion()); double s = 1; if (iGetSignalScale(); else s = m_NonFiberModels.at(i-m_FiberModels.size())->GetSignalScale(); while(!it.IsAtEnd()) { DoubleDwiType::PixelType pix = it.Get(); if (pix[0]*s>maxValue) { maxValue = pix[0]*s; usedS = s; } ++it; } } maxValue /= usedS; + maxValue = m_Upsampling*m_Upsampling; MITK_INFO << "Summing compartments and adding noise"; ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_FiberModels[0]->GetNumGradients()); boost::progress_display disp4(outImage->GetLargestPossibleRegion().GetNumberOfPixels()); while(!it4.IsAtEnd()) { ++disp4; DWIImageType::IndexType index = it4.GetIndex(); signal.Fill(0.0); // adjust fiber signal for (int i=0; iGetSignalScale()/maxValue; signal += compartments.at(i)->GetPixel(index)*s; } // adjust non-fiber signal for (int i=0; iGetSignalScale()/maxValue; signal += compartments.at(m_FiberModels.size()+i)->GetPixel(index)*s; } DoubleDwiType::PixelType accu = signal; accu.Fill(0.0); for (int i=0; iAddNoise(temp); accu += temp; } signal = accu/m_NumberOfRepetitions; for (int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); } it4.Set(signal); ++it4; } this->SetNthOutput(0, outImage); } itk::Point TractsToDWIImageFilter::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } itk::Vector TractsToDWIImageFilter::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } vnl_vector_fixed TractsToDWIImageFilter::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } vnl_vector_fixed TractsToDWIImageFilter::GetVnlVector(Vector& vector) { vnl_vector_fixed vnlVector; vnlVector[0] = vector[0]; vnlVector[1] = vector[1]; vnlVector[2] = vector[2]; return vnlVector; } } diff --git a/Modules/DiffusionImaging/SignalModels/mitkBallModel.cpp b/Modules/DiffusionImaging/SignalModels/mitkBallModel.cpp index 7c909f0c9f..8160f8adff 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkBallModel.cpp +++ b/Modules/DiffusionImaging/SignalModels/mitkBallModel.cpp @@ -1,49 +1,51 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include template< class ScalarType > BallModel< ScalarType >::BallModel() : m_Diffusivity(0.001) , m_BValue(1000) { } template< class ScalarType > BallModel< ScalarType >::~BallModel() { } template< class ScalarType > typename BallModel< ScalarType >::PixelType BallModel< ScalarType >::SimulateMeasurement() { PixelType signal; signal.SetSize(this->m_GradientList.size()); for( unsigned int i=0; im_GradientList.size(); i++) { GradientType g = this->m_GradientList[i]; - if (g.GetNorm()>0.0001) - signal[i] = exp( -m_BValue * m_Diffusivity ); + double bVal = g.GetNorm(); bVal *= bVal; + + if (bVal>0.0001) + signal[i] = exp( -m_BValue * bVal * m_Diffusivity ); else signal[i] = 1; } return signal; } diff --git a/Modules/DiffusionImaging/SignalModels/mitkDiffusionNoiseModel.h b/Modules/DiffusionImaging/SignalModels/mitkDiffusionNoiseModel.h index 0e00d32b26..5281eec741 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkDiffusionNoiseModel.h +++ b/Modules/DiffusionImaging/SignalModels/mitkDiffusionNoiseModel.h @@ -1,57 +1,55 @@ /*=================================================================== 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 _MITK_DiffusionNoiseModel_H #define _MITK_DiffusionNoiseModel_H #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion noise models * */ template< class ScalarType > class DiffusionNoiseModel { public: DiffusionNoiseModel(){} ~DiffusionNoiseModel(){} typedef itk::VariableLengthVector< ScalarType > PixelType; /** Adds noise according to model to the input pixel. Has to be implemented in subclass. **/ virtual void AddNoise(PixelType& pixel) = 0; - void SetScaleFactor(ScalarType scale){ m_ScaleFactor = scale; } void SetNoiseVariance(double var){ m_NoiseVariance = var; } protected: - ScalarType m_ScaleFactor; ///< scaling factor for generated noise values double m_NoiseVariance; ///< variance of underlying distribution }; } #endif diff --git a/Modules/DiffusionImaging/SignalModels/mitkRicianNoiseModel.cpp b/Modules/DiffusionImaging/SignalModels/mitkRicianNoiseModel.cpp index 09b602e992..aa0a7b879b 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkRicianNoiseModel.cpp +++ b/Modules/DiffusionImaging/SignalModels/mitkRicianNoiseModel.cpp @@ -1,42 +1,41 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include template< class ScalarType > RicianNoiseModel< ScalarType >::RicianNoiseModel() { m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); this->m_NoiseVariance = 0; - this->m_ScaleFactor = 0; } template< class ScalarType > RicianNoiseModel< ScalarType >::~RicianNoiseModel() { } template< class ScalarType > void RicianNoiseModel< ScalarType >::AddNoise(PixelType& pixel) { for( unsigned int i=0; im_ScaleFactor*m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance), 2) + pow(this->m_ScaleFactor*m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance),2)); + pixel[i] = sqrt(pow(signal + m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance), 2) + pow(m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance),2)); } } diff --git a/Modules/DiffusionImaging/SignalModels/mitkStickModel.cpp b/Modules/DiffusionImaging/SignalModels/mitkStickModel.cpp index 20cac07b07..9189411df6 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkStickModel.cpp +++ b/Modules/DiffusionImaging/SignalModels/mitkStickModel.cpp @@ -1,52 +1,54 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include template< class ScalarType > StickModel< ScalarType >::StickModel() : m_Diffusivity(0.001) , m_BValue(1000) { } template< class ScalarType > StickModel< ScalarType >::~StickModel() { } template< class ScalarType > typename StickModel< ScalarType >::PixelType StickModel< ScalarType >::SimulateMeasurement() { PixelType signal; signal.SetSize(this->m_GradientList.size()); for( unsigned int i=0; im_GradientList.size(); i++) { GradientType g = this->m_GradientList[i]; - if (g.GetNorm()>0.0001) + double bVal = g.GetNorm(); bVal *= bVal; + + if (bVal>0.0001) { double dot = this->m_FiberDirection*g; - signal[i] = exp( -m_BValue*m_Diffusivity*dot*dot ); + signal[i] = exp( -m_BValue * bVal * m_Diffusivity*dot*dot ); } else signal[i] = 1; } return signal; } diff --git a/Modules/DiffusionImaging/SignalModels/mitkTensorModel.cpp b/Modules/DiffusionImaging/SignalModels/mitkTensorModel.cpp index 35b74f47c5..b23d6d6443 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkTensorModel.cpp +++ b/Modules/DiffusionImaging/SignalModels/mitkTensorModel.cpp @@ -1,114 +1,115 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include template< class ScalarType > TensorModel< ScalarType >::TensorModel() : m_KernelFA(0.6) , m_KernelADC(0.001) , m_BValue(1000) { m_KernelDirection[0]=1; m_KernelDirection[1]=0; m_KernelDirection[2]=0; UpdateKernelTensor(); } template< class ScalarType > TensorModel< ScalarType >::~TensorModel() { } template< class ScalarType > void TensorModel< ScalarType >::UpdateKernelTensor() { ItkTensorType tensor; tensor.Fill(0.0); float e1 = m_KernelADC*(1+2*m_KernelFA/sqrt(3-2*m_KernelFA*m_KernelFA)); float e2 = m_KernelADC*(1-m_KernelFA/sqrt(3-2*m_KernelFA*m_KernelFA)); tensor.SetElement(0, e1); tensor.SetElement(3, e2); tensor.SetElement(5, e2); m_KernelTensorMatrix.fill(0.0); m_KernelTensorMatrix[0][0] = e1; m_KernelTensorMatrix[1][1] = e2; m_KernelTensorMatrix[2][2] = e2; } template< class ScalarType > void TensorModel< ScalarType >::SetKernelFA(float FA) { m_KernelFA = FA; UpdateKernelTensor(); } template< class ScalarType > void TensorModel< ScalarType >::SetKernelADC(float ADC) { m_KernelADC = ADC; UpdateKernelTensor(); } template< class ScalarType > void TensorModel< ScalarType >::SetKernelTensor(ItkTensorType& tensor) { m_KernelTensorMatrix[0][0] = tensor[0]; m_KernelTensorMatrix[0][1] = tensor[1]; m_KernelTensorMatrix[0][2] = tensor[2]; m_KernelTensorMatrix[1][0] = tensor[1]; m_KernelTensorMatrix[1][1] = tensor[3]; m_KernelTensorMatrix[1][2] = tensor[4]; m_KernelTensorMatrix[2][0] = tensor[2]; m_KernelTensorMatrix[2][1] = tensor[4]; m_KernelTensorMatrix[2][2] = tensor[5]; } template< class ScalarType > typename TensorModel< ScalarType >::PixelType TensorModel< ScalarType >::SimulateMeasurement() { PixelType signal; signal.SetSize(this->m_GradientList.size()); signal.Fill(0.0); ItkTensorType tensor; tensor.Fill(0.0); this->m_FiberDirection.Normalize(); vnl_vector_fixed axis = itk::CrossProduct(m_KernelDirection, this->m_FiberDirection).GetVnlVector(); axis.normalize(); vnl_quaternion rotation(axis, acos(m_KernelDirection*this->m_FiberDirection)); rotation.normalize(); vnl_matrix_fixed matrix = rotation.rotation_matrix_transpose(); vnl_matrix_fixed tensorMatrix = matrix.transpose()*m_KernelTensorMatrix*matrix; tensor[0] = tensorMatrix[0][0]; tensor[1] = tensorMatrix[0][1]; tensor[2] = tensorMatrix[0][2]; tensor[3] = tensorMatrix[1][1]; tensor[4] = tensorMatrix[1][2]; tensor[5] = tensorMatrix[2][2]; for( unsigned int i=0; im_GradientList.size(); i++) { GradientType g = this->m_GradientList[i]; + double bVal = g.GetNorm(); bVal *= bVal; - if (g.GetNorm()>0.0001) + if (bVal>0.0001) { itk::DiffusionTensor3D S; S[0] = g[0]*g[0]; S[1] = g[1]*g[0]; S[2] = g[2]*g[0]; S[3] = g[1]*g[1]; S[4] = g[2]*g[1]; S[5] = g[2]*g[2]; double D = tensor[0]*S[0] + tensor[1]*S[1] + tensor[2]*S[2] + tensor[1]*S[1] + tensor[3]*S[3] + tensor[4]*S[4] + tensor[2]*S[2] + tensor[4]*S[4] + tensor[5]*S[5]; // check for corrupted tensor and generate signal if (D>=0) - signal[i] = exp ( -m_BValue * D ); + signal[i] = exp ( -m_BValue * bVal * D ); } else signal[i] = 1; } return signal; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index ca99c35985..9d33168ac2 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,922 +1,935 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkFiberfoxView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImage( NULL ) , m_SelectedBundle( NULL ) { } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { } void QmitkFiberfoxView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); + m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_T2bluringParamFrame->setVisible(false); m_Controls->m_KspaceParamFrame->setVisible(false); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberSamplingChanged(int))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); connect((QObject*) m_Controls->m_AddT2Smearing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddT2Smearing(int))); connect((QObject*) m_Controls->m_AddGibbsRinging, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGibbsRinging(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(TransformBundles())); } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddT2Smearing(int value) { if (value>0) m_Controls->m_T2bluringParamFrame->setVisible(true); else m_Controls->m_T2bluringParamFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGibbsRinging(int value) { if (value>0) m_Controls->m_KspaceParamFrame->setVisible(true); else m_Controls->m_KspaceParamFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(int value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; vnl_vector theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); for (int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } return retval; } void QmitkFiberfoxView::OnAddBundle() { if (m_SelectedImage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage); mitk::FiberBundleX::Pointer bundle = mitk::FiberBundleX::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundle = node; m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImage); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundle.IsNull()) OnAddBundle(); if (m_SelectedBundle.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundle); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); GetDataStorage()->Add(node, m_SelectedBundle); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); UpdateGui(); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return li > fiducials; vector< vector< unsigned int > > fliplist; for (int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); sort(childVector.begin(), childVector.end(), CompareLayer); vector< mitk::PlanarEllipse::Pointer > fib; vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) radius = v.GetVnlVector().magnitude(); else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { fiducials.push_back(fib); fliplist.push_back(flip); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (fib.size()<3) return; } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetFiducials(fiducials); filter->SetFlipList(fliplist); switch(m_Controls->m_DistributionBox->currentIndex()){ case 0: filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_UNIFORM); break; case 1: filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_GAUSSIAN); filter->SetVariance(m_Controls->m_VarianceBox->value()); break; } filter->SetDensity(m_Controls->m_FiberDensityBox->value()); filter->SetTension(m_Controls->m_TensionBox->value()); filter->SetContinuity(m_Controls->m_ContinuityBox->value()); filter->SetBias(m_Controls->m_BiasBox->value()); filter->SetFiberSampling(m_Controls->m_FiberSamplingBox->value()); filter->Update(); vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); for (int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { itk::ImageRegion<3> imageRegion; imageRegion.SetSize(0, m_Controls->m_SizeX->currentText().toInt()); imageRegion.SetSize(1, m_Controls->m_SizeY->currentText().toInt()); imageRegion.SetSize(2, m_Controls->m_SizeZ->currentText().toInt()); mitk::Vector3D spacing; spacing[0] = m_Controls->m_SpacingX->value(); spacing[1] = m_Controls->m_SpacingY->value(); spacing[2] = m_Controls->m_SpacingZ->value(); mitk::Point3D origin; origin.Fill(0.0); itk::Matrix directionMatrix; directionMatrix.SetIdentity(); if (m_SelectedBundle.IsNull()) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->currentText().toInt(), m_Controls->m_SizeY->currentText().toInt(), m_Controls->m_SizeZ->currentText().toInt(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); GetDataStorage()->Add(node); m_SelectedImage = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); return; } DiffusionSignalModel::GradientListType gradientList; double bVal = 1000; if (m_SelectedDWI.IsNull()) { gradientList = GenerateHalfShell(m_Controls->m_NumGradientsBox->value());; - bVal = m_Controls->m_TensorsToDWIBValueEdit->value(); + bVal = m_Controls->m_BvalueBox->value(); } else { mitk::DiffusionImage::Pointer dwi = dynamic_cast*>(m_SelectedDWI->GetData()); bVal = dwi->GetB_Value(); mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = dwi->GetDirectionsWithMeasurementFrame(); for (int i=0; iSize(); i++) { DiffusionSignalModel::GradientType g; g[0] = dirs->at(i)[0]; g[1] = dirs->at(i)[1]; g[2] = dirs->at(i)[2]; gradientList.push_back(g); } } // signal models mitk::TensorModel extraAxonal; extraAxonal.SetGradientList(gradientList); extraAxonal.SetBvalue(bVal); extraAxonal.SetKernelFA(m_Controls->m_MaxFaBox->value()); extraAxonal.SetSignalScale(m_Controls->m_FiberS0Box->value()); extraAxonal.SetRelaxationT2(m_Controls->m_FiberRelaxationT2Box->value()); // mitk::StickModel intraAxonal; // intraAxonal.SetGradientList(gradientList); // intraAxonal.SetDiffusivity(m_Controls->m_MaxFaBox->value()); // intraAxonal.SetSignalScale(m_Controls->m_FiberS0Box->value()); // intraAxonal.SetRelaxationT2(m_Controls->m_FiberRelaxationT2Box->value()); mitk::BallModel freeDiffusion; freeDiffusion.SetGradientList(gradientList); freeDiffusion.SetBvalue(bVal); freeDiffusion.SetSignalScale(m_Controls->m_NonFiberS0Box->value()); freeDiffusion.SetRelaxationT2(m_Controls->m_NonFiberRelaxationT2Box->value()); itk::TractsToDWIImageFilter::DiffusionModelList modelList; itk::TractsToDWIImageFilter::KspaceArtifactList artifactList; // noise model double snr = m_Controls->m_NoiseLevel->value(); double noiseVariance = 0; if (snr <= 0) snr = 0.0001; if (snr<=99) { - noiseVariance = 1/snr; + noiseVariance = (double)m_Controls->m_FiberS0Box->value()/snr; noiseVariance *= noiseVariance; } mitk::RicianNoiseModel noiseModel; - noiseModel.SetScaleFactor(m_Controls->m_FiberS0Box->value()); noiseModel.SetNoiseVariance(noiseVariance); // artifact models mitk::GibbsRingingArtifact gibbsModel; if (m_Controls->m_AddGibbsRinging->isChecked()) { gibbsModel.SetKspaceCropping((double)m_Controls->m_KspaceUndersamplingBox->currentText().toInt()); artifactList.push_back(&gibbsModel); } mitk::T2SmearingArtifact t2Model; if (m_Controls->m_AddT2Smearing->isChecked()) { t2Model.SetReadoutPulseLength(1); artifactList.push_back(&t2Model); } for (int i=0; i(m_SelectedBundles.at(i)->GetData()); if (fiberBundle->GetNumFibers()<=0) continue; itk::TractsToDWIImageFilter::Pointer filter = itk::TractsToDWIImageFilter::New(); filter->SetImageRegion(imageRegion); filter->SetSpacing(spacing); filter->SetFiberBundle(fiberBundle); modelList.push_back(&extraAxonal); // modelList.push_back(&intraAxonal); filter->SetFiberModels(modelList); modelList.clear(); modelList.push_back(&freeDiffusion); filter->SetNonFiberModels(modelList); filter->SetNoiseModel(&noiseModel); filter->SetKspaceArtifacts(artifactList); filter->SetVolumeAccuracy(m_Controls->m_VolumeAccuracyBox->value()); filter->SetNumberOfRepetitions(m_Controls->m_RepetitionsBox->value()); filter->SetEnforcePureFiberVoxels(m_Controls->m_EnforcePureFiberVoxelsBox->isChecked()); if (m_TissueMask.IsNotNull()) { ItkUcharImgType::Pointer mask = ItkUcharImgType::New(); mitk::CastToItkImage(m_TissueMask, mask); filter->SetTissueMask(mask); } filter->Update(); mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(bVal); image->SetDirections(gradientList); image->InitializeFromVectorImage(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(m_Controls->m_ImageName->text().toStdString()); GetDataStorage()->Add(node, m_SelectedBundle); if (m_Controls->m_KspaceImageBox->isChecked()) { itk::Image::Pointer kspace = filter->GetKspaceImage(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(kspace.GetPointer()); image->SetVolume(kspace->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("k-space"); node->SetBoolProperty("use color", false); GetDataStorage()->Add(node, m_SelectedBundle); } mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkFiberfoxView::TransformBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); for (it; it!=m_SelectedBundles.end(); ++it) { mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); for (it; it!=m_SelectedBundles.end(); ++it) { mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundleX::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { if (m_SelectedFiducial.IsNotNull()) m_Controls->m_FlipButton->setEnabled(true); else m_Controls->m_FlipButton->setEnabled(false); if (m_SelectedImage.IsNotNull()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } else if (m_SelectedBundle.IsNull()) { m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_FiberGenMessage->setVisible(true); } + if (m_SelectedDWI.IsNotNull()) + { + m_Controls->m_DiffusionPropsMessage->setVisible(true); + m_Controls->m_BvalueBox->setEnabled(false); + m_Controls->m_NumGradientsBox->setEnabled(false); + } + else + { + m_Controls->m_DiffusionPropsMessage->setVisible(false); + m_Controls->m_BvalueBox->setEnabled(true); + m_Controls->m_NumGradientsBox->setEnabled(true); + } + if (m_SelectedBundle.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); m_Controls->m_FiberBundleLabel->setText(m_SelectedBundle->GetName().c_str()); } else { m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FiberBundleLabel->setText("mandatory"); } if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); else m_Controls->m_JoinBundlesButton->setEnabled(false); } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedFiducial = NULL; m_TissueMask = NULL; m_SelectedBundles.clear(); m_SelectedBundle = NULL; m_SelectedImage = NULL; m_SelectedDWI = NULL; m_Controls->m_TissueMaskLabel->setText("optional"); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_GeometryFrame->setEnabled(true); // iterate all selected objects, adjust warning visibility for( int i=0; i*>(node->GetData()) ) { m_SelectedDWI = node; } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImage = node; bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) { m_TissueMask = dynamic_cast(node->GetData()); m_Controls->m_TissueMaskLabel->setText(node->GetName().c_str()); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { if (m_Controls->m_RealTimeFibers->isChecked() && node!=m_SelectedBundle) { m_SelectedBundle = node; m_SelectedBundles.push_back(node); mitk::FiberBundleX::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else { m_SelectedBundle = node; m_SelectedBundles.push_back(node); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) { m_SelectedBundle = pNode; m_SelectedBundles.push_back(pNode); } } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { MITK_DEBUG << "EnableCrosshairNavigation"; // enable the crosshair navigation if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "enabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(true); // linkedRenderWindow->EnableSlicingPlanes(true); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { MITK_DEBUG << "DisableCrosshairNavigation"; // disable the crosshair navigation during the drawing if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "disabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(false); // linkedRenderWindow->EnableSlicingPlanes(false); } } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { if (node == m_SelectedImage) m_SelectedImage = NULL; if (node == m_SelectedBundle) m_SelectedBundle = NULL; mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetInteractor()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", nonConstNode); } else { // just to be sure that the interactor is not added twice mitk::GlobalInteraction::GetInstance()->RemoveInteractor(figureInteractor); } MITK_DEBUG << "adding interactor to globalinteraction"; mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui index c28f9ea5bb..8d3db0bbc7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,1747 +1,1757 @@ QmitkFiberfoxViewControls 0 0 493 - 886 + 909 Form 0 Fiber Generation Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true color: rgb(255, 0, 0); Please select an image to draw the fiber fiducials. If you can't provide a suitable image, generate one using the "Signal Generation" tab. Qt::AutoText Qt::AlignJustify|Qt::AlignVCenter true All fiducials are treated as circles with the same radius as the first fiducial. Use Constant Fiducial Radius false Fiber Operations false Transform Bundles QFrame::NoFrame QFrame::Raised 0 X false Y false Translation: false Rotation: false Z false Axis: false Rotation angle (in degree) around x-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Rotation angle (in degree) around y-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Rotation angle (in degree) around z-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. -100.000000000000000 100.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. -100.000000000000000 100.000000000000000 0.100000000000000 Translation (in mm) in direction of the z-axis. -100.000000000000000 100.000000000000000 0.100000000000000 false Copy Bundles false Join Bundles Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 Fiber Sampling: false Fiber sampling points (per cm) 1 100 1 10 Tension: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 QFrame::NoFrame QFrame::Raised 0 false 30 30 Draw elliptical fiducial. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true false 30 30 Flip fiber waypoints of selcted fiducial around one axis. :/QmitkDiffusionImaging/refresh.xpm:/QmitkDiffusionImaging/refresh.xpm 32 32 false true Qt::Horizontal 40 20 QFrame::NoFrame QFrame::Raised 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 false Generate Fibers Signal Generation true Start DWI generation from selected fiebr bundle. If no fiber bundle is selected, a grayscale image containing a simple gradient is generated. Generate Image Noise and Artifacts true QFrame::NoFrame QFrame::Raised 6 0 k-Space undersampling: false Image is upsampled using this factor, afterwards fourier transformed, cropped to the original size and then inverse fourier transformed. 1 2 4 8 16 32 64 128 256 Add T2 Blurring false QFrame::NoFrame QFrame::Raised 0 SNR: Signal to noise ratio (for values > 99, no noise at all is added to the image). Value relative to the fiber signal scaling factor. 4 0.000000000000000 100.000000000000000 0.001000000000000 15.000000000000000 true QFrame::NoFrame QFrame::Raised 0 Fiber T2: false T2 of fiber tissue (in milliseconds). 1 10000 1 90 Non Fiber T2: false T2 of non-fiber tissue (in milliseconds). 1 10000 1 2200 Add Gibbs ringing false Data Fiber Bundle: false <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> Output Name: false phantom Tissue Mask: false <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> Image Settings QFrame::NoFrame QFrame::Raised 0 - - + + 3 0.100000000000000 50.000000000000000 0.100000000000000 2.500000000000000 - - - - Image Spacing: - - - - - - - Image Dimensions: - - - - - + + 3 0.100000000000000 50.000000000000000 0.100000000000000 2.500000000000000 + + + + Image Spacing: + + + + + + + Image Dimensions: + + + 4 4 8 16 32 64 128 256 512 1024 2048 4096 4 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 3 0.100000000000000 50.000000000000000 0.100000000000000 2.500000000000000 4 4 8 16 32 64 128 256 512 1024 2048 4096 Output k-space image false QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 6 0 #Gradient Directions: 1 10000 1 60 b-value: false - + 0 10000 100 1000 Kernel FA: Signal model parameter. Determins anisotropy of kernel tensor. 0.010000000000000 1.000000000000000 0.100000000000000 0.700000000000000 Fiber S0: false Scaling factor of fiber signal. 0 10000 1 200 Non Fiber S0: false Scaling factor of non-fiber signal. 0 10000 1 1000 Volume Accuracy: false Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 100 1 5 Repetitions: 1 100 1 1 color: rgb(255, 0, 0); Using mask image geometry! Treat voxel content as fiber-only if at least one fiber is present. Enforce Pure Fiber Voxels false + + + + color: rgb(255, 0, 0); + + + Using gradients of selected DWI! + + + Qt::Vertical 20 40 tabWidget m_RealTimeFibers m_CircleButton m_FlipButton m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_DistributionBox m_VarianceBox m_GenerateFibersButton m_ImageName m_GenerateImageButton m_KspaceImageBox m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox - m_TensorsToDWIBValueEdit + m_BvalueBox m_MaxFaBox m_FiberS0Box m_NonFiberS0Box m_VolumeAccuracyBox m_NoiseLevel m_AddT2Smearing m_FiberRelaxationT2Box m_NonFiberRelaxationT2Box m_AddGibbsRinging m_KspaceUndersamplingBox