diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h index 7a467447ba..267f5e8b8c 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h @@ -1,97 +1,97 @@ /*=================================================================== 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 __itkAddArtifactsToDwiImageFilter_h_ #define __itkAddArtifactsToDwiImageFilter_h_ #include "FiberTrackingExports.h" #include #include #include #include #include #include namespace itk{ /** * \brief Adds several artifacts to the input DWI. */ template< class TPixelType > class AddArtifactsToDwiImageFilter : public ImageToImageFilter< VectorImage< TPixelType, 3 >, VectorImage< TPixelType, 3 > > { public: typedef AddArtifactsToDwiImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< VectorImage< TPixelType, 3 >, VectorImage< TPixelType, 3 > > Superclass; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Runtime information support. */ itkTypeMacro(AddArtifactsToDwiImageFilter, ImageToImageFilter) typedef typename Superclass::InputImageType DiffusionImageType; - typedef mitk::DiffusionNoiseModel NoiseModelType; + typedef mitk::DiffusionNoiseModel NoiseModelType; typedef itk::Image< double, 2 > SliceType; typedef typename itk::KspaceImageFilter< double >::OutputImageType ComplexSliceType; typedef itk::Image ItkDoubleImgType; typedef itk::Matrix MatrixType; void SetNoiseModel(NoiseModelType* noiseModel){ m_NoiseModel = noiseModel; } itkSetMacro( FrequencyMap, ItkDoubleImgType::Pointer ) itkSetMacro( kOffset, double ) itkSetMacro( tLine, double ) itkSetMacro( SimulateEddyCurrents, bool ) itkSetMacro( EddyGradientStrength, double ) void SetGradientList(mitk::DiffusionSignalModel::GradientListType list) { m_GradientList=list; } itkSetMacro( TE, double ) itkSetMacro( Upsampling, double ) protected: AddArtifactsToDwiImageFilter(); ~AddArtifactsToDwiImageFilter() {} typename ComplexSliceType::Pointer RearrangeSlice(typename ComplexSliceType::Pointer slice); void GenerateData(); NoiseModelType* m_NoiseModel; ItkDoubleImgType::Pointer m_FrequencyMap; double m_kOffset; double m_tLine; bool m_SimulateEddyCurrents; double m_EddyGradientStrength; mitk::DiffusionSignalModel::GradientListType m_GradientList; double m_TE; double m_Upsampling; ///< causes ringing artifacts private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkAddArtifactsToDwiImageFilter.cpp" #endif #endif //__itkAddArtifactsToDwiImageFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp index 7d34b094ff..5587282de6 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp @@ -1,237 +1,237 @@ /*=================================================================== 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 __itkKspaceImageFilter_txx #define __itkKspaceImageFilter_txx #include #include #include #include "itkKspaceImageFilter.h" #include #include #include #include #define _USE_MATH_DEFINES #include namespace itk { template< class TPixelType > KspaceImageFilter< TPixelType > ::KspaceImageFilter() : m_tLine(1) , m_kOffset(0) , m_FrequencyMap(NULL) , m_SimulateRelaxation(true) , m_SimulateEddyCurrents(false) , m_Tau(70) , m_EddyGradientMagnitude(30) , m_IsBaseline(true) , m_SignalScale(1) { m_DiffusionGradientDirection.Fill(0.0); } template< class TPixelType > void KspaceImageFilter< TPixelType > ::BeforeThreadedGenerateData() { typename OutputImageType::Pointer outputImage = OutputImageType::New(); outputImage->SetSpacing( m_CompartmentImages.at(0)->GetSpacing() ); outputImage->SetOrigin( m_CompartmentImages.at(0)->GetOrigin() ); outputImage->SetDirection( m_CompartmentImages.at(0)->GetDirection() ); itk::ImageRegion<2> region; region.SetSize(0, m_OutSize[0]); region.SetSize(1, m_OutSize[1]); outputImage->SetLargestPossibleRegion( region ); outputImage->SetBufferedRegion( region ); outputImage->SetRequestedRegion( region ); outputImage->Allocate(); m_TEMPIMAGE = InputImageType::New(); m_TEMPIMAGE->SetSpacing( m_CompartmentImages.at(0)->GetSpacing() ); m_TEMPIMAGE->SetOrigin( m_CompartmentImages.at(0)->GetOrigin() ); m_TEMPIMAGE->SetDirection( m_CompartmentImages.at(0)->GetDirection() ); m_TEMPIMAGE->SetLargestPossibleRegion( region ); m_TEMPIMAGE->SetBufferedRegion( region ); m_TEMPIMAGE->SetRequestedRegion( region ); m_TEMPIMAGE->Allocate(); m_SimulateDistortions = true; if (m_FrequencyMap.IsNull()) { m_SimulateDistortions = false; m_FrequencyMap = InputImageType::New(); m_FrequencyMap->SetSpacing( m_CompartmentImages.at(0)->GetSpacing() ); m_FrequencyMap->SetOrigin( m_CompartmentImages.at(0)->GetOrigin() ); m_FrequencyMap->SetDirection( m_CompartmentImages.at(0)->GetDirection() ); m_FrequencyMap->SetLargestPossibleRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); m_FrequencyMap->SetBufferedRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); m_FrequencyMap->SetRequestedRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); m_FrequencyMap->Allocate(); m_FrequencyMap->FillBuffer(0); } double gamma = 42576000; // Gyromagnetic ratio in Hz/T if (m_DiffusionGradientDirection.GetNorm()>0.001) { m_DiffusionGradientDirection.Normalize(); m_EddyGradientMagnitude /= 1000; // eddy gradient magnitude in T/m m_DiffusionGradientDirection = m_DiffusionGradientDirection * m_EddyGradientMagnitude * gamma; m_IsBaseline = false; } else m_EddyGradientMagnitude = gamma*m_EddyGradientMagnitude/1000; this->SetNthOutput(0, outputImage); } template< class TPixelType > void KspaceImageFilter< TPixelType > ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType threadId) { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread); typedef ImageRegionConstIterator< InputImageType > InputIteratorType; double szx = outputImage->GetLargestPossibleRegion().GetSize(0); double szy = outputImage->GetLargestPossibleRegion().GetSize(1); double numPix = szx*szy; double dt = m_tLine/szx; double fromMaxEcho = - m_tLine*szy/2; double in_szx = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(0); double in_szy = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(1); int xOffset = in_szx-szx; int yOffset = in_szy-szy; while( !oit.IsAtEnd() ) { itk::Index< 2 > kIdx; kIdx[0] = oit.GetIndex()[0]; kIdx[1] = oit.GetIndex()[1]; double t = fromMaxEcho + ((double)kIdx[1]*szx+(double)kIdx[0])*dt; // dephasing time // rearrange slice if( kIdx[0] < szx/2 ) kIdx[0] = kIdx[0] + szx/2; else kIdx[0] = kIdx[0] - szx/2; if( kIdx[1] < szx/2 ) kIdx[1] = kIdx[1] + szy/2; else kIdx[1] = kIdx[1] - szy/2; // calculate eddy current decay factors double eddyDecay = 0; if (m_SimulateEddyCurrents) eddyDecay = exp(-(m_TE/2 + t)/m_Tau) * t/1000; // calcualte signal relaxation factors std::vector< double > relaxFactor; if (m_SimulateRelaxation) { for (int i=0; i s(0,0); InputIteratorType it(m_CompartmentImages.at(0), m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); while( !it.IsAtEnd() ) { double x = it.GetIndex()[0]; double y = it.GetIndex()[1]; vcl_complex f(0, 0); // sum compartment signals and simulate relaxation for (int i=0; i( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * relaxFactor.at(i) * m_SignalScale, 0); else f += std::complex( m_CompartmentImages.at(i)->GetPixel(it.GetIndex()) * m_SignalScale ); // simulate eddy currents and other distortions double omega_t = 0; if ( m_SimulateEddyCurrents ) { if (!m_IsBaseline) { itk::Vector< double, 3 > pos; pos[0] = x-szx/2; pos[1] = y-szy/2; pos[2] = m_Z; pos = m_DirectionMatrix*pos/1000; // vector from image center to current position (in meter) omega_t += (m_DiffusionGradientDirection[0]*pos[0]+m_DiffusionGradientDirection[1]*pos[1]+m_DiffusionGradientDirection[2]*pos[2])*eddyDecay; } else omega_t += m_EddyGradientMagnitude*eddyDecay; } if (m_SimulateDistortions) omega_t += m_FrequencyMap->GetPixel(it.GetIndex())*t/1000; // add gibbs ringing offset (cropps k-space) double tempOffsetX = 0; if (temp_kx>=szx/2) tempOffsetX = xOffset; double temp_ky = kIdx[1]; if (temp_ky>=szy/2) temp_ky += yOffset; // actual DFT term - s += f * exp( std::complex(0, 2 * M_PI * ((temp_kx+tempOffsetX)*x/in_szx + temp_ky*y/in_szy) + omega_t ) ); + s += f * exp( std::complex(0, 2 * M_PI * ((temp_kx+tempOffsetX)*x/in_szx + temp_ky*y/in_szy + omega_t )) ); ++it; } s /= numPix; m_TEMPIMAGE->SetPixel(kIdx, sqrt(s.real()*s.real()+s.imag()*s.imag())); outputImage->SetPixel(kIdx, s); ++oit; } // typedef itk::ImageFileWriter< InputImageType > WriterType; // typename WriterType::Pointer writer = WriterType::New(); // writer->SetFileName("/local/kspace.nrrd"); // writer->SetInput(m_TEMPIMAGE); // writer->Update(); } template< class TPixelType > void KspaceImageFilter< TPixelType > ::AfterThreadedGenerateData() { } } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 9a3f838d71..022fa7e40f 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,698 +1,711 @@ /*=================================================================== 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 #include #include namespace itk { -TractsToDWIImageFilter::TractsToDWIImageFilter() + +template< class PixelType > +TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() : m_CircleDummy(false) , m_VolumeAccuracy(10) , m_Upsampling(1) , m_NumberOfRepetitions(1) , m_EnforcePureFiberVoxels(false) , m_InterpolationShrink(1000) , m_FiberRadius(0) , m_SignalScale(25) , m_kOffset(0) , m_tLine(1) , m_UseInterpolation(false) , m_SimulateRelaxation(true) , m_tInhom(50) , m_TE(100) , m_FrequencyMap(NULL) , m_EddyGradientStrength(0.001) , m_SimulateEddyCurrents(false) { 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() +template< class PixelType > +TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } -TractsToDWIImageFilter::DoubleDwiType::Pointer TractsToDWIImageFilter::DoKspaceStuff( std::vector< DoubleDwiType::Pointer >& images ) +template< class PixelType > +TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >::DoKspaceStuff( std::vector< DoubleDwiType::Pointer >& images ) { // create slice object ImageRegion<2> sliceRegion; sliceRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); sliceRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); + Vector< double, 2 > sliceSpacing; + sliceSpacing[0] = m_UpsampledSpacing[0]; + sliceSpacing[1] = m_UpsampledSpacing[1]; // frequency map slice SliceType::Pointer fMap = NULL; if (m_FrequencyMap.IsNotNull()) { fMap = SliceType::New(); ImageRegion<2> region; region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); fMap->SetLargestPossibleRegion( region ); fMap->SetBufferedRegion( region ); fMap->SetRequestedRegion( region ); fMap->Allocate(); } DoubleDwiType::Pointer newImage = DoubleDwiType::New(); newImage->SetSpacing( m_Spacing ); newImage->SetOrigin( m_Origin ); newImage->SetDirection( m_DirectionMatrix ); newImage->SetLargestPossibleRegion( m_ImageRegion ); newImage->SetBufferedRegion( m_ImageRegion ); newImage->SetRequestedRegion( m_ImageRegion ); newImage->SetVectorLength( images.at(0)->GetVectorLength() ); newImage->Allocate(); MatrixType transform = m_DirectionMatrix; for (int i=0; i<3; i++) for (int j=0; j<3; j++) { if (j<2) transform[i][j] *= m_UpsampledSpacing[j]; else transform[i][j] *= m_Spacing[j]; } boost::progress_display disp(images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2)); for (int g=0; gGetVectorLength(); g++) for (int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { std::vector< SliceType::Pointer > compartmentSlices; std::vector< double > t2Vector; for (int i=0; i* signalModel; if (iSetLargestPossibleRegion( sliceRegion ); slice->SetBufferedRegion( sliceRegion ); slice->SetRequestedRegion( sliceRegion ); + slice->SetSpacing(sliceSpacing); slice->Allocate(); slice->FillBuffer(0.0); // 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; slice->SetPixel(index2D, images.at(i)->GetPixel(index3D)[g]); if (fMap.IsNotNull() && i==0) fMap->SetPixel(index2D, m_FrequencyMap->GetPixel(index3D)); } compartmentSlices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); } // create k-sapce (inverse fourier transform slices) itk::Size<2> outSize; outSize.SetElement(0, m_ImageRegion.GetSize(0)); outSize.SetElement(1, m_ImageRegion.GetSize(1)); itk::KspaceImageFilter< SliceType::PixelType >::Pointer idft = itk::KspaceImageFilter< SliceType::PixelType >::New(); idft->SetCompartmentImages(compartmentSlices); idft->SetT2(t2Vector); idft->SetkOffset(m_kOffset); idft->SettLine(m_tLine); idft->SetTE(m_TE); idft->SetTinhom(m_tInhom); idft->SetSimulateRelaxation(m_SimulateRelaxation); idft->SetSimulateEddyCurrents(m_SimulateEddyCurrents); idft->SetEddyGradientMagnitude(m_EddyGradientStrength); idft->SetZ((double)z-(double)images.at(0)->GetLargestPossibleRegion().GetSize(2)/2.0); idft->SetDirectionMatrix(transform); idft->SetDiffusionGradientDirection(m_FiberModels.at(0)->GetGradientDirection(g)); idft->SetFrequencyMap(fMap); idft->SetSignalScale(m_SignalScale); idft->SetOutSize(outSize); idft->Update(); ComplexSliceType::Pointer fSlice; fSlice = idft->GetOutput(); for (int i=0; iAddArtifact(fSlice); // fourier transform slice SliceType::Pointer newSlice; itk::DftImageFilter< SliceType::PixelType >::Pointer dft = itk::DftImageFilter< SliceType::PixelType >::New(); dft->SetInput(fSlice); dft->Update(); newSlice = dft->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; SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::PixelType pix3D = newImage->GetPixel(index3D); pix3D[g] = newSlice->GetPixel(index2D); newImage->SetPixel(index3D, pix3D); } ++disp; } return newImage; } -TractsToDWIImageFilter::ComplexSliceType::Pointer TractsToDWIImageFilter::RearrangeSlice(ComplexSliceType::Pointer slice) +template< class PixelType > +TractsToDWIImageFilter< PixelType >::ComplexSliceType::Pointer TractsToDWIImageFilter< PixelType >::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() +template< class PixelType > +void TractsToDWIImageFilter< PixelType >::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!"); // check k-space undersampling 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.00001) { MITK_INFO << "Adding ringing artifacts. Image upsampling factor: " << m_Upsampling; ImageRegion<3> region = m_ImageRegion; region.SetSize(0, m_ImageRegion.GetSize(0)*m_Upsampling); region.SetSize(1, m_ImageRegion.GetSize(1)*m_Upsampling); itk::Vector 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(); + typename 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; + typename 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=m_ImageRegion.GetSize(0); int y=m_ImageRegion.GetSize(1); if ( x%2 == 1 ) x += 1; if ( y%2 == 1 ) y += 1; // if not, adjust size and dimension (needed for FFT); zero-padding if (x!=m_ImageRegion.GetSize(0)) m_ImageRegion.SetSize(0, x); if (y!=m_ImageRegion.GetSize(1)) m_ImageRegion.SetSize(1, y); // 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 frequency map if (m_FrequencyMap.IsNotNull()) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(m_FrequencyMap); resampler->SetOutputParametersFromImage(m_FrequencyMap); resampler->SetSize(m_UpsampledImageRegion.GetSize()); resampler->SetOutputSpacing(m_UpsampledSpacing); resampler->Update(); m_FrequencyMap = resampler->GetOutput(); } // initialize volume fraction images m_VolumeFractions.clear(); for (int i=0; iSetSpacing( m_UpsampledSpacing ); tempimg->SetOrigin( m_Origin ); tempimg->SetDirection( m_DirectionMatrix ); tempimg->SetLargestPossibleRegion( m_UpsampledImageRegion ); tempimg->SetBufferedRegion( m_UpsampledImageRegion ); tempimg->SetRequestedRegion( m_UpsampledImageRegion ); tempimg->Allocate(); tempimg->FillBuffer(0); m_VolumeFractions.push_back(tempimg); } // resample fiber bundle for sufficient voxel coverage double segmentVolume = 0.0001; float minSpacing = 1; if(m_UpsampledSpacing[0]GetDeepCopy(); fiberBundle->ResampleFibers(minSpacing/m_VolumeAccuracy); double mmRadius = m_FiberRadius/1000; if (mmRadius>0) segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/m_VolumeAccuracy; // generate double images to work 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); } double interpFact = 2*atan(-0.5*m_InterpolationShrink); double maxVolume = 0; MITK_INFO << "Generating signal of " << m_FiberModels.size() << " fiber compartments"; vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); boost::progress_display disp(numFibers); for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (numPoints<2) continue; for( int j=0; jGetPoint(j); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(j+1))-v; else dir = v-GetItkVector(points->GetPoint(j-1)); itk::Index<3> idx; itk::ContinuousIndex contIndex; m_TissueMask->TransformPhysicalPointToIndex(vertex, idx); m_TissueMask->TransformPhysicalPointToContinuousIndex(vertex, contIndex); if (!m_UseInterpolation) // use nearest neighbour interpolation { if (!m_TissueMask->GetLargestPossibleRegion().IsInside(idx) || m_TissueMask->GetPixel(idx)<=0) continue; // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(idx); pix += segmentVolume*m_FiberModels[k]->SimulateMeasurement(); doubleDwi->SetPixel(idx, pix ); if (pix[baselineIndex]>maxVolume) maxVolume = pix[baselineIndex]; } continue; } 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; } frac_x = atan((0.5-frac_x)*m_InterpolationShrink)/interpFact + 0.5; frac_y = atan((0.5-frac_y)*m_InterpolationShrink)/interpFact + 0.5; frac_z = atan((0.5-frac_z)*m_InterpolationShrink)/interpFact + 0.5; // 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); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(newIdx); pix += segmentVolume*frac*m_FiberModels[k]->SimulateMeasurement(); doubleDwi->SetPixel(newIdx, pix ); if (pix[baselineIndex]>maxVolume) maxVolume = pix[baselineIndex]; } } } } } ++disp; } MITK_INFO << "Generating signal of " << m_NonFiberModels.size() << " non-fiber compartments"; ImageRegionIterator it3(m_TissueMask, m_TissueMask->GetLargestPossibleRegion()); boost::progress_display disp3(m_TissueMask->GetLargestPossibleRegion().GetNumberOfPixels()); double voxelVolume = m_UpsampledSpacing[0]*m_UpsampledSpacing[1]*m_UpsampledSpacing[2]; double fact = 1; if (m_FiberRadius<0.0001) fact = voxelVolume/maxVolume; while(!it3.IsAtEnd()) { DoubleDwiType::IndexType index = it3.GetIndex(); if (it3.Get()>0) { // get fiber volume fraction DoubleDwiType::Pointer fiberDwi = compartments.at(0); DoubleDwiType::PixelType fiberPix = fiberDwi->GetPixel(index); // intra axonal compartment if (fact>1) // auto scale intra-axonal if no fiber radius is specified { fiberPix *= fact; fiberDwi->SetPixel(index, fiberPix); } double f = fiberPix[baselineIndex]; if (f>voxelVolume || f>0 && m_EnforcePureFiberVoxels) // more fiber than space in voxel? { fiberDwi->SetPixel(index, fiberPix*voxelVolume/f); for (int i=1; iSetPixel(index, pix); m_VolumeFractions.at(i)->SetPixel(index, 1); } } else { m_VolumeFractions.at(0)->SetPixel(index, f); double nonf = voxelVolume-f; // non-fiber volume double inter = 0; if (m_FiberModels.size()>1) inter = nonf * f/voxelVolume; // intra-axonal fraction of non fiber compartment scales linearly with f double other = nonf - inter; // rest of compartment double singleinter = inter/(m_FiberModels.size()-1); // adjust non-fiber and intra-axonal signal for (int i=1; iGetPixel(index); if (pix[baselineIndex]>0) pix /= pix[baselineIndex]; pix *= singleinter; doubleDwi->SetPixel(index, pix); m_VolumeFractions.at(i)->SetPixel(index, singleinter/voxelVolume); } for (int i=0; iGetPixel(index) + m_NonFiberModels[i]->SimulateMeasurement()*other*m_NonFiberModels[i]->GetWeight(); doubleDwi->SetPixel(index, pix); m_VolumeFractions.at(i+m_FiberModels.size())->SetPixel(index, other/voxelVolume*m_NonFiberModels[i]->GetWeight()); } } } ++it3; ++disp3; } // do k-space stuff DoubleDwiType::Pointer doubleOutImage; if (m_FrequencyMap.IsNotNull() || !m_KspaceArtifacts.empty() || m_kOffset>0 || m_SimulateRelaxation || m_SimulateEddyCurrents || m_Upsampling>1.00001) { MITK_INFO << "Adjusting complex signal"; doubleOutImage = DoKspaceStuff(compartments); m_SignalScale = 1; } else { MITK_INFO << "Summing compartments"; doubleOutImage = compartments.at(0); for (int i=1; i::Pointer adder = itk::AddImageFilter< DoubleDwiType, DoubleDwiType, DoubleDwiType>::New(); adder->SetInput1(doubleOutImage); adder->SetInput2(compartments.at(i)); adder->Update(); doubleOutImage = adder->GetOutput(); } } MITK_INFO << "Finalizing image"; unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); - ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); + 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(); + typename OutputImageType::IndexType index = it4.GetIndex(); signal = doubleOutImage->GetPixel(index)*m_SignalScale; if (m_NoiseModel->GetNoiseVariance() > 0) { 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); if (!m_FiberModels.at(0)->IsBaselineIndex(i) && signal[i]>window) window = signal[i]; if (!m_FiberModels.at(0)->IsBaselineIndex(i) && signal[i]SetNthOutput(0, outImage); } -itk::Point TractsToDWIImageFilter::GetItkPoint(double point[3]) +template< class PixelType > +itk::Point TractsToDWIImageFilter< PixelType >::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]) +template< class PixelType > +itk::Vector TractsToDWIImageFilter< PixelType >::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]) +template< class PixelType > +vnl_vector_fixed TractsToDWIImageFilter< PixelType >::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) +template< class PixelType > +vnl_vector_fixed TractsToDWIImageFilter< PixelType >::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/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h index c09dfbc671..cf847f9b48 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,151 +1,153 @@ /*=================================================================== 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 __itkTractsToDWIImageFilter_h__ #define __itkTractsToDWIImageFilter_h__ // MITK #include #include #include #include // ITK #include #include #include #include #include #include -typedef itk::VectorImage< short, 3 > DWIImageType; namespace itk { /** * \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. */ -class TractsToDWIImageFilter : public ImageSource< DWIImageType > +template< class PixelType > +class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > > { public: + typedef TractsToDWIImageFilter Self; - typedef ImageSource< DWIImageType > Superclass; + typedef ImageSource< itk::VectorImage< PixelType, 3 > > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; + typedef typename Superclass::OutputImageType OutputImageType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; typedef mitk::FiberBundleX::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef std::vector< mitk::KspaceArtifact* > KspaceArtifactList; typedef std::vector< mitk::DiffusionSignalModel* > DiffusionModelList; typedef itk::Matrix MatrixType; typedef mitk::DiffusionNoiseModel NoiseModelType; typedef itk::Image< double, 2 > SliceType; typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; itkNewMacro(Self) itkTypeMacro( TractsToDWIImageFilter, ImageToImageFilter ) // input itkSetMacro( SignalScale, double ) itkSetMacro( FiberRadius, double ) itkSetMacro( InterpolationShrink, double ) ///< large values shrink (towards nearest neighbour interpolation), small values strech interpolation function (towards linear interpolation) itkSetMacro( VolumeAccuracy, unsigned int ) ///< determines fiber sampling density and thereby the accuracy of the fiber volume fraction itkSetMacro( FiberBundle, FiberBundleType ) ///< input fiber bundle itkSetMacro( Spacing, mitk::Vector3D ) ///< output image spacing itkSetMacro( Origin, mitk::Point3D ) ///< output image origin itkSetMacro( DirectionMatrix, MatrixType ) ///< output image rotation itkSetMacro( EnforcePureFiberVoxels, bool ) ///< treat all voxels containing at least one fiber as fiber-only (actually disable non-fiber compartments for this voxel). itkSetMacro( ImageRegion, ImageRegion<3> ) ///< output image size itkSetMacro( NumberOfRepetitions, unsigned int ) ///< number of acquisition repetitions to reduce noise (default is no additional repetition) itkSetMacro( TissueMask, ItkUcharImgType::Pointer ) ///< voxels outside of this binary mask contain only noise (are treated as air) void SetNoiseModel(NoiseModelType* noiseModel){ m_NoiseModel = noiseModel; } ///< generates the noise added to the image values void SetFiberModels(DiffusionModelList modelList){ m_FiberModels = modelList; } ///< generate signal of fiber compartments void SetNonFiberModels(DiffusionModelList modelList){ m_NonFiberModels = modelList; } ///< generate signal of non-fiber compartments void SetKspaceArtifacts(KspaceArtifactList artifactList){ m_KspaceArtifacts = artifactList; } mitk::LevelWindow GetLevelWindow(){ return m_LevelWindow; } itkSetMacro( FrequencyMap, ItkDoubleImgType::Pointer ) itkSetMacro( kOffset, double ) itkSetMacro( tLine, double ) itkSetMacro( tInhom, double ) itkSetMacro( TE, double ) itkSetMacro( UseInterpolation, bool ) itkSetMacro( SimulateEddyCurrents, bool ) itkSetMacro( SimulateRelaxation, bool ) itkSetMacro( EddyGradientStrength, double ) itkSetMacro( Upsampling, double ) // output std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions(){ return m_VolumeFractions; } void GenerateData(); protected: TractsToDWIImageFilter(); virtual ~TractsToDWIImageFilter(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< float, 3 >& vector); /** Transform generated image compartment by compartment, channel by channel and slice by slice using FFT and add k-space artifacts. */ DoubleDwiType::Pointer DoKspaceStuff(std::vector< DoubleDwiType::Pointer >& images); /** Rearrange FFT output to shift low frequencies to the iamge center (correct itk). */ TractsToDWIImageFilter::ComplexSliceType::Pointer RearrangeSlice(ComplexSliceType::Pointer slice); itk::Vector m_Spacing; ///< output image spacing itk::Vector m_UpsampledSpacing; mitk::Point3D m_Origin; ///< output image origin MatrixType m_DirectionMatrix; ///< output image rotation ImageRegion<3> m_ImageRegion; ///< output image size ImageRegion<3> m_UpsampledImageRegion; ItkUcharImgType::Pointer m_TissueMask; ///< voxels outside of this binary mask contain only noise (are treated as air) ItkDoubleImgType::Pointer m_FrequencyMap; ///< map of the B0 inhomogeneities double m_kOffset; double m_tLine; double m_TE; double m_tInhom; FiberBundleType m_FiberBundle; ///< input fiber bundle DiffusionModelList m_FiberModels; ///< generate signal of fiber compartments DiffusionModelList m_NonFiberModels; ///< generate signal of non-fiber compartments KspaceArtifactList m_KspaceArtifacts; NoiseModelType* m_NoiseModel; ///< generates the noise added to the image values bool m_CircleDummy; unsigned int m_VolumeAccuracy; double m_Upsampling; ///< causes ringing artifacts unsigned int m_NumberOfRepetitions; bool m_EnforcePureFiberVoxels; double m_InterpolationShrink; double m_FiberRadius; double m_SignalScale; mitk::LevelWindow m_LevelWindow; bool m_UseInterpolation; std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; ///< one double image for each compartment containing the corresponding volume fraction per voxel bool m_SimulateRelaxation; bool m_SimulateEddyCurrents; double m_EddyGradientStrength; }; } #include "itkTractsToDWIImageFilter.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.cpp b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.cpp index aa0a7b879b..e2fb8f7824 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.cpp +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.cpp @@ -1,41 +1,44 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include +#include + +using namespace mitk; template< class ScalarType > RicianNoiseModel< ScalarType >::RicianNoiseModel() { m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); this->m_NoiseVariance = 0; } template< class ScalarType > RicianNoiseModel< ScalarType >::~RicianNoiseModel() { } template< class ScalarType > void RicianNoiseModel< ScalarType >::AddNoise(PixelType& pixel) { for( unsigned int i=0; iGetNormalVariate(0.0, this->m_NoiseVariance), 2) + pow(m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance),2)); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox index 1361a54a73..1eb85b88f7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox @@ -1,111 +1,111 @@ /** \page org_mitk_views_fiberfoxview Fiberfox -This view provides the user interface for Fiberfox [1], an interactive simulation tool for defining artificial white matter fibers and generating corresponding diffusion weighted images. Arbitrary fiber configurations like bent, crossing, kissing, twisting, and fanning bundles can be intuitively defined by positioning only a few 3D waypoints to trigger the automated generation of synthetic fibers. From these fibers a diffusion weighted signal is simulated using a flexible combination of various diffusion models. It can be modified using specified acquisition settings such as gradient direction, b-value, signal-to-noise ratio, image size, and resolution. +This view provides the user interface for Fiberfox [1], an interactive simulation tool for defining artificial white matter fibers and generating corresponding diffusion weighted images. Arbitrary fiber configurations like bent, crossing, kissing, twisting, and fanning bundles can be intuitively defined by positioning only a few 3D waypoints to trigger the automated generation of synthetic fibers. From these fibers a diffusion weighted signal is simulated using a flexible combination of various diffusion models. It can be modified using specified acquisition settings such as gradient direction, b-value, signal-to-noise ratio, image size, and resolution. Additionally it enables the simulation of magnetic resonance artifacts including thermal noise, Gibbs ringing, N/2 ghosting and susceptibility distortions. The employed parameters can be saved and loaded as xml file with the ending ".ffp" (Fiberfox parameters). Available sections: - \ref QmitkFiberfoxViewUserManualFiberDefinition - \ref QmitkFiberfoxViewUserManualSignalGeneration - \ref QmitkFiberfoxViewUserManualKnownIssues - \ref QmitkFiberfoxViewUserManualReferences \image html Fiberfox.png Fig. 1: Screenshot of the Fiberfox framework. The four render windows display an axial (top left), sagittal (top right) and coronal (bottom left) 2D cut as well as a 3D view of a synthetic fiber helix and the fiducials used to define its shape. In the 2D views the helix is superimposing the baseline volume of the corresponding diffusion weighted image. The sagittal render window shows a close-up view on one of the circular fiducials. \section QmitkFiberfoxViewUserManualFiberDefinition Fiber Definition Fiber strands are defined simply by placing markers in a 3D image volume. The fibers are then interpolated between these fiducials. Example: \li Chose an image volume to place the markers used to define the fiber pathway. If you don't have such an image available switch to the "Signal Generation" tab, define the size and spacing of the desired image and click "Generate Image". If no fiber bundle is selected, this will generate a dummy image that can be used to place the fiducials. \li Start placing fiducials at the desired positions to define the fiber pathway. To do that, click on the button with the circle pictogram, then click at the desired position and plane in the image volume and drag your mouse while keeping the button pressed to generate a circular shape. Adjust the shape using the control points (Fig. 2). The position of control point D introduces a twist of the fibers between two successive fiducials. The actual fiber generation is triggered automatically as soon as you place the second control point. \li In some cases the fibers are entangled in a way that can't be resolved by introducing an additional fiber twist. Fiberfox tries to avoid these situations, which arise from different normal orientations of succeeding fiducials, automatically. In rare cases this is not successful. Use the double-arrow button to flip the fiber positions of the selected fiducial in one dimension. Either the problem is resolved now or you can resolve it manually by adjusting the twist-control point. \li To create non elliptical fiber profile shapes switch to the Fiber Extraction View. This view provides tools to extract subesets of fibers from fiber bundles and enables to cut out arbitrary polygonal fiber shapes from existing bundles. \image html Fiberfox-Fiducial.png Fig. 2: Control points defining the actual shape of the fiducial. A specifies the fiducials position in space, B and C the two ellipse radii and D the twisting angle between two successive fiducials. Fiber Options: \li Real Time Fibers: If checked, each parameter adjustment (fiducial position, number of fibers, ...) will be directly applied to the selected fiber bundle. If unchecked, the fibers will only be generated if the corresponding button "Generate Fibers" is clicked. \li Advanced Options: Show/hide advanced options \li #Fibers: Specifies the number of fibers that will be generated for the selected bundle. \li Fiber Sampling: Adjusts the distenace of the fiber sampling points (in mm). A higher sampling rate is needed if high curvatures are modeled. \li Tension, Continuity, Bias: Parameters controlling the shape of the splines interpolation the fiducials. See Wikipedia for details. Fiducial Options: \li Use Constant Fiducial Radius: If checked, all fiducials are treated as circles with the same radius. The first fiducial of the bundle defines the radius of all other fiducials. \li Align with grid: Click to shift all fiducial center points to the next voxel center. Operations: \li Rotation: Define the rotation of the selected fiber bundle around each axis (in degree). \li Translation: Define the translation of the selected fiber bundle along each axis (in mm). \li Scaling: Define a scaling factor for the selected fiber bundle in each dimension. \li Transform Selection: Apply specified rotation, translation and scaling to the selected Bundle/Fiducial \li Copy Bundles: Add copies of the selected fiber bundles to the datamanager. \li Join Bundles: Add new bundle to the datamanager that contains all fibers from the selected bundles. \li Include Fiducials: If checked, the specified transformation is also applied to the fiducials belonging to the selected fiber bundle and the fiducials are also copied. \image html FiberfoxExamples.png Fig. 3: Examples of artificial crossing (a,b), fanning (c,d), highly curved (e,f), kissing (g,h) and twisting (i,j) fibers as well as of the corresponding tensor images generated with Fiberfox. \section QmitkFiberfoxViewUserManualSignalGeneration Signal Generation To generate an artificial signal from the input fibers we follow the concepts recently presented by Panagiotaki et al. in a review and taxonomy of different compartment models [2]: a flexible model combining multiple compartments is used to simulate the anisotropic diffusion inside (intra-axonal compartment) and between axons (inter-axonal compartment), isotropic diffusion outside of the axons (extra-axonal compartment 1) and the restricted diffusion in other cell types (extra-axonal compartment 2) weighted according to their respective volume fraction. A diffusion weighted image is generated from the fibers by selecting the according fiber bundle in the datamanager and clicking "Generate Image". If some other diffusion weighted image is selected together with the fiber bundle, Fiberfox directly uses the parameters of the selected image (size, spacing, gradient directions, b-values) for the signal generation process. Additionally a binary image can be selected that defines the tissue area. Voxels outside of this mask will contain no signal, only noise. Basic Image Settings: \li Image Dimensions: Specifies actual image size (number of voxels in each dimension). \li Image Spacing: Specifies voxel size in mm. Beware that changing the voxel size also changes the signal strength, e.g. increasing the resolution from 2x2x2 mm to 1x1x1 mm decreases the signal obtained for each voxel by a factor 8. \li Gradient Directions: Number of gradients directions distributed equally over the half sphere. 10% baseline images are automatically added. \li b-Value: Diffusion weighting in s/mm². If an existing diffusion weighted image is used to set the basic parameters, the b-value is defined by the gradient direction magnitudes of this image, which also enables the use of multiple b-values. Advanced Image Settings (activate checkbox "Advanced Options"): \li Repetitions: Specifies the number of averages used for the acquisition to reduce noise. \li Signal Scale: Additional scaling factor for the signal in each voxel. The default value of 125 results in a maximum signal amplitude of 1000 for 2x2x2 mm voxels. Beware that changing this value without changing the noise variance results in a changed SNR. Adjustment of this value might be needed if the overall signal values are much too high or much too low (depends on a variety of factors like voxel size and relaxation times). \li Echo Time TE: Time between the 90° excitation pulse and the first spin echo. Increasing this time results in a stronger T2-relaxation effect (Wikipedia). \li Line Readout Time: Time to read one line in k-space. Increasing this time results in a stronger T2* effect which causes an attenuation of the higher frequencies in phase direction (here along y-axis) which again results in a blurring effect of sharp edges perpendicular to the phase direction. \li Tinhom Relaxation: Time constant specifying the signal decay due to magnetic field inhomogeneities (also called T2'). Together with the tissue specific relaxation time constant T2 this defines the T2* decay constant: T2*=(T2 T2')/(T2+T2') \li Fiber Radius (in µm): Used to calculate the volume fractions of the used compartments (fiber, water, etc.). If set to 0 (default) the fiber radius is set automatically so that the voxel containing the most fibers is filled completely. A realistic axon radius ranges from about 5 to 20 microns. Using the automatic estimation the resulting value might very well be much larger or smaller than this range. \li Interpolation Shrink: The signal generated at each position along the fibers is distributed on the surrounding voxels using an interpolation scheme shaped like an arctangent function. Large values result in a steeper interpolation scheme approximating a nearest neighbor interpolation. Very small values result in an almost linear interpolation. \li Simulate Signal Relaxation: If checked, the relaxation induced signal decay is simulated, other wise the parameters TE, Line Readout Time, Tinhom, and T2 are ignored. \li Disable Partial Volume Effects: If checked, the actual volume fractions of the single compartments are ignored. A voxel will either be filled by the intra axonal compartment completely or will contain no fiber at all. \li Output k-Space Image: Some of the effects simulated in our framework are modeled in the k-space representation of the actual image. Checking this box will output this frequency representation (amplitude spectrum). Compartment Settings: The group-boxes "Intra-axonal Compartment", "Inter-axonal Compartment" and "Extra-axonal Compartments" allow the specification which model to use and the corresponding model parameters. Currently the following models are implemented: \li Stick: The “stick” model describes diffusion in an idealized cylinder with zero radius. Parameter: Diffusivity d \li Zeppelin: Cylindrically symmetric diffusion tensor. Parameters: Parallel diffusivity d|| and perpendicular diffusivity d \li Tensor: Full diffusion tensor. Parameters: Parallel diffusivity d|| and perpendicular diffusivity constants d⊥1 and d⊥2 \li Ball: Isotropic compartment. Parameter: Diffusivity d \li Astrosticks: Consists of multiple stick models pointing in different directions. The single stick orientations can either be distributed equally over the sphere or are sampled randomly. The model represents signal coming from a type of glial cell called astrocytes, or populations of axons with arbitrary orientation. Parameters: randomization of the stick orientations and diffusivity of the sticks d. \li Dot: Isotropically restricted compartment. No parameter. For a detailed description of the single models, please refer to Panagiotaki et al. "Compartment models of the diffusion MR signal in brain white matter: A taxonomy and comparison."[2]. Additionally to the model parameters, each compartment has its own T2 signal relaxation constant (in ms). Noise and Artifacts: \li Rician Noise: Add Rician noise with the specified variance to the signal. \li N/2 Ghosts: Specify the offset between successive lines in k-space. This offset causes ghost images in distance N/2 in phase direction due to the alternating EPI readout directions. -\li Distortions: Simulate distortions due to magnetic field inhomogeneities. This is achieved by adding an additional phase during the readout process. The input is a frequency map specifying the inhomogeneities. +\li Distortions: Simulate distortions due to magnetic field inhomogeneities. This is achieved by adding an additional phase during the readout process. The input is a frequency map specifying the inhomogeneities. The "Fieldmap Generator" view provides an interface to generate simple artificial frequency maps. \li Eddy Currents: EXPERIMENTAL! This feature is currently being tested and might not yet behave as expected! \li Gibbs Ringing: Ringing artifacts occurring on edges in the image due to the frequency low-pass filtering caused by the limited size of the k-space. The higher the oversampling factor, the larger the distance from the corresponding edge in which the ringing is still visible. Keep in mind that increasing the oversampling factor results in a quadratic increase of computation time. \section QmitkFiberfoxViewUserManualKnownIssues Known Issues \li If fiducials are created in one of the marginal slices of the underlying image, a position change of the fiducial can be observed upon selection/deselection. If the fiducial is created in any other slice this bug does not occur. \li If a scaling factor is applied to the selcted fiber bundle, the corresponding fiducials are not scaled accordingly. \li In some cases the automatic update of the selected fiber bundle is not triggered even if "Real Time Fibers" is checked, e.g. if a fiducial is deleted. If this happens on can always force an update by pressing the "Generate Fibers" button. If any other issues or feature requests arises during the use of Fiberfox, please don't hesitate to send us an e-mail or directly report the issue in our bugtracker: http://bugs.mitk.org/ \section QmitkFiberfoxViewUserManualReferences References [1] Peter F. Neher, Bram Stieltjes, Frederik B. Laun, Hans-Peter Meinzer, and Klaus H. Fritzsche: Fiberfox: A novel tool to generate software phantoms of complex fiber geometries. In proceedings: ISMRM 2013 [2] Panagiotaki, E., Schneider, T., Siow, B., Hall, M.G., Lythgoe, M.F., Alexander, D.C.: Compartment models of the diffusion mr signal in brain white matter: A taxonomy and comparison. Neuroimage 59 (2012) 2241–2254 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h index c3190454ff..17208db130 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidget.h @@ -1,58 +1,62 @@ /*=================================================================== 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 _QMITKAstrosticksModelParametersWidget_H_INCLUDED #define _QMITKAstrosticksModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkAstrosticksModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkAstrosticksModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkAstrosticksModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkAstrosticksModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } + void SetD(double d){ m_Controls->m_D1box->setValue(d); } + void SetRandomizeSticks(bool r){ m_Controls->m_RandomCheck->setChecked(r); } + double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } bool GetRandomizeSticks(){ return m_Controls->m_RandomCheck->isChecked(); } public slots: protected: // member variables Ui::QmitkAstrosticksModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKAstrosticksModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui index 5c051077b9..6ef5cf7f8f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkAstrosticksModelParametersWidgetControls.ui @@ -1,109 +1,109 @@ QmitkAstrosticksModelParametersWidgetControls 0 0 410 106 0 0 Form 0 Use random number and orientation of sticks. Randomize Sticks true QFrame::NoFrame QFrame::Raised 0 <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> T2 relaxation time of this compartment (in milliseconds). 10000 - 100 + 80 <html><head/><body><p><span style=" font-style:italic;">d</span>:</p></body></html> Diffusivity along sticks. 5 1.000000000000000 0.000100000000000 0.001000000000000 m_T2box m_D1box m_RandomCheck diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h index a7bdbfcd20..7c116906d3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidget.h @@ -1,57 +1,60 @@ /*=================================================================== 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 _QMITKBallModelParametersWidget_H_INCLUDED #define _QMITKBallModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkBallModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkBallModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkBallModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkBallModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } + void SetD(double d){ m_Controls->m_D1box->setValue(d); } + double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } public slots: protected: // member variables Ui::QmitkBallModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKBallModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui index dd132ce030..f32a8da795 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkBallModelParametersWidgetControls.ui @@ -1,80 +1,80 @@ QmitkBallModelParametersWidgetControls 0 0 410 78 0 0 Form 0 <html><head/><body><p><span style=" font-style:italic;">d</span>:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> T2 relaxation time of this compartment (in milliseconds). 10000 - 100 + 80 Diffusivity along stick. 5 1.000000000000000 0.000100000000000 0.001000000000000 m_T2box m_D1box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h index af3d1a098b..2be6744353 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidget.h @@ -1,56 +1,57 @@ /*=================================================================== 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 _QMITKDotModelParametersWidget_H_INCLUDED #define _QMITKDotModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkDotModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkDotModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkDotModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkDotModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } public slots: protected: // member variables Ui::QmitkDotModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKDotModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui index 35fb44cd99..aff8841f3c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkDotModelParametersWidgetControls.ui @@ -1,50 +1,50 @@ QmitkDotModelParametersWidgetControls 0 0 410 45 0 0 Form 0 <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> T2 relaxation time of this compartment (in milliseconds). 10000 - 100 + 80 diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h index ead2f66299..5aecaa1589 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidget.h @@ -1,57 +1,60 @@ /*=================================================================== 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 _QMITKStickModelParametersWidget_H_INCLUDED #define _QMITKStickModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkStickModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkStickModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkStickModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkStickModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } + void SetD(double d){ m_Controls->m_D1box->setValue(d); } + double GetD(){ return m_Controls->m_D1box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } public slots: protected: // member variables Ui::QmitkStickModelParametersWidgetControls* m_Controls; private: }; #endif // _QMITKStickModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui index 67fa97782d..f85e3255ac 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkStickModelParametersWidgetControls.ui @@ -1,80 +1,80 @@ QmitkStickModelParametersWidgetControls 0 0 410 78 0 0 Form 0 <html><head/><body><p><span style=" font-style:italic;">d</span>:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> T2 relaxation time of this compartment (in milliseconds). 10000 - 200 + 110 Diffusivity along stick. 5 1.000000000000000 0.000100000000000 0.001000000000000 m_T2box m_D1box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h index f09273c18c..a61e9e3861 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidget.h @@ -1,62 +1,67 @@ /*=================================================================== 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 _QMITKTensorModelParametersWidget_H_INCLUDED #define _QMITKTensorModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkTensorModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkTensorModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkTensorModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkTensorModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } + void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); } + void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); } + void SetD3(double d3){ m_Controls->m_D3box->setValue(d3); } + double GetD1(){ return m_Controls->m_D1box->value(); } double GetD2(){ return m_Controls->m_D2box->value(); } double GetD3(){ return m_Controls->m_D3box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } public slots: void DChanged( double value ); protected: // member variables Ui::QmitkTensorModelParametersWidgetControls* m_Controls; void UpdateUi(); private: }; #endif // _QMITKTensorModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui index b2320d4f41..a11ce9c8d4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkTensorModelParametersWidgetControls.ui @@ -1,151 +1,151 @@ QmitkTensorModelParametersWidgetControls 0 0 410 167 0 0 Form 0 <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂1</span>:</p></body></html> Diffusivity along second eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span>:</p></body></html> Diffusivity along largest eigenvector. 5 1.000000000000000 0.000100000000000 0.001000000000000 Diffusivity along third eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂2</span>:</p></body></html> Fractional anisotropy of resulting tensor. <html><head/><body><p>-</p></body></html> <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> T2 relaxation time of this compartment (in milliseconds). 10000 - 100 + 110 m_T2box m_D1box m_D2box m_D3box diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h index 583cf21c80..c1cc871f5c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidget.h @@ -1,61 +1,65 @@ /*=================================================================== 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 _QMITKZeppelinModelParametersWidget_H_INCLUDED #define _QMITKZeppelinModelParametersWidget_H_INCLUDED //QT headers #include #include #include "ui_QmitkZeppelinModelParametersWidgetControls.h" #include class QmitkStdMultiWidget; /** @brief */ class DIFFUSIONIMAGING_EXPORT QmitkZeppelinModelParametersWidget : public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkZeppelinModelParametersWidget (QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~QmitkZeppelinModelParametersWidget(); virtual void CreateQtPartControl(QWidget *parent); + void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); } + void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); } + void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); } + double GetD1(){ return m_Controls->m_D1box->value(); } double GetD2(){ return m_Controls->m_D2box->value(); } unsigned int GetT2(){ return m_Controls->m_T2box->value(); } public slots: void DChanged( double value ); protected: // member variables Ui::QmitkZeppelinModelParametersWidgetControls* m_Controls; void UpdateUi(); private: }; #endif // _QMITKZeppelinModelParametersWidget_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui index ceca723203..210e2fcb3c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/QmitkZeppelinModelParametersWidgetControls.ui @@ -1,124 +1,124 @@ QmitkZeppelinModelParametersWidgetControls 0 0 410 116 0 0 Form 0 Fractional anisotropy of resulting tensor. <html><head/><body><p>-</p></body></html> Diffusivity along second and third eigenvector. 5 1.000000000000000 0.000100000000000 0.000250000000000 T2 relaxation time of this compartment (in milliseconds). 10000 - 200 + 110 Diffusivity along largest eigenvector. 5 1.000000000000000 0.000100000000000 0.001000000000000 <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">⟂</span>:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">d</span><span style=" vertical-align:sub;">||</span>:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">T2</span> - Relaxation:</p></body></html> <html><head/><body><p><span style=" font-style:italic;">FA</span>:</p></body></html> m_T2box m_D1box m_D2box 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 2da9116c31..2239656b86 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,1789 +1,1989 @@ /*=================================================================== 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 #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 ) { } // 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_StickWidget1->setVisible(true); m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); m_Controls->m_BallWidget1->setVisible(true); m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_GibbsRingingFrame->setVisible(false); m_Controls->m_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isQbi); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); m_Controls->m_FrequencyMapBox->SetPredicate(finalPredicate); 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(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); 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_AddGibbsRinging, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGibbsRinging(int))); connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int))); connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int))); connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int))); connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(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(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); + + connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); + connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); + } +} + +void QmitkFiberfoxView::UpdateImageParameters() +{ + m_ImageGenParameters.artifactList.clear(); + m_ImageGenParameters.nonFiberModelList.clear(); + m_ImageGenParameters.fiberModelList.clear(); + m_ImageGenParameters.signalModelString = ""; + m_ImageGenParameters.artifactModelString = ""; + m_ImageGenParameters.resultNode = mitk::DataNode::New(); + m_ImageGenParameters.tissueMaskImage = NULL; + m_ImageGenParameters.frequencyMap = NULL; + m_ImageGenParameters.gradientDirections.clear(); + + if (m_SelectedDWI.IsNotNull()) // use parameters of selected DWI + { + mitk::DiffusionImage::Pointer dwi = dynamic_cast*>(m_SelectedDWI->GetData()); + m_ImageGenParameters.imageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); + m_ImageGenParameters.imageSpacing = dwi->GetVectorImage()->GetSpacing(); + m_ImageGenParameters.imageOrigin = dwi->GetVectorImage()->GetOrigin(); + m_ImageGenParameters.imageDirection = dwi->GetVectorImage()->GetDirection(); + m_ImageGenParameters.b_value = dwi->GetB_Value(); + mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = dwi->GetDirections(); + + m_ImageGenParameters.numGradients = 0; + 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]; + m_ImageGenParameters.gradientDirections.push_back(g); + if (dirs->at(i).magnitude()>0.0001) + m_ImageGenParameters.numGradients++; + } + } + else if (m_SelectedImage.IsNotNull()) // use geometry of selected image + { + mitk::Image::Pointer img = dynamic_cast(m_SelectedImage->GetData()); + itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); + CastToItkImage< itk::Image< float, 3 > >(img, itkImg); + + m_ImageGenParameters.imageRegion = itkImg->GetLargestPossibleRegion(); + m_ImageGenParameters.imageSpacing = itkImg->GetSpacing(); + m_ImageGenParameters.imageOrigin = itkImg->GetOrigin(); + m_ImageGenParameters.imageDirection = itkImg->GetDirection(); + + m_ImageGenParameters.numGradients = m_Controls->m_NumGradientsBox->value(); + m_ImageGenParameters.gradientDirections = GenerateHalfShell(m_Controls->m_NumGradientsBox->value()); + m_ImageGenParameters.b_value = m_Controls->m_BvalueBox->value(); + } + else // use GUI parameters + { + m_ImageGenParameters.imageRegion.SetSize(0, m_Controls->m_SizeX->value()); + m_ImageGenParameters.imageRegion.SetSize(1, m_Controls->m_SizeY->value()); + m_ImageGenParameters.imageRegion.SetSize(2, m_Controls->m_SizeZ->value()); + m_ImageGenParameters.imageSpacing[0] = m_Controls->m_SpacingX->value(); + m_ImageGenParameters.imageSpacing[1] = m_Controls->m_SpacingY->value(); + m_ImageGenParameters.imageSpacing[2] = m_Controls->m_SpacingZ->value(); + m_ImageGenParameters.imageOrigin[0] = m_ImageGenParameters.imageSpacing[0]/2; + m_ImageGenParameters.imageOrigin[1] = m_ImageGenParameters.imageSpacing[1]/2; + m_ImageGenParameters.imageOrigin[2] = m_ImageGenParameters.imageSpacing[2]/2; + m_ImageGenParameters.imageDirection.SetIdentity(); + + m_ImageGenParameters.numGradients = m_Controls->m_NumGradientsBox->value(); + m_ImageGenParameters.gradientDirections = GenerateHalfShell(m_Controls->m_NumGradientsBox->value());; + m_ImageGenParameters.b_value = m_Controls->m_BvalueBox->value(); + } + + // signal relaxation + m_ImageGenParameters.doSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); + if (m_ImageGenParameters.doSimulateRelaxation) + m_ImageGenParameters.artifactModelString += "_RELAX"; + + // N/2 ghosts + if (m_Controls->m_AddGhosts->isChecked()) + { + m_ImageGenParameters.artifactModelString += "_GHOST"; + m_ImageGenParameters.kspaceLineOffset = m_Controls->m_kOffsetBox->value(); + } + else + m_ImageGenParameters.kspaceLineOffset = 0; + + m_ImageGenParameters.tLine = m_Controls->m_LineReadoutTimeBox->value(); + m_ImageGenParameters.tInhom = m_Controls->m_T2starBox->value(); + m_ImageGenParameters.tEcho = m_Controls->m_TEbox->value(); + m_ImageGenParameters.repetitions = m_Controls->m_RepetitionsBox->value(); + m_ImageGenParameters.doDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); + m_ImageGenParameters.interpolationShrink = m_Controls->m_InterpolationShrink->value(); + m_ImageGenParameters.axonRadius = m_Controls->m_FiberRadius->value(); + m_ImageGenParameters.signalScale = m_Controls->m_SignalScaleBox->value(); + + // adjust echo time if needed + if ( m_ImageGenParameters.tEcho < m_ImageGenParameters.imageRegion.GetSize(1)*m_ImageGenParameters.tLine ) + { + this->m_Controls->m_TEbox->setValue( m_ImageGenParameters.imageRegion.GetSize(1)*m_ImageGenParameters.tLine ); + m_ImageGenParameters.tEcho = m_Controls->m_TEbox->value(); + QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(m_ImageGenParameters.tEcho)+" ms"); + } + + // check tissue mask + if (m_TissueMask.IsNotNull()) + { + m_ImageGenParameters.tissueMaskImage = ItkUcharImgType::New(); + mitk::CastToItkImage(m_TissueMask, m_ImageGenParameters.tissueMaskImage); + } + + // rician noise + if (m_Controls->m_AddNoise->isChecked()) + { + double noiseVariance = m_Controls->m_NoiseLevel->value(); + m_ImageGenParameters.ricianNoiseModel.SetNoiseVariance(noiseVariance); + m_ImageGenParameters.artifactModelString += "_NOISE"; + m_ImageGenParameters.artifactModelString += QString::number(noiseVariance); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); + } + else + m_ImageGenParameters.ricianNoiseModel.SetNoiseVariance(0); + + // gibbs ringing + m_ImageGenParameters.upsampling = 1; + if (m_Controls->m_AddGibbsRinging->isChecked()) + { + m_ImageGenParameters.artifactModelString += "_RINGING"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Ringing-Upsampling", DoubleProperty::New(m_Controls->m_ImageUpsamplingBox->value())); + m_ImageGenParameters.upsampling = m_Controls->m_ImageUpsamplingBox->value(); + } + + // adjusting line readout time to the adapted image size needed for the DFT + int y = m_ImageGenParameters.imageRegion.GetSize(1); + if ( y%2 == 1 ) + y += 1; + if ( y>m_ImageGenParameters.imageRegion.GetSize(1) ) + m_ImageGenParameters.tLine *= (double)m_ImageGenParameters.imageRegion.GetSize(1)/y; + + // add distortions + if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) + { + mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); + mitk::Image* img = dynamic_cast(fMapNode->GetData()); + ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); + CastToItkImage< ItkDoubleImgType >(img, itkImg); + + if (m_ImageGenParameters.imageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && + m_ImageGenParameters.imageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && + m_ImageGenParameters.imageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) + { + m_ImageGenParameters.frequencyMap = itkImg; + m_ImageGenParameters.artifactModelString += "_DISTORTED"; + } + } + + m_ImageGenParameters.doSimulateEddyCurrents = m_Controls->m_AddEddy->isChecked(); + m_ImageGenParameters.eddyStrength = 0; + if (m_Controls->m_AddEddy->isChecked()) + { + m_ImageGenParameters.eddyStrength = m_Controls->m_EddyGradientStrength->value(); + m_ImageGenParameters.artifactModelString += "_EDDY"; + } + + // signal models + m_ImageGenParameters.comp3Weight = 1; + m_ImageGenParameters.comp4Weight = 0; + if (m_Controls->m_Compartment4Box->currentIndex()>0) + { + m_ImageGenParameters.comp4Weight = m_Controls->m_Comp4FractionBox->value(); + m_ImageGenParameters.comp3Weight -= m_ImageGenParameters.comp4Weight; + } + + // compartment 1 + switch (m_Controls->m_Compartment1Box->currentIndex()) + { + case 0: + m_StickModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_StickModel1.SetBvalue(m_ImageGenParameters.b_value); + m_StickModel1.SetDiffusivity(m_Controls->m_StickWidget1->GetD()); + m_StickModel1.SetT2(m_Controls->m_StickWidget1->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_StickModel1); + m_ImageGenParameters.signalModelString += "Stick"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_StickModel1.GetT2()) ); + break; + case 1: + m_ZeppelinModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_ZeppelinModel1.SetBvalue(m_ImageGenParameters.b_value); + m_ZeppelinModel1.SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); + m_ZeppelinModel1.SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); + m_ZeppelinModel1.SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); + m_ZeppelinModel1.SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_ZeppelinModel1); + m_ImageGenParameters.signalModelString += "Zeppelin"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) ); + break; + case 2: + m_TensorModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_TensorModel1.SetBvalue(m_ImageGenParameters.b_value); + m_TensorModel1.SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); + m_TensorModel1.SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); + m_TensorModel1.SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); + m_TensorModel1.SetT2(m_Controls->m_TensorWidget1->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_TensorModel1); + m_ImageGenParameters.signalModelString += "Tensor"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) ); + break; + } + + // compartment 2 + switch (m_Controls->m_Compartment2Box->currentIndex()) + { + case 0: + break; + case 1: + m_StickModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_StickModel2.SetBvalue(m_ImageGenParameters.b_value); + m_StickModel2.SetDiffusivity(m_Controls->m_StickWidget2->GetD()); + m_StickModel2.SetT2(m_Controls->m_StickWidget2->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_StickModel2); + m_ImageGenParameters.signalModelString += "Stick"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_StickModel2.GetT2()) ); + break; + case 2: + m_ZeppelinModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_ZeppelinModel2.SetBvalue(m_ImageGenParameters.b_value); + m_ZeppelinModel2.SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); + m_ZeppelinModel2.SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); + m_ZeppelinModel2.SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); + m_ZeppelinModel2.SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_ZeppelinModel2); + m_ImageGenParameters.signalModelString += "Zeppelin"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) ); + break; + case 3: + m_TensorModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_TensorModel2.SetBvalue(m_ImageGenParameters.b_value); + m_TensorModel2.SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); + m_TensorModel2.SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); + m_TensorModel2.SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); + m_TensorModel2.SetT2(m_Controls->m_TensorWidget2->GetT2()); + m_ImageGenParameters.fiberModelList.push_back(&m_TensorModel2); + m_ImageGenParameters.signalModelString += "Tensor"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) ); + break; + } + + // compartment 3 + switch (m_Controls->m_Compartment3Box->currentIndex()) + { + case 0: + m_BallModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_BallModel1.SetBvalue(m_ImageGenParameters.b_value); + m_BallModel1.SetDiffusivity(m_Controls->m_BallWidget1->GetD()); + m_BallModel1.SetT2(m_Controls->m_BallWidget1->GetT2()); + m_BallModel1.SetWeight(m_ImageGenParameters.comp3Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_BallModel1); + m_ImageGenParameters.signalModelString += "Ball"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_BallModel1.GetT2()) ); + break; + case 1: + m_AstrosticksModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_AstrosticksModel1.SetBvalue(m_ImageGenParameters.b_value); + m_AstrosticksModel1.SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); + m_AstrosticksModel1.SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); + m_AstrosticksModel1.SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); + m_AstrosticksModel1.SetWeight(m_ImageGenParameters.comp3Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_AstrosticksModel1); + m_ImageGenParameters.signalModelString += "Astrosticks"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_AstrosticksModel1.GetT2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); + break; + case 2: + m_DotModel1.SetGradientList(m_ImageGenParameters.gradientDirections); + m_DotModel1.SetT2(m_Controls->m_DotWidget1->GetT2()); + m_DotModel1.SetWeight(m_ImageGenParameters.comp3Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_DotModel1); + m_ImageGenParameters.signalModelString += "Dot"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_DotModel1.GetT2()) ); + break; + } + + // compartment 4 + switch (m_Controls->m_Compartment4Box->currentIndex()) + { + case 0: + break; + case 1: + m_BallModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_BallModel2.SetBvalue(m_ImageGenParameters.b_value); + m_BallModel2.SetDiffusivity(m_Controls->m_BallWidget2->GetD()); + m_BallModel2.SetT2(m_Controls->m_BallWidget2->GetT2()); + m_BallModel2.SetWeight(m_ImageGenParameters.comp4Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_BallModel2); + m_ImageGenParameters.signalModelString += "Ball"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_BallModel2.GetT2()) ); + break; + case 2: + m_AstrosticksModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_AstrosticksModel2.SetBvalue(m_ImageGenParameters.b_value); + m_AstrosticksModel2.SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); + m_AstrosticksModel2.SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); + m_AstrosticksModel2.SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); + m_AstrosticksModel2.SetWeight(m_ImageGenParameters.comp4Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_AstrosticksModel2); + m_ImageGenParameters.signalModelString += "Astrosticks"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_AstrosticksModel2.GetT2()) ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); + break; + case 3: + m_DotModel2.SetGradientList(m_ImageGenParameters.gradientDirections); + m_DotModel2.SetT2(m_Controls->m_DotWidget2->GetT2()); + m_DotModel2.SetWeight(m_ImageGenParameters.comp4Weight); + m_ImageGenParameters.nonFiberModelList.push_back(&m_DotModel2); + m_ImageGenParameters.signalModelString += "Dot"; + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_DotModel2.GetT2()) ); + break; + } + + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.InterpolationShrink", IntProperty::New(m_ImageGenParameters.interpolationShrink)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(m_ImageGenParameters.signalScale)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(m_ImageGenParameters.axonRadius)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Tinhom", IntProperty::New(m_ImageGenParameters.tInhom)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(m_ImageGenParameters.repetitions)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(m_ImageGenParameters.b_value)); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.Model", StringProperty::New(m_ImageGenParameters.signalModelString.toStdString())); + m_ImageGenParameters.resultNode->AddProperty("Fiberfox.PureFiberVoxels", BoolProperty::New(m_ImageGenParameters.doDisablePartialVolume)); + m_ImageGenParameters.resultNode->AddProperty("binary", BoolProperty::New(false)); +} + +void QmitkFiberfoxView::SaveParameters() +{ + UpdateImageParameters(); + + QString filename = QFileDialog::getSaveFileName( + 0, + tr("Save Parameters"), + QDir::currentPath()+"/param.ffp", + tr("Fiberfox Parameters (*.ffp)") ); + + if(filename.isEmpty() || filename.isNull()) + return; + if(!filename.endsWith(".ffp")) + filename += ".ffp"; + + boost::property_tree::ptree parameters; + + // fiber generation parameters + parameters.put("fiberfox.fibers.realtime", m_Controls->m_RealTimeFibers->isChecked()); + parameters.put("fiberfox.fibers.showadvanced", m_Controls->m_AdvancedOptionsBox->isChecked()); + parameters.put("fiberfox.fibers.distribution", m_Controls->m_DistributionBox->currentIndex()); + parameters.put("fiberfox.fibers.variance", m_Controls->m_VarianceBox->value()); + parameters.put("fiberfox.fibers.density", m_Controls->m_FiberDensityBox->value()); + parameters.put("fiberfox.fibers.spline.sampling", m_Controls->m_FiberSamplingBox->value()); + parameters.put("fiberfox.fibers.spline.tension", m_Controls->m_TensionBox->value()); + parameters.put("fiberfox.fibers.spline.continuity", m_Controls->m_ContinuityBox->value()); + parameters.put("fiberfox.fibers.spline.bias", m_Controls->m_BiasBox->value()); + parameters.put("fiberfox.fibers.constantradius", m_Controls->m_ConstantRadiusBox->isChecked()); + parameters.put("fiberfox.fibers.rotation.x", m_Controls->m_XrotBox->value()); + parameters.put("fiberfox.fibers.rotation.y", m_Controls->m_YrotBox->value()); + parameters.put("fiberfox.fibers.rotation.z", m_Controls->m_ZrotBox->value()); + parameters.put("fiberfox.fibers.translation.x", m_Controls->m_XtransBox->value()); + parameters.put("fiberfox.fibers.translation.y", m_Controls->m_YtransBox->value()); + parameters.put("fiberfox.fibers.translation.z", m_Controls->m_ZtransBox->value()); + parameters.put("fiberfox.fibers.scale.x", m_Controls->m_XscaleBox->value()); + parameters.put("fiberfox.fibers.scale.y", m_Controls->m_YscaleBox->value()); + parameters.put("fiberfox.fibers.scale.z", m_Controls->m_ZscaleBox->value()); + parameters.put("fiberfox.fibers.includeFiducials", m_Controls->m_IncludeFiducials->isChecked()); + parameters.put("fiberfox.fibers.includeFiducials", m_Controls->m_IncludeFiducials->isChecked()); + + // image generation parameters + parameters.put("fiberfox.image.basic.size.x", m_ImageGenParameters.imageRegion.GetSize(0)); + parameters.put("fiberfox.image.basic.size.y", m_ImageGenParameters.imageRegion.GetSize(1)); + parameters.put("fiberfox.image.basic.size.z", m_ImageGenParameters.imageRegion.GetSize(2)); + parameters.put("fiberfox.image.basic.spacing.x", m_ImageGenParameters.imageSpacing[0]); + parameters.put("fiberfox.image.basic.spacing.y", m_ImageGenParameters.imageSpacing[1]); + parameters.put("fiberfox.image.basic.spacing.z", m_ImageGenParameters.imageSpacing[2]); + parameters.put("fiberfox.image.basic.numgradients", m_ImageGenParameters.numGradients); + parameters.put("fiberfox.image.basic.bvalue", m_ImageGenParameters.b_value); + parameters.put("fiberfox.image.showadvanced", m_Controls->m_AdvancedOptionsBox_2->isChecked()); + parameters.put("fiberfox.image.repetitions", m_ImageGenParameters.repetitions); + parameters.put("fiberfox.image.signalScale", m_ImageGenParameters.signalScale); + parameters.put("fiberfox.image.tEcho", m_ImageGenParameters.tEcho); + parameters.put("fiberfox.image.tLine", m_Controls->m_LineReadoutTimeBox->value()); + parameters.put("fiberfox.image.tInhom", m_ImageGenParameters.tInhom); + parameters.put("fiberfox.image.axonRadius", m_ImageGenParameters.axonRadius); + parameters.put("fiberfox.image.interpolationShrink", m_ImageGenParameters.interpolationShrink); + parameters.put("fiberfox.image.doSimulateRelaxation", m_ImageGenParameters.doSimulateRelaxation); + parameters.put("fiberfox.image.doDisablePartialVolume", m_ImageGenParameters.doDisablePartialVolume); + parameters.put("fiberfox.image.outputvolumefractions", m_Controls->m_VolumeFractionsBox->isChecked()); + + parameters.put("fiberfox.image.artifacts.addnoise", m_Controls->m_AddNoise->isChecked()); + parameters.put("fiberfox.image.artifacts.noisevariance", m_Controls->m_NoiseLevel->value()); + parameters.put("fiberfox.image.artifacts.addghost", m_Controls->m_AddGhosts->isChecked()); + parameters.put("fiberfox.image.artifacts.kspaceLineOffset", m_Controls->m_kOffsetBox->value()); + parameters.put("fiberfox.image.artifacts.distortions", m_Controls->m_AddDistortions->isChecked()); + parameters.put("fiberfox.image.artifacts.addeddy", m_Controls->m_AddEddy->isChecked()); + parameters.put("fiberfox.image.artifacts.eddyStrength", m_Controls->m_EddyGradientStrength->value()); + parameters.put("fiberfox.image.artifacts.addringing", m_Controls->m_AddGibbsRinging->isChecked()); + parameters.put("fiberfox.image.artifacts.ringingupsampling", m_Controls->m_ImageUpsamplingBox->value()); + + parameters.put("fiberfox.image.compartment1.index", m_Controls->m_Compartment1Box->currentIndex()); + parameters.put("fiberfox.image.compartment2.index", m_Controls->m_Compartment2Box->currentIndex()); + parameters.put("fiberfox.image.compartment3.index", m_Controls->m_Compartment3Box->currentIndex()); + parameters.put("fiberfox.image.compartment4.index", m_Controls->m_Compartment4Box->currentIndex()); + + parameters.put("fiberfox.image.compartment1.stick.d", m_Controls->m_StickWidget1->GetD()); + parameters.put("fiberfox.image.compartment1.stick.t2", m_Controls->m_StickWidget1->GetT2()); + parameters.put("fiberfox.image.compartment1.zeppelin.d1", m_Controls->m_ZeppelinWidget1->GetD1()); + parameters.put("fiberfox.image.compartment1.zeppelin.d2", m_Controls->m_ZeppelinWidget1->GetD2()); + parameters.put("fiberfox.image.compartment1.zeppelin.t2", m_Controls->m_ZeppelinWidget1->GetT2()); + parameters.put("fiberfox.image.compartment1.tensor.d1", m_Controls->m_TensorWidget1->GetD1()); + parameters.put("fiberfox.image.compartment1.tensor.d2", m_Controls->m_TensorWidget1->GetD2()); + parameters.put("fiberfox.image.compartment1.tensor.d3", m_Controls->m_TensorWidget1->GetD3()); + parameters.put("fiberfox.image.compartment1.tensor.t2", m_Controls->m_TensorWidget1->GetT2()); + + parameters.put("fiberfox.image.compartment2.stick.d", m_Controls->m_StickWidget2->GetD()); + parameters.put("fiberfox.image.compartment2.stick.t2", m_Controls->m_StickWidget2->GetT2()); + parameters.put("fiberfox.image.compartment2.zeppelin.d1", m_Controls->m_ZeppelinWidget2->GetD1()); + parameters.put("fiberfox.image.compartment2.zeppelin.d2", m_Controls->m_ZeppelinWidget2->GetD2()); + parameters.put("fiberfox.image.compartment2.zeppelin.t2", m_Controls->m_ZeppelinWidget2->GetT2()); + parameters.put("fiberfox.image.compartment2.tensor.d1", m_Controls->m_TensorWidget2->GetD1()); + parameters.put("fiberfox.image.compartment2.tensor.d2", m_Controls->m_TensorWidget2->GetD2()); + parameters.put("fiberfox.image.compartment2.tensor.d3", m_Controls->m_TensorWidget2->GetD3()); + parameters.put("fiberfox.image.compartment2.tensor.t2", m_Controls->m_TensorWidget2->GetT2()); + + parameters.put("fiberfox.image.compartment3.ball.d", m_Controls->m_BallWidget1->GetD()); + parameters.put("fiberfox.image.compartment3.ball.t2", m_Controls->m_BallWidget1->GetT2()); + parameters.put("fiberfox.image.compartment3.astrosticks.d", m_Controls->m_AstrosticksWidget1->GetD()); + parameters.put("fiberfox.image.compartment3.astrosticks.t2", m_Controls->m_AstrosticksWidget1->GetT2()); + parameters.put("fiberfox.image.compartment3.astrosticks.randomize", m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); + parameters.put("fiberfox.image.compartment3.dot.t2", m_Controls->m_DotWidget1->GetT2()); + + parameters.put("fiberfox.image.compartment4.ball.d", m_Controls->m_BallWidget2->GetD()); + parameters.put("fiberfox.image.compartment4.ball.t2", m_Controls->m_BallWidget2->GetT2()); + parameters.put("fiberfox.image.compartment4.astrosticks.d", m_Controls->m_AstrosticksWidget2->GetD()); + parameters.put("fiberfox.image.compartment4.astrosticks.t2", m_Controls->m_AstrosticksWidget2->GetT2()); + parameters.put("fiberfox.image.compartment4.astrosticks.randomize", m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); + parameters.put("fiberfox.image.compartment4.dot.t2", m_Controls->m_DotWidget2->GetT2()); + + parameters.put("fiberfox.image.compartment4.weight", m_Controls->m_Comp4FractionBox->value()); + + boost::property_tree::xml_parser::write_xml(filename.toStdString(), parameters); +} + +void QmitkFiberfoxView::LoadParameters() +{ + QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Fiberfox Parameters (*.ffp)") ); + if(filename.isEmpty() || filename.isNull()) + return; + + boost::property_tree::ptree parameters; + boost::property_tree::xml_parser::read_xml(filename.toStdString(), parameters); + + BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameters.get_child("fiberfox") ) + { + if( v1.first == "fibers" ) + { + m_Controls->m_RealTimeFibers->setChecked(v1.second.get("realtime")); + m_Controls->m_AdvancedOptionsBox->setChecked(v1.second.get("showadvanced")); + m_Controls->m_DistributionBox->setCurrentIndex(v1.second.get("distribution")); + m_Controls->m_VarianceBox->setValue(v1.second.get("variance")); + m_Controls->m_FiberDensityBox->setValue(v1.second.get("density")); + m_Controls->m_IncludeFiducials->setChecked(v1.second.get("includeFiducials")); + m_Controls->m_ConstantRadiusBox->setChecked(v1.second.get("constantradius")); + + BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second ) + { + if( v2.first == "spline" ) + { + m_Controls->m_FiberSamplingBox->setValue(v2.second.get("sampling")); + m_Controls->m_TensionBox->setValue(v2.second.get("tension")); + m_Controls->m_ContinuityBox->setValue(v2.second.get("continuity")); + m_Controls->m_BiasBox->setValue(v2.second.get("bias")); + } + if( v2.first == "rotation" ) + { + m_Controls->m_XrotBox->setValue(v2.second.get("x")); + m_Controls->m_YrotBox->setValue(v2.second.get("y")); + m_Controls->m_ZrotBox->setValue(v2.second.get("z")); + } + if( v2.first == "translation" ) + { + m_Controls->m_XtransBox->setValue(v2.second.get("x")); + m_Controls->m_YtransBox->setValue(v2.second.get("y")); + m_Controls->m_ZtransBox->setValue(v2.second.get("z")); + } + if( v2.first == "scale" ) + { + m_Controls->m_XscaleBox->setValue(v2.second.get("x")); + m_Controls->m_YscaleBox->setValue(v2.second.get("y")); + m_Controls->m_ZscaleBox->setValue(v2.second.get("z")); + } + } + } + if( v1.first == "image" ) + { + m_Controls->m_SizeX->setValue(v1.second.get("basic.size.x")); + m_Controls->m_SizeY->setValue(v1.second.get("basic.size.y")); + m_Controls->m_SizeZ->setValue(v1.second.get("basic.size.z")); + m_Controls->m_SpacingX->setValue(v1.second.get("basic.spacing.x")); + m_Controls->m_SpacingY->setValue(v1.second.get("basic.spacing.y")); + m_Controls->m_SpacingZ->setValue(v1.second.get("basic.spacing.z")); + m_Controls->m_NumGradientsBox->setValue(v1.second.get("basic.numgradients")); + m_Controls->m_BvalueBox->setValue(v1.second.get("basic.bvalue")); + m_Controls->m_AdvancedOptionsBox_2->setChecked(v1.second.get("showadvanced")); + m_Controls->m_RepetitionsBox->setValue(v1.second.get("repetitions")); + m_Controls->m_SignalScaleBox->setValue(v1.second.get("signalScale")); + m_Controls->m_TEbox->setValue(v1.second.get("tEcho")); + m_Controls->m_LineReadoutTimeBox->setValue(v1.second.get("tLine")); + m_Controls->m_T2starBox->setValue(v1.second.get("tInhom")); + m_Controls->m_FiberRadius->setValue(v1.second.get("axonRadius")); + m_Controls->m_InterpolationShrink->setValue(v1.second.get("interpolationShrink")); + m_Controls->m_RelaxationBox->setChecked(v1.second.get("doSimulateRelaxation")); + m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(v1.second.get("doDisablePartialVolume")); + m_Controls->m_VolumeFractionsBox->setChecked(v1.second.get("outputvolumefractions")); + + m_Controls->m_AddNoise->setChecked(v1.second.get("artifacts.addnoise")); + m_Controls->m_NoiseLevel->setValue(v1.second.get("artifacts.noisevariance")); + m_Controls->m_AddGhosts->setChecked(v1.second.get("artifacts.addghost")); + m_Controls->m_kOffsetBox->setValue(v1.second.get("artifacts.kspaceLineOffset")); + m_Controls->m_AddDistortions->setChecked(v1.second.get("artifacts.distortions")); + + m_Controls->m_AddEddy->setChecked(v1.second.get("artifacts.addeddy")); + m_Controls->m_EddyGradientStrength->setValue(v1.second.get("artifacts.eddyStrength")); + m_Controls->m_AddGibbsRinging->setChecked(v1.second.get("artifacts.addringing")); + m_Controls->m_ImageUpsamplingBox->setValue(v1.second.get("artifacts.ringingupsampling")); + + m_Controls->m_Compartment1Box->setCurrentIndex(v1.second.get("compartment1.index")); + m_Controls->m_Compartment2Box->setCurrentIndex(v1.second.get("compartment2.index")); + m_Controls->m_Compartment3Box->setCurrentIndex(v1.second.get("compartment3.index")); + m_Controls->m_Compartment4Box->setCurrentIndex(v1.second.get("compartment4.index")); + + + m_Controls->m_StickWidget1->SetD(v1.second.get("compartment1.stick.d")); + m_Controls->m_StickWidget1->SetT2(v1.second.get("compartment1.stick.t2")); + m_Controls->m_ZeppelinWidget1->SetD1(v1.second.get("compartment1.zeppelin.d1")); + m_Controls->m_ZeppelinWidget1->SetD2(v1.second.get("compartment1.zeppelin.d2")); + m_Controls->m_ZeppelinWidget1->SetT2(v1.second.get("compartment1.zeppelin.t2")); + m_Controls->m_TensorWidget1->SetD1(v1.second.get("compartment1.tensor.d1")); + m_Controls->m_TensorWidget1->SetD2(v1.second.get("compartment1.tensor.d2")); + m_Controls->m_TensorWidget1->SetD3(v1.second.get("compartment1.tensor.d3")); + m_Controls->m_TensorWidget1->SetT2(v1.second.get("compartment1.tensor.t2")); + + m_Controls->m_StickWidget2->SetD(v1.second.get("compartment2.stick.d")); + m_Controls->m_StickWidget2->SetT2(v1.second.get("compartment2.stick.t2")); + m_Controls->m_ZeppelinWidget2->SetD1(v1.second.get("compartment2.zeppelin.d1")); + m_Controls->m_ZeppelinWidget2->SetD2(v1.second.get("compartment2.zeppelin.d2")); + m_Controls->m_ZeppelinWidget2->SetT2(v1.second.get("compartment2.zeppelin.t2")); + m_Controls->m_TensorWidget2->SetD1(v1.second.get("compartment2.tensor.d1")); + m_Controls->m_TensorWidget2->SetD2(v1.second.get("compartment2.tensor.d2")); + m_Controls->m_TensorWidget2->SetD3(v1.second.get("compartment2.tensor.d3")); + m_Controls->m_TensorWidget2->SetT2(v1.second.get("compartment2.tensor.t2")); + + m_Controls->m_BallWidget1->SetD(v1.second.get("compartment3.ball.d")); + m_Controls->m_BallWidget1->SetT2(v1.second.get("compartment3.ball.t2")); + m_Controls->m_AstrosticksWidget1->SetD(v1.second.get("compartment3.astrosticks.d")); + m_Controls->m_AstrosticksWidget1->SetT2(v1.second.get("compartment3.astrosticks.t2")); + m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(v1.second.get("compartment3.astrosticks.randomize")); + m_Controls->m_DotWidget1->SetT2(v1.second.get("compartment3.dot.t2")); + + m_Controls->m_BallWidget2->SetD(v1.second.get("compartment4.ball.d")); + m_Controls->m_BallWidget2->SetT2(v1.second.get("compartment4.ball.t2")); + m_Controls->m_AstrosticksWidget2->SetD(v1.second.get("compartment4.astrosticks.d")); + m_Controls->m_AstrosticksWidget2->SetT2(v1.second.get("compartment4.astrosticks.t2")); + m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(v1.second.get("compartment4.astrosticks.randomize")); + m_Controls->m_DotWidget2->SetT2(v1.second.get("compartment4.dot.t2")); + + m_Controls->m_Comp4FractionBox->setValue(v1.second.get("compartment4.weight")); + } } + UpdateImageParameters(); } void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); m_Controls->m_AdvancedOptionsBox_2->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); m_Controls->m_AdvancedOptionsBox_2->setChecked(false); } } void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index) { m_Controls->m_StickWidget1->setVisible(false); m_Controls->m_ZeppelinWidget1->setVisible(false); m_Controls->m_TensorWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_StickWidget1->setVisible(true); break; case 1: m_Controls->m_ZeppelinWidget1->setVisible(true); break; case 2: m_Controls->m_TensorWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index) { m_Controls->m_StickWidget2->setVisible(false); m_Controls->m_ZeppelinWidget2->setVisible(false); m_Controls->m_TensorWidget2->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); break; } } void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index) { m_Controls->m_BallWidget1->setVisible(false); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_DotWidget1->setVisible(false); switch (index) { case 0: m_Controls->m_BallWidget1->setVisible(true); break; case 1: m_Controls->m_AstrosticksWidget1->setVisible(true); break; case 2: m_Controls->m_DotWidget1->setVisible(true); break; } } void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index) { m_Controls->m_BallWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_Comp4FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_BallWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 2: m_Controls->m_AstrosticksWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; case 3: m_Controls->m_DotWidget2->setVisible(true); m_Controls->m_Comp4FractionFrame->setVisible(true); break; } } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnAddEddy(int value) { if (value>0) m_Controls->m_EddyFrame->setVisible(true); else m_Controls->m_EddyFrame->setVisible(false); } void QmitkFiberfoxView::OnAddDistortions(int value) { if (value>0) m_Controls->m_DistortionsFrame->setVisible(true); else m_Controls->m_DistortionsFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGhosts(int value) { if (value>0) m_Controls->m_GhostFrame->setVisible(true); else m_Controls->m_GhostFrame->setVisible(false); } void QmitkFiberfoxView::OnAddNoise(int value) { if (value>0) m_Controls->m_NoiseFrame->setVisible(true); else m_Controls->m_NoiseFrame->setVisible(false); } void QmitkFiberfoxView::OnAddGibbsRinging(int value) { if (value>0) m_Controls->m_GibbsRingingFrame->setVisible(true); else m_Controls->m_GibbsRingingFrame->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(double 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::AlignOnGrid() { for (int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for( int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for( int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); 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; GradientListType pointshell; int numB0 = NPoints/20; 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_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImage); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); 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_SelectedBundles.at(0)); 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 liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } vector< vector< mitk::PlanarEllipse::Pointer > > 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(); ellipse->SetControlPoint(1, p); } 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); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundleX::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } 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->value()); - imageRegion.SetSize(1, m_Controls->m_SizeY->value()); - imageRegion.SetSize(2, m_Controls->m_SizeZ->value()); - 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[0] = spacing[0]/2; - origin[1] = spacing[1]/2; - origin[2] = spacing[2]/2; - itk::Matrix directionMatrix; directionMatrix.SetIdentity(); - - if (m_SelectedImage.IsNotNull()) - { - mitk::Image* img = dynamic_cast(m_SelectedImage->GetData()); - itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); - CastToItkImage< itk::Image< float, 3 > >(img, itkImg); - - imageRegion = itkImg->GetLargestPossibleRegion(); - spacing = itkImg->GetSpacing(); - origin = itkImg->GetOrigin(); - directionMatrix = itkImg->GetDirection(); - } - - 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()); - imageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); - spacing = dwi->GetVectorImage()->GetSpacing(); - origin = dwi->GetVectorImage()->GetOrigin(); - directionMatrix = dwi->GetVectorImage()->GetDirection(); - bVal = dwi->GetB_Value(); - mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = dwi->GetDirections(); - 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); - } - } - + UpdateImageParameters(); if (m_SelectedBundles.empty()) { if (m_SelectedDWI.IsNotNull()) // add artifacts to existing diffusion weighted image { for (int i=0; i*>(m_SelectedImages.at(i)->GetData())) continue; - mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(m_SelectedImages.at(i)->GetData()); - double noiseVariance = 0; - if (m_Controls->m_AddNoise->isChecked()) - { - noiseVariance = m_Controls->m_NoiseLevel->value(); - artifactModelString += "_NOISE"; - artifactModelString += QString::number(noiseVariance); - } - mitk::RicianNoiseModel noiseModel; - noiseModel.SetNoiseVariance(noiseVariance); - - if ( this->m_Controls->m_TEbox->value() < imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ) - { - this->m_Controls->m_TEbox->setValue( imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ); - QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(this->m_Controls->m_TEbox->value())+" ms"); - } - double lineReadoutTime = m_Controls->m_LineReadoutTimeBox->value(); - - // add N/2 ghosting - double kOffset = 0; - if (m_Controls->m_AddGhosts->isChecked()) - { - artifactModelString += "_GHOST"; - kOffset = m_Controls->m_kOffsetBox->value(); - } + m_SelectedDWI = m_SelectedImages.at(i); + UpdateImageParameters(); + mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(m_SelectedImages.at(i)->GetData()); - if ( this->m_Controls->m_TEbox->value() < imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ) - { - this->m_Controls->m_TEbox->setValue( imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ); - QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(this->m_Controls->m_TEbox->value())+" ms"); - } + mitk::RicianNoiseModel noiseModel; + noiseModel.SetNoiseVariance(m_ImageGenParameters.ricianNoiseModel.GetNoiseVariance()); itk::AddArtifactsToDwiImageFilter< short >::Pointer filter = itk::AddArtifactsToDwiImageFilter< short >::New(); filter->SetInput(diffImg->GetVectorImage()); - filter->SettLine(lineReadoutTime); - filter->SetkOffset(kOffset); + filter->SettLine(m_ImageGenParameters.tLine); + filter->SetkOffset(m_ImageGenParameters.kspaceLineOffset); filter->SetNoiseModel(&noiseModel); - filter->SetGradientList(gradientList); - filter->SetTE(this->m_Controls->m_TEbox->value()); - - if (m_Controls->m_AddEddy->isChecked()) - { - filter->SetSimulateEddyCurrents(true); - filter->SetEddyGradientStrength(m_Controls->m_EddyGradientStrength->value()); - artifactModelString += "_EDDY"; - } - - if (m_Controls->m_AddGibbsRinging->isChecked()) - { - resultNode->AddProperty("Fiberfox.kRinging-Upsampling", DoubleProperty::New(m_Controls->m_ImageUpsamplingBox->value())); - filter->SetUpsampling(m_Controls->m_ImageUpsamplingBox->value()); - } - - if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) - { - mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); - mitk::Image* img = dynamic_cast(fMapNode->GetData()); - ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); - CastToItkImage< ItkDoubleImgType >(img, itkImg); - - if (imageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && - imageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && - imageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) - { - filter->SetFrequencyMap(itkImg); - artifactModelString += "_DISTORTED"; - } - } - + filter->SetGradientList(m_ImageGenParameters.gradientDirections); + filter->SetTE(m_ImageGenParameters.tEcho); + filter->SetSimulateEddyCurrents(m_ImageGenParameters.doSimulateEddyCurrents); + filter->SetEddyGradientStrength(m_ImageGenParameters.eddyStrength); + filter->SetUpsampling(m_ImageGenParameters.upsampling); + filter->SetFrequencyMap(m_ImageGenParameters.frequencyMap); filter->Update(); - resultNode->AddProperty("Fiberfox.Line-Offset", DoubleProperty::New(kOffset)); - resultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); - resultNode->AddProperty("Fiberfox.Tinhom", IntProperty::New(m_Controls->m_T2starBox->value())); - resultNode->AddProperty("binary", BoolProperty::New(false)); - mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(diffImg->GetB_Value()); image->SetDirections(diffImg->GetDirections()); image->InitializeFromVectorImage(); - resultNode->SetData( image ); - resultNode->SetName(m_SelectedImages.at(i)->GetName()+artifactModelString.toStdString()); - GetDataStorage()->Add(resultNode); + m_ImageGenParameters.resultNode->SetData( image ); + m_ImageGenParameters.resultNode->SetName(m_SelectedImages.at(i)->GetName()+m_ImageGenParameters.artifactModelString.toStdString()); + GetDataStorage()->Add(m_ImageGenParameters.resultNode); } + m_SelectedDWI = m_SelectedImages.front(); return; } + mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::Geometry3D* geom = image->GetGeometry(); - geom->SetOrigin(origin); + geom->SetOrigin(m_ImageGenParameters.imageOrigin); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); unsigned int window = m_Controls->m_SizeX->value()*m_Controls->m_SizeY->value()*m_Controls->m_SizeZ->value(); unsigned int level = window/2; mitk::LevelWindow lw; lw.SetLevelWindow(level, window); node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); 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()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); return; } for (int i=0; im_Compartment4Box->currentIndex()>0) - { - comp4Weight = m_Controls->m_Comp4FractionBox->value(); - comp3Weight -= comp4Weight; - } - - mitk::StickModel stickModel1; - mitk::StickModel stickModel2; - mitk::TensorModel zeppelinModel1; - mitk::TensorModel zeppelinModel2; - mitk::TensorModel tensorModel1; - mitk::TensorModel tensorModel2; - mitk::BallModel ballModel1; - mitk::BallModel ballModel2; - mitk::AstroStickModel astrosticksModel1; - mitk::AstroStickModel astrosticksModel2; - mitk::DotModel dotModel1; - mitk::DotModel dotModel2; - - // compartment 1 - switch (m_Controls->m_Compartment1Box->currentIndex()) - { - case 0: - MITK_INFO << "Using stick model"; - stickModel1.SetGradientList(gradientList); - stickModel1.SetDiffusivity(m_Controls->m_StickWidget1->GetD()); - stickModel1.SetT2(m_Controls->m_StickWidget1->GetT2()); - fiberModelList.push_back(&stickModel1); - signalModelString += "Stick"; - resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); - resultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(stickModel1.GetT2()) ); - break; - case 1: - MITK_INFO << "Using zeppelin model"; - zeppelinModel1.SetGradientList(gradientList); - zeppelinModel1.SetBvalue(bVal); - zeppelinModel1.SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); - zeppelinModel1.SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); - zeppelinModel1.SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); - zeppelinModel1.SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); - fiberModelList.push_back(&zeppelinModel1); - signalModelString += "Zeppelin"; - resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); - resultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); - resultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); - resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(zeppelinModel1.GetT2()) ); - break; - case 2: - MITK_INFO << "Using tensor model"; - tensorModel1.SetGradientList(gradientList); - tensorModel1.SetBvalue(bVal); - tensorModel1.SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); - tensorModel1.SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); - tensorModel1.SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); - tensorModel1.SetT2(m_Controls->m_TensorWidget1->GetT2()); - fiberModelList.push_back(&tensorModel1); - signalModelString += "Tensor"; - resultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); - resultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); - resultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); - resultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); - resultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(zeppelinModel1.GetT2()) ); - break; - } - - // compartment 2 - switch (m_Controls->m_Compartment2Box->currentIndex()) - { - case 0: - break; - case 1: - stickModel2.SetGradientList(gradientList); - stickModel2.SetDiffusivity(m_Controls->m_StickWidget2->GetD()); - stickModel2.SetT2(m_Controls->m_StickWidget2->GetT2()); - fiberModelList.push_back(&stickModel2); - signalModelString += "Stick"; - resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); - resultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(stickModel2.GetT2()) ); - break; - case 2: - zeppelinModel2.SetGradientList(gradientList); - zeppelinModel2.SetBvalue(bVal); - zeppelinModel2.SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); - zeppelinModel2.SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); - zeppelinModel2.SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); - zeppelinModel2.SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); - fiberModelList.push_back(&zeppelinModel2); - signalModelString += "Zeppelin"; - resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); - resultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); - resultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); - resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(zeppelinModel2.GetT2()) ); - break; - case 3: - tensorModel2.SetGradientList(gradientList); - tensorModel2.SetBvalue(bVal); - tensorModel2.SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); - tensorModel2.SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); - tensorModel2.SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); - tensorModel2.SetT2(m_Controls->m_TensorWidget2->GetT2()); - fiberModelList.push_back(&tensorModel2); - signalModelString += "Tensor"; - resultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - resultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); - resultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); - resultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); - resultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); - resultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(zeppelinModel2.GetT2()) ); - break; - } - - // compartment 3 - switch (m_Controls->m_Compartment3Box->currentIndex()) - { - case 0: - ballModel1.SetGradientList(gradientList); - ballModel1.SetBvalue(bVal); - ballModel1.SetDiffusivity(m_Controls->m_BallWidget1->GetD()); - ballModel1.SetT2(m_Controls->m_BallWidget1->GetT2()); - ballModel1.SetWeight(comp3Weight); - nonFiberModelList.push_back(&ballModel1); - signalModelString += "Ball"; - resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); - resultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(ballModel1.GetT2()) ); - break; - case 1: - astrosticksModel1.SetGradientList(gradientList); - astrosticksModel1.SetBvalue(bVal); - astrosticksModel1.SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); - astrosticksModel1.SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); - astrosticksModel1.SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); - astrosticksModel1.SetWeight(comp3Weight); - nonFiberModelList.push_back(&astrosticksModel1); - signalModelString += "Astrosticks"; - resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); - resultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(astrosticksModel1.GetT2()) ); - resultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); - break; - case 2: - dotModel1.SetGradientList(gradientList); - dotModel1.SetT2(m_Controls->m_DotWidget1->GetT2()); - dotModel1.SetWeight(comp3Weight); - nonFiberModelList.push_back(&dotModel1); - signalModelString += "Dot"; - resultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - resultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); - resultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(dotModel1.GetT2()) ); - break; - } - - // compartment 4 - switch (m_Controls->m_Compartment4Box->currentIndex()) - { - case 0: - break; - case 1: - ballModel2.SetGradientList(gradientList); - ballModel2.SetBvalue(bVal); - ballModel2.SetDiffusivity(m_Controls->m_BallWidget2->GetD()); - ballModel2.SetT2(m_Controls->m_BallWidget2->GetT2()); - ballModel2.SetWeight(comp4Weight); - nonFiberModelList.push_back(&ballModel2); - signalModelString += "Ball"; - resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); - resultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(ballModel2.GetT2()) ); - break; - case 2: - astrosticksModel2.SetGradientList(gradientList); - astrosticksModel2.SetBvalue(bVal); - astrosticksModel2.SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); - astrosticksModel2.SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); - astrosticksModel2.SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); - astrosticksModel2.SetWeight(comp4Weight); - nonFiberModelList.push_back(&astrosticksModel2); - signalModelString += "Astrosticks"; - resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); - resultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); - resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(astrosticksModel2.GetT2()) ); - resultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); - break; - case 3: - dotModel2.SetGradientList(gradientList); - dotModel2.SetT2(m_Controls->m_DotWidget2->GetT2()); - dotModel2.SetWeight(comp4Weight); - nonFiberModelList.push_back(&dotModel2); - signalModelString += "Dot"; - resultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - resultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); - resultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(dotModel2.GetT2()) ); - break; - } - - itk::TractsToDWIImageFilter::KspaceArtifactList artifactList; - - // artifact models - QString artifactModelString(""); - double noiseVariance = 0; - if (m_Controls->m_AddNoise->isChecked()) - { - noiseVariance = m_Controls->m_NoiseLevel->value(); - artifactModelString += "_NOISE"; - artifactModelString += QString::number(noiseVariance); - resultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); - } - mitk::RicianNoiseModel noiseModel; - noiseModel.SetNoiseVariance(noiseVariance); - - if (m_Controls->m_AddGibbsRinging->isChecked()) - { - artifactModelString += "_RINGING"; - resultNode->AddProperty("Fiberfox.Ringing-Upsampling", DoubleProperty::New(m_Controls->m_ImageUpsamplingBox->value())); - tractsToDwiFilter->SetUpsampling(m_Controls->m_ImageUpsamplingBox->value()); - } - - if ( this->m_Controls->m_TEbox->value() < imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ) - { - this->m_Controls->m_TEbox->setValue( imageRegion.GetSize(1)*m_Controls->m_LineReadoutTimeBox->value() ); - QMessageBox::information( NULL, "Warning", "Echo time is too short! Time not sufficient to read slice. Automaticall adjusted to "+QString::number(this->m_Controls->m_TEbox->value())+" ms"); - } - - double lineReadoutTime = m_Controls->m_LineReadoutTimeBox->value(); - - // adjusting line readout time to the adapted image size needed for the DFT - int y = imageRegion.GetSize(1); - if ( y%2 == 1 ) - y += 1; - if ( y>imageRegion.GetSize(1) ) - lineReadoutTime *= (double)imageRegion.GetSize(1)/y; - - // add N/2 ghosting - double kOffset = 0; - if (m_Controls->m_AddGhosts->isChecked()) - { - artifactModelString += "_GHOST"; - kOffset = m_Controls->m_kOffsetBox->value(); - resultNode->AddProperty("Fiberfox.Line-Offset", DoubleProperty::New(kOffset)); - } - - // add distortions - if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull()) - { - mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode(); - mitk::Image* img = dynamic_cast(fMapNode->GetData()); - ItkDoubleImgType::Pointer itkImg = ItkDoubleImgType::New(); - CastToItkImage< ItkDoubleImgType >(img, itkImg); - - if (imageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && - imageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && - imageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) - { - tractsToDwiFilter->SetFrequencyMap(itkImg); - artifactModelString += "_DISTORTED"; - } - } - - if (m_Controls->m_AddEddy->isChecked()) - { - tractsToDwiFilter->SetSimulateEddyCurrents(true); - tractsToDwiFilter->SetEddyGradientStrength(m_Controls->m_EddyGradientStrength->value()); - artifactModelString += "_EDDY"; - } - mitk::FiberBundleX::Pointer fiberBundle = dynamic_cast(m_SelectedBundles.at(i)->GetData()); if (fiberBundle->GetNumFibers()<=0) continue; - if (m_Controls->m_RelaxationBox->isChecked()) - artifactModelString += "_RELAX"; + itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); - tractsToDwiFilter->SetSimulateRelaxation(m_Controls->m_RelaxationBox->isChecked()); - tractsToDwiFilter->SetImageRegion(imageRegion); - tractsToDwiFilter->SetSpacing(spacing); - tractsToDwiFilter->SetOrigin(origin); - tractsToDwiFilter->SetDirectionMatrix(directionMatrix); + tractsToDwiFilter->SetSimulateEddyCurrents(m_ImageGenParameters.doSimulateEddyCurrents); + tractsToDwiFilter->SetEddyGradientStrength(m_ImageGenParameters.eddyStrength); + tractsToDwiFilter->SetUpsampling(m_ImageGenParameters.upsampling); + tractsToDwiFilter->SetSimulateRelaxation(m_ImageGenParameters.doSimulateRelaxation); + tractsToDwiFilter->SetImageRegion(m_ImageGenParameters.imageRegion); + tractsToDwiFilter->SetSpacing(m_ImageGenParameters.imageSpacing); + tractsToDwiFilter->SetOrigin(m_ImageGenParameters.imageOrigin); + tractsToDwiFilter->SetDirectionMatrix(m_ImageGenParameters.imageDirection); tractsToDwiFilter->SetFiberBundle(fiberBundle); - tractsToDwiFilter->SetFiberModels(fiberModelList); - tractsToDwiFilter->SetNonFiberModels(nonFiberModelList); - tractsToDwiFilter->SetNoiseModel(&noiseModel); - tractsToDwiFilter->SetKspaceArtifacts(artifactList); - tractsToDwiFilter->SetkOffset(kOffset); - tractsToDwiFilter->SettLine(m_Controls->m_LineReadoutTimeBox->value()); - tractsToDwiFilter->SettInhom(this->m_Controls->m_T2starBox->value()); - tractsToDwiFilter->SetTE(this->m_Controls->m_TEbox->value()); - tractsToDwiFilter->SetNumberOfRepetitions(m_Controls->m_RepetitionsBox->value()); - tractsToDwiFilter->SetEnforcePureFiberVoxels(m_Controls->m_EnforcePureFiberVoxelsBox->isChecked()); - tractsToDwiFilter->SetInterpolationShrink(m_Controls->m_InterpolationShrink->value()); - tractsToDwiFilter->SetFiberRadius(m_Controls->m_FiberRadius->value()); - tractsToDwiFilter->SetSignalScale(m_Controls->m_SignalScaleBox->value()); - if (m_Controls->m_InterpolationShrink->value()<1000) + tractsToDwiFilter->SetFiberModels(m_ImageGenParameters.fiberModelList); + tractsToDwiFilter->SetNonFiberModels(m_ImageGenParameters.nonFiberModelList); + tractsToDwiFilter->SetNoiseModel(&m_ImageGenParameters.ricianNoiseModel); + tractsToDwiFilter->SetKspaceArtifacts(m_ImageGenParameters.artifactList); + tractsToDwiFilter->SetkOffset(m_ImageGenParameters.kspaceLineOffset); + tractsToDwiFilter->SettLine(m_ImageGenParameters.tLine); + tractsToDwiFilter->SettInhom(m_ImageGenParameters.tInhom); + tractsToDwiFilter->SetTE(m_ImageGenParameters.tEcho); + tractsToDwiFilter->SetNumberOfRepetitions(m_ImageGenParameters.repetitions); + tractsToDwiFilter->SetEnforcePureFiberVoxels(m_ImageGenParameters.doDisablePartialVolume); + tractsToDwiFilter->SetInterpolationShrink(m_ImageGenParameters.interpolationShrink); + tractsToDwiFilter->SetFiberRadius(m_ImageGenParameters.axonRadius); + tractsToDwiFilter->SetSignalScale(m_ImageGenParameters.signalScale); + if (m_ImageGenParameters.interpolationShrink) tractsToDwiFilter->SetUseInterpolation(true); + tractsToDwiFilter->SetTissueMask(m_ImageGenParameters.tissueMaskImage); + tractsToDwiFilter->SetFrequencyMap(m_ImageGenParameters.frequencyMap); - if (m_TissueMask.IsNotNull()) - { - ItkUcharImgType::Pointer mask = ItkUcharImgType::New(); - mitk::CastToItkImage(m_TissueMask, mask); - tractsToDwiFilter->SetTissueMask(mask); - } tractsToDwiFilter->Update(); mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( tractsToDwiFilter->GetOutput() ); - image->SetB_Value(bVal); - image->SetDirections(gradientList); + image->SetB_Value(m_ImageGenParameters.b_value); + image->SetDirections(m_ImageGenParameters.gradientDirections); image->InitializeFromVectorImage(); - resultNode->SetData( image ); - resultNode->SetName(m_SelectedBundles.at(i)->GetName() - +"_D"+QString::number(imageRegion.GetSize(0)).toStdString() - +"-"+QString::number(imageRegion.GetSize(1)).toStdString() - +"-"+QString::number(imageRegion.GetSize(2)).toStdString() - +"_S"+QString::number(spacing[0]).toStdString() - +"-"+QString::number(spacing[1]).toStdString() - +"-"+QString::number(spacing[2]).toStdString() - +"_b"+QString::number(bVal).toStdString() - +"_"+signalModelString.toStdString() - +artifactModelString.toStdString()); - GetDataStorage()->Add(resultNode, m_SelectedBundles.at(i)); - - resultNode->AddProperty("Fiberfox.InterpolationShrink", IntProperty::New(m_Controls->m_InterpolationShrink->value())); - resultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(m_Controls->m_SignalScaleBox->value())); - resultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(m_Controls->m_FiberRadius->value())); - resultNode->AddProperty("Fiberfox.Tinhom", IntProperty::New(m_Controls->m_T2starBox->value())); - resultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(m_Controls->m_RepetitionsBox->value())); - resultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(bVal)); - resultNode->AddProperty("Fiberfox.Model", StringProperty::New(signalModelString.toStdString())); - resultNode->AddProperty("Fiberfox.PureFiberVoxels", BoolProperty::New(m_Controls->m_EnforcePureFiberVoxelsBox->isChecked())); - resultNode->AddProperty("binary", BoolProperty::New(false)); - resultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(tractsToDwiFilter->GetLevelWindow()) ); + m_ImageGenParameters.resultNode->SetData( image ); + m_ImageGenParameters.resultNode->SetName(m_SelectedBundles.at(i)->GetName() + +"_D"+QString::number(m_ImageGenParameters.imageRegion.GetSize(0)).toStdString() + +"-"+QString::number(m_ImageGenParameters.imageRegion.GetSize(1)).toStdString() + +"-"+QString::number(m_ImageGenParameters.imageRegion.GetSize(2)).toStdString() + +"_S"+QString::number(m_ImageGenParameters.imageSpacing[0]).toStdString() + +"-"+QString::number(m_ImageGenParameters.imageSpacing[1]).toStdString() + +"-"+QString::number(m_ImageGenParameters.imageSpacing[2]).toStdString() + +"_b"+QString::number(m_ImageGenParameters.b_value).toStdString() + +"_"+m_ImageGenParameters.signalModelString.toStdString() + +m_ImageGenParameters.artifactModelString.toStdString()); + + GetDataStorage()->Add(m_ImageGenParameters.resultNode, m_SelectedBundles.at(i)); + + m_ImageGenParameters.resultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(tractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { - std::vector< itk::TractsToDWIImageFilter::ItkDoubleImgType::Pointer > volumeFractions = tractsToDwiFilter->GetVolumeFractions(); + std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = tractsToDwiFilter->GetVolumeFractions(); for (int k=0; kInitializeByItk(volumeFractions.at(k).GetPointer()); image->SetVolume(volumeFractions.at(k)->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName(m_SelectedBundles.at(i)->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, m_SelectedBundles.at(i)); } } - mitk::BaseData::Pointer basedata = resultNode->GetData(); + mitk::BaseData::Pointer basedata = m_ImageGenParameters.resultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkFiberfoxView::ApplyTransform() { vector< mitk::DataNode::Pointer > selectedBundles; for( int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { std::vector::const_iterator it = selectedBundles.begin(); for (it; it!=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()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::Geometry3D* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< float, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< float, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< float, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< float, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); } } } } } else { for (int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Geometry3D* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< float, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< float, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< float, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< float, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } 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) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } 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); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = mitk::PlanarEllipse::New(); pe->DeepCopy(dynamic_cast(fiducialNode->GetData())); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); GetDataStorage()->Add(newNode, 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() { m_Controls->m_FiberBundleLabel->setText("mandatory"); m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedImage.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_TissueMask.IsNotNull() || m_SelectedImage.IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_SelectedDWI.IsNotNull()) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (!m_SelectedBundles.empty()) { m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); m_Controls->m_FiberBundleLabel->setText(m_SelectedBundles.at(0)->GetName().c_str()); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = NULL; m_TissueMask = NULL; m_SelectedBundles.clear(); m_SelectedImage = NULL; m_SelectedDWI = NULL; m_Controls->m_TissueMaskLabel->setText("optional"); // iterate all selected objects, adjust warning visibility for( int i=0; i*>(node->GetData()) ) { m_SelectedDWI = node; m_SelectedImage = node; m_SelectedImages.push_back(node); } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImages.push_back(node); 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()); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundleX::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); 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_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) { 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/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h index 95cb15ff89..55d920f7dd 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h @@ -1,142 +1,210 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkFiberfoxViewControls.h" #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). \sa QmitkFunctionality \ingroup Functionalities */ // Forward Qt class declarations using namespace std; class QmitkFiberfoxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent); void SetFocus(); typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef itk::Vector GradientType; typedef vector GradientListType; - template vector > MakeGradientList() ; + template vector > MakeGradientList(); protected slots: + void LoadParameters(); + void SaveParameters(); + void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void GenerateImage(); ///< generate artificial image from the selected fiber bundle void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void Comp1ModelFrameVisibility(int index);///< only show parameters of selected fiber model type void Comp2ModelFrameVisibility(int index);///< only show parameters of selected non-fiber model type void Comp3ModelFrameVisibility(int index);///< only show parameters of selected non-fiber model type void Comp4ModelFrameVisibility(int index);///< only show parameters of selected non-fiber model type void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(double value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); void OnAddGibbsRinging(int value); void OnAddNoise(int value); void OnAddGhosts(int value); void OnAddDistortions(int value); void OnAddEddy(int value); void OnConstantRadius(int value); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList&); GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; - void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection + void UpdateImageParameters(); ///< update iamge generation paaremeter struct + void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); - void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends - void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts + void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends + void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ); ///< add observers void NodeRemoved(const mitk::DataNode* node); ///< remove observers /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; + /** structure storing the image generation parameters */ + struct ImageParameters { + itk::ImageRegion<3> imageRegion; + itk::Vector imageSpacing; + itk::Point imageOrigin; + itk::Matrix imageDirection; + unsigned int numGradients; + double b_value; + unsigned int repetitions; + double signalScale; + double tEcho; + double tLine; + double tInhom; + double axonRadius; + unsigned int interpolationShrink; + double kspaceLineOffset; + double upsampling; + double eddyStrength; + double comp3Weight; + double comp4Weight; + + bool doSimulateRelaxation; + bool doSimulateEddyCurrents; + bool doDisablePartialVolume; + + mitk::RicianNoiseModel ricianNoiseModel; + mitk::DiffusionSignalModel::GradientListType gradientDirections; + itk::TractsToDWIImageFilter< short >::DiffusionModelList fiberModelList, nonFiberModelList; + itk::TractsToDWIImageFilter< short >::KspaceArtifactList artifactList; + QString signalModelString, artifactModelString; + + ItkDoubleImgType::Pointer frequencyMap; + ItkUcharImgType::Pointer tissueMaskImage; + + mitk::DataNode::Pointer resultNode; + }; + + ImageParameters m_ImageGenParameters; + std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::Image::Pointer m_TissueMask; ///< mask defining which regions of the image should contain signal and which are containing only noise mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImage; mitk::DataNode::Pointer m_SelectedDWI; vector< mitk::DataNode::Pointer > m_SelectedBundles; vector< mitk::DataNode::Pointer > m_SelectedBundles2; vector< mitk::DataNode::Pointer > m_SelectedFiducials; vector< mitk::DataNode::Pointer > m_SelectedImages; + + // intra and inter axonal compartments + mitk::StickModel m_StickModel1; + mitk::StickModel m_StickModel2; + mitk::TensorModel m_ZeppelinModel1; + mitk::TensorModel m_ZeppelinModel2; + mitk::TensorModel m_TensorModel1; + mitk::TensorModel m_TensorModel2; + + // extra axonal compartment models + mitk::BallModel m_BallModel1; + mitk::BallModel m_BallModel2; + mitk::AstroStickModel m_AstrosticksModel1; + mitk::AstroStickModel m_AstrosticksModel2; + mitk::DotModel m_DotModel1; + mitk::DotModel m_DotModel2; }; 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 59ea9db940..9a9990a7d1 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,2214 +1,2228 @@ QmitkFiberfoxViewControls 0 0 - 493 + 435 1588 Form + + + + Save Parameters + + + 0 Fiber Definition Qt::Vertical 20 40 color: rgb(255, 0, 0); Please select an image or an existing fiber bundle 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 Fiducial Options All fiducials are treated as circles with the same radius as the first fiducial. Use Constant Fiducial Radius false false Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. Align With Grid Operations - - - - false - - - Copy Bundles - - - - - + + false - Transform Selection + Join Bundles QFrame::NoFrame QFrame::Raised 0 Y false Rotation angle (in degree) around x-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Axis: false Rotation angle (in degree) around y-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Translation: false Translation (in mm) in direction of the z-axis. -1000.000000000000000 1000.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. -1000.000000000000000 1000.000000000000000 0.100000000000000 X false Rotation: false Z false Rotation angle (in degree) around z-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. -1000.000000000000000 1000.000000000000000 0.100000000000000 Scaling: false Scaling factor for selected fiber bundle along the x-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the y-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the z-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 - - + + false - Join Bundles + Copy Bundles + + + + + + + false + + + Transform Selection If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Fiber Options QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 Tension: false Fiber Sampling: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Distance of fiber sampling points (in mm) 1 0.100000000000000 0.100000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 6 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false Generate Fibers QFrame::NoFrame QFrame::Raised 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false Variance of the gaussian 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true Disable to only generate fibers if "Generate Fibers" button is pressed. Advanced Options false 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 Signal Generation Data Fiber Bundle: false <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Tissue Mask: false <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> true Image Settings QFrame::NoFrame QFrame::Raised 0 6 <html><head/><body><p><span style=" font-style:italic;">TE</span>, <span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> and <span style=" font-style:italic;">T2</span> will have no effect if unchecked.</p></body></html> Simulate Signal Relaxation true Repetitions: T2* relaxation time (in milliseconds). 100.000000000000000 0.100000000000000 1.000000000000000 Fiber Radius: Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. 0 1000 0 TE in milliseconds 1 10000 1 100 Interpolation Shrink: Line Readout Time: false <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> false Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. Disable Partial Volume Effects false Output one image per compartment containing the corresponding volume fractions per voxel. Output Volume Fractions false <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> false Number of signal averages. Increase to reduce noise. 1 100 1 1 Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). 1 10000 1 50 TE in milliseconds 1 10000 1 100 <html><head/><body><p>Large values shrink (towards nearest neighbour interpolation), small values strech interpolation function (towards linear interpolation). 1000 equals nearest neighbour interpolation.</p></body></html> 1 1000 1000 Signal Scale: color: rgb(255, 0, 0); Using geometry of selected image! color: rgb(255, 0, 0); Using gradients of selected DWI! QFrame::NoFrame QFrame::Raised 0 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Spacing: 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 3 0.100000000000000 50.000000000000000 0.100000000000000 2.000000000000000 Image Dimensions: Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 11 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 11 Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 1000 1 3 QFrame::NoFrame QFrame::Raised 0 6 Gradient Directions: Number of gradient directions distributed over the half sphere. 0 10000 1 30 b-Value: false b-value in mm/s² 0 10000 100 1000 Advanced Options Qt::Vertical 20 40 Noise and other Artifacts Add N/2 Ghosts false true QFrame::NoFrame QFrame::Raised 6 0 K-Space Line Offset: false A larger offset increases the inensity of the ghost image. 3 1.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 Variance: Variance of Rician noise model. 4 0.000000000000000 100000.000000000000000 0.001000000000000 25.000000000000000 Add ringing artifacts occuring at strong edges in the image. Add Gibbs Ringing false Add Rician Noise false true QFrame::NoFrame QFrame::Raised 6 0 Upsampling: false Larger values increase the ringing range. Beware of performance issues! 2 1.000000000000000 10.000000000000000 0.100000000000000 2.000000000000000 Add Distortions false true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 Magnitude: false Maximum magnitude of eddy current induced magnetic field inhomogeneities (in mT). 5 1000.000000000000000 0.001000000000000 0.001000000000000 color: rgb(255, 0, 0); Experimental! true QFrame::NoFrame QFrame::Raised 6 0 Frequency Map: false Select image specifying the frequency inhomogeneities (in Hz). !!!EXPERIMENTAL!!! Add Eddy Current Effects false Inter-axonal Compartment Select signal model for intra-axonal compartment. -- Stick Model Zeppelin Model Tensor Model Extra-axonal Compartments Select signal model for extra-axonal compartment. Ball Model Astrosticks Model Dot Model Select signal model for extra-axonal compartment. -- Ball Model Astrosticks Model Dot Model Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 Weighting factor between the two extra-axonal compartments. 1.000000000000000 0.100000000000000 0.300000000000000 Compartment Fraction: 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 Intra-axonal Compartment Select signal model for intra-axonal compartment. Stick Model Zeppelin Model Tensor Model + + + + Load Parameters + + + QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkTensorModelParametersWidget QWidget
QmitkTensorModelParametersWidget.h
1
QmitkStickModelParametersWidget QWidget
QmitkStickModelParametersWidget.h
1
QmitkZeppelinModelParametersWidget QWidget
QmitkZeppelinModelParametersWidget.h
1
QmitkBallModelParametersWidget QWidget
QmitkBallModelParametersWidget.h
1
QmitkAstrosticksModelParametersWidget QWidget
QmitkAstrosticksModelParametersWidget.h
1
QmitkDotModelParametersWidget QWidget
QmitkDotModelParametersWidget.h
1
m_CircleButton m_FlipButton m_RealTimeFibers m_AdvancedOptionsBox m_DistributionBox m_VarianceBox m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_GenerateFibersButton m_ConstantRadiusBox m_AlignOnGrid m_XrotBox m_YrotBox m_ZrotBox m_XtransBox m_YtransBox m_ZtransBox m_XscaleBox m_YscaleBox m_ZscaleBox m_TransformBundlesButton m_CopyBundlesButton m_JoinBundlesButton m_IncludeFiducials m_GenerateImageButton m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox m_BvalueBox m_AdvancedOptionsBox_2 m_RepetitionsBox m_SignalScaleBox m_TEbox m_LineReadoutTimeBox m_T2starBox m_FiberRadius m_InterpolationShrink m_EnforcePureFiberVoxelsBox m_Compartment1Box m_Compartment2Box m_Compartment3Box m_Compartment4Box m_Comp4FractionBox m_AddNoise m_NoiseLevel m_AddGhosts m_kOffsetBox m_AddDistortions m_FrequencyMapBox m_AddGibbsRinging tabWidget