diff --git a/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp index 2e5691312f..44fda2c997 100644 --- a/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,620 +1,624 @@ /*=================================================================== 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!"); + int baselineIndex = m_FiberModels[0]->GetFirstBaselineIndex(); + if (baselineIndex<0) + itkExceptionMacro("No baseline index found!"); + // 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) + 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]; + if (pix[baselineIndex]>maxFiberDensity) + maxFiberDensity = pix[baselineIndex]; } } } } } } 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; + double w = compartments.at(0)->GetPixel(index)[baselineIndex]/maxFiberDensity; if (m_EnforcePureFiberVoxels && w>0) w = 1; // adjust fiber signal for (int i=0; iGetPixel(index); - if (pix[0]>0) - pix /= pix[0]; + if (pix[baselineIndex]>0) + pix /= pix[baselineIndex]; 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]; + if (pix[baselineIndex]>0) + pix /= pix[baselineIndex]; pix *= (1-w)/m_NonFiberModels.size(); doubleDwi->SetPixel(index, pix); } } ++it3; } } // do k-space stuff if (!m_KspaceArtifacts.empty()) MITK_INFO << "Generating k-space artifacts"; else MITK_INFO << "Generating k-space image"; compartments = AddKspaceArtifacts(compartments); MITK_INFO << "Summing compartments and adding noise"; double correction = m_Upsampling*m_Upsampling; 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()/correction; signal += compartments.at(i)->GetPixel(index)*s; } // adjust non-fiber signal for (int i=0; iGetSignalScale()/correction; 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/mitkDiffusionSignalModel.h b/Modules/DiffusionImaging/SignalModels/mitkDiffusionSignalModel.h index 5a5eda99a2..eca85986e5 100644 --- a/Modules/DiffusionImaging/SignalModels/mitkDiffusionSignalModel.h +++ b/Modules/DiffusionImaging/SignalModels/mitkDiffusionSignalModel.h @@ -1,66 +1,81 @@ /*=================================================================== 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_DiffusionSignalModel_H #define _MITK_DiffusionSignalModel_H #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion signal models * */ template< class ScalarType > class DiffusionSignalModel { public: DiffusionSignalModel() : m_SignalScale(200){} ~DiffusionSignalModel(){} typedef itk::VariableLengthVector< ScalarType > PixelType; typedef itk::Vector GradientType; typedef std::vector GradientListType; /** Realizes actual signal generation. Has to be implemented in subclass. **/ virtual PixelType SimulateMeasurement() = 0; void SetFiberDirection(GradientType fiberDirection){ m_FiberDirection = fiberDirection; } void SetGradientList(GradientListType gradientList) { m_GradientList = gradientList; } void SetSignalScale(ScalarType signalScale) { m_SignalScale = signalScale; } void SetRelaxationT2(double T2) { m_RelaxationT2 = T2; } double GetRelaxationT2() { return m_RelaxationT2; } ScalarType GetSignalScale() { return m_SignalScale; } int GetNumGradients(){ return m_GradientList.size(); } + std::vector< int > GetBaselineIndices() + { + std::vector< int > result; + for( unsigned int i=0; im_GradientList.size(); i++) + if (m_GradientList.at(i).GetNorm()<0.0001) + result.push_back(i); + return result; + } + int GetFirstBaselineIndex() + { + for( unsigned int i=0; im_GradientList.size(); i++) + if (m_GradientList.at(i).GetNorm()<0.0001) + return i; + return -1; + } protected: GradientType m_FiberDirection; ///< Needed to generate anisotropc signal to determin direction of anisotropy GradientListType m_GradientList; ///< Diffusion gradient direction container ScalarType m_SignalScale; ///< Scaling factor for signal value double m_RelaxationT2; ///< Tissue specific relaxation time (used for artificial artifacts) }; } #endif 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 9d33168ac2..aa89970107 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,935 +1,934 @@ /*=================================================================== 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); + GradientListType pointshell; - vnl_vector phi; phi.set_size(NPoints); + int numB0 = NPoints/10; + if (numB0==0) + numB0=1; + GradientType g; + g.Fill(0.0); + for (int i=0; i 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_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 = (double)m_Controls->m_FiberS0Box->value()/snr; noiseVariance *= noiseVariance; } mitk::RicianNoiseModel noiseModel; 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 8d3db0bbc7..65d6ee769a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,1757 +1,1757 @@ QmitkFiberfoxViewControls 0 0 493 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 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 + 0 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_BvalueBox m_MaxFaBox m_FiberS0Box m_NonFiberS0Box m_VolumeAccuracyBox m_NoiseLevel m_AddT2Smearing m_FiberRelaxationT2Box m_NonFiberRelaxationT2Box m_AddGibbsRinging m_KspaceUndersamplingBox