diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp index 80d1b97949..6fabde0dc5 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp @@ -1,349 +1,337 @@ /*=================================================================== 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_txx #define __itkAddArtifactsToDwiImageFilter_txx #include #include #include #include "itkAddArtifactsToDwiImageFilter.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include namespace itk { template< class TPixelType > AddArtifactsToDwiImageFilter< TPixelType > ::AddArtifactsToDwiImageFilter() - : m_NoiseModel(NULL) - , m_FrequencyMap(NULL) - , m_kOffset(0) - , m_tLine(1) - , m_SimulateEddyCurrents(false) - , m_EddyGradientStrength(0.0) - , m_TE(100) - , m_AddGibbsRinging(false) - , m_Spikes(0) - , m_SpikeAmplitude(1) - , m_Wrap(1.0) - , m_UseConstantRandSeed(false) + : m_UseConstantRandSeed(false) { this->SetNumberOfRequiredInputs( 1 ); m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); } template< class TPixelType > void AddArtifactsToDwiImageFilter< TPixelType > ::GenerateData() { if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); m_StartTime = clock(); m_StatusText = "Starting simulation\n"; - typename DiffusionImageType::Pointer inputImage = static_cast< DiffusionImageType * >( this->ProcessObject::GetInput(0) ); + typename InputImageType::Pointer inputImage = static_cast< InputImageType* >( this->ProcessObject::GetInput(0) ); itk::ImageRegion<3> inputRegion = inputImage->GetLargestPossibleRegion(); - typename itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); + typename itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage( inputImage ); duplicator->Update(); - typename DiffusionImageType::Pointer outputImage = duplicator->GetOutput(); + typename InputImageType::Pointer outputImage = duplicator->GetOutput(); // is input slize size even? int xMax=inputRegion.GetSize(0); int yMax=inputRegion.GetSize(1); if ( xMax%2 == 1 ) xMax += 1; if ( yMax%2 == 1 ) yMax += 1; // create slice object typename SliceType::Pointer slice = SliceType::New(); ImageRegion<2> sliceRegion; sliceRegion.SetSize(0, xMax); sliceRegion.SetSize(1, yMax); slice->SetLargestPossibleRegion( sliceRegion ); slice->SetBufferedRegion( sliceRegion ); slice->SetRequestedRegion( sliceRegion ); slice->Allocate(); slice->FillBuffer(0.0); ImageRegion<2> upsampledSliceRegion; - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) { upsampledSliceRegion.SetSize(0, xMax*2); upsampledSliceRegion.SetSize(1, yMax*2); } // frequency map slice typename SliceType::Pointer fMap = NULL; - if (m_FrequencyMap.IsNotNull()) + if (m_Parameters.m_FrequencyMap.IsNotNull()) { fMap = SliceType::New(); fMap->SetLargestPossibleRegion( sliceRegion ); fMap->SetBufferedRegion( sliceRegion ); fMap->SetRequestedRegion( sliceRegion ); fMap->Allocate(); fMap->FillBuffer(0.0); } - if (m_Spikes>0 || m_FrequencyMap.IsNotNull() || m_kOffset>0.0 || m_AddGibbsRinging || m_SimulateEddyCurrents || m_Wrap<1.0) + if (m_Parameters.m_Spikes>0 || m_Parameters.m_FrequencyMap.IsNotNull() || m_Parameters.m_KspaceLineOffset>0.0 || m_Parameters.m_DoAddGibbsRinging || m_Parameters.m_EddyStrength>0 || m_Parameters.m_CroppingFactor<1.0) { - ImageRegion<3> croppedRegion = inputRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Wrap); + ImageRegion<3> croppedRegion = inputRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Parameters.m_CroppingFactor); itk::Point shiftedOrigin = inputImage->GetOrigin(); shiftedOrigin[1] += (inputRegion.GetSize(1)-croppedRegion.GetSize(1))*inputImage->GetSpacing()[1]/2; - outputImage = DiffusionImageType::New(); + outputImage = InputImageType::New(); outputImage->SetSpacing( inputImage->GetSpacing() ); outputImage->SetOrigin( shiftedOrigin ); outputImage->SetDirection( inputImage->GetDirection() ); outputImage->SetLargestPossibleRegion( croppedRegion ); outputImage->SetBufferedRegion( croppedRegion ); outputImage->SetRequestedRegion( croppedRegion ); outputImage->SetVectorLength( inputImage->GetVectorLength() ); outputImage->Allocate(); - typename DiffusionImageType::PixelType temp; + typename InputImageType::PixelType temp; temp.SetSize(inputImage->GetVectorLength()); temp.Fill(0.0); outputImage->FillBuffer(temp); int tempY=croppedRegion.GetSize(1); tempY += tempY%2; croppedRegion.SetSize(1, tempY); MatrixType transform = inputImage->GetDirection(); for (int i=0; i<3; i++) for (int j=0; j<3; j++) transform[i][j] *= inputImage->GetSpacing()[j]; m_StatusText += this->GetTime()+" > Adjusting complex signal\n"; - if (m_FrequencyMap.IsNotNull()) + if (m_Parameters.m_FrequencyMap.IsNotNull()) m_StatusText += "Simulating distortions\n"; - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) m_StatusText += "Simulating ringing artifacts\n"; - if (m_SimulateEddyCurrents) + if (m_Parameters.m_EddyStrength>0) m_StatusText += "Simulating eddy currents\n"; - if (m_Spikes>0) + if (m_Parameters.m_Spikes>0) m_StatusText += "Simulating spikes\n"; - if (m_Wrap<1.0) + if (m_Parameters.m_CroppingFactor<1.0) m_StatusText += "Simulating aliasing artifacts\n"; - if (m_kOffset>0) + if (m_Parameters.m_KspaceLineOffset>0) m_StatusText += "Simulating ghosts\n"; - std::vector< unsigned int > spikeVolume; - for (int i=0; i spikeVolume; + for (int i=0; iGetIntegerVariate()%inputImage->GetVectorLength()); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned long lastTick = 0; boost::progress_display disp(inputImage->GetVectorLength()*inputRegion.GetSize(2)); for (unsigned int g=0; gGetVectorLength(); g++) { - std::vector< unsigned int > spikeSlice; + std::vector< int > spikeSlice; while (!spikeVolume.empty() && spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%inputImage->GetLargestPossibleRegion().GetSize(2)); spikeVolume.pop_back(); } std::sort (spikeSlice.begin(), spikeSlice.end()); std::reverse (spikeSlice.begin(), spikeSlice.end()); for (unsigned int z=0; zGetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } std::vector< SliceType::Pointer > compartmentSlices; // extract slice from channel g for (unsigned int y=0; yGetPixel(index3D)[g]; slice->SetPixel(index2D, pix2D); if (fMap.IsNotNull()) - fMap->SetPixel(index2D, m_FrequencyMap->GetPixel(index3D)); + fMap->SetPixel(index2D, m_Parameters.m_FrequencyMap->GetPixel(index3D)); } - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(slice); resampler->SetOutputParametersFromImage(slice); resampler->SetSize(upsampledSliceRegion.GetSize()); resampler->SetOutputSpacing(slice->GetSpacing()/2); resampler->Update(); typename SliceType::Pointer upslice = resampler->GetOutput(); compartmentSlices.push_back(upslice); if (fMap.IsNotNull()) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(fMap); resampler->SetOutputParametersFromImage(fMap); resampler->SetSize(upsampledSliceRegion.GetSize()); resampler->SetOutputSpacing(fMap->GetSpacing()/2); resampler->Update(); fMap = resampler->GetOutput(); } } else compartmentSlices.push_back(slice); // fourier transform slice typename ComplexSliceType::Pointer fSlice; itk::Size<2> outSize; outSize.SetElement(0, xMax); outSize.SetElement(1, croppedRegion.GetSize()[1]); typename itk::KspaceImageFilter< SliceType::PixelType >::Pointer idft = itk::KspaceImageFilter< SliceType::PixelType >::New(); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); idft->SetCompartmentImages(compartmentSlices); - idft->SetkOffset(m_kOffset); - idft->SettLine(m_tLine); + idft->SetkOffset(m_Parameters.m_KspaceLineOffset); + idft->SettLine(m_Parameters.m_tLine); idft->SetSimulateRelaxation(false); idft->SetFrequencyMap(fMap); - idft->SetDiffusionGradientDirection(m_GradientList.at(g)); - idft->SetSimulateEddyCurrents(m_SimulateEddyCurrents); - idft->SetEddyGradientMagnitude(m_EddyGradientStrength); - idft->SetTE(m_TE); + idft->SetDiffusionGradientDirection(m_Parameters.GetGradientDirection(g)); + idft->SetEddyGradientMagnitude(m_Parameters.m_EddyStrength); + idft->SetTE(m_Parameters.m_tEcho); idft->SetZ((double)z-(double)inputRegion.GetSize(2)/2.0); idft->SetDirectionMatrix(transform); idft->SetOutSize(outSize); int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } idft->SetSpikes(numSpikes); - idft->SetSpikeAmplitude(m_SpikeAmplitude); + idft->SetSpikeAmplitude(m_Parameters.m_SpikeAmplitude); idft->Update(); fSlice = idft->GetOutput(); // inverse fourier transform slice typename SliceType::Pointer newSlice; typename 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 (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { - typename DiffusionImageType::IndexType index3D; + typename InputImageType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; - typename DiffusionImageType::PixelType pix3D = outputImage->GetPixel(index3D); + typename InputImageType::PixelType pix3D = outputImage->GetPixel(index3D); typename SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; double signal = newSlice->GetPixel(index2D); if (signal>0) signal = floor(signal+0.5); else signal = ceil(signal-0.5); pix3D[g] = signal; outputImage->SetPixel(index3D, pix3D); } ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } } m_StatusText += "\n\n"; } - if (m_NoiseModel!=NULL) + if (m_Parameters.m_NoiseModel!=NULL) { m_StatusText += this->GetTime()+" > Adding noise\n"; m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned long lastTick = 0; - ImageRegionIterator it1 (outputImage, outputImage->GetLargestPossibleRegion()); + ImageRegionIterator it1 (outputImage, outputImage->GetLargestPossibleRegion()); boost::progress_display disp(outputImage->GetLargestPossibleRegion().GetNumberOfPixels()); while(!it1.IsAtEnd()) { if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; - typename DiffusionImageType::PixelType signal = it1.Get(); - m_NoiseModel->AddNoise(signal); + typename InputImageType::PixelType signal = it1.Get(); + m_Parameters.m_NoiseModel->AddNoise(signal); it1.Set(signal); ++it1; } m_StatusText += "\n\n"; } this->SetNthOutput(0, outputImage); m_StatusText += "Finished simulation\n"; m_StatusText += "Simulation time: "+GetTime(); } template< class TPixelType > std::string AddArtifactsToDwiImageFilter< TPixelType >::GetTime() { unsigned long total = (double)(clock() - m_StartTime)/CLOCKS_PER_SEC; unsigned long hours = total/3600; unsigned long minutes = (total%3600)/60; unsigned long seconds = total%60; std::string out = ""; out.append(boost::lexical_cast(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); return out; } } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h index 347b43869c..8af89446d0 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.h @@ -1,109 +1,89 @@ /*=================================================================== 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 +#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 VectorImage< TPixelType, 3 > InputImageType; 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( AddGibbsRinging, bool ) - itkSetMacro( Spikes, int ) - itkSetMacro( SpikeAmplitude, double ) - itkSetMacro( Wrap, double ) itkGetMacro( StatusText, std::string ) itkSetMacro( UseConstantRandSeed, bool ) + void SetParameters( FiberfoxParameters param ){ m_Parameters = param; } + FiberfoxParameters GetParameters(){ return m_Parameters; } + protected: AddArtifactsToDwiImageFilter(); ~AddArtifactsToDwiImageFilter() {} std::string GetTime(); 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; - bool m_AddGibbsRinging; ///< causes ringing artifacts - int m_Spikes; - double m_SpikeAmplitude; - double m_Wrap; - std::string m_StatusText; - time_t m_StartTime; + FiberfoxParameters m_Parameters; + std::string m_StatusText; + time_t m_StartTime; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; - bool m_UseConstantRandSeed; + bool m_UseConstantRandSeed; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkAddArtifactsToDwiImageFilter.cpp" #endif #endif //__itkAddArtifactsToDwiImageFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h index 495231d160..aaa55c32d4 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h @@ -1,110 +1,111 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkEvaluateDirectionImagesFilter_h_ #define __itkEvaluateDirectionImagesFilter_h_ #include #include #include namespace itk{ -/** \class EvaluateDirectionImagesFilter +/** \brief Evaluates the voxel-wise angular error between two sets of directions. */ template< class PixelType > class EvaluateDirectionImagesFilter : public ImageSource< Image< PixelType, 3 > > { public: typedef EvaluateDirectionImagesFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< PixelType, 3 > > Superclass; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef typename Superclass::OutputImageType OutputImageType; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Runtime information support. */ itkTypeMacro(EvaluateDirectionImagesFilter, ImageToImageFilter) typedef Vector< float, 3 > DirectionType; typedef Image< DirectionType, 3 > DirectionImageType; typedef VectorContainer< unsigned int, DirectionImageType::Pointer > DirectionImageContainerType; typedef Image< float, 3 > FloatImageType; typedef Image< bool, 3 > BoolImageType; typedef Image< unsigned char, 3 > UCharImageType; - itkSetMacro( ImageSet , DirectionImageContainerType::Pointer) - itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) - itkSetMacro( MaskImage , UCharImageType::Pointer) - itkSetMacro( IgnoreMissingDirections , bool) + itkSetMacro( ImageSet , DirectionImageContainerType::Pointer) ///< test image containers + itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) ///< reference image containers + itkSetMacro( MaskImage , UCharImageType::Pointer) ///< Calculation is only performed inside of the mask image. + itkSetMacro( IgnoreMissingDirections , bool) ///< If in one voxel, the number of directions differs between the test container and the reference, the excess directions are ignored. Otherwise, the error to the next closest direction is calculated. + /** Output statistics of the measured angular errors. */ itkGetMacro( MeanAngularError, float) itkGetMacro( MinAngularError, float) itkGetMacro( MaxAngularError, float) itkGetMacro( VarAngularError, float) itkGetMacro( MedianAngularError, float) + /** Output statistics of the measured peak length errors. */ itkGetMacro( MeanLengthError, float) itkGetMacro( MinLengthError, float) itkGetMacro( MaxLengthError, float) itkGetMacro( VarLengthError, float) itkGetMacro( MedianLengthError, float) protected: EvaluateDirectionImagesFilter(); ~EvaluateDirectionImagesFilter() {} void GenerateData(); - UCharImageType::Pointer m_MaskImage; - DirectionImageContainerType::Pointer m_ImageSet; - DirectionImageContainerType::Pointer m_ReferenceImageSet; - bool m_IgnoreMissingDirections; + UCharImageType::Pointer m_MaskImage; + DirectionImageContainerType::Pointer m_ImageSet; + DirectionImageContainerType::Pointer m_ReferenceImageSet; + bool m_IgnoreMissingDirections; double m_MeanAngularError; double m_MedianAngularError; double m_MaxAngularError; double m_MinAngularError; double m_VarAngularError; std::vector< double > m_AngularErrorVector; - double m_MeanLengthError; double m_MedianLengthError; double m_MaxLengthError; double m_MinLengthError; double m_VarLengthError; std::vector< double > m_LengthErrorVector; double m_Eps; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkEvaluateDirectionImagesFilter.cpp" #endif #endif //__itkEvaluateDirectionImagesFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h index cf1cddc6c7..4396531a8b 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h @@ -1,107 +1,107 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkEvaluateTractogramDirectionsFilter_h_ #define __itkEvaluateTractogramDirectionsFilter_h_ #include #include #include #include namespace itk{ -/** \class EvaluateTractogramDirectionsFilter +/** \brief Calculates the voxel-wise angular error of the input tractogram to a set of voxel-wise directions. */ template< class PixelType > class EvaluateTractogramDirectionsFilter : public ImageSource< Image< PixelType, 3 > > { public: typedef EvaluateTractogramDirectionsFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< PixelType, 3 > > Superclass; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef typename Superclass::OutputImageType OutputImageType; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Runtime information support. */ itkTypeMacro(EvaluateTractogramDirectionsFilter, ImageToImageFilter) typedef mitk::FiberBundleX FiberBundleType; typedef Vector< float, 3 > DirectionType; typedef Image< DirectionType, 3 > DirectionImageType; typedef VectorContainer< int, DirectionImageType::Pointer > DirectionImageContainerType; typedef Image< float, 3 > FloatImageType; typedef Image< bool, 3 > BoolImageType; typedef Image< unsigned char, 3 > UCharImageType; typedef Image< double, 3 > DoubleImageType; - itkSetMacro( Tractogram, FiberBundleType::Pointer) - itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) - itkSetMacro( MaskImage , UCharImageType::Pointer) - itkSetMacro( IgnoreMissingDirections , bool) - itkSetMacro( UseInterpolation , bool) + itkSetMacro( Tractogram, FiberBundleType::Pointer) ///< Input tractogram + itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) ///< Input images containing one reference direction per voxel. + itkSetMacro( MaskImage , UCharImageType::Pointer) ///< Calculation is only performed inside of the mask image. + itkSetMacro( IgnoreMissingDirections , bool) ///< If in one voxel, the number of directions differs between the input tractogram and the reference, the excess directions are ignored. Otherwise, the error to the next closest direction is calculated. + itkSetMacro( UseInterpolation , bool) ///< Use trilinear interpolation. + /** Output statistics. */ itkGetMacro( MeanAngularError, float) itkGetMacro( MinAngularError, float) itkGetMacro( MaxAngularError, float) itkGetMacro( VarAngularError, float) itkGetMacro( MedianAngularError, float) protected: EvaluateTractogramDirectionsFilter(); ~EvaluateTractogramDirectionsFilter() {} void GenerateData(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< PixelType, 3 >& vector); - UCharImageType::Pointer m_MaskImage; - DirectionImageContainerType::Pointer m_ReferenceImageSet; - bool m_IgnoreMissingDirections; - double m_MeanAngularError; - double m_MedianAngularError; - double m_MaxAngularError; - double m_MinAngularError; - double m_VarAngularError; - std::vector< double > m_AngularErrorVector; - + UCharImageType::Pointer m_MaskImage; + DirectionImageContainerType::Pointer m_ReferenceImageSet; + bool m_IgnoreMissingDirections; + double m_MeanAngularError; + double m_MedianAngularError; + double m_MaxAngularError; + double m_MinAngularError; + double m_VarAngularError; + std::vector< double > m_AngularErrorVector; double m_Eps; FiberBundleType::Pointer m_Tractogram; bool m_UseInterpolation; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkEvaluateTractogramDirectionsFilter.cpp" #endif #endif //__itkEvaluateTractogramDirectionsFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h index b0d24d3530..2445de2fbd 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFibersFromPlanarFiguresFilter.h @@ -1,105 +1,105 @@ /*=================================================================== 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 itkFibersFromPlanarFiguresFilter_h #define itkFibersFromPlanarFiguresFilter_h // MITK #include #include // ITK #include // VTK #include #include #include #include #include using namespace std; namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FibersFromPlanarFiguresFilter : public ProcessObject { public: enum FiberDistribution{ DISTRIBUTE_UNIFORM, // distribute fibers uniformly in the ROIs DISTRIBUTE_GAUSSIAN // distribute fibers using a 2D gaussian }; typedef FibersFromPlanarFiguresFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef vector< vector< mitk::PlanarEllipse::Pointer > > FiducialListType; typedef vector< vector< unsigned int > > FlipListType; typedef mitk::FiberBundleX::Pointer FiberType; typedef vector< mitk::FiberBundleX::Pointer > FiberContainerType; itkNewMacro(Self) itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) - void GenerateData(); - virtual void Update(){ this->GenerateData(); } // input void SetFlipList(FlipListType fliplist){ m_FlipList = fliplist; } ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting) void SetFiducials(FiducialListType fiducials){ m_Fiducials = fiducials; } ///< container of the planar ellipses used as fiducials for the fiber generation process itkSetMacro(Density, int) ///< number of fibers per bundle - itkSetMacro(FiberSampling, double) ///< sampling points of the fibers per cm + itkSetMacro(FiberSampling, double) ///< sampling points of the fibers per cm itkSetMacro(Tension, double) ///< tension parameter of the Kochanek-Bartels splines itkSetMacro(Continuity, double) ///< continuity parameter of the Kochanek-Bartels splines itkSetMacro(Bias, double) ///< bias parameter of the Kochanek-Bartels splines itkSetMacro(FiberDistribution, FiberDistribution) ///< flag to switch between uniform and gaussian distribution of the fiber waypoints inside of the fiducials itkSetMacro(Variance, double) ///< variance of the gaussian waypoint distribution // output FiberContainerType GetFiberBundles(){ return m_FiberBundles; } protected: + void GenerateData(); + FibersFromPlanarFiguresFilter(); virtual ~FibersFromPlanarFiguresFilter(); void GeneratePoints(); FiberDistribution m_FiberDistribution; ///< flag to switch between uniform and gaussian distribution of the fiber waypoints inside of the fiducials FlipListType m_FlipList; ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting) FiducialListType m_Fiducials; ///< container of the planar ellipses used as fiducials for the fiber generation process FiberContainerType m_FiberBundles; ///< container for the output fiber bundles int m_Density; ///< number of fibers per bundle double m_FiberSampling; ///< sampling points of the fibers per cm double m_Tension; ///< tension parameter of the Kochanek-Bartels splines double m_Continuity; ///< continuity parameter of the Kochanek-Bartels splines double m_Bias; ///< bias parameter of the Kochanek-Bartels splines double m_Variance; ///< variance of the gaussian waypoint distribution vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFibersFromPlanarFiguresFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFieldmapGeneratorFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFieldmapGeneratorFilter.h index 73030eef3c..eda579bbd0 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFieldmapGeneratorFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkFieldmapGeneratorFilter.h @@ -1,85 +1,92 @@ /*=================================================================== 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 __itkFieldmapGeneratorFilter_h__ #define __itkFieldmapGeneratorFilter_h__ #include #include #include #include #include #include #include namespace itk{ /** -* \brief Generates tract density images from input fiberbundles (Calamante 2010). */ +* \brief Generate float image with artificial frequency maps used by Fiberfox. Simulates additional frequencies at (possibly multiple) positions based on 3D gaussians with the specified variance and amplitude and/or as a linear gradient in the image. +* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. +*/ template< class OutputImageType > class FieldmapGeneratorFilter : public ImageSource< OutputImageType > { public: typedef FieldmapGeneratorFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef typename OutputImageType::PixelType PixelType; typedef typename OutputImageType::IndexType IndexType; typedef itk::ImageRegion<3> OutputImageRegionType; typedef itk::Matrix MatrixType; itkNewMacro(Self) itkTypeMacro( FieldmapGeneratorFilter, ImageSource ) + /** Output image parameters. */ itkSetMacro( Spacing, itk::Vector ) itkSetMacro( Origin, mitk::Point3D ) itkSetMacro( DirectionMatrix, MatrixType ) itkSetMacro( ImageRegion, OutputImageRegionType ) + + /** Gradient direction and offset. */ void SetGradient( vnl_vector_fixed< double, 3 > gradient ) { m_Gradient=gradient; } void SetOffset( vnl_vector_fixed< double, 3 > offset ) { m_Offset=offset; } + + /** Parameters of gaussian frequency sources. */ void SetVariances( std::vector< double > variances ) { m_Variances=variances; } void SetHeights( std::vector< double > heights ) { m_Heights=heights; } void SetWorldPositions( std::vector< mitk::Point3D > worldPositions ) { m_WorldPositions=worldPositions; } protected: void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId); FieldmapGeneratorFilter(); virtual ~FieldmapGeneratorFilter(); itk::Vector m_Spacing; ///< output image spacing mitk::Point3D m_Origin; ///< output image origin MatrixType m_DirectionMatrix; ///< output image rotation OutputImageRegionType m_ImageRegion; ///< output image size std::vector< double > m_Variances; std::vector< double > m_Heights; std::vector< mitk::Point3D > m_WorldPositions; vnl_vector_fixed< double, 3 > m_Gradient; vnl_vector_fixed< double, 3 > m_Offset; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFieldmapGeneratorFilter.cpp" #endif #endif // __itkFieldmapGeneratorFilter_h__ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.h index 831e995140..470f22c8a9 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkGibbsTrackingFilter.h @@ -1,153 +1,152 @@ /*=================================================================== 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 itkGibbsTrackingFilter_h #define itkGibbsTrackingFilter_h // MITK #include // ITK #include #include #include #include // VTK #include #include #include #include #include namespace itk{ /** * \brief Performes global fiber tractography on the input Q-Ball or tensor image (Gibbs tracking, Reisert 2010). */ template< class ItkQBallImageType > class GibbsTrackingFilter : public ProcessObject { public: typedef GibbsTrackingFilter Self; typedef ProcessObject Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkNewMacro(Self) itkTypeMacro( GibbsTrackingFilter, ProcessObject ) typedef Image< DiffusionTensor3D, 3 > ItkTensorImage; typedef typename ItkQBallImageType::Pointer ItkQBallImageTypePointer; typedef Image< float, 3 > ItkFloatImageType; typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType; - // parameter setter - itkSetMacro( StartTemperature, float ) - itkSetMacro( EndTemperature, float ) - itkSetMacro( Iterations, unsigned long ) - itkSetMacro( ParticleWeight, float ) - itkSetMacro( ParticleWidth, float ) + /** Setter. */ + itkSetMacro( StartTemperature, float ) ///< Start temperature of simulated annealing process. + itkSetMacro( EndTemperature, float ) ///< End temperature of simulated annealing process. + itkSetMacro( Iterations, unsigned long ) ///< Number of iterations. More iterations usually mean better results. Maximum 5x10^8 + itkSetMacro( ParticleWeight, float ) ///< Smaller particle weights result in a higher sensitivity if the method. + itkSetMacro( ParticleWidth, float ) ///< Thinner particles cause more reconstructed fibers. itkSetMacro( ParticleLength, float ) itkSetMacro( ConnectionPotential, float ) - itkSetMacro( InexBalance, float ) + itkSetMacro( InexBalance, float ) ///< Values < 0 result in a stronger weighting of the internal energy, values > 0 cause a stronger weighting of the external energy, itkSetMacro( ParticlePotential, float ) - itkSetMacro( MinFiberLength, int ) - itkSetMacro( AbortTracking, bool ) - itkSetMacro( CurvatureThreshold, float) - itkSetMacro( DuplicateImage, bool ) - itkSetMacro( RandomSeed, int ) - itkSetMacro( LoadParameterFile, std::string ) + itkSetMacro( MinFiberLength, int ) ///< Shorter fibers are discarded + itkSetMacro( AbortTracking, bool ) ///< Set flag to prematurely abort tracking. + itkSetMacro( CurvatureThreshold, float) ///< Absolute angular threshold between two particles (in radians). + itkSetMacro( DuplicateImage, bool ) ///< Work on copy of input image. + itkSetMacro( RandomSeed, int ) ///< Seed for random generator. + itkSetMacro( LoadParameterFile, std::string ) ///< Parameter file. itkSetMacro( SaveParameterFile, std::string ) - itkSetMacro( LutPath, std::string ) + itkSetMacro( LutPath, std::string ) ///< Path to lookuptables. Default is binary directory. - // getter + /** Getter. */ itkGetMacro( ParticleWeight, float ) itkGetMacro( ParticleWidth, float ) itkGetMacro( ParticleLength, float ) itkGetMacro( CurrentStep, unsigned long ) itkGetMacro( NumParticles, int ) itkGetMacro( NumConnections, int ) itkGetMacro( NumAcceptedFibers, int ) itkGetMacro( ProposalAcceptance, float ) itkGetMacro( Steps, unsigned int) itkGetMacro( IsInValidState, bool) + FiberPolyDataType GetFiberBundle(); ///< Output fibers - // input data + /** Input images. */ itkSetMacro(QBallImage, typename ItkQBallImageType::Pointer) itkSetMacro(MaskImage, ItkFloatImageType::Pointer) itkSetMacro(TensorImage, ItkTensorImage::Pointer) - void GenerateData(); - virtual void Update(){ this->GenerateData(); } - FiberPolyDataType GetFiberBundle(); - protected: + void GenerateData(); + GibbsTrackingFilter(); virtual ~GibbsTrackingFilter(); void EstimateParticleWeight(); void PrepareMaskImage(); bool LoadParameters(); bool SaveParameters(); // Input Images typename ItkQBallImageType::Pointer m_QBallImage; typename ItkFloatImageType::Pointer m_MaskImage; typename ItkTensorImage::Pointer m_TensorImage; // Tracking parameters float m_StartTemperature; ///< Start temperature float m_EndTemperature; ///< End temperature unsigned long m_Iterations; ///< Total number of iterations unsigned long m_CurrentStep; ///< current tracking step float m_ParticleWeight; ///< w (unitless) float m_ParticleWidth; ///< sigma (mm) float m_ParticleLength; ///< l (mm) float m_ConnectionPotential; ///< gross L (chemisches potential, default 10) float m_InexBalance; ///< gewichtung zwischen den lambdas; -5 ... 5 -> nur intern ... nur extern,default 0 float m_ParticlePotential; ///< default 0.2 int m_MinFiberLength; ///< discard all fibers shortan than the specified length in mm bool m_AbortTracking; ///< set flag to abort tracking int m_NumAcceptedFibers; ///< number of reconstructed fibers generated by the FiberBuilder volatile bool m_BuildFibers; ///< set flag to generate fibers from particle grid unsigned int m_Steps; ///< number of temperature decrease steps float m_ProposalAcceptance; ///< proposal acceptance rate (0-1) float m_CurvatureThreshold; ///< curvature threshold in radians (1 -> no curvature is accepted, -1 all curvature angles are accepted) bool m_DuplicateImage; ///< generates a working copy of the qball image so that the original image won't be changed by the mean subtraction int m_NumParticles; ///< current number of particles in grid int m_NumConnections; ///< current number of connections between particles in grid int m_RandomSeed; ///< seed value for random generator (-1 for standard seeding) std::string m_LoadParameterFile; ///< filename of parameter file (reader) std::string m_SaveParameterFile; ///< filename of parameter file (writer) std::string m_LutPath; ///< path to lookuptables used by the sphere interpolator bool m_IsInValidState; ///< Whether the filter is in a valid state, false if error occured FiberPolyDataType m_FiberPolyData; ///< container for reconstructed fibers //Constant values static const int m_ParticleGridCellCapacity = 1024; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkGibbsTrackingFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp index e46cb29be6..b1658b5849 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp @@ -1,235 +1,223 @@ /*=================================================================== 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_SimulateRelaxation(true) - , m_SimulateEddyCurrents(false) - , m_FrequencyMap(NULL) - , m_tLine(1) + : m_tLine(1) , m_kOffset(0) + , m_FrequencyMap(NULL) + , m_SimulateRelaxation(true) , m_Tau(70) , m_EddyGradientMagnitude(30) , m_IsBaseline(true) - , m_SignalScale(1) + , m_SignalScale(25) , m_Spikes(0) , m_SpikeAmplitude(1) , m_UseConstantRandSeed(false) + , m_Tinhom(50) { m_DiffusionGradientDirection.Fill(0.0); m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); } template< class TPixelType > void KspaceImageFilter< TPixelType > ::BeforeThreadedGenerateData() { if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); typename OutputImageType::Pointer outputImage = OutputImageType::New(); 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_SimulateDistortions = true; - if (m_FrequencyMap.IsNull()) - { - m_SimulateDistortions = false; - m_FrequencyMap = InputImageType::New(); - 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) + if (m_EddyGradientMagnitude>0 && m_DiffusionGradientDirection.GetNorm()>0.001) { m_EddyGradientMagnitude /= 1000; // eddy gradient magnitude in T/m m_DiffusionGradientDirection.Normalize(); m_DiffusionGradientDirection = m_DiffusionGradientDirection * m_EddyGradientMagnitude * gamma; m_IsBaseline = false; } this->SetNthOutput(0, outputImage); m_Spike = vcl_complex(0,0); } 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 kxMax = outputImage->GetLargestPossibleRegion().GetSize(0); // k-space size in x-direction double kyMax = outputImage->GetLargestPossibleRegion().GetSize(1); // k-space size in y-direction double xMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(0); // scanner coverage in x-direction double yMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(1); // scanner coverage in y-direction double numPix = kxMax*kyMax; double dt = m_tLine/kxMax; double fromMaxEcho = - m_tLine*kyMax/2; double upsampling = xMax/kxMax; // discrepany between k-space resolution and image resolution double yMaxFov = kyMax*upsampling; // actual FOV in y-direction (in x-direction xMax==FOV) int xRingingOffset = xMax-kxMax; int yRingingOffset = yMaxFov-kyMax; while( !oit.IsAtEnd() ) { itk::Index< 2 > kIdx; kIdx[0] = oit.GetIndex()[0]; kIdx[1] = oit.GetIndex()[1]; double t = fromMaxEcho + ((double)kIdx[1]*kxMax+(double)kIdx[0])*dt; // dephasing time // rearrange slice if( kIdx[0] < kxMax/2 ) kIdx[0] = kIdx[0] + kxMax/2; else kIdx[0] = kIdx[0] - kxMax/2; if( kIdx[1] < kyMax/2 ) kIdx[1] = kIdx[1] + kyMax/2; else kIdx[1] = kIdx[1] - kyMax/2; // calculate eddy current decay factors double eddyDecay = 0; - if (m_SimulateEddyCurrents) + if (m_EddyGradientMagnitude>0) eddyDecay = exp(-(m_TE/2 + t)/m_Tau) * t/1000; // calcualte signal relaxation factors std::vector< double > relaxFactor; if (m_SimulateRelaxation) for (unsigned int i=0; i=kxMax/2) kx += xRingingOffset; if (ky>=kyMax/2) ky += yRingingOffset; vcl_complex s(0,0); InputIteratorType it(m_CompartmentImages.at(0), m_CompartmentImages.at(0)->GetLargestPossibleRegion() ); while( !it.IsAtEnd() ) { double x = it.GetIndex()[0]-xMax/2; double y = it.GetIndex()[1]-yMax/2; vcl_complex f(0, 0); // sum compartment signals and simulate relaxation for (unsigned 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 && !m_IsBaseline) + if ( m_EddyGradientMagnitude>0 && !m_IsBaseline) { itk::Vector< double, 3 > pos; pos[0] = x; pos[1] = y; 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; } - if (m_SimulateDistortions) + if (m_FrequencyMap.IsNotNull()) // simulate distortions omega_t += m_FrequencyMap->GetPixel(it.GetIndex())*t/1000; if (y<-yMaxFov/2) y += yMaxFov; else if (y>=yMaxFov/2) y -= yMaxFov; // actual DFT term s += f * exp( std::complex(0, 2 * M_PI * (kx*x/xMax + ky*y/yMaxFov + omega_t )) ); ++it; } s /= numPix; if (m_Spikes>0 && sqrt(s.imag()*s.imag()+s.real()*s.real()) > sqrt(m_Spike.imag()*m_Spike.imag()+m_Spike.real()*m_Spike.real()) ) m_Spike = s; outputImage->SetPixel(kIdx, s); ++oit; } } template< class TPixelType > void KspaceImageFilter< TPixelType > ::AfterThreadedGenerateData() { typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0)); double kxMax = outputImage->GetLargestPossibleRegion().GetSize(0); // k-space size in x-direction double kyMax = outputImage->GetLargestPossibleRegion().GetSize(1); // k-space size in y-direction m_Spike *= m_SpikeAmplitude; itk::Index< 2 > spikeIdx; for (int i=0; iGetIntegerVariate()%(int)kxMax; spikeIdx[1] = m_RandGen->GetIntegerVariate()%(int)kyMax; outputImage->SetPixel(spikeIdx, m_Spike); } } } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h index fa98d45f4b..63ebd14c39 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h @@ -1,130 +1,134 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkKspaceImageFilter_h_ #define __itkKspaceImageFilter_h_ #include "FiberTrackingExports.h" #include #include #include #include using namespace std; namespace itk{ /** -* \brief Performes deterministic streamline tracking on the input tensor image. */ +* \brief Simulates k-space acquisition of one slice with a single shot EPI sequence. Enables the simulation of various effects occuring during real MR acquisitions: +* - T2 signal relaxation +* - Spikes +* - N/2 Ghosts +* - Aliasing (wrap around) +* - Image distortions (off-frequency effects) +* - Gibbs ringing +* - Eddy current effects +* Based on a discrete fourier transformation. +* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. +*/ template< class TPixelType > class KspaceImageFilter : public ImageSource< Image< vcl_complex< TPixelType >, 2 > > { public: typedef KspaceImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageSource< Image< vcl_complex< TPixelType >, 2 > > Superclass; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Runtime information support. */ itkTypeMacro(KspaceImageFilter, ImageToImageFilter) typedef typename itk::Image< double, 2 > InputImageType; typedef typename InputImageType::Pointer InputImagePointerType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::Matrix MatrixType; typedef itk::Point Point2D; - itkSetMacro( FrequencyMap, typename InputImageType::Pointer ) - itkSetMacro( tLine, double ) - itkSetMacro( kOffset, double ) - itkSetMacro( TE, double) - itkSetMacro( Tinhom, double) - itkSetMacro( Tau, double) - itkSetMacro( SimulateRelaxation, bool ) - itkSetMacro( SimulateEddyCurrents, bool ) - itkSetMacro( Z, double ) - itkSetMacro( DirectionMatrix, MatrixType ) - itkSetMacro( SignalScale, double ) - itkSetMacro( OutSize, itk::Size<2> ) - itkSetMacro( Spikes, int ) - itkSetMacro( SpikeAmplitude, double ) - itkSetMacro( UseConstantRandSeed, bool ) - - void SetT2( std::vector< double > t2Vector ) { m_T2=t2Vector; } - void SetCompartmentImages( std::vector< InputImagePointerType > cImgs ) { m_CompartmentImages=cImgs; } - void SetDiffusionGradientDirection(itk::Vector g) { m_DiffusionGradientDirection=g; } - void SetEddyGradientMagnitude(double g_mag) { m_EddyGradientMagnitude=g_mag; } ///< in T/m + itkSetMacro( FrequencyMap, typename InputImageType::Pointer ) ///< Used to simulate distortions. Specifies additional frequency component per voxel. + itkSetMacro( tLine, double ) ///< Time needed to fill one line in k-space (in ms). + itkSetMacro( kOffset, double ) ///< Causes N/2 ghosting artifacts. + itkSetMacro( TE, double) ///< Echo time TE (in ms). + itkSetMacro( Tinhom, double) ///< T2' signal relaxation constant (in ms). + itkSetMacro( Tau, double) ///< Eddy current decay constant (in ms). + itkSetMacro( SimulateRelaxation, bool ) ///< Enable T2 signal relaxation. + itkSetMacro( Z, double ) ///< Slice position, necessary for eddy current simulation. + itkSetMacro( DirectionMatrix, MatrixType ) ///< Image rotation matrix, necessary for eddy current simulation. + itkSetMacro( SignalScale, double ) ///< Scaling factor for resulting signal. + itkSetMacro( OutSize, itk::Size<2> ) ///< Output slice size. Can be different from input size, e.g. if Gibbs ringing is enabled. + itkSetMacro( Spikes, int ) ///< Number of randomly placed spikes per slice. + itkSetMacro( SpikeAmplitude, double ) ///< Spike amplitude relative to the largest slice value (magnitude of complex). + itkSetMacro( UseConstantRandSeed, bool ) ///< Use constant seed for random generator for reproducible results. + itkSetMacro( EddyGradientMagnitude, double) ///< Magnitude of eddy current induced gradients in T/m + + void SetCompartmentImages( std::vector< InputImagePointerType > cImgs ) { m_CompartmentImages=cImgs; } ///< One signal image per compartment. + void SetT2( std::vector< double > t2Vector ) { m_T2=t2Vector; } ///< One T2 relaxation constant per compartment image. + void SetDiffusionGradientDirection(itk::Vector g) { m_DiffusionGradientDirection=g; } ///< Gradient direction is needed for eddy current simulation. protected: KspaceImageFilter(); ~KspaceImageFilter() {} void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId); void AfterThreadedGenerateData(); bool m_SimulateRelaxation; - bool m_SimulateDistortions; - bool m_SimulateEddyCurrents; - - typename InputImageType::Pointer m_TEMPIMAGE; typename InputImageType::Pointer m_FrequencyMap; double m_tLine; double m_kOffset; - double m_Tinhom; double m_TE; vector< double > m_T2; vector< InputImagePointerType > m_CompartmentImages; itk::Vector m_DiffusionGradientDirection; - double m_Tau; ///< eddy current decay constant - double m_EddyGradientMagnitude; ///< in T/m + double m_Tau; + double m_EddyGradientMagnitude; double m_Z; MatrixType m_DirectionMatrix; bool m_IsBaseline; double m_SignalScale; itk::Size<2> m_OutSize; int m_Spikes; double m_SpikeAmplitude; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; bool m_UseConstantRandSeed; vcl_complex m_Spike; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkKspaceImageFilter.cpp" #endif #endif //__itkKspaceImageFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h index 7d588adad0..9885496b5b 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h @@ -1,141 +1,141 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkStreamlineTrackingFilter_h_ #define __itkStreamlineTrackingFilter_h_ #include "FiberTrackingExports.h" #include #include #include #include #include #include #include #include #include namespace itk{ /** * \brief Performes deterministic streamline tracking on the input tensor image. */ template< class TTensorPixelType, class TPDPixelType=double> class StreamlineTrackingFilter : public ImageToImageFilter< Image< DiffusionTensor3D, 3 >, Image< Vector< TPDPixelType, 3 >, 3 > > { public: typedef StreamlineTrackingFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< Image< DiffusionTensor3D, 3 >, Image< Vector< TPDPixelType, 3 >, 3 > > Superclass; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Runtime information support. */ itkTypeMacro(StreamlineTrackingFilter, ImageToImageFilter) typedef TTensorPixelType TensorComponentType; typedef TPDPixelType DirectionPixelType; typedef typename Superclass::InputImageType InputImageType; typedef typename Superclass::OutputImageType OutputImageType; typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef itk::Image ItkUcharImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image< vnl_vector_fixed, 3> ItkPDImgType; typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType; - itkGetMacro( FiberPolyData, FiberPolyDataType ) - itkSetMacro( SeedImage, ItkUcharImgType::Pointer) - itkSetMacro( MaskImage, ItkUcharImgType::Pointer) - itkSetMacro( FaImage, ItkFloatImgType::Pointer) - itkSetMacro( SeedsPerVoxel, int) - itkSetMacro( FaThreshold, float) - itkSetMacro( StepSize, float) - itkSetMacro( F, float ) - itkSetMacro( G, float ) - itkSetMacro( Interpolate, bool ) - itkSetMacro( MinTractLength, float ) + itkGetMacro( FiberPolyData, FiberPolyDataType ) ///< Output fibers + itkSetMacro( SeedImage, ItkUcharImgType::Pointer) ///< Seeds are only placed inside of this mask. + itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< Tracking is only performed inside of this mask image. + itkSetMacro( FaImage, ItkFloatImgType::Pointer) ///< Use this FA image instead of the automatically calculated one. Necessary for multi tensor tracking. + itkSetMacro( SeedsPerVoxel, int) ///< One seed placed in the center of each voxel or multiple seeds randomly placed inside each voxel. + itkSetMacro( FaThreshold, float) ///< FA termination criterion. + itkSetMacro( StepSize, float) ///< Integration step size in mm + itkSetMacro( F, float ) ///< Tensor deflection parameter f + itkSetMacro( G, float ) ///< Tensor deflection parameter g + itkSetMacro( Interpolate, bool ) ///< Toggle between nearest neighbour (false) and trilinear interpolation (true) + itkSetMacro( MinTractLength, float ) ///< Shorter tracts are discarded. itkGetMacro( MinTractLength, float ) - itkSetMacro( MinCurvatureRadius, float ) + itkSetMacro( MinCurvatureRadius, float ) ///< Tracking is stopped if curvature radius (in mm) is too small. itkGetMacro( MinCurvatureRadius, float ) - itkSetMacro( ResampleFibers, bool ) + itkSetMacro( ResampleFibers, bool ) ///< If enabled, the resulting fibers are resampled to feature point distances of 0.5*MinSpacing. This is recommendable for very short integration steps and many seeds. If disabled, the resulting fiber bundle might become very large. protected: StreamlineTrackingFilter(); ~StreamlineTrackingFilter() {} void PrintSelf(std::ostream& os, Indent indent) const; - void CalculateNewPosition(itk::ContinuousIndex& pos, vnl_vector_fixed& dir, typename InputImageType::IndexType& index); - float FollowStreamline(itk::ContinuousIndex pos, int dirSign, vtkPoints* points, std::vector< vtkIdType >& ids, int imageIdx); - bool IsValidPosition(itk::ContinuousIndex& pos, typename InputImageType::IndexType& index, vnl_vector_fixed< float, 8 >& interpWeights, int imageIdx); + void CalculateNewPosition(itk::ContinuousIndex& pos, vnl_vector_fixed& dir, typename InputImageType::IndexType& index); ///< Calculate next integration step. + float FollowStreamline(itk::ContinuousIndex pos, int dirSign, vtkPoints* points, std::vector< vtkIdType >& ids, int imageIdx); ///< Start streamline in one direction. + bool IsValidPosition(itk::ContinuousIndex& pos, typename InputImageType::IndexType& index, vnl_vector_fixed< float, 8 >& interpWeights, int imageIdx); ///< Are we outside of the mask image? Is the FA too low? double RoundToNearest(double num); void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId); void AfterThreadedGenerateData(); - FiberPolyDataType AddPolyData(FiberPolyDataType poly1, FiberPolyDataType poly2); - - FiberPolyDataType m_FiberPolyData; - vtkSmartPointer m_Points; - vtkSmartPointer m_Cells; - - std::vector< ItkFloatImgType::Pointer > m_EmaxImage; - ItkFloatImgType::Pointer m_FaImage; - std::vector< ItkPDImgType::Pointer > m_PdImage; - std::vector< typename InputImageType::Pointer > m_InputImage; - - int m_NumberOfInputs; - float m_FaThreshold; - float m_MinCurvatureRadius; - float m_StepSize; - int m_MaxLength; - float m_MinTractLength; - int m_SeedsPerVoxel; - float m_F; - float m_G; - std::vector< int > m_ImageSize; - std::vector< float > m_ImageSpacing; - ItkUcharImgType::Pointer m_SeedImage; - ItkUcharImgType::Pointer m_MaskImage; - bool m_Interpolate; - float m_PointPistance; - bool m_ResampleFibers; + FiberPolyDataType AddPolyData(FiberPolyDataType poly1, FiberPolyDataType poly2); ///< Combine tracking results generated by the individual threads. + + FiberPolyDataType m_FiberPolyData; + vtkSmartPointer m_Points; + vtkSmartPointer m_Cells; + + std::vector< ItkFloatImgType::Pointer > m_EmaxImage; ///< Stores largest eigenvalues per voxel (one for each tensor) + ItkFloatImgType::Pointer m_FaImage; ///< FA image used to determine streamline termination. + std::vector< ItkPDImgType::Pointer > m_PdImage; ///< Stores principal direction of each tensor in each voxel. + std::vector< typename InputImageType::Pointer > m_InputImage; ///< Input tensor images. For multi tensor tracking provide multiple tensor images. + + int m_NumberOfInputs; + float m_FaThreshold; + float m_MinCurvatureRadius; + float m_StepSize; + int m_MaxLength; + float m_MinTractLength; + int m_SeedsPerVoxel; + float m_F; + float m_G; + bool m_Interpolate; + float m_PointPistance; + bool m_ResampleFibers; + std::vector< int > m_ImageSize; + std::vector< float > m_ImageSpacing; + ItkUcharImgType::Pointer m_SeedImage; + ItkUcharImgType::Pointer m_MaskImage; itk::VectorContainer< int, FiberPolyDataType >::Pointer m_PolyDataContainer; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkStreamlineTrackingFilter.cpp" #endif #endif //__itkStreamlineTrackingFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 48f94a4d87..0b474f357c 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,989 +1,885 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() - : m_CircleDummy(false) - , m_VolumeAccuracy(10) - , m_AddGibbsRinging(false) - , 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_Spikes(0) - , m_Wrap(1.0) - , m_NoiseModel(NULL) - , m_SpikeAmplitude(1) - , m_AddMotionArtifact(false) - , m_UseConstantRandSeed(false) + : m_UseConstantRandSeed(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); - - m_MaxTranslation.Fill(0.0); - m_MaxRotation.Fill(0.0); - m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); m_RandGen->SetSeed(); } template< class PixelType > TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } 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 fMapSlice = NULL; - if (m_FrequencyMap.IsNotNull()) + if (m_Parameters.m_FrequencyMap.IsNotNull()) { fMapSlice = SliceType::New(); ImageRegion<2> region; region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); fMapSlice->SetLargestPossibleRegion( region ); fMapSlice->SetBufferedRegion( region ); fMapSlice->SetRequestedRegion( region ); fMapSlice->Allocate(); fMapSlice->FillBuffer(0.0); } 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->SetSpacing( m_Parameters.m_ImageSpacing ); + newImage->SetOrigin( m_Parameters.m_ImageOrigin ); + newImage->SetDirection( m_Parameters.m_ImageDirection ); + newImage->SetLargestPossibleRegion( m_Parameters.m_ImageRegion ); + newImage->SetBufferedRegion( m_Parameters.m_ImageRegion ); + newImage->SetRequestedRegion( m_Parameters.m_ImageRegion ); newImage->SetVectorLength( images.at(0)->GetVectorLength() ); newImage->Allocate(); - MatrixType transform = m_DirectionMatrix; + MatrixType transform = m_Parameters.m_ImageDirection; 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]; + transform[i][j] *= m_Parameters.m_ImageSpacing[j]; } std::vector< unsigned int > spikeVolume; - for (int i=0; iGetIntegerVariate()%images.at(0)->GetVectorLength()); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned long lastTick = 0; boost::progress_display disp(2*images.at(0)->GetVectorLength()*images.at(0)->GetLargestPossibleRegion().GetSize(2)); for (unsigned int g=0; gGetVectorLength(); g++) { - std::vector< unsigned int > spikeSlice; + std::vector< int > spikeSlice; while (!spikeVolume.empty() && spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%images.at(0)->GetLargestPossibleRegion().GetSize(2)); spikeVolume.pop_back(); } std::sort (spikeSlice.begin(), spikeSlice.end()); std::reverse (spikeSlice.begin(), spikeSlice.end()); for (unsigned int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { std::vector< SliceType::Pointer > compartmentSlices; std::vector< double > t2Vector; for (unsigned 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 (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned 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 (fMapSlice.IsNotNull() && i==0) - fMapSlice->SetPixel(index2D, m_FrequencyMap->GetPixel(index3D)); + fMapSlice->SetPixel(index2D, m_Parameters.m_FrequencyMap->GetPixel(index3D)); } compartmentSlices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); } if (this->GetAbortGenerateData()) return NULL; // 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::Size<2> outSize; outSize.SetElement(0, m_Parameters.m_ImageRegion.GetSize(0)); outSize.SetElement(1, m_Parameters.m_ImageRegion.GetSize(1)); itk::KspaceImageFilter< SliceType::PixelType >::Pointer idft = itk::KspaceImageFilter< SliceType::PixelType >::New(); idft->SetCompartmentImages(compartmentSlices); idft->SetT2(t2Vector); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); - 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->SetkOffset(m_Parameters.m_KspaceLineOffset); + idft->SettLine(m_Parameters.m_tLine); + idft->SetTE(m_Parameters.m_tEcho); + idft->SetTinhom(m_Parameters.m_tInhom); + idft->SetSimulateRelaxation(m_Parameters.m_DoSimulateRelaxation); + idft->SetEddyGradientMagnitude(m_Parameters.m_EddyStrength); 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->SetDiffusionGradientDirection(m_Parameters.m_FiberModelList.at(0)->GetGradientDirection(g)); idft->SetFrequencyMap(fMapSlice); - idft->SetSignalScale(m_SignalScale); + idft->SetSignalScale(m_Parameters.m_SignalScale); idft->SetOutSize(outSize); - unsigned int numSpikes = 0; + int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } idft->SetSpikes(numSpikes); - idft->SetSpikeAmplitude(m_SpikeAmplitude); + idft->SetSpikeAmplitude(m_Parameters.m_SpikeAmplitude); idft->Update(); ComplexSliceType::Pointer fSlice; fSlice = idft->GetOutput(); ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); - for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) + for (int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; // 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 (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned 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; newTick = 50*disp.count()/disp.expected_count(); - for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) + for (int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; } } m_StatusText += "\n\n"; return newImage; } template< class PixelType > void TractsToDWIImageFilter< PixelType >::GenerateData() { m_StartTime = clock(); m_StatusText = "Starting simulation\n"; // 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_EnforcePureFiberVoxels) - while (m_FiberModels.size()>1) - m_FiberModels.pop_back(); + if (m_Parameters.m_DoDisablePartialVolume) + while (m_Parameters.m_FiberModelList.size()>1) + m_Parameters.m_FiberModelList.pop_back(); - if (m_NonFiberModels.empty()) + if (m_Parameters.m_NonFiberModelList.empty()) itkExceptionMacro("No diffusion model for non-fiber compartments defined!"); - int baselineIndex = m_FiberModels[0]->GetFirstBaselineIndex(); + int baselineIndex = m_Parameters.GetFirstBaselineIndex(); if (baselineIndex<0) itkExceptionMacro("No baseline index found!"); if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); // initialize output dwi image - ImageRegion<3> croppedRegion = m_ImageRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Wrap); - itk::Point shiftedOrigin = m_Origin; shiftedOrigin[1] += (m_ImageRegion.GetSize(1)-croppedRegion.GetSize(1))*m_Spacing[1]/2; - + ImageRegion<3> croppedRegion = m_Parameters.m_ImageRegion; croppedRegion.SetSize(1, croppedRegion.GetSize(1)*m_Parameters.m_CroppingFactor); + itk::Point shiftedOrigin = m_Parameters.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_ImageRegion.GetSize(1)-croppedRegion.GetSize(1))*m_Parameters.m_ImageSpacing[1]/2; typename OutputImageType::Pointer outImage = OutputImageType::New(); - outImage->SetSpacing( m_Spacing ); + outImage->SetSpacing( m_Parameters.m_ImageSpacing ); outImage->SetOrigin( shiftedOrigin ); - outImage->SetDirection( m_DirectionMatrix ); + outImage->SetDirection( m_Parameters.m_ImageDirection ); outImage->SetLargestPossibleRegion( croppedRegion ); outImage->SetBufferedRegion( croppedRegion ); outImage->SetRequestedRegion( croppedRegion ); - outImage->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); + outImage->SetVectorLength( m_Parameters.GetNumVolumes() ); outImage->Allocate(); typename OutputImageType::PixelType temp; - temp.SetSize(m_FiberModels[0]->GetNumGradients()); + temp.SetSize(m_Parameters.GetNumVolumes()); temp.Fill(0.0); outImage->FillBuffer(temp); // ADJUST GEOMETRY FOR FURTHER PROCESSING // is input slize size a power of two? - unsigned int x=m_ImageRegion.GetSize(0); unsigned int y=m_ImageRegion.GetSize(1); + unsigned int x=m_Parameters.m_ImageRegion.GetSize(0); unsigned int y=m_Parameters.m_ImageRegion.GetSize(1); ItkDoubleImgType::SizeType pad; pad[0]=x%2; pad[1]=y%2; pad[2]=0; - m_ImageRegion.SetSize(0, x+pad[0]); - m_ImageRegion.SetSize(1, y+pad[1]); - if (m_FrequencyMap.IsNotNull() && (pad[0]>0 || pad[1]>0)) + m_Parameters.m_ImageRegion.SetSize(0, x+pad[0]); + m_Parameters.m_ImageRegion.SetSize(1, y+pad[1]); + if (m_Parameters.m_FrequencyMap.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); - zeroPadder->SetInput(m_FrequencyMap); + zeroPadder->SetInput(m_Parameters.m_FrequencyMap); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); - m_FrequencyMap = zeroPadder->GetOutput(); + m_Parameters.m_FrequencyMap = zeroPadder->GetOutput(); } - if (m_TissueMask.IsNotNull() && (pad[0]>0 || pad[1]>0)) + if (m_Parameters.m_MaskImage.IsNotNull() && (pad[0]>0 || pad[1]>0)) { itk::ConstantPadImageFilter::Pointer zeroPadder = itk::ConstantPadImageFilter::New(); - zeroPadder->SetInput(m_TissueMask); + zeroPadder->SetInput(m_Parameters.m_MaskImage); zeroPadder->SetConstant(0); zeroPadder->SetPadUpperBound(pad); zeroPadder->Update(); - m_TissueMask = zeroPadder->GetOutput(); + m_Parameters.m_MaskImage = zeroPadder->GetOutput(); } - // apply in-plane upsampling + // Apply in-plane upsampling for Gibbs ringing artifact double upsampling = 1; - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) upsampling = 2; - m_UpsampledSpacing = m_Spacing; + m_UpsampledSpacing = m_Parameters.m_ImageSpacing; m_UpsampledSpacing[0] /= upsampling; m_UpsampledSpacing[1] /= upsampling; - m_UpsampledImageRegion = m_ImageRegion; - m_UpsampledImageRegion.SetSize(0, m_ImageRegion.GetSize()[0]*upsampling); - m_UpsampledImageRegion.SetSize(1, m_ImageRegion.GetSize()[1]*upsampling); - m_UpsampledOrigin = m_Origin; - m_UpsampledOrigin[0] -= m_Spacing[0]/2; m_UpsampledOrigin[0] += m_UpsampledSpacing[0]/2; - m_UpsampledOrigin[1] -= m_Spacing[1]/2; m_UpsampledOrigin[1] += m_UpsampledSpacing[1]/2; - m_UpsampledOrigin[2] -= m_Spacing[2]/2; m_UpsampledOrigin[2] += m_UpsampledSpacing[2]/2; + m_UpsampledImageRegion = m_Parameters.m_ImageRegion; + m_UpsampledImageRegion.SetSize(0, m_Parameters.m_ImageRegion.GetSize()[0]*upsampling); + m_UpsampledImageRegion.SetSize(1, m_Parameters.m_ImageRegion.GetSize()[1]*upsampling); + m_UpsampledOrigin = m_Parameters.m_ImageOrigin; + m_UpsampledOrigin[0] -= m_Parameters.m_ImageSpacing[0]/2; m_UpsampledOrigin[0] += m_UpsampledSpacing[0]/2; + m_UpsampledOrigin[1] -= m_Parameters.m_ImageSpacing[1]/2; m_UpsampledOrigin[1] += m_UpsampledSpacing[1]/2; + m_UpsampledOrigin[2] -= m_Parameters.m_ImageSpacing[2]/2; m_UpsampledOrigin[2] += m_UpsampledSpacing[2]/2; // generate double images to store the individual compartment signals std::vector< DoubleDwiType::Pointer > compartments; - for (unsigned int i=0; iSetSpacing( m_UpsampledSpacing ); doubleDwi->SetOrigin( m_UpsampledOrigin ); - doubleDwi->SetDirection( m_DirectionMatrix ); + doubleDwi->SetDirection( m_Parameters.m_ImageDirection ); doubleDwi->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleDwi->SetBufferedRegion( m_UpsampledImageRegion ); doubleDwi->SetRequestedRegion( m_UpsampledImageRegion ); - doubleDwi->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); + doubleDwi->SetVectorLength( m_Parameters.GetNumVolumes() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; - pix.SetSize(m_FiberModels[0]->GetNumGradients()); + pix.SetSize(m_Parameters.GetNumVolumes()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); compartments.push_back(doubleDwi); } // initialize volume fraction images m_VolumeFractions.clear(); - for (unsigned int i=0; iSetSpacing( m_UpsampledSpacing ); doubleImg->SetOrigin( m_UpsampledOrigin ); - doubleImg->SetDirection( m_DirectionMatrix ); + doubleImg->SetDirection( m_Parameters.m_ImageDirection ); doubleImg->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleImg->SetBufferedRegion( m_UpsampledImageRegion ); doubleImg->SetRequestedRegion( m_UpsampledImageRegion ); doubleImg->Allocate(); doubleImg->FillBuffer(0); m_VolumeFractions.push_back(doubleImg); } // resample mask image and frequency map to fit upsampled geometry - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) { - if (m_TissueMask.IsNotNull()) + if (m_Parameters.m_MaskImage.IsNotNull()) { // rescale mask image (otherwise there are problems with the resampling) itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); - rescaler->SetInput(0,m_TissueMask); + rescaler->SetInput(0,m_Parameters.m_MaskImage); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); // resample mask image itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); - resampler->SetOutputParametersFromImage(m_TissueMask); + resampler->SetOutputParametersFromImage(m_Parameters.m_MaskImage); resampler->SetSize(m_UpsampledImageRegion.GetSize()); resampler->SetOutputSpacing(m_UpsampledSpacing); resampler->SetOutputOrigin(m_UpsampledOrigin); resampler->Update(); - m_TissueMask = resampler->GetOutput(); + m_Parameters.m_MaskImage = resampler->GetOutput(); } // resample frequency map - if (m_FrequencyMap.IsNotNull()) + if (m_Parameters.m_FrequencyMap.IsNotNull()) { itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); - resampler->SetInput(m_FrequencyMap); - resampler->SetOutputParametersFromImage(m_FrequencyMap); + resampler->SetInput(m_Parameters.m_FrequencyMap); + resampler->SetOutputParametersFromImage(m_Parameters.m_FrequencyMap); resampler->SetSize(m_UpsampledImageRegion.GetSize()); resampler->SetOutputSpacing(m_UpsampledSpacing); resampler->SetOutputOrigin(m_UpsampledOrigin); resampler->Update(); - m_FrequencyMap = resampler->GetOutput(); + m_Parameters.m_FrequencyMap = resampler->GetOutput(); } } // no input tissue mask is set -> create default bool maskImageSet = true; - if (m_TissueMask.IsNull()) + if (m_Parameters.m_MaskImage.IsNull()) { m_StatusText += "No tissue mask set\n"; MITK_INFO << "No tissue mask set"; - m_TissueMask = ItkUcharImgType::New(); - m_TissueMask->SetSpacing( m_UpsampledSpacing ); - m_TissueMask->SetOrigin( m_UpsampledOrigin ); - 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); + m_Parameters.m_MaskImage = ItkUcharImgType::New(); + m_Parameters.m_MaskImage->SetSpacing( m_UpsampledSpacing ); + m_Parameters.m_MaskImage->SetOrigin( m_UpsampledOrigin ); + m_Parameters.m_MaskImage->SetDirection( m_Parameters.m_ImageDirection ); + m_Parameters.m_MaskImage->SetLargestPossibleRegion( m_UpsampledImageRegion ); + m_Parameters.m_MaskImage->SetBufferedRegion( m_UpsampledImageRegion ); + m_Parameters.m_MaskImage->SetRequestedRegion( m_UpsampledImageRegion ); + m_Parameters.m_MaskImage->Allocate(); + m_Parameters.m_MaskImage->FillBuffer(1); maskImageSet = false; } else { m_StatusText += "Using tissue mask\n"; MITK_INFO << "Using tissue mask"; } - m_ImageRegion = croppedRegion; - x=m_ImageRegion.GetSize(0); y=m_ImageRegion.GetSize(1); + m_Parameters.m_ImageRegion = croppedRegion; + x=m_Parameters.m_ImageRegion.GetSize(0); y=m_Parameters.m_ImageRegion.GetSize(1); if ( x%2 == 1 ) - m_ImageRegion.SetSize(0, x+1); + m_Parameters.m_ImageRegion.SetSize(0, x+1); if ( y%2 == 1 ) - m_ImageRegion.SetSize(1, y+1); + m_Parameters.m_ImageRegion.SetSize(1, y+1); // resample fiber bundle for sufficient voxel coverage m_StatusText += "\n"+this->GetTime()+" > Resampling fibers ...\n"; double segmentVolume = 0.0001; float minSpacing = 1; if(m_UpsampledSpacing[0]GetDeepCopy(); - fiberBundle->ResampleFibers(minSpacing/m_VolumeAccuracy); - double mmRadius = m_FiberRadius/1000; + double volumeAccuracy = 10; + fiberBundle->ResampleFibers(minSpacing/volumeAccuracy); + double mmRadius = m_Parameters.m_AxonRadius/1000; if (mmRadius>0) - segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/m_VolumeAccuracy; + segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/volumeAccuracy; - double interpFact = 2*atan(-0.5*m_InterpolationShrink); double maxVolume = 0; double voxelVolume = m_UpsampledSpacing[0]*m_UpsampledSpacing[1]*m_UpsampledSpacing[2]; - if (m_AddMotionArtifact) + if (m_Parameters.m_DoAddMotion) { - if (m_RandomMotion) + if (m_Parameters.m_DoRandomizeMotion) { m_StatusText += "Adding random motion artifacts:\n"; - m_StatusText += "Maximum rotation: +/-" + boost::lexical_cast(m_MaxRotation) + "°\n"; - m_StatusText += "Maximum translation: +/-" + boost::lexical_cast(m_MaxTranslation) + "mm\n"; + m_StatusText += "Maximum rotation: +/-" + boost::lexical_cast(m_Parameters.m_Rotation) + "°\n"; + m_StatusText += "Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_Translation) + "mm\n"; } else { m_StatusText += "Adding linear motion artifacts:\n"; - m_StatusText += "Maximum rotation: " + boost::lexical_cast(m_MaxRotation) + "°\n"; - m_StatusText += "Maximum translation: " + boost::lexical_cast(m_MaxTranslation) + "mm\n"; + m_StatusText += "Maximum rotation: " + boost::lexical_cast(m_Parameters.m_Rotation) + "°\n"; + m_StatusText += "Maximum translation: " + boost::lexical_cast(m_Parameters.m_Translation) + "mm\n"; } MITK_INFO << "Adding motion artifacts"; - MITK_INFO << "Maximum rotation: " << m_MaxRotation; - MITK_INFO << "Maxmimum translation: " << m_MaxTranslation; + MITK_INFO << "Maximum rotation: " << m_Parameters.m_Rotation; + MITK_INFO << "Maxmimum translation: " << m_Parameters.m_Translation; } maxVolume = 0; - m_StatusText += "\n"+this->GetTime()+" > Generating signal of " + boost::lexical_cast(m_FiberModels.size()) + " fiber compartments\n"; - MITK_INFO << "Generating signal of " << m_FiberModels.size() << " fiber compartments"; - boost::progress_display disp(numFibers*m_FiberModels.at(0)->GetNumGradients()); + m_StatusText += "\n"+this->GetTime()+" > Generating signal of " + boost::lexical_cast(m_Parameters.m_FiberModelList.size()) + " fiber compartments\n"; + MITK_INFO << "Generating signal of " << m_Parameters.m_FiberModelList.size() << " fiber compartments"; + int numFibers = m_FiberBundle->GetNumFibers(); + boost::progress_display disp(numFibers*m_Parameters.GetNumVolumes()); ofstream logFile; logFile.open("fiberfox_motion.log"); logFile << "0 rotation: 0,0,0; translation: 0,0,0\n"; // get transform for motion artifacts FiberBundleType fiberBundleTransformed = fiberBundle; - VectorType rotation = m_MaxRotation/m_FiberModels.at(0)->GetNumGradients(); - VectorType translation = m_MaxTranslation/m_FiberModels.at(0)->GetNumGradients(); + VectorType rotation = m_Parameters.m_Rotation/m_Parameters.GetNumVolumes(); + VectorType translation = m_Parameters.m_Translation/m_Parameters.GetNumVolumes(); // creat image to hold transformed mask (motion artifact) ItkUcharImgType::Pointer tempTissueMask = ItkUcharImgType::New(); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); - duplicator->SetInputImage(m_TissueMask); + duplicator->SetInputImage(m_Parameters.m_MaskImage); duplicator->Update(); tempTissueMask = duplicator->GetOutput(); // second upsampling needed for motion artifacts ImageRegion<3> upsampledImageRegion = m_UpsampledImageRegion; itk::Vector upsampledSpacing = m_UpsampledSpacing; upsampledSpacing[0] /= 4; upsampledSpacing[1] /= 4; upsampledSpacing[2] /= 4; upsampledImageRegion.SetSize(0, m_UpsampledImageRegion.GetSize()[0]*4); upsampledImageRegion.SetSize(1, m_UpsampledImageRegion.GetSize()[1]*4); upsampledImageRegion.SetSize(2, m_UpsampledImageRegion.GetSize()[2]*4); itk::Point upsampledOrigin = m_UpsampledOrigin; upsampledOrigin[0] -= m_UpsampledSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; upsampledOrigin[1] -= m_UpsampledSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; upsampledOrigin[2] -= m_UpsampledSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; ItkUcharImgType::Pointer upsampledTissueMask = ItkUcharImgType::New(); itk::ResampleImageFilter::Pointer upsampler = itk::ResampleImageFilter::New(); - upsampler->SetInput(m_TissueMask); - upsampler->SetOutputParametersFromImage(m_TissueMask); + upsampler->SetInput(m_Parameters.m_MaskImage); + upsampler->SetOutputParametersFromImage(m_Parameters.m_MaskImage); upsampler->SetSize(upsampledImageRegion.GetSize()); upsampler->SetOutputSpacing(upsampledSpacing); upsampler->SetOutputOrigin(upsampledOrigin); itk::NearestNeighborInterpolateImageFunction::Pointer nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); upsampler->SetInterpolator(nn_interpolator); upsampler->Update(); upsampledTissueMask = upsampler->GetOutput(); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; unsigned int lastTick = 0; - for (int g=0; gGetNumGradients(); g++) + for (int g=0; gGetFiberPolyData(); ItkDoubleImgType::Pointer intraAxonalVolume = ItkDoubleImgType::New(); intraAxonalVolume->SetSpacing( m_UpsampledSpacing ); intraAxonalVolume->SetOrigin( m_UpsampledOrigin ); - intraAxonalVolume->SetDirection( m_DirectionMatrix ); + intraAxonalVolume->SetDirection( m_Parameters.m_ImageDirection ); intraAxonalVolume->SetLargestPossibleRegion( m_UpsampledImageRegion ); intraAxonalVolume->SetBufferedRegion( m_UpsampledImageRegion ); intraAxonalVolume->SetRequestedRegion( m_UpsampledImageRegion ); intraAxonalVolume->Allocate(); intraAxonalVolume->FillBuffer(0); - // generate fiber signal - for( int i=0; iGetCell(i); - int numPoints = cell->GetNumberOfPoints(); - vtkPoints* points = cell->GetPoints(); + // generate fiber signal (if there are any fiber models present) + if (!m_Parameters.m_FiberModelList.empty()) + for( int i=0; iGetCell(i); + int numPoints = cell->GetNumberOfPoints(); + vtkPoints* points = cell->GetPoints(); - if (numPoints<2) - continue; + if (numPoints<2) + continue; - for( int j=0; jGetAbortGenerateData()) + for( int j=0; jGetTime()+" > Simulation aborted\n"; - return; - } + if (this->GetAbortGenerateData()) + { + m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; + return; + } - double* temp = points->GetPoint(j); - itk::Point vertex = GetItkPoint(temp); - itk::Vector v = GetItkVector(temp); + double* temp = points->GetPoint(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::Vector dir(3); + if (jGetPoint(j+1))-v; + else + dir = v-GetItkVector(points->GetPoint(j-1)); - if (dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) - continue; + if (dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2]) + continue; - itk::Index<3> idx; - itk::ContinuousIndex contIndex; - tempTissueMask->TransformPhysicalPointToIndex(vertex, idx); - tempTissueMask->TransformPhysicalPointToContinuousIndex(vertex, contIndex); + itk::Index<3> idx; + itk::ContinuousIndex contIndex; + tempTissueMask->TransformPhysicalPointToIndex(vertex, idx); + tempTissueMask->TransformPhysicalPointToContinuousIndex(vertex, contIndex); - if (!m_UseInterpolation) // use nearest neighbour interpolation - { if (!tempTissueMask->GetLargestPossibleRegion().IsInside(idx) || tempTissueMask->GetPixel(idx)<=0) continue; // generate signal for each fiber compartment - for (unsigned int k=0; kSetFiberDirection(dir); + m_Parameters.m_FiberModelList[k]->SetFiberDirection(dir); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(idx); - pix[g] += segmentVolume*m_FiberModels[k]->SimulateMeasurement(g); + pix[g] += segmentVolume*m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g); doubleDwi->SetPixel(idx, pix ); double vol = intraAxonalVolume->GetPixel(idx) + segmentVolume; intraAxonalVolume->SetPixel(idx, vol ); if (g==0 && vol>maxVolume) maxVolume = vol; } - 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 (!tempTissueMask->GetLargestPossibleRegion().IsInside(newIdx) || tempTissueMask->GetPixel(newIdx)<=0) - continue; - - // generate signal for each fiber compartment - for (unsigned int k=0; kSetFiberDirection(dir); - DoubleDwiType::PixelType pix = doubleDwi->GetPixel(newIdx); - pix[g] += segmentVolume*frac*m_FiberModels[k]->SimulateMeasurement(g); - doubleDwi->SetPixel(newIdx, pix ); - - double vol = intraAxonalVolume->GetPixel(idx) + segmentVolume; - intraAxonalVolume->SetPixel(idx, vol ); - - if (g==0 && vol>maxVolume) - maxVolume = vol; - } - } - } } + ++disp; + unsigned long newTick = 50*disp.count()/disp.expected_count(); + for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) + m_StatusText += "*"; + lastTick = newTick; } - ++disp; - unsigned long newTick = 50*disp.count()/disp.expected_count(); - for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) - m_StatusText += "*"; - lastTick = newTick; - } // generate non-fiber signal ImageRegionIterator it3(tempTissueMask, tempTissueMask->GetLargestPossibleRegion()); double fact = 1; - if (m_FiberRadius<0.0001) + if (m_Parameters.m_AxonRadius<0.0001) fact = voxelVolume/maxVolume; while(!it3.IsAtEnd()) { if (it3.Get()>0) { DoubleDwiType::IndexType index = it3.GetIndex(); // 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[g] *= fact; fiberDwi->SetPixel(index, fiberPix); } double f = intraAxonalVolume->GetPixel(index)*fact; - if (f>voxelVolume || (f>0.0 && m_EnforcePureFiberVoxels) ) // more fiber than space in voxel? + if (f>voxelVolume || (f>0.0 && m_Parameters.m_DoDisablePartialVolume) ) // more fiber than space in voxel? { fiberPix[g] *= voxelVolume/f; fiberDwi->SetPixel(index, fiberPix); m_VolumeFractions.at(0)->SetPixel(index, 1); } else { m_VolumeFractions.at(0)->SetPixel(index, f/voxelVolume); double nonf = voxelVolume-f; // non-fiber volume double inter = 0; - if (m_FiberModels.size()>1) + if (m_Parameters.m_FiberModelList.size()>1) inter = nonf * f/voxelVolume; // inter-axonal fraction of non fiber compartment scales linearly with f double other = nonf - inter; // rest of compartment - double singleinter = inter/(m_FiberModels.size()-1); + double singleinter = inter/(m_Parameters.m_FiberModelList.size()-1); // adjust non-fiber and intra-axonal signal - for (unsigned int i=1; iGetPixel(index); if (f>0) pix[g] /= f; pix[g] *= singleinter; doubleDwi->SetPixel(index, pix); m_VolumeFractions.at(i)->SetPixel(index, singleinter/voxelVolume); } - for (unsigned int i=0; iGetPixel(index); - // if (dynamic_cast< mitk::AstroStickModel* >(m_NonFiberModels.at(i))) + // if (dynamic_cast< mitk::AstroStickModel* >(m_Parameters.m_NonFiberModelList.at(i))) // { - // mitk::AstroStickModel* model = dynamic_cast< mitk::AstroStickModel* >(m_NonFiberModels.at(i)); + // mitk::AstroStickModel* model = dynamic_cast< mitk::AstroStickModel* >(m_Parameters.m_NonFiberModelList.at(i)); // model->SetSeed(8111984); // } - pix[g] += m_NonFiberModels[i]->SimulateMeasurement(g)*other*m_NonFiberModels[i]->GetWeight(); + pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g)*other*m_Parameters.m_NonFiberModelList[i]->GetWeight(); doubleDwi->SetPixel(index, pix); - m_VolumeFractions.at(i+m_FiberModels.size())->SetPixel(index, other/voxelVolume*m_NonFiberModels[i]->GetWeight()); + m_VolumeFractions.at(i+m_Parameters.m_FiberModelList.size())->SetPixel(index, other/voxelVolume*m_Parameters.m_NonFiberModelList[i]->GetWeight()); } } } ++it3; } // move fibers - if (m_AddMotionArtifact) + if (m_Parameters.m_DoAddMotion) { - if (m_RandomMotion) + if (m_Parameters.m_DoRandomizeMotion) { fiberBundleTransformed = fiberBundle->GetDeepCopy(); - rotation[0] = m_RandGen->GetVariateWithClosedRange(m_MaxRotation[0]*2)-m_MaxRotation[0]; - rotation[1] = m_RandGen->GetVariateWithClosedRange(m_MaxRotation[1]*2)-m_MaxRotation[1]; - rotation[2] = m_RandGen->GetVariateWithClosedRange(m_MaxRotation[2]*2)-m_MaxRotation[2]; - translation[0] = m_RandGen->GetVariateWithClosedRange(m_MaxTranslation[0]*2)-m_MaxTranslation[0]; - translation[1] = m_RandGen->GetVariateWithClosedRange(m_MaxTranslation[1]*2)-m_MaxTranslation[1]; - translation[2] = m_RandGen->GetVariateWithClosedRange(m_MaxTranslation[2]*2)-m_MaxTranslation[2]; + rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Rotation[0]*2)-m_Parameters.m_Rotation[0]; + rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Rotation[1]*2)-m_Parameters.m_Rotation[1]; + rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Rotation[2]*2)-m_Parameters.m_Rotation[2]; + translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Translation[0]*2)-m_Parameters.m_Translation[0]; + translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Translation[1]*2)-m_Parameters.m_Translation[1]; + translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_Translation[2]*2)-m_Parameters.m_Translation[2]; } // rotate mask image if (maskImageSet) { ImageRegionIterator maskIt(upsampledTissueMask, upsampledTissueMask->GetLargestPossibleRegion()); tempTissueMask->FillBuffer(0); while(!maskIt.IsAtEnd()) { if (maskIt.Get()<=0) { ++maskIt; continue; } DoubleDwiType::IndexType index = maskIt.GetIndex(); itk::Point point; upsampledTissueMask->TransformIndexToPhysicalPoint(index, point); - if (m_RandomMotion) + if (m_Parameters.m_DoRandomizeMotion) point = fiberBundle->TransformPoint(point.GetVnlVector(), rotation[0],rotation[1],rotation[2],translation[0],translation[1],translation[2]); else point = fiberBundle->TransformPoint(point.GetVnlVector(), rotation[0]*(g+1),rotation[1]*(g+1),rotation[2]*(g+1),translation[0]*(g+1),translation[1]*(g+1),translation[2]*(g+1)); tempTissueMask->TransformPhysicalPointToIndex(point, index); if (tempTissueMask->GetLargestPossibleRegion().IsInside(index)) tempTissueMask->SetPixel(index,100); ++maskIt; } } // rotate fibers logFile << g+1 << " rotation:" << rotation[0] << "," << rotation[1] << "," << rotation[2] << ";"; logFile << " translation:" << translation[0] << "," << translation[1] << "," << translation[2] << "\n"; fiberBundleTransformed->TransformFibers(rotation[0],rotation[1],rotation[2],translation[0],translation[1],translation[2]); } } logFile.close(); m_StatusText += "\n\n"; if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } // do k-space stuff DoubleDwiType::Pointer doubleOutImage; - if (m_Spikes>0 || m_FrequencyMap.IsNotNull() || m_kOffset>0 || m_SimulateRelaxation || m_SimulateEddyCurrents || m_AddGibbsRinging || m_Wrap<1.0) + if (m_Parameters.m_Spikes>0 || m_Parameters.m_FrequencyMap.IsNotNull() || m_Parameters.m_KspaceLineOffset>0 || m_Parameters.m_DoSimulateRelaxation || m_Parameters.m_EddyStrength>0 || m_Parameters.m_DoAddGibbsRinging || m_Parameters.m_CroppingFactor<1.0) { m_StatusText += this->GetTime()+" > Adjusting complex signal\n"; MITK_INFO << "Adjusting complex signal:"; - if (m_SimulateRelaxation) + if (m_Parameters.m_DoSimulateRelaxation) m_StatusText += "Simulating signal relaxation\n"; - if (m_FrequencyMap.IsNotNull()) + if (m_Parameters.m_FrequencyMap.IsNotNull()) m_StatusText += "Simulating distortions\n"; - if (m_AddGibbsRinging) + if (m_Parameters.m_DoAddGibbsRinging) m_StatusText += "Simulating ringing artifacts\n"; - if (m_SimulateEddyCurrents) + if (m_Parameters.m_EddyStrength>0) m_StatusText += "Simulating eddy currents\n"; - if (m_Spikes>0) + if (m_Parameters.m_Spikes>0) m_StatusText += "Simulating spikes\n"; - if (m_Wrap<1.0) + if (m_Parameters.m_CroppingFactor<1.0) m_StatusText += "Simulating aliasing artifacts\n"; - if (m_kOffset>0) + if (m_Parameters.m_KspaceLineOffset>0) m_StatusText += "Simulating ghosts\n"; doubleOutImage = DoKspaceStuff(compartments); - m_SignalScale = 1; + m_Parameters.m_SignalScale = 1; } else { m_StatusText += this->GetTime()+" > Summing compartments\n"; MITK_INFO << "Summing compartments"; doubleOutImage = compartments.at(0); for (unsigned 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(); } } if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } m_StatusText += this->GetTime()+" > Finalizing image\n"; MITK_INFO << "Finalizing image"; - if (m_SignalScale>1) + if (m_Parameters.m_SignalScale>1) m_StatusText += " Scaling signal\n"; - if (m_NoiseModel!=NULL) + if (m_Parameters.m_NoiseModel!=NULL) m_StatusText += " Adding noise\n"; unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); - DoubleDwiType::PixelType signal; signal.SetSize(m_FiberModels[0]->GetNumGradients()); + DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.GetNumVolumes()); boost::progress_display disp2(outImage->GetLargestPossibleRegion().GetNumberOfPixels()); m_StatusText += "0% 10 20 30 40 50 60 70 80 90 100%\n"; m_StatusText += "|----|----|----|----|----|----|----|----|----|----|\n*"; lastTick = 0; while(!it4.IsAtEnd()) { if (this->GetAbortGenerateData()) { m_StatusText += "\n"+this->GetTime()+" > Simulation aborted\n"; return; } ++disp2; unsigned long newTick = 50*disp2.count()/disp2.expected_count(); - for (unsigned int tick = 0; tick<(newTick-lastTick); tick++) + for (int tick = 0; tick<(newTick-lastTick); tick++) m_StatusText += "*"; lastTick = newTick; typename OutputImageType::IndexType index = it4.GetIndex(); - signal = doubleOutImage->GetPixel(index)*m_SignalScale; + signal = doubleOutImage->GetPixel(index)*m_Parameters.m_SignalScale; - if (m_NoiseModel!=NULL) + if (m_Parameters.m_NoiseModel!=NULL) { DoubleDwiType::PixelType accu = signal; accu.Fill(0.0); - for (unsigned int i=0; iAddNoise(temp); + m_Parameters.m_NoiseModel->AddNoise(temp); accu += temp; } - signal = accu/m_NumberOfRepetitions; + signal = accu/m_Parameters.m_Repetitions; } for (unsigned 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) + if (!m_Parameters.IsBaselineIndex(i) && signal[i]>window) window = signal[i]; - if (!m_FiberModels.at(0)->IsBaselineIndex(i) && signal[i]SetNthOutput(0, outImage); m_StatusText += "\n\n"; m_StatusText += "Finished simulation\n"; m_StatusText += "Simulation time: "+GetTime(); } 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; } 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; } 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; } 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; } template< class PixelType > std::string TractsToDWIImageFilter< PixelType >::GetTime() { unsigned long total = (double)(clock() - m_StartTime)/CLOCKS_PER_SEC; unsigned long hours = total/3600; unsigned long minutes = (total%3600)/60; unsigned long seconds = total%60; std::string out = ""; out.append(boost::lexical_cast(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); return out; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h index cb9e1d4b32..55e21eee46 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,172 +1,104 @@ /*=================================================================== 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 - -// ITK -#include -#include -#include #include -#include -#include - +#include #include -#include - +#include +#include "FiberTrackingExports.h" namespace itk { /** -* \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. */ +* \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. +* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. +*/ template< class PixelType > class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > > { public: - typedef TractsToDWIImageFilter Self; + typedef TractsToDWIImageFilter Self; 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::DiffusionSignalModel* > DiffusionModelList; - typedef itk::Matrix MatrixType; - typedef mitk::DiffusionNoiseModel NoiseModelType; - typedef itk::Image< double, 2 > SliceType; - typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; - typedef itk::Vector< double,3> VectorType; - typedef itk::Point< double,3> PointType; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::OutputImageType OutputImageType; + typedef itk::Image ItkDoubleImgType; + typedef itk::Image ItkUcharImgType; + typedef mitk::FiberBundleX::Pointer FiberBundleType; + typedef itk::VectorImage< double, 3 > DoubleDwiType; + typedef itk::Matrix MatrixType; + typedef itk::Image< double, 2 > SliceType; + typedef itk::VnlForwardFFTImageFilter::OutputImageType ComplexSliceType; + typedef itk::Vector< double,3> VectorType; 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, VectorType ) ///< output image spacing - itkSetMacro( Origin, PointType ) ///< 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 + itkTypeMacro( TractsToDWIImageFilter, ImageSource ) + + /** Input */ + itkSetMacro( FiberBundle, FiberBundleType ) ///< Input fiber bundle + itkSetMacro( UseConstantRandSeed, bool ) ///< Seed for random generator. + void SetParameters( FiberfoxParameters param ) ///< Simulation parameters. + { m_Parameters = param; } + + /** Output */ + FiberfoxParameters GetParameters(){ return m_Parameters; } + std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel + { return m_VolumeFractions; } 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( AddGibbsRinging, bool ) - itkSetMacro( Spikes, int ) - itkSetMacro( SpikeAmplitude, double ) - itkSetMacro( Wrap, double ) - itkSetMacro( MaxTranslation, VectorType ) - itkSetMacro( MaxRotation, VectorType ) - itkSetMacro( AddMotionArtifact, bool ) - itkSetMacro( RandomMotion, bool ) itkGetMacro( StatusText, std::string ) - itkSetMacro( UseConstantRandSeed, bool ) - - // 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); std::string GetTime(); - /** Transform generated image compartment by compartment, channel by channel and slice by slice using FFT and add k-space artifacts. */ + /** Transform generated image compartment by compartment, channel by channel and slice by slice using DFT and add k-space artifacts. */ DoubleDwiType::Pointer DoKspaceStuff(std::vector< DoubleDwiType::Pointer >& images); - bool m_CircleDummy; - unsigned int m_VolumeAccuracy; - bool m_AddGibbsRinging; ///< causes ringing artifacts - unsigned int m_NumberOfRepetitions; - bool m_EnforcePureFiberVoxels; - double m_InterpolationShrink; - double m_FiberRadius; - double m_SignalScale; - double m_kOffset; - double m_tLine; - 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; - double m_tInhom; - double m_TE; - ItkDoubleImgType::Pointer m_FrequencyMap; ///< map of the B0 inhomogeneities - double m_EddyGradientStrength; - bool m_SimulateEddyCurrents; - int m_Spikes; - double m_Wrap; - NoiseModelType* m_NoiseModel; ///< generates the noise added to the image values - double m_SpikeAmplitude; - itk::Vector m_Spacing; ///< output image spacing - itk::Vector m_UpsampledSpacing; - itk::Point m_Origin; ///< output image origin - itk::Point m_UpsampledOrigin; - 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) - FiberBundleType m_FiberBundle; ///< input fiber bundle - DiffusionModelList m_FiberModels; ///< generate signal of fiber compartments - DiffusionModelList m_NonFiberModels; ///< generate signal of non-fiber compartments - mitk::LevelWindow m_LevelWindow; - VectorType m_MaxTranslation; - VectorType m_MaxRotation; - bool m_AddMotionArtifact; - bool m_RandomMotion; + mitk::FiberfoxParameters m_Parameters; + itk::Vector m_UpsampledSpacing; + itk::Point m_UpsampledOrigin; + ImageRegion<3> m_UpsampledImageRegion; + FiberBundleType m_FiberBundle; + mitk::LevelWindow m_LevelWindow; + std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; + std::string m_StatusText; + time_t m_StartTime; + bool m_UseConstantRandSeed; itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; - std::string m_StatusText; - time_t m_StartTime; - bool m_UseConstantRandSeed; }; } +#ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToDWIImageFilter.cpp" +#endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp index 735fa45f7f..3314f2fc3c 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp @@ -1,121 +1,450 @@ /*=================================================================== 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 -using namespace mitk; +#include +#include +#include +#include "mitkFiberfoxParameters.h" -FiberfoxParameters::FiberfoxParameters() - : m_NumGradients(6) +#include +#include +#include +#include +#include + +template< class ScalarType > +mitk::FiberfoxParameters< ScalarType >::FiberfoxParameters() + : m_DoAddGibbsRinging(false) + , m_ArtifactModelString("") + , m_AxonRadius(0) , m_Bvalue(1000) + , m_DoAddMotion(false) + , m_DoDisablePartialVolume(false) + , m_DoSimulateRelaxation(true) + , m_EddyStrength(0) + , m_KspaceLineOffset(0) + , m_NumGradients(6) + , m_NumBaseline(1) + , m_OutputPath("") + , m_DoRandomizeMotion(true) , m_Repetitions(1) + , m_SignalModelString("") , m_SignalScale(100) + , m_SpikeAmplitude(1) + , m_Spikes(0) , m_tEcho(100) - , m_tLine(1) , m_tInhom(50) - , m_AxonRadius(0) - , m_InterpolationShrink(0) - , m_KspaceLineOffset(0) - , m_AddGibbsRinging(false) - , m_EddyStrength(0) - , m_Comp3Weight(1) - , m_Comp4Weight(0) - , m_Spikes(0) - , m_SpikeAmplitude(1) - , m_Wrap(1) - , m_DoSimulateRelaxation(true) - , m_DoSimulateEddyCurrents(false) - , m_DoDisablePartialVolume(false) - , m_DoAddMotion(false) - , m_RandomMotion(true) - , m_NoiseModel(NULL) - , m_NoiseModelShort(NULL) - , m_FrequencyMap(NULL) + , m_tLine(1) + , m_CroppingFactor(1) , m_MaskImage(NULL) - , m_SignalModelString("") - , m_ArtifactModelString("") - , m_OutputPath("") + , m_FrequencyMap(NULL) + , m_NoiseModel(NULL) { m_ImageDirection.SetIdentity(); m_ImageOrigin.Fill(0.0); m_ImageRegion.SetSize(0, 11); m_ImageRegion.SetSize(1, 11); m_ImageRegion.SetSize(2, 3); m_ImageSpacing.Fill(2.0); m_Translation.Fill(0.0); m_Rotation.Fill(0.0); m_ResultNode = mitk::DataNode::New(); m_ParentNode = NULL; + + GenerateGradientHalfShell(); +} + +template< class ScalarType > +mitk::FiberfoxParameters< ScalarType >::~FiberfoxParameters() +{ + // if (m_NoiseModel!=NULL) + // delete m_NoiseModel; +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::GenerateGradientHalfShell() +{ + int NPoints = 2*m_NumGradients; + m_GradientDirections.clear(); + + m_NumBaseline = NPoints/20; + if (m_NumBaseline==0) + m_NumBaseline=1; + + GradientType g; + g.Fill(0.0); + for (unsigned 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< int > mitk::FiberfoxParameters< ScalarType >::GetBaselineIndices() +{ + std::vector< int > result; + for( unsigned int i=0; im_GradientDirections.size(); i++) + if (m_GradientDirections.at(i).GetNorm()<0.0001) + result.push_back(i); + return result; } -FiberfoxParameters::~FiberfoxParameters() -{ -// if (m_NoiseModel!=NULL) -// delete m_NoiseModel; -// if (m_NoiseModelShort!=NULL) -// delete m_NoiseModelShort; -} - -void FiberfoxParameters::PrintSelf() -{ - MITK_INFO << m_ImageRegion; - MITK_INFO << m_ImageSpacing; - MITK_INFO << m_ImageOrigin; - MITK_INFO << m_ImageDirection; - MITK_INFO << m_NumGradients; - MITK_INFO << m_Bvalue; - MITK_INFO << m_Repetitions; - MITK_INFO << m_SignalScale; - MITK_INFO << m_tEcho; - MITK_INFO << m_tLine; - MITK_INFO << m_tInhom; - MITK_INFO << m_AxonRadius; - MITK_INFO << m_InterpolationShrink; - MITK_INFO << m_KspaceLineOffset; - MITK_INFO << m_AddGibbsRinging; - MITK_INFO << m_EddyStrength; - MITK_INFO << m_Comp3Weight; - MITK_INFO << m_Comp4Weight; - MITK_INFO << m_Spikes; - MITK_INFO << m_SpikeAmplitude; - MITK_INFO << m_Wrap; - MITK_INFO << m_Translation; - MITK_INFO << m_Rotation; - MITK_INFO << m_DoSimulateRelaxation; - MITK_INFO << m_DoSimulateEddyCurrents; - MITK_INFO << m_DoDisablePartialVolume; - MITK_INFO << m_DoAddMotion; - MITK_INFO << "m_RandomMotion " << m_RandomMotion; - - MITK_INFO << m_NoiseModel; - MITK_INFO << m_NoiseModelShort; -// MITK_INFO << m_GradientDirections; -// MITK_INFO << m_FiberModelList; -// MITK_INFO << m_NonFiberModelList; - if (m_FrequencyMap.IsNotNull()) - MITK_INFO << "m_FrequencyMap " << m_FrequencyMap; - if (m_MaskImage.IsNotNull()) - MITK_INFO << "m_MaskImage " << m_MaskImage; - if (m_ResultNode.IsNotNull()) - MITK_INFO << "m_ResultNode " << m_ResultNode; - if (m_ParentNode.IsNotNull()) - MITK_INFO << "m_ParentNode " << m_ParentNode; - - MITK_INFO << m_SignalModelString; - MITK_INFO << m_ArtifactModelString; - MITK_INFO << m_OutputPath; +template< class ScalarType > +unsigned int mitk::FiberfoxParameters< ScalarType >::GetFirstBaselineIndex() +{ + for( unsigned int i=0; im_GradientDirections.size(); i++) + if (m_GradientDirections.at(i).GetNorm()<0.0001) + return i; + return -1; +} + +template< class ScalarType > +bool mitk::FiberfoxParameters< ScalarType >::IsBaselineIndex(unsigned int idx) +{ + if (m_GradientDirections.size()>idx && m_GradientDirections.at(idx).GetNorm()<0.0001) + return true; + return false; +} + +template< class ScalarType > +unsigned int mitk::FiberfoxParameters< ScalarType >::GetNumWeightedVolumes() +{ + return m_NumGradients; +} + +template< class ScalarType > +unsigned int mitk::FiberfoxParameters< ScalarType >::GetNumBaselineVolumes() +{ + return m_NumBaseline; +} + +template< class ScalarType > +unsigned int mitk::FiberfoxParameters< ScalarType >::GetNumVolumes() +{ + return m_GradientDirections.size(); +} + +template< class ScalarType > +typename mitk::FiberfoxParameters< ScalarType >::GradientListType mitk::FiberfoxParameters< ScalarType >::GetGradientDirections() +{ + return m_GradientDirections; +} + +template< class ScalarType > +typename mitk::FiberfoxParameters< ScalarType >::GradientType mitk::FiberfoxParameters< ScalarType >::GetGradientDirection(unsigned int i) +{ + if (i +void mitk::FiberfoxParameters< ScalarType >::SetNumWeightedGradients(int numGradients) +{ + m_NumGradients = numGradients; + GenerateGradientHalfShell(); +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::SetGradienDirections(GradientListType gradientList) +{ + m_GradientDirections = gradientList; + m_NumGradients = 0; + m_NumBaseline = 0; + for( unsigned int i=0; im_GradientDirections.size(); i++) + { + if (m_GradientDirections.at(i).GetNorm()>0.0001) + m_NumGradients++; + else + m_NumBaseline++; + } +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::SetGradienDirections(mitk::DiffusionImage::GradientDirectionContainerType::Pointer gradientList) +{ + m_NumGradients = 0; + m_NumBaseline = 0; + m_GradientDirections.clear(); + + for( unsigned int i=0; iSize(); i++) + { + GradientType g; + g[0] = gradientList->at(i)[0]; + g[1] = gradientList->at(i)[1]; + g[2] = gradientList->at(i)[2]; + m_GradientDirections.push_back(g); + + if (m_GradientDirections.at(i).GetNorm()>0.0001) + m_NumGradients++; + else + m_NumBaseline++; + } +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::LoadParameters(string filename) +{ + boost::property_tree::ptree parameters; + boost::property_tree::xml_parser::read_xml(filename, parameters); + + m_FiberModelList.clear(); + m_NonFiberModelList.clear(); + if (m_NoiseModel!=NULL) + delete m_NoiseModel; + + BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameters.get_child("fiberfox") ) + { + if( v1.first == "image" ) + { + m_ImageRegion.SetSize(0, v1.second.get("basic.size.x")); + m_ImageRegion.SetSize(1, v1.second.get("basic.size.y")); + m_ImageRegion.SetSize(2, v1.second.get("basic.size.z")); + m_ImageSpacing[0] = v1.second.get("basic.spacing.x"); + m_ImageSpacing[1] = v1.second.get("basic.spacing.y"); + m_ImageSpacing[2] = v1.second.get("basic.spacing.z"); + m_NumGradients = v1.second.get("basic.numgradients"); + GenerateGradientHalfShell(); + m_Bvalue = v1.second.get("basic.bvalue"); + m_Repetitions = v1.second.get("repetitions"); + m_SignalScale = v1.second.get("signalScale"); + m_tEcho = v1.second.get("tEcho"); + m_tLine = v1.second.get("tLine"); + m_tInhom = v1.second.get("tInhom"); + m_AxonRadius = v1.second.get("axonRadius"); + m_DoSimulateRelaxation = v1.second.get("doSimulateRelaxation"); + m_DoDisablePartialVolume = v1.second.get("doDisablePartialVolume"); + if (v1.second.get("artifacts.addnoise")) + { + switch (v1.second.get("artifacts.noisedistribution")) + { + case 0: + m_NoiseModel = new mitk::RicianNoiseModel< ScalarType >(); + break; + case 1: + m_NoiseModel = new mitk::ChiSquareNoiseModel< ScalarType >(); + break; + default: + m_NoiseModel = new mitk::RicianNoiseModel< ScalarType >(); + } + m_NoiseModel->SetNoiseVariance(v1.second.get("artifacts.noisevariance")); + } + + m_KspaceLineOffset = v1.second.get("artifacts.m_KspaceLineOffset"); + m_CroppingFactor = (100-v1.second.get("artifacts.aliasingfactor"))/100; + m_Spikes = v1.second.get("artifacts.m_Spikesnum"); + m_SpikeAmplitude = v1.second.get("artifacts.m_Spikesscale"); + m_EddyStrength = v1.second.get("artifacts.m_EddyStrength"); + m_DoAddGibbsRinging = v1.second.get("artifacts.addringing"); + m_DoAddMotion = v1.second.get("artifacts.m_DoAddMotion"); + m_DoRandomizeMotion = v1.second.get("artifacts.m_RandomMotion"); + m_Translation[0] = v1.second.get("artifacts.m_Translation0"); + m_Translation[1] = v1.second.get("artifacts.m_Translation1"); + m_Translation[2] = v1.second.get("artifacts.m_Translation2"); + m_Rotation[0] = v1.second.get("artifacts.m_Rotation0"); + m_Rotation[1] = v1.second.get("artifacts.m_Rotation1"); + m_Rotation[2] = v1.second.get("artifacts.m_Rotation2"); + + // compartment 1 + switch (v1.second.get("compartment1.index")) + { + case 0: + mitk::StickModel* stickModel = new mitk::StickModel(); + stickModel->SetGradientList(m_GradientDirections); + stickModel->SetBvalue(m_Bvalue); + stickModel->SetDiffusivity(v1.second.get("compartment1.stick.d")); + stickModel->SetT2(v1.second.get("compartment1.stick.t2")); + m_FiberModelList.push_back(stickModel); + break; + case 1: + mitk::TensorModel* zeppelinModel = new mitk::TensorModel(); + zeppelinModel->SetGradientList(m_GradientDirections); + zeppelinModel->SetBvalue(m_Bvalue); + zeppelinModel->SetDiffusivity1(v1.second.get("compartment1.zeppelin.d1")); + zeppelinModel->SetDiffusivity2(v1.second.get("compartment1.zeppelin.d2")); + zeppelinModel->SetDiffusivity3(v1.second.get("compartment1.zeppelin.d2")); + zeppelinModel->SetT2(v1.second.get("compartment1.zeppelin.t2")); + m_FiberModelList.push_back(zeppelinModel); + break; + case 2: + mitk::TensorModel* tensorModel = new mitk::TensorModel(); + tensorModel->SetGradientList(m_GradientDirections); + tensorModel->SetBvalue(m_Bvalue); + tensorModel->SetDiffusivity1(v1.second.get("compartment1.tensor.d1")); + tensorModel->SetDiffusivity2(v1.second.get("compartment1.tensor.d2")); + tensorModel->SetDiffusivity3(v1.second.get("compartment1.tensor.d3")); + tensorModel->SetT2(v1.second.get("compartment1.tensor.t2")); + m_FiberModelList.push_back(tensorModel); + break; + } + + // compartment 2 + switch (v1.second.get("compartment2.index")) + { + case 0: + mitk::StickModel* stickModel = new mitk::StickModel(); + stickModel->SetGradientList(m_GradientDirections); + stickModel->SetBvalue(m_Bvalue); + stickModel->SetDiffusivity(v1.second.get("compartment2.stick.d")); + stickModel->SetT2(v1.second.get("compartment2.stick.t2")); + m_FiberModelList.push_back(stickModel); + break; + case 1: + mitk::TensorModel* zeppelinModel = new mitk::TensorModel(); + zeppelinModel->SetGradientList(m_GradientDirections); + zeppelinModel->SetBvalue(m_Bvalue); + zeppelinModel->SetDiffusivity1(v1.second.get("compartment2.zeppelin.d1")); + zeppelinModel->SetDiffusivity2(v1.second.get("compartment2.zeppelin.d2")); + zeppelinModel->SetDiffusivity3(v1.second.get("compartment2.zeppelin.d2")); + zeppelinModel->SetT2(v1.second.get("compartment2.zeppelin.t2")); + m_FiberModelList.push_back(zeppelinModel); + break; + case 2: + mitk::TensorModel* tensorModel = new mitk::TensorModel(); + tensorModel->SetGradientList(m_GradientDirections); + tensorModel->SetBvalue(m_Bvalue); + tensorModel->SetDiffusivity1(v1.second.get("compartment2.tensor.d1")); + tensorModel->SetDiffusivity2(v1.second.get("compartment2.tensor.d2")); + tensorModel->SetDiffusivity3(v1.second.get("compartment2.tensor.d3")); + tensorModel->SetT2(v1.second.get("compartment2.tensor.t2")); + m_FiberModelList.push_back(tensorModel); + break; + } + + // compartment 3 + switch (v1.second.get("compartment3.index")) + { + case 0: + mitk::BallModel* ballModel = new mitk::BallModel(); + ballModel->SetGradientList(m_GradientDirections); + ballModel->SetBvalue(m_Bvalue); + ballModel->SetDiffusivity(v1.second.get("compartment3.ball.d")); + ballModel->SetT2(v1.second.get("compartment3.ball.t2")); + ballModel->SetWeight(v1.second.get("compartment3.weight")); + m_NonFiberModelList.push_back(ballModel); + break; + case 1: + mitk::AstroStickModel* astrosticksModel = new mitk::AstroStickModel(); + astrosticksModel->SetGradientList(m_GradientDirections); + astrosticksModel->SetBvalue(m_Bvalue); + astrosticksModel->SetDiffusivity(v1.second.get("compartment3.astrosticks.d")); + astrosticksModel->SetT2(v1.second.get("compartment3.astrosticks.t2")); + astrosticksModel->SetRandomizeSticks(v1.second.get("compartment3.astrosticks.randomize")); + astrosticksModel->SetWeight(v1.second.get("compartment3.weight")); + m_NonFiberModelList.push_back(astrosticksModel); + break; + case 2: + mitk::DotModel* dotModel = new mitk::DotModel(); + dotModel->SetGradientList(m_GradientDirections); + dotModel->SetT2(v1.second.get("compartment3.dot.t2")); + dotModel->SetWeight(v1.second.get("compartment3.weight")); + m_NonFiberModelList.push_back(dotModel); + break; + } + + // compartment 4 + switch (v1.second.get("compartment4.index")) + { + case 0: + mitk::BallModel* ballModel = new mitk::BallModel(); + ballModel->SetGradientList(m_GradientDirections); + ballModel->SetBvalue(m_Bvalue); + ballModel->SetDiffusivity(v1.second.get("compartment4.ball.d")); + ballModel->SetT2(v1.second.get("compartment4.ball.t2")); + ballModel->SetWeight(v1.second.get("compartment4.weight")); + m_NonFiberModelList.push_back(ballModel); + break; + case 1: + mitk::AstroStickModel* astrosticksModel = new mitk::AstroStickModel(); + astrosticksModel->SetGradientList(m_GradientDirections); + astrosticksModel->SetBvalue(m_Bvalue); + astrosticksModel->SetDiffusivity(v1.second.get("compartment4.astrosticks.d")); + astrosticksModel->SetT2(v1.second.get("compartment4.astrosticks.t2")); + astrosticksModel->SetRandomizeSticks(v1.second.get("compartment4.astrosticks.randomize")); + astrosticksModel->SetWeight(v1.second.get("compartment4.weight")); + m_NonFiberModelList.push_back(astrosticksModel); + break; + case 2: + mitk::DotModel* dotModel = new mitk::DotModel(); + dotModel->SetGradientList(m_GradientDirections); + dotModel->SetT2(v1.second.get("compartment4.dot.t2")); + dotModel->SetWeight(v1.second.get("compartment4.weight")); + m_NonFiberModelList.push_back(dotModel); + break; + } + } + } +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::PrintSelf() +{ + MITK_INFO << "m_ImageRegion: " << m_ImageRegion; + MITK_INFO << "m_ImageSpacing: " << m_ImageSpacing; + MITK_INFO << "m_ImageOrigin: " << m_ImageOrigin; + MITK_INFO << "m_ImageDirection: " << m_ImageDirection; + MITK_INFO << "m_NumGradients: " << m_NumGradients; + MITK_INFO << "m_Bvalue: " << m_Bvalue; + MITK_INFO << "m_Repetitions: " << m_Repetitions; + MITK_INFO << "m_SignalScale: " << m_SignalScale; + MITK_INFO << "m_tEcho: " << m_tEcho; + MITK_INFO << "m_tLine: " << m_tLine; + MITK_INFO << "m_tInhom: " << m_tInhom; + MITK_INFO << "m_AxonRadius: " << m_AxonRadius; + MITK_INFO << "m_KspaceLineOffset: " << m_KspaceLineOffset; + MITK_INFO << "m_AddGibbsRinging: " << m_DoAddGibbsRinging; + MITK_INFO << "m_EddyStrength: " << m_EddyStrength; + MITK_INFO << "m_Spikes: " << m_Spikes; + MITK_INFO << "m_SpikeAmplitude: " << m_SpikeAmplitude; + MITK_INFO << "m_Wrap: " << m_CroppingFactor; + MITK_INFO << "m_DoSimulateRelaxation: " << m_DoSimulateRelaxation; + MITK_INFO << "m_DoDisablePartialVolume: " << m_DoDisablePartialVolume; + MITK_INFO << "m_DoAddMotion: " << m_DoAddMotion; + MITK_INFO << "m_RandomMotion: " << m_DoRandomizeMotion; + MITK_INFO << "m_Translation: " << m_Translation; + MITK_INFO << "m_Rotation: " << m_Rotation; + MITK_INFO << "m_SignalModelString: " << m_SignalModelString; + MITK_INFO << "m_ArtifactModelString: " << m_ArtifactModelString; + MITK_INFO << "m_OutputPath: " << m_OutputPath; } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h index 3e86d4fcef..6986f45286 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h @@ -1,99 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_FiberfoxParameters_H #define _MITK_FiberfoxParameters_H -#include #include #include #include #include #include -#include +#include +#include +#include using namespace std; namespace mitk { /** - * \brief Datastructure to manage the Fiberfox signal generation parameters + * \brief Datastructure to manage the Fiberfox signal generation parameters. * */ -class FiberTracking_EXPORT FiberfoxParameters +template< class ScalarType > +class FiberfoxParameters { public: - typedef itk::Image ItkDoubleImgType; - typedef itk::Image ItkUcharImgType; + typedef itk::Image ItkDoubleImgType; + typedef itk::Image ItkUcharImgType; + typedef std::vector< DiffusionSignalModel* > DiffusionModelListType; + typedef DiffusionSignalModel::GradientListType GradientListType; + typedef DiffusionSignalModel::GradientType GradientType; + typedef DiffusionNoiseModel NoiseModelType; + typedef DiffusionSignalModel* DiffusionModelType; FiberfoxParameters(); ~FiberfoxParameters(); - itk::ImageRegion<3> m_ImageRegion; - itk::Vector m_ImageSpacing; - itk::Point m_ImageOrigin; - itk::Matrix m_ImageDirection; - unsigned int m_NumGradients; + /** Get same parameter object with different template parameter */ + template< class OutType > FiberfoxParameters< OutType > CopyParameters() + { + FiberfoxParameters< OutType > out; + + out.m_ImageRegion = m_ImageRegion; + out.m_ImageSpacing = m_ImageSpacing; + out.m_ImageOrigin = m_ImageOrigin; + out.m_ImageDirection = m_ImageDirection; + out.SetNumWeightedGradients(m_NumGradients); + out.m_Bvalue = m_Bvalue; + out.m_Repetitions = m_Repetitions; + out.m_SignalScale = m_SignalScale; + out.m_tEcho = m_tEcho; + out.m_tLine = m_tLine; + out.m_tInhom = m_tInhom; + out.m_AxonRadius = m_AxonRadius; + out.m_KspaceLineOffset = m_KspaceLineOffset; + out.m_DoAddGibbsRinging = m_DoAddGibbsRinging; + out.m_EddyStrength = m_EddyStrength; + out.m_Spikes = m_Spikes; + out.m_SpikeAmplitude = m_SpikeAmplitude; + out.m_CroppingFactor = m_CroppingFactor; + out.m_DoSimulateRelaxation = m_DoSimulateRelaxation; + out.m_DoDisablePartialVolume = m_DoDisablePartialVolume; + out.m_DoAddMotion = m_DoAddMotion; + out.m_DoRandomizeMotion = m_DoRandomizeMotion; + out.m_Translation = m_Translation; + out.m_Rotation = m_Rotation; + if (m_NoiseModel!=NULL) + { + if (dynamic_cast*>(m_NoiseModel)) + out.m_NoiseModel = new mitk::RicianNoiseModel(); + else if (dynamic_cast*>(m_NoiseModel)) + out.m_NoiseModel = new mitk::ChiSquareNoiseModel(); + out.m_NoiseModel->SetNoiseVariance(m_NoiseModel->GetNoiseVariance()); + } + out.m_FrequencyMap = m_FrequencyMap; + out.m_MaskImage = m_MaskImage; + out.m_ResultNode = m_ResultNode; + out.m_ParentNode = m_ParentNode; + out.m_SignalModelString = m_SignalModelString; + out.m_ArtifactModelString = m_ArtifactModelString; + out.m_OutputPath = m_OutputPath; + + return out; + } + + /** Output image specifications */ + itk::ImageRegion<3> m_ImageRegion; ///< Image size. + itk::Vector m_ImageSpacing; ///< Image voxel size. + itk::Point m_ImageOrigin; ///< Image origin. + itk::Matrix m_ImageDirection; ///< Image rotation matrix. + + /** Other acquisitions parameters */ + unsigned int m_Repetitions; ///< Noise will be summed N times and afterwards averaged. + double m_SignalScale; ///< Scaling factor for output signal (before noise is added). + double m_tEcho; ///< Echo time TE. + double m_tLine; ///< k-space line readout time. + double m_tInhom; ///< T2' double m_Bvalue; - unsigned int m_Repetitions; - double m_SignalScale; - double m_tEcho; - double m_tLine; - double m_tInhom; - double m_AxonRadius; - unsigned int m_InterpolationShrink; - double m_KspaceLineOffset; - bool m_AddGibbsRinging; - double m_EddyStrength; - double m_Comp3Weight; - double m_Comp4Weight; - int m_Spikes; - double m_SpikeAmplitude; - double m_Wrap; - itk::Vector m_Translation; - itk::Vector m_Rotation; - bool m_DoSimulateRelaxation; - bool m_DoSimulateEddyCurrents; - bool m_DoDisablePartialVolume; - bool m_DoAddMotion; - bool m_RandomMotion; - - mitk::DiffusionNoiseModel* m_NoiseModel; - mitk::DiffusionNoiseModel* m_NoiseModelShort; - mitk::DiffusionSignalModel::GradientListType m_GradientDirections; - itk::TractsToDWIImageFilter< short >::DiffusionModelList m_FiberModelList; - itk::TractsToDWIImageFilter< short >::DiffusionModelList m_NonFiberModelList; - ItkDoubleImgType::Pointer m_FrequencyMap; - ItkUcharImgType::Pointer m_MaskImage; - mitk::DataNode::Pointer m_ResultNode; - mitk::DataNode::Pointer m_ParentNode; - - string m_SignalModelString; - string m_ArtifactModelString; - string m_OutputPath; - - void PrintSelf(); + + /** Signal generation */ + DiffusionModelListType m_FiberModelList; ///< Intra- and inter-axonal compartments. + DiffusionModelListType m_NonFiberModelList; ///< Extra-axonal compartments. + double m_AxonRadius; ///< Determines compartment volume fractions (0 == automatic axon radius estimation) + + /** Artifacts */ + int m_Spikes; ///< Number of spikes randomly appearing in the image + double m_SpikeAmplitude; ///< amplitude of spikes relative to the largest signal intensity (magnitude of complex) + double m_KspaceLineOffset; ///< Causes N/2 ghosts. Larger offset means stronger ghost. + double m_EddyStrength; ///< Strength of eddy current induced gradients in T/m. + double m_CroppingFactor; ///< FOV size in y-direction is multiplied by this factor. Causes aliasing artifacts. + bool m_DoAddGibbsRinging; ///< Add Gibbs ringing artifact + bool m_DoSimulateRelaxation; ///< Add T2 relaxation effects + bool m_DoDisablePartialVolume; ///< Disable partial volume effects. Each voxel is either all fiber or all non-fiber. + bool m_DoAddMotion; ///< Enable motion artifacts. + bool m_DoRandomizeMotion; ///< Toggles between random and linear motion. + itk::Vector m_Translation; ///< Maximum translational motion. + itk::Vector m_Rotation; ///< Maximum rotational motion. + NoiseModelType* m_NoiseModel; ///< If != NULL, noise is added to the image. + ItkDoubleImgType::Pointer m_FrequencyMap; ///< If != NULL, distortions are added to the image using this frequency map. + ItkUcharImgType::Pointer m_MaskImage; ///< Signal is only genrated inside of the mask image. + + /** Output parameters (only relevant in GUI application) */ + mitk::DataNode::Pointer m_ResultNode; ///< Stores resulting image. + mitk::DataNode::Pointer m_ParentNode; ///< Parent node or result node. + string m_SignalModelString; ///< Appendet to the name of the result node + string m_ArtifactModelString; ///< Appendet to the name of the result node + string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished. + + void PrintSelf(); ///< Print parameters to stdout. + void LoadParameters(string filename); ///< Load image generation parameters from .ffp file. + void GenerateGradientHalfShell(); ///< Generates half shell of gradient directions (with m_NumGradients non-zero directions) + + std::vector< int > GetBaselineIndices(); + unsigned int GetFirstBaselineIndex(); + bool IsBaselineIndex(unsigned int idx); + + unsigned int GetNumWeightedVolumes(); + unsigned int GetNumBaselineVolumes(); + unsigned int GetNumVolumes(); + GradientListType GetGradientDirections(); + GradientType GetGradientDirection(unsigned int i); + + void SetNumWeightedGradients(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards. + void SetGradienDirections(GradientListType gradientList); + void SetGradienDirections(mitk::DiffusionImage::GradientDirectionContainerType::Pointer gradientList); protected: -}; + unsigned int m_NumBaseline; ///< Number of non-diffusion-weighted image volumes. + unsigned int m_NumGradients; ///< Number of diffusion-weighted image volumes. + GradientListType m_GradientDirections; ///< Total number of image volumes. +}; } +#include "mitkFiberfoxParameters.cpp" + #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkAstroStickModel.cpp b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkAstroStickModel.cpp index 44ec36ff13..70eb8e429d 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkAstroStickModel.cpp +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkAstroStickModel.cpp @@ -1,132 +1,132 @@ /*=================================================================== 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 > AstroStickModel< ScalarType >::AstroStickModel() : m_BValue(1000) , m_Diffusivity(0.001) , m_NumSticks(42) , m_RandomizeSticks(false) { m_RandGen = ItkRandGenType::New(); vnl_matrix_fixed* sticks = itk::PointShell<42, vnl_matrix_fixed >::DistributePointShell(); for (unsigned int i=0; iget(0,i); stick[1] = sticks->get(1,i); stick[2] = sticks->get(2,i); stick.Normalize(); m_Sticks.push_back(stick); } } template< class ScalarType > AstroStickModel< ScalarType >::~AstroStickModel() { } template< class ScalarType > void AstroStickModel< ScalarType >::SetSeed(int s) { m_RandGen->SetSeed(s); } template< class ScalarType > ScalarType AstroStickModel< ScalarType >::SimulateMeasurement(unsigned int dir) { ScalarType signal = 0; if (dir>=this->m_GradientList.size()) return signal; ScalarType b = -m_BValue*m_Diffusivity; - if (m_RandomizeSticks) + if (m_RandomizeSticks) // random number of sticks m_NumSticks = 30 + m_RandGen->GetIntegerVariate()%31; GradientType g = this->m_GradientList[dir]; ScalarType bVal = g.GetNorm(); bVal *= bVal; - if (bVal>0.0001) + if (bVal>0.0001) // is weighted direction { for (unsigned int j=0; j typename AstroStickModel< ScalarType >::GradientType AstroStickModel< ScalarType >::GetRandomDirection() { GradientType vec; vec[0] = m_RandGen->GetNormalVariate(); vec[1] = m_RandGen->GetNormalVariate(); vec[2] = m_RandGen->GetNormalVariate(); vec.Normalize(); return vec; } template< class ScalarType > typename AstroStickModel< ScalarType >::PixelType AstroStickModel< ScalarType >::SimulateMeasurement() { PixelType signal; signal.SetSize(this->m_GradientList.size()); ScalarType b = -m_BValue*m_Diffusivity; if (m_RandomizeSticks) m_NumSticks = 30 + m_RandGen->GetIntegerVariate()%31; for( unsigned int i=0; im_GradientList.size(); i++) { GradientType g = this->m_GradientList[i]; ScalarType bVal = g.GetNorm(); bVal *= bVal; if (bVal>0.0001) { for (unsigned int j=0; j #include namespace mitk { /** - * \brief Generates the diffusion signal using an idealised cylinder with zero radius: e^(-bd(ng)²) + * \brief Generates the diffusion signal using a collection of idealised cylinder with zero radius: e^(-bd(ng)²) * */ template< class ScalarType > class AstroStickModel : public DiffusionSignalModel< ScalarType > { public: AstroStickModel(); ~AstroStickModel(); typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType; typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType; typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType; typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType; /** Actual signal generation **/ PixelType SimulateMeasurement(); ScalarType SimulateMeasurement(unsigned int dir); void SetSeed(int s); ///< set seed for random generator that creates the stick orientations - void SetRandomizeSticks(bool randomize=true){ m_RandomizeSticks=randomize; } + void SetRandomizeSticks(bool randomize=true){ m_RandomizeSticks=randomize; } ///< Random stick configuration in each voxel void SetBvalue(ScalarType bValue) { m_BValue = bValue; } ///< b-value used to generate the artificial signal void SetDiffusivity(ScalarType diffusivity) { m_Diffusivity = diffusivity; } ///< Scalar diffusion constant void SetNumSticks(unsigned int order) { vnl_matrix sticks; switch (order) { case 1: m_NumSticks = 12; sticks = itk::PointShell<12, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; case 2: m_NumSticks = 42; sticks = itk::PointShell<42, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; case 3: m_NumSticks = 92; sticks = itk::PointShell<92, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; case 4: m_NumSticks = 162; sticks = itk::PointShell<162, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; case 5: m_NumSticks = 252; sticks = itk::PointShell<252, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; default: m_NumSticks = 42; sticks = itk::PointShell<42, vnl_matrix_fixed >::DistributePointShell()->as_matrix(); break; } for (int i=0; i #include namespace mitk { /** - * \brief Implementation of noise following a rician distribution + * \brief Implementation of noise following a chi-squared distribution * */ template< class ScalarType > class ChiSquareNoiseModel : public DiffusionNoiseModel< ScalarType > { public: ChiSquareNoiseModel(); ~ChiSquareNoiseModel(); typedef typename DiffusionNoiseModel< ScalarType >::PixelType PixelType; /** Adds rician noise to the input pixel **/ void AddNoise(PixelType& pixel); - void SetDOF(double var){ m_Distribution = boost::random::chi_squared_distribution(var); } - double GetNoiseVariance(){ return m_Distribution.n(); } - void SetSeed(int seed); + void SetNoiseVariance(double var){ m_Distribution = boost::random::chi_squared_distribution(var/2); } + double GetNoiseVariance(){ return m_Distribution.n()*2; } + void SetSeed(int seed); ///< seed for random number generator protected: boost::random::mt19937 m_RandGen; boost::random::chi_squared_distribution m_Distribution; }; } #include "mitkChiSquareNoiseModel.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionNoiseModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionNoiseModel.h index 6b140c7c65..6ea5ce8ee0 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionNoiseModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionNoiseModel.h @@ -1,56 +1,59 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_DiffusionNoiseModel_H #define _MITK_DiffusionNoiseModel_H #include #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion noise models * */ template< class ScalarType > class DiffusionNoiseModel { public: DiffusionNoiseModel(){} virtual ~DiffusionNoiseModel(){} typedef itk::VariableLengthVector< ScalarType > PixelType; /** Adds noise according to model to the input pixel. Has to be implemented in subclass. **/ virtual void AddNoise(PixelType& pixel) = 0; - /** Seed random generator. Has to be implemented in subclass. **/ + /** Seed for random generator. Has to be implemented in subclass. **/ virtual void SetSeed(int seed) = 0; + virtual double GetNoiseVariance() = 0; + virtual void SetNoiseVariance(double var) = 0; + protected: }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h index f585803339..a6fadf1363 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h @@ -1,93 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_DiffusionSignalModel_H #define _MITK_DiffusionSignalModel_H #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion signal models * */ template< class ScalarType > class DiffusionSignalModel { public: DiffusionSignalModel() : m_T2(100) , m_Weight(1) {} ~DiffusionSignalModel(){} typedef itk::VariableLengthVector< ScalarType > PixelType; typedef itk::Vector GradientType; typedef std::vector GradientListType; /** Realizes actual signal generation. Has to be implemented in subclass. **/ virtual PixelType SimulateMeasurement() = 0; virtual ScalarType SimulateMeasurement(unsigned int dir) = 0; GradientType GetGradientDirection(int i) { return m_GradientList.at(i); } void SetFiberDirection(GradientType fiberDirection){ m_FiberDirection = fiberDirection; } void SetGradientList(GradientListType gradientList) { m_GradientList = gradientList; } void SetT2(double T2) { m_T2 = T2; } void SetWeight(double Weight) { m_Weight = Weight; } double GetWeight() { return m_Weight; } double GetT2() { return m_T2; } - int GetNumGradients(){ return m_GradientList.size(); } - std::vector< int > GetBaselineIndices() - { - std::vector< int > result; - for( unsigned int i=0; im_GradientList.size(); i++) - if (m_GradientList.at(i).GetNorm()<0.0001) - result.push_back(i); - return result; - } - int GetFirstBaselineIndex() - { - for( unsigned int i=0; im_GradientList.size(); i++) - if (m_GradientList.at(i).GetNorm()<0.0001) - return i; - return -1; - } - bool IsBaselineIndex(unsigned int idx) - { - if (m_GradientList.size()>idx && m_GradientList.at(idx).GetNorm()<0.0001) - return true; - return false; - } protected: GradientType m_FiberDirection; ///< Needed to generate anisotropc signal to determin direction of anisotropy GradientListType m_GradientList; ///< Diffusion gradient direction container double m_T2; ///< Tissue specific relaxation time double m_Weight; }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDotModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDotModel.h index fb644f4cdc..02a3181a7d 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDotModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDotModel.h @@ -1,53 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_DotModel_H #define _MITK_DotModel_H #include namespace mitk { /** - * \brief Generates direction independent diffusion measurement employing a scalar diffusion constant d: e^(-bd) + * \brief Generates constant direction independent signal. * */ template< class ScalarType > class DotModel : public DiffusionSignalModel< ScalarType > { public: DotModel(); ~DotModel(); typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType; typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType; /** Actual signal generation **/ PixelType SimulateMeasurement(); ScalarType SimulateMeasurement(unsigned int dir); protected: }; } #include "mitkDotModel.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.h index 694a0ca269..ee4e4f90f2 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkRicianNoiseModel.h @@ -1,59 +1,59 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_RicianNoiseModel_H #define _MITK_RicianNoiseModel_H #include #include namespace mitk { /** * \brief Implementation of noise following a rician distribution * */ template< class ScalarType > class RicianNoiseModel : public DiffusionNoiseModel< ScalarType > { public: RicianNoiseModel(); ~RicianNoiseModel(); typedef typename DiffusionNoiseModel< ScalarType >::PixelType PixelType; /** Adds rician noise to the input pixel **/ void AddNoise(PixelType& pixel); void SetNoiseVariance(double var){ m_NoiseVariance = var; } double GetNoiseVariance(){ return m_NoiseVariance; } - void SetSeed(int seed); + void SetSeed(int seed); ///< Set seed for random number generator protected: itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen; double m_NoiseVariance; ///< variance of underlying distribution }; } #include "mitkRicianNoiseModel.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp index b0afe6cc25..44a19dab9f 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp @@ -1,216 +1,193 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /**Documentation * Test the Fiberfox simulation functions (diffusion weighted image -> diffusion weighted image) */ class mitkFiberfoxAddArtifactsToDwiTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkFiberfoxAddArtifactsToDwiTestSuite); MITK_TEST(Spikes); MITK_TEST(GibbsRinging); MITK_TEST(Ghost); MITK_TEST(Aliasing); MITK_TEST(Eddy); MITK_TEST(RicianNoise); MITK_TEST(ChiSquareNoise); MITK_TEST(Distortions); CPPUNIT_TEST_SUITE_END(); private: mitk::DiffusionImage::Pointer m_InputDwi; - FiberfoxParameters m_Parameters; + FiberfoxParameters m_Parameters; public: void setUp() { RegisterDiffusionCoreObjectFactory(); // reference files m_InputDwi = dynamic_cast*>(mitk::IOUtil::LoadDataNode(GetTestDataFilePath("DiffusionImaging/Fiberfox/StickBall_RELAX.dwi"))->GetData()); // parameter setup - m_Parameters = FiberfoxParameters(); + m_Parameters = FiberfoxParameters(); m_Parameters.m_ImageRegion = m_InputDwi->GetVectorImage()->GetLargestPossibleRegion(); m_Parameters.m_ImageSpacing = m_InputDwi->GetVectorImage()->GetSpacing(); m_Parameters.m_ImageOrigin = m_InputDwi->GetVectorImage()->GetOrigin(); m_Parameters.m_ImageDirection = m_InputDwi->GetVectorImage()->GetDirection(); m_Parameters.m_Bvalue = m_InputDwi->GetB_Value(); - mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = m_InputDwi->GetDirections(); - m_Parameters.m_NumGradients = 0; - for (unsigned 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_Parameters.m_GradientDirections.push_back(g); - if (dirs->at(i).magnitude()>0.0001) - m_Parameters.m_NumGradients++; - } + m_Parameters.SetGradienDirections(m_InputDwi->GetDirections()); } bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) return false; ++it1; ++it2; } } catch(...) { return false; } return true; } void StartSimulation(string testFileName) { mitk::DiffusionImage::Pointer refImage = NULL; if (!testFileName.empty()) CPPUNIT_ASSERT(refImage = dynamic_cast*>(mitk::IOUtil::LoadDataNode(testFileName)->GetData())); itk::AddArtifactsToDwiImageFilter< short >::Pointer artifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); artifactsToDwiFilter->SetUseConstantRandSeed(true); artifactsToDwiFilter->SetInput(m_InputDwi->GetVectorImage()); - artifactsToDwiFilter->SettLine(m_Parameters.m_tLine); - artifactsToDwiFilter->SetkOffset(m_Parameters.m_KspaceLineOffset); - artifactsToDwiFilter->SetNoiseModel(m_Parameters.m_NoiseModelShort); - artifactsToDwiFilter->SetGradientList(m_Parameters.m_GradientDirections); - artifactsToDwiFilter->SetTE(m_Parameters.m_tEcho); - artifactsToDwiFilter->SetSimulateEddyCurrents(m_Parameters.m_DoSimulateEddyCurrents); - artifactsToDwiFilter->SetEddyGradientStrength(m_Parameters.m_EddyStrength); - artifactsToDwiFilter->SetAddGibbsRinging(m_Parameters.m_AddGibbsRinging); - artifactsToDwiFilter->SetFrequencyMap(m_Parameters.m_FrequencyMap); - artifactsToDwiFilter->SetSpikeAmplitude(m_Parameters.m_SpikeAmplitude); - artifactsToDwiFilter->SetSpikes(m_Parameters.m_Spikes); - artifactsToDwiFilter->SetWrap(m_Parameters.m_Wrap); + artifactsToDwiFilter->SetParameters(m_Parameters); CPPUNIT_ASSERT_NO_THROW(artifactsToDwiFilter->Update()); mitk::DiffusionImage::Pointer testImage = mitk::DiffusionImage::New(); testImage->SetVectorImage( artifactsToDwiFilter->GetOutput() ); testImage->SetB_Value(m_Parameters.m_Bvalue); - testImage->SetDirections(m_Parameters.m_GradientDirections); + testImage->SetDirections(m_Parameters.GetGradientDirections()); testImage->InitializeFromVectorImage(); if (refImage.IsNotNull()) { CPPUNIT_ASSERT_MESSAGE(testFileName, CompareDwi(testImage->GetVectorImage(), refImage->GetVectorImage())); } else { NrrdDiffusionImageWriter::Pointer writer = NrrdDiffusionImageWriter::New(); writer->SetFileName("/local/distortions2.dwi"); writer->SetInput(testImage); writer->Update(); } } void Spikes() { m_Parameters.m_Spikes = 5; m_Parameters.m_SpikeAmplitude = 1; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/spikes2.dwi") ); } void GibbsRinging() { - m_Parameters.m_AddGibbsRinging = true; + m_Parameters.m_DoAddGibbsRinging = true; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/gibbsringing2.dwi") ); } void Ghost() { m_Parameters.m_KspaceLineOffset = 0.25; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/ghost2.dwi") ); } void Aliasing() { - m_Parameters.m_Wrap = 0.4; + m_Parameters.m_CroppingFactor = 0.4; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/aliasing2.dwi") ); } void Eddy() { - m_Parameters.m_DoSimulateEddyCurrents = true; m_Parameters.m_EddyStrength = 0.05; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/eddy2.dwi") ); } void RicianNoise() { - mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); + mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); ricianNoiseModel->SetNoiseVariance(1000000); ricianNoiseModel->SetSeed(0); m_Parameters.m_NoiseModel = ricianNoiseModel; - StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/riciannoise2.dwi") ); +// StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/riciannoise2.dwi") ); delete m_Parameters.m_NoiseModel; } void ChiSquareNoise() { - mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); - chiSquareNoiseModel->SetDOF(500000); + mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); + chiSquareNoiseModel->SetNoiseVariance(1000000); chiSquareNoiseModel->SetSeed(0); m_Parameters.m_NoiseModel = chiSquareNoiseModel; - StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/chisquarenoise2.dwi") ); +// StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/chisquarenoise2.dwi") ); delete m_Parameters.m_NoiseModel; } void Distortions() { mitk::Image::Pointer mitkFMap = dynamic_cast(mitk::IOUtil::LoadDataNode( GetTestDataFilePath("DiffusionImaging/Fiberfox/Fieldmap.nrrd") )->GetData()); typedef itk::Image ItkDoubleImgType; ItkDoubleImgType::Pointer fMap = ItkDoubleImgType::New(); mitk::CastToItkImage(mitkFMap, fMap); m_Parameters.m_FrequencyMap = fMap; StartSimulation( GetTestDataFilePath("DiffusionImaging/Fiberfox/distortions2.dwi") ); } }; MITK_TEST_SUITE_REGISTRATION(mitkFiberfoxAddArtifactsToDwi) diff --git a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp index 3af9506e81..14684e2e3b 100644 --- a/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxSignalGenerationTest.cpp @@ -1,337 +1,294 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /**Documentation * Test the Fiberfox simulation functions (fiberBundle -> diffusion weighted image) */ bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2) { typedef itk::VectorImage< short, 3 > DwiImageType; try{ itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion()); itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion()); while(!it1.IsAtEnd()) { if (it1.Get()!=it2.Get()) return false; ++it1; ++it2; } } catch(...) { return false; } return true; } -void StartSimulation(FiberfoxParameters parameters, FiberBundleX::Pointer fiberBundle, mitk::DiffusionImage::Pointer refImage, string message) +void StartSimulation(FiberfoxParameters parameters, FiberBundleX::Pointer fiberBundle, mitk::DiffusionImage::Pointer refImage, string message) { itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); tractsToDwiFilter->SetUseConstantRandSeed(true); - tractsToDwiFilter->SetSimulateEddyCurrents(parameters.m_DoSimulateEddyCurrents); - tractsToDwiFilter->SetEddyGradientStrength(parameters.m_EddyStrength); - tractsToDwiFilter->SetAddGibbsRinging(parameters.m_AddGibbsRinging); - tractsToDwiFilter->SetSimulateRelaxation(parameters.m_DoSimulateRelaxation); - tractsToDwiFilter->SetImageRegion(parameters.m_ImageRegion); - tractsToDwiFilter->SetSpacing(parameters.m_ImageSpacing); - tractsToDwiFilter->SetOrigin(parameters.m_ImageOrigin); - tractsToDwiFilter->SetDirectionMatrix(parameters.m_ImageDirection); + tractsToDwiFilter->SetParameters(parameters); tractsToDwiFilter->SetFiberBundle(fiberBundle); - tractsToDwiFilter->SetFiberModels(parameters.m_FiberModelList); - tractsToDwiFilter->SetNonFiberModels(parameters.m_NonFiberModelList); - tractsToDwiFilter->SetNoiseModel(parameters.m_NoiseModel); - tractsToDwiFilter->SetkOffset(parameters.m_KspaceLineOffset); - tractsToDwiFilter->SettLine(parameters.m_tLine); - tractsToDwiFilter->SettInhom(parameters.m_tInhom); - tractsToDwiFilter->SetTE(parameters.m_tEcho); - tractsToDwiFilter->SetNumberOfRepetitions(parameters.m_Repetitions); - tractsToDwiFilter->SetEnforcePureFiberVoxels(parameters.m_DoDisablePartialVolume); - tractsToDwiFilter->SetInterpolationShrink(parameters.m_InterpolationShrink); - tractsToDwiFilter->SetFiberRadius(parameters.m_AxonRadius); - tractsToDwiFilter->SetSignalScale(parameters.m_SignalScale); - if (parameters.m_InterpolationShrink>0) - tractsToDwiFilter->SetUseInterpolation(true); - tractsToDwiFilter->SetTissueMask(parameters.m_MaskImage); - tractsToDwiFilter->SetFrequencyMap(parameters.m_FrequencyMap); - tractsToDwiFilter->SetSpikeAmplitude(parameters.m_SpikeAmplitude); - tractsToDwiFilter->SetSpikes(parameters.m_Spikes); - tractsToDwiFilter->SetWrap(parameters.m_Wrap); - tractsToDwiFilter->SetAddMotionArtifact(parameters.m_DoAddMotion); - tractsToDwiFilter->SetMaxTranslation(parameters.m_Translation); - tractsToDwiFilter->SetMaxRotation(parameters.m_Rotation); - tractsToDwiFilter->SetRandomMotion(parameters.m_RandomMotion); tractsToDwiFilter->Update(); mitk::DiffusionImage::Pointer testImage = mitk::DiffusionImage::New(); testImage->SetVectorImage( tractsToDwiFilter->GetOutput() ); testImage->SetB_Value(parameters.m_Bvalue); - testImage->SetDirections(parameters.m_GradientDirections); + testImage->SetDirections(parameters.GetGradientDirections()); testImage->InitializeFromVectorImage(); if (refImage.IsNotNull()) { bool cond = CompareDwi(testImage->GetVectorImage(), refImage->GetVectorImage()); if (!cond) { NrrdDiffusionImageWriter::Pointer writer = NrrdDiffusionImageWriter::New(); writer->SetFileName("/tmp/testImage.dwi"); writer->SetInput(testImage); writer->Update(); writer->SetFileName("/tmp/refImage.dwi"); writer->SetInput(refImage); writer->Update(); } MITK_TEST_CONDITION_REQUIRED(cond, message); } else { MITK_INFO << "Saving test image to " << message; NrrdDiffusionImageWriter::Pointer writer = NrrdDiffusionImageWriter::New(); writer->SetFileName(message); writer->SetInput(testImage); writer->Update(); } } int mitkFiberfoxSignalGenerationTest(int argc, char* argv[]) { RegisterDiffusionCoreObjectFactory(); MITK_TEST_BEGIN("mitkFiberfoxSignalGenerationTest"); MITK_TEST_CONDITION_REQUIRED(argc>=19,"check for input data"); // input fiber bundle FiberBundleXReader::Pointer fibReader = FiberBundleXReader::New(); fibReader->SetFileName(argv[1]); fibReader->Update(); FiberBundleX::Pointer fiberBundle = dynamic_cast(fibReader->GetOutput()); // reference diffusion weighted images mitk::DiffusionImage::Pointer stickBall = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[2])->GetData()); mitk::DiffusionImage::Pointer stickAstrosticks = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[3])->GetData()); mitk::DiffusionImage::Pointer stickDot = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[4])->GetData()); mitk::DiffusionImage::Pointer tensorBall = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[5])->GetData()); mitk::DiffusionImage::Pointer stickTensorBall = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[6])->GetData()); mitk::DiffusionImage::Pointer stickTensorBallAstrosticks = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[7])->GetData()); mitk::DiffusionImage::Pointer gibbsringing = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[8])->GetData()); mitk::DiffusionImage::Pointer ghost = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[9])->GetData()); mitk::DiffusionImage::Pointer aliasing = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[10])->GetData()); mitk::DiffusionImage::Pointer eddy = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[11])->GetData()); mitk::DiffusionImage::Pointer linearmotion = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[12])->GetData()); mitk::DiffusionImage::Pointer randommotion = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[13])->GetData()); mitk::DiffusionImage::Pointer spikes = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[14])->GetData()); mitk::DiffusionImage::Pointer riciannoise = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[15])->GetData()); mitk::DiffusionImage::Pointer chisquarenoise = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[16])->GetData()); mitk::DiffusionImage::Pointer distortions = dynamic_cast*>(mitk::IOUtil::LoadDataNode(argv[17])->GetData()); mitk::Image::Pointer mitkFMap = dynamic_cast(mitk::IOUtil::LoadDataNode(argv[18])->GetData()); typedef itk::Image ItkDoubleImgType; ItkDoubleImgType::Pointer fMap = ItkDoubleImgType::New(); mitk::CastToItkImage(mitkFMap, fMap); - FiberfoxParameters parameters; + FiberfoxParameters parameters; parameters.m_DoSimulateRelaxation = true; parameters.m_SignalScale = 10000; parameters.m_ImageRegion = stickBall->GetVectorImage()->GetLargestPossibleRegion(); parameters.m_ImageSpacing = stickBall->GetVectorImage()->GetSpacing(); parameters.m_ImageOrigin = stickBall->GetVectorImage()->GetOrigin(); parameters.m_ImageDirection = stickBall->GetVectorImage()->GetDirection(); parameters.m_Bvalue = stickBall->GetB_Value(); - mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = stickBall->GetDirections(); - parameters.m_NumGradients = 0; - for (unsigned 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]; - parameters.m_GradientDirections.push_back(g); - if (dirs->at(i).magnitude()>0.0001) - parameters.m_NumGradients++; - } + parameters.SetGradienDirections(stickBall->GetDirections()); // intra and inter axonal compartments mitk::StickModel stickModel; stickModel.SetBvalue(parameters.m_Bvalue); stickModel.SetT2(110); stickModel.SetDiffusivity(0.001); - stickModel.SetGradientList(parameters.m_GradientDirections); + stickModel.SetGradientList(parameters.GetGradientDirections()); mitk::TensorModel tensorModel; tensorModel.SetT2(110); stickModel.SetBvalue(parameters.m_Bvalue); tensorModel.SetDiffusivity1(0.001); tensorModel.SetDiffusivity2(0.00025); tensorModel.SetDiffusivity3(0.00025); - tensorModel.SetGradientList(parameters.m_GradientDirections); + tensorModel.SetGradientList(parameters.GetGradientDirections()); // extra axonal compartment models mitk::BallModel ballModel; ballModel.SetT2(80); ballModel.SetBvalue(parameters.m_Bvalue); ballModel.SetDiffusivity(0.001); - ballModel.SetGradientList(parameters.m_GradientDirections); + ballModel.SetGradientList(parameters.GetGradientDirections()); mitk::AstroStickModel astrosticksModel; astrosticksModel.SetT2(80); astrosticksModel.SetBvalue(parameters.m_Bvalue); astrosticksModel.SetDiffusivity(0.001); astrosticksModel.SetRandomizeSticks(true); astrosticksModel.SetSeed(0); - astrosticksModel.SetGradientList(parameters.m_GradientDirections); + astrosticksModel.SetGradientList(parameters.GetGradientDirections()); mitk::DotModel dotModel; dotModel.SetT2(80); - dotModel.SetGradientList(parameters.m_GradientDirections); + dotModel.SetGradientList(parameters.GetGradientDirections()); // noise models mitk::RicianNoiseModel* ricianNoiseModel = new mitk::RicianNoiseModel(); ricianNoiseModel->SetNoiseVariance(1000000); ricianNoiseModel->SetSeed(0); // Rician noise mitk::ChiSquareNoiseModel* chiSquareNoiseModel = new mitk::ChiSquareNoiseModel(); - chiSquareNoiseModel->SetDOF(500000); + chiSquareNoiseModel->SetNoiseVariance(1000000); chiSquareNoiseModel->SetSeed(0); try{ // Stick-Ball parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickBall, argv[2]); // Srick-Astrosticks parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&astrosticksModel); StartSimulation(parameters, fiberBundle, stickAstrosticks, argv[3]); // Stick-Dot parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&dotModel); StartSimulation(parameters, fiberBundle, stickDot, argv[4]); // Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, tensorBall, argv[5]); // Stick-Tensor-Ball parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_FiberModelList.push_back(&tensorModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); StartSimulation(parameters, fiberBundle, stickTensorBall, argv[6]); // Stick-Tensor-Ball-Astrosticks parameters.m_NonFiberModelList.push_back(&astrosticksModel); StartSimulation(parameters, fiberBundle, stickTensorBallAstrosticks, argv[7]); // Gibbs ringing parameters.m_FiberModelList.clear(); parameters.m_FiberModelList.push_back(&stickModel); parameters.m_NonFiberModelList.clear(); parameters.m_NonFiberModelList.push_back(&ballModel); - parameters.m_AddGibbsRinging = true; + parameters.m_DoAddGibbsRinging = true; StartSimulation(parameters, fiberBundle, gibbsringing, argv[8]); // Ghost - parameters.m_AddGibbsRinging = false; + parameters.m_DoAddGibbsRinging = false; parameters.m_KspaceLineOffset = 0.25; StartSimulation(parameters, fiberBundle, ghost, argv[9]); // Aliasing parameters.m_KspaceLineOffset = 0; - parameters.m_Wrap = 0.4; + parameters.m_CroppingFactor = 0.4; parameters.m_SignalScale = 1000; StartSimulation(parameters, fiberBundle, aliasing, argv[10]); // Eddy currents - parameters.m_Wrap = 1; + parameters.m_CroppingFactor = 1; parameters.m_SignalScale = 10000; - parameters.m_DoSimulateEddyCurrents = true; parameters.m_EddyStrength = 0.05; StartSimulation(parameters, fiberBundle, eddy, argv[11]); // Motion (linear) - parameters.m_DoSimulateEddyCurrents = false; parameters.m_EddyStrength = 0.0; parameters.m_DoAddMotion = true; - parameters.m_RandomMotion = false; + parameters.m_DoRandomizeMotion = false; parameters.m_Translation[1] = 10; parameters.m_Rotation[2] = 90; StartSimulation(parameters, fiberBundle, linearmotion, argv[12]); // Motion (random) - parameters.m_RandomMotion = true; + parameters.m_DoRandomizeMotion = true; parameters.m_Translation[1] = 5; parameters.m_Rotation[2] = 45; StartSimulation(parameters, fiberBundle, randommotion, argv[13]); // Spikes parameters.m_DoAddMotion = false; parameters.m_Spikes = 5; parameters.m_SpikeAmplitude = 1; StartSimulation(parameters, fiberBundle, spikes, argv[14]); // Rician noise parameters.m_Spikes = 0; parameters.m_NoiseModel = ricianNoiseModel; StartSimulation(parameters, fiberBundle, riciannoise, argv[15]); delete parameters.m_NoiseModel; // Chi-square noise parameters.m_NoiseModel = chiSquareNoiseModel; StartSimulation(parameters, fiberBundle, chisquarenoise, argv[16]); delete parameters.m_NoiseModel; // Distortions parameters.m_NoiseModel = NULL; parameters.m_FrequencyMap = fMap; StartSimulation(parameters, fiberBundle, distortions, argv[17]); } catch (std::exception &e) { MITK_TEST_CONDITION_REQUIRED(false, e.what()); } // always end with this! MITK_TEST_END(); } diff --git a/Modules/DiffusionImaging/FiberTracking/files.cmake b/Modules/DiffusionImaging/FiberTracking/files.cmake index d04fd7e21f..c1bcaaeb36 100644 --- a/Modules/DiffusionImaging/FiberTracking/files.cmake +++ b/Modules/DiffusionImaging/FiberTracking/files.cmake @@ -1,93 +1,92 @@ set(CPP_FILES ## IO datastructures IODataStructures/FiberBundleX/mitkFiberBundleX.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriter.cpp IODataStructures/FiberBundleX/mitkFiberBundleXReader.cpp IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.cpp IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.cpp IODataStructures/FiberBundleX/mitkTrackvis.cpp IODataStructures/PlanarFigureComposite/mitkPlanarFigureComposite.cpp IODataStructures/mitkFiberTrackingObjectFactory.cpp - IODataStructures/mitkFiberfoxParameters.cpp # Rendering Rendering/mitkFiberBundleXMapper2D.cpp Rendering/mitkFiberBundleXMapper3D.cpp # Interactions Interactions/mitkFiberBundleInteractor.cpp # Tractography Algorithms/GibbsTracking/mitkParticleGrid.cpp Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp Algorithms/GibbsTracking/mitkEnergyComputer.cpp Algorithms/GibbsTracking/mitkGibbsEnergyComputer.cpp Algorithms/GibbsTracking/mitkFiberBuilder.cpp Algorithms/GibbsTracking/mitkSphereInterpolator.cpp ) set(H_FILES # Rendering Rendering/mitkFiberBundleXMapper3D.h Rendering/mitkFiberBundleXMapper2D.h # DataStructures -> FiberBundleX IODataStructures/FiberBundleX/mitkFiberBundleX.h IODataStructures/FiberBundleX/mitkFiberBundleXWriter.h IODataStructures/FiberBundleX/mitkFiberBundleXReader.h IODataStructures/FiberBundleX/mitkFiberBundleXIOFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXWriterFactory.h IODataStructures/FiberBundleX/mitkFiberBundleXSerializer.h IODataStructures/FiberBundleX/mitkTrackvis.h IODataStructures/mitkFiberTrackingObjectFactory.h IODataStructures/mitkFiberfoxParameters.h # Algorithms Algorithms/itkTractDensityImageFilter.h Algorithms/itkTractsToFiberEndingsImageFilter.h Algorithms/itkTractsToRgbaImageFilter.h Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h Algorithms/itkFibersFromPlanarFiguresFilter.h Algorithms/itkTractsToDWIImageFilter.h Algorithms/itkTractsToVectorImageFilter.h Algorithms/itkKspaceImageFilter.h Algorithms/itkDftImageFilter.h Algorithms/itkAddArtifactsToDwiImageFilter.h Algorithms/itkFieldmapGeneratorFilter.h Algorithms/itkEvaluateDirectionImagesFilter.h Algorithms/itkEvaluateTractogramDirectionsFilter.h # (old) Tractography Algorithms/itkGibbsTrackingFilter.h Algorithms/itkStochasticTractographyFilter.h Algorithms/itkStreamlineTrackingFilter.h Algorithms/GibbsTracking/mitkParticle.h Algorithms/GibbsTracking/mitkParticleGrid.h Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h Algorithms/GibbsTracking/mitkSimpSamp.h Algorithms/GibbsTracking/mitkEnergyComputer.h Algorithms/GibbsTracking/mitkGibbsEnergyComputer.h Algorithms/GibbsTracking/mitkSphereInterpolator.h Algorithms/GibbsTracking/mitkFiberBuilder.h # Signal Models SignalModels/mitkDiffusionSignalModel.h SignalModels/mitkTensorModel.h SignalModels/mitkBallModel.h SignalModels/mitkDotModel.h SignalModels/mitkAstroStickModel.h SignalModels/mitkStickModel.h SignalModels/mitkDiffusionNoiseModel.h SignalModels/mitkRicianNoiseModel.h SignalModels/mitkChiSquareNoiseModel.h ) set(RESOURCE_FILES # Binary directory resources FiberTrackingLUTBaryCoords.bin FiberTrackingLUTIndices.bin # Shaders Shaders/mitkShaderFiberClipping.xml ) diff --git a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt index bdaf88c02b..80021cd166 100755 --- a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt +++ b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt @@ -1,63 +1,63 @@ option(BUILD_DiffusionMiniApps "Build commandline tools for diffusion" OFF) if(BUILD_DiffusionMiniApps OR MITK_BUILD_ALL_APPS) # needed include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) project( mitkDiffusionMiniApps ) # fill in the standalone executables here set(DIFFUSIONMINIAPPS mitkDiffusionMiniApps ) # set additional files here set(DIFFUSIONCORE_ADDITIONAL_FILES MiniAppManager.cpp FileFormatConverter.cpp TensorReconstruction.cpp QballReconstruction.cpp DiffusionIndices.cpp CopyGeometry.cpp GibbsTracking.cpp StreamlineTracking.cpp FiberProcessing.cpp LocalDirectionalFiberPlausibility.cpp #TractogramAngularError.cpp FiberDirectionExtraction.cpp PeakExtraction.cpp PeaksAngularError.cpp MultishellMethods.cpp - FiberFoxProcessing.cpp + #FiberFoxProcessing.cpp ExportShImage.cpp NetworkCreation.cpp NetworkStatistics.cpp ) # deprecated # FOREACH(tool ${DIFFUSIONMINIAPPS}) # ADD_EXECUTABLE( # ${tool} # ${tool}.cpp # ${DIFFUSIONCORE_ADDITIONAL_FILES} # ) # TARGET_LINK_LIBRARIES( # ${tool} # ${ALL_LIBRARIES} ) # ENDFOREACH(tool) mitk_create_executable(mitkDiffusionMiniApps DEPENDS DiffusionCore FiberTracking Connectomics PACKAGE_DEPENDS ITK|ITKDiffusionTensorImage ) if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES mitkDiffusionMiniApps ) endif() endif() diff --git a/Modules/DiffusionImaging/MiniApps/FiberFoxProcessing.cpp b/Modules/DiffusionImaging/MiniApps/FiberFoxProcessing.cpp index f202e2f69b..7faf6a0b01 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberFoxProcessing.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberFoxProcessing.cpp @@ -1,547 +1,547 @@ /*=================================================================== 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 "MiniAppManager.h" #include #include #include #include #include #include #include #include //#include "ctkCommandLineParser.h" #include "ctkCommandLineParser.h" #include #include #include #include "boost/property_tree/ptree.hpp" #include "boost/property_tree/xml_parser.hpp" #include "boost/foreach.hpp" #include #include #include #include #include using namespace mitk; 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; int spikes; double spikeAmplitude; bool doSimulateRelaxation; bool doSimulateEddyCurrents; bool doDisablePartialVolume; mitk::RicianNoiseModel ricianNoiseModel; mitk::DiffusionSignalModel::GradientListType gradientDirections; - itk::TractsToDWIImageFilter< short >::DiffusionModelList fiberModelList, nonFiberModelList; + itk::TractsToDWIImageFilter< short >::DiffusionModelListType fiberModelList, nonFiberModelList; std::string signalModelString, artifactModelString; itk::Image::Pointer frequencyMap; itk::Image::Pointer tissueMaskImage; mitk::DataNode::Pointer resultNode; }; void LoadParameters(const std::string & filename, ImageParameters & m_ImageGenParameters, mitk::Image::Pointer m_fImage, mitk::Image::Pointer m_maskImage, 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) { MITK_INFO << "Initialize Diffusion Models"; boost::property_tree::ptree parameters; boost::property_tree::xml_parser::read_xml(filename, parameters); 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(); m_ImageGenParameters.spikes = 0; m_ImageGenParameters.spikeAmplitude = 1; MITK_INFO << "reset params"; BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameters.get_child("fiberfox") ) { if( v1.first == "image" ) { MITK_INFO << "Load image params"; m_ImageGenParameters.tEcho = v1.second.get("tEcho"); m_ImageGenParameters.tLine = v1.second.get("tLine"); m_ImageGenParameters.doSimulateEddyCurrents = v1.second.get("artifacts.addeddy"); m_ImageGenParameters.eddyStrength = 0; if (m_ImageGenParameters.doSimulateEddyCurrents) { m_ImageGenParameters.eddyStrength = v1.second.get("artifacts.eddyStrength"); } // signal relaxation m_ImageGenParameters.doSimulateRelaxation = v1.second.get("doSimulateRelaxation"); if (m_ImageGenParameters.doSimulateRelaxation) // N/2 ghosts if (v1.second.get("artifacts.addghost")) { m_ImageGenParameters.kspaceLineOffset = v1.second.get("artifacts.kspaceLineOffset"); } else { m_ImageGenParameters.kspaceLineOffset = 0; } if (v1.second.get("artifacts.addspikes")) { m_ImageGenParameters.spikes = v1.second.get("artifacts.spikesnum"); m_ImageGenParameters.spikeAmplitude = v1.second.get("artifacts.spikesscale"); } // add distortions if (v1.second.get("artifacts.distortions") && m_fImage) { itk::Image::Pointer itkImg = itk::Image::New(); mitk::CastToItkImage< itk::Image >(m_fImage, 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; } } // rician noise if (v1.second.get("artifacts.addnoise")) m_ImageGenParameters.ricianNoiseModel.SetNoiseVariance(v1.second.get("artifacts.noisevariance")); else m_ImageGenParameters.ricianNoiseModel.SetNoiseVariance(0); // gibbs ringing m_ImageGenParameters.upsampling = 1; if (v1.second.get("artifacts.addringing")) m_ImageGenParameters.upsampling = v1.second.get("artifacts.ringingupsampling"); // 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; // check tissue mask if (m_maskImage.IsNotNull()) { m_ImageGenParameters.tissueMaskImage = itk::Image::New(); mitk::CastToItkImage >(m_maskImage.GetPointer(), m_ImageGenParameters.tissueMaskImage); } // signal models m_ImageGenParameters.comp3Weight = 1; m_ImageGenParameters.comp4Weight = 0; if (v1.second.get("compartment4.index") > 0) { m_ImageGenParameters.comp4Weight = v1.second.get("compartment4.weight"); m_ImageGenParameters.comp3Weight -= m_ImageGenParameters.comp4Weight; } // compartment 1 switch(v1.second.get("compartment1.index")){ case 0: m_StickModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_StickModel1->SetBvalue(m_ImageGenParameters.b_value); m_StickModel1->SetDiffusivity(v1.second.get("compartment1.stick.d")); m_StickModel1->SetT2(v1.second.get("compartment1.stick.t2")); m_ImageGenParameters.fiberModelList.push_back(m_StickModel1); break; case 1: m_ZeppelinModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_ZeppelinModel1->SetBvalue(m_ImageGenParameters.b_value); m_ZeppelinModel1->SetDiffusivity1(v1.second.get("compartment1.zeppelin.d1")); m_ZeppelinModel1->SetDiffusivity2(v1.second.get("compartment1.zeppelin.d2")); m_ZeppelinModel1->SetDiffusivity3(v1.second.get("compartment1.zeppelin.d2")); m_ZeppelinModel1->SetT2(v1.second.get("compartment1.zeppelin.t2")); m_ImageGenParameters.fiberModelList.push_back(m_ZeppelinModel1); break; case 2: m_TensorModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_TensorModel1->SetBvalue(m_ImageGenParameters.b_value); m_TensorModel1->SetDiffusivity1(v1.second.get("compartment1.tensor.d1")); m_TensorModel1->SetDiffusivity2(v1.second.get("compartment1.tensor.d2")); m_TensorModel1->SetDiffusivity3(v1.second.get("compartment1.tensor.d3")); m_TensorModel1->SetT2(v1.second.get("compartment1.tensor.t2")); m_ImageGenParameters.fiberModelList.push_back(m_TensorModel1); break; } // compartment 2 switch(v1.second.get("compartment2.index")){ case 0: m_StickModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_StickModel2->SetBvalue(m_ImageGenParameters.b_value); m_StickModel2->SetDiffusivity(v1.second.get("compartment2.stick.d")); m_StickModel2->SetT2(v1.second.get("compartment2.stick.t2")); m_ImageGenParameters.fiberModelList.push_back(m_StickModel2); break; case 1: m_ZeppelinModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_ZeppelinModel2->SetBvalue(m_ImageGenParameters.b_value); m_ZeppelinModel2->SetDiffusivity1(v1.second.get("compartment2.zeppelin.d1")); m_ZeppelinModel2->SetDiffusivity2(v1.second.get("compartment2.zeppelin.d2")); m_ZeppelinModel2->SetDiffusivity3(v1.second.get("compartment2.zeppelin.d2")); m_ZeppelinModel2->SetT2(v1.second.get("compartment2.zeppelin.t2")); m_ImageGenParameters.fiberModelList.push_back(m_ZeppelinModel2); break; case 2: m_TensorModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_TensorModel2->SetBvalue(m_ImageGenParameters.b_value); m_TensorModel2->SetDiffusivity1(v1.second.get("compartment2.tensor.d1")); m_TensorModel2->SetDiffusivity2(v1.second.get("compartment2.tensor.d2")); m_TensorModel2->SetDiffusivity3(v1.second.get("compartment2.tensor.d3")); m_TensorModel2->SetT2(v1.second.get("compartment2.tensor.t2")); m_ImageGenParameters.fiberModelList.push_back(m_TensorModel2); break; } // compartment 3 switch(v1.second.get("compartment3.index")){ case 0: m_BallModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_BallModel1->SetBvalue(m_ImageGenParameters.b_value); m_BallModel1->SetDiffusivity(v1.second.get("compartment3.ball.d")); m_BallModel1->SetT2(v1.second.get("compartment3.ball.t2")); m_BallModel1->SetWeight(m_ImageGenParameters.comp3Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_BallModel1); break; case 1: m_AstrosticksModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_AstrosticksModel1->SetBvalue(m_ImageGenParameters.b_value); m_AstrosticksModel1->SetDiffusivity(v1.second.get("compartment3.astrosticks.d")); m_AstrosticksModel1->SetT2(v1.second.get("compartment3.astrosticks.t2")); m_AstrosticksModel1->SetRandomizeSticks(v1.second.get("compartment3.astrosticks.randomize")); m_AstrosticksModel1->SetWeight(m_ImageGenParameters.comp3Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_AstrosticksModel1); break; case 2: m_DotModel1->SetGradientList(m_ImageGenParameters.gradientDirections); m_DotModel1->SetT2(v1.second.get("compartment3.dot.t2")); m_DotModel1->SetWeight(m_ImageGenParameters.comp3Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_DotModel1); break; } // compartment 4 switch(v1.second.get("compartment4.index")){ case 0: m_BallModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_BallModel2->SetBvalue(m_ImageGenParameters.b_value); m_BallModel2->SetDiffusivity(v1.second.get("compartment4.ball.d")); m_BallModel2->SetT2(v1.second.get("compartment4.ball.t2")); m_BallModel2->SetWeight(m_ImageGenParameters.comp4Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_BallModel2); break; case 1: m_AstrosticksModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_AstrosticksModel2->SetBvalue(m_ImageGenParameters.b_value); m_AstrosticksModel2->SetDiffusivity(v1.second.get("compartment4.astrosticks.d")); m_AstrosticksModel2->SetT2(v1.second.get("compartment4.astrosticks.t2")); m_AstrosticksModel2->SetRandomizeSticks(v1.second.get("compartment4.astrosticks.randomize")); m_AstrosticksModel2->SetWeight(m_ImageGenParameters.comp4Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_AstrosticksModel2); break; case 2: m_DotModel2->SetGradientList(m_ImageGenParameters.gradientDirections); m_DotModel2->SetT2(v1.second.get("compartment4.dot.t2")); m_DotModel2->SetWeight(m_ImageGenParameters.comp4Weight); m_ImageGenParameters.nonFiberModelList.push_back(m_DotModel2); break; } m_ImageGenParameters.signalScale = v1.second.get("signalScale"); m_ImageGenParameters.repetitions = v1.second.get("repetitions"); m_ImageGenParameters.tInhom = v1.second.get("tInhom"); m_ImageGenParameters.doDisablePartialVolume = v1.second.get("doDisablePartialVolume"); m_ImageGenParameters.interpolationShrink = v1.second.get("interpolationShrink"); m_ImageGenParameters.axonRadius = v1.second.get("axonRadius"); } /* m_Controls->m_VarianceBox->setValue(v1.second.get("variance")); m_Controls->m_AdvancedOptionsBox->setChecked(v1.second.get("showadvanced")); m_Controls->m_AdvancedOptionsBox_2->setChecked(v1.second.get("showadvanced")); m_Controls->m_VolumeFractionsBox->setChecked(v1.second.get("outputvolumefractions")); m_Controls->m_RealTimeFibers->setChecked(v1.second.get("realtime")); m_Controls->m_DistributionBox->setCurrentIndex(v1.second.get("distribution")); 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")); */ } } int FiberFoxProcessing(int argc, char* argv[]) { ctkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("in", "i", ctkCommandLineParser::String, "input file", us::Any(), false); parser.addArgument("out", "o", ctkCommandLineParser::String, "output file", us::Any(), false); parser.addArgument("fiberbundle", "f", ctkCommandLineParser::String, "defined fiber bundle for signal generation", us::Any(), false); parser.addArgument("loadparameters", "l", ctkCommandLineParser::String, "load fiber fox signal parameter file", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments string inName = us::any_cast(parsedArgs["in"]); string outName = us::any_cast(parsedArgs["out"]); string fbName = us::any_cast(parsedArgs["fiberbundle"]); string paramName = us::any_cast(parsedArgs["loadparameters"]); { RegisterDiffusionCoreObjectFactory(); RegisterFiberTrackingObjectFactory(); ImageParameters m_ImageGenParameters; mitk::Image::Pointer m_maskImage = 0; mitk::Image::Pointer m_fImage = 0; MITK_INFO << "Loading " << inName; const std::string s1="", s2=""; std::vector infile = BaseDataIO::LoadBaseDataFromFile( inName, s1, s2, false ); mitk::BaseData::Pointer baseData = infile.at(0); MITK_INFO << "Loading " << fbName; std::vector infile2 = BaseDataIO::LoadBaseDataFromFile( fbName, s1, s2, false ); mitk::BaseData::Pointer baseData2 = infile2.at(0); DiffusionImage::Pointer dwi; FiberBundleX::Pointer fbi; if ( dynamic_cast*>(baseData.GetPointer()) ) dwi = dynamic_cast*>(baseData.GetPointer()); else MITK_ERROR << "LOADING DWI FAILD: " << inName; if ( dynamic_cast(baseData2.GetPointer()) ) fbi = dynamic_cast(baseData2.GetPointer()); else MITK_ERROR << "LOADING FBI FAILD: " << fbName; 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++; } 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; LoadParameters(paramName,m_ImageGenParameters,NULL, NULL, &m_StickModel1, &m_StickModel2, &m_ZeppelinModel1, &m_ZeppelinModel2, &m_TensorModel1, &m_TensorModel2, &m_BallModel1, &m_BallModel2, &m_AstrosticksModel1, &m_AstrosticksModel2, &m_DotModel1, &m_DotModel2); MITK_INFO << "Parameter loaded"; itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); 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(fbi); tractsToDwiFilter->SetFiberModels(m_ImageGenParameters.fiberModelList); tractsToDwiFilter->SetNonFiberModels(m_ImageGenParameters.nonFiberModelList); tractsToDwiFilter->SetNoiseModel(&m_ImageGenParameters.ricianNoiseModel); 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>0) tractsToDwiFilter->SetUseInterpolation(true); tractsToDwiFilter->SetTissueMask(m_ImageGenParameters.tissueMaskImage); tractsToDwiFilter->SetFrequencyMap(m_ImageGenParameters.frequencyMap); tractsToDwiFilter->SetSpikeAmplitude(m_ImageGenParameters.spikeAmplitude); tractsToDwiFilter->SetSpikes(m_ImageGenParameters.spikes); tractsToDwiFilter->Update(); mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( tractsToDwiFilter->GetOutput() ); image->SetB_Value(dwi->GetB_Value()); image->SetDirections(dwi->GetDirections()); image->InitializeFromVectorImage(); MITK_INFO << "Writing " << outName; NrrdDiffusionImageWriter::Pointer writer = NrrdDiffusionImageWriter::New(); writer->SetFileName(outName); writer->SetInput(image); writer->Update(); } MITK_INFO << "DONE"; return EXIT_SUCCESS; } RegisterDiffusionMiniApp(FiberFoxProcessing); diff --git a/Modules/DiffusionImaging/MiniApps/files.cmake b/Modules/DiffusionImaging/MiniApps/files.cmake index bebe55de6e..30c2fb70da 100644 --- a/Modules/DiffusionImaging/MiniApps/files.cmake +++ b/Modules/DiffusionImaging/MiniApps/files.cmake @@ -1,22 +1,22 @@ set(CPP_FILES mitkDiffusionMiniApps.cpp MiniAppManager.cpp FileFormatConverter.cpp TensorReconstruction.cpp QballReconstruction.cpp DiffusionIndices.cpp CopyGeometry.cpp GibbsTracking.cpp StreamlineTracking.cpp FiberProcessing.cpp LocalDirectionalFiberPlausibility.cpp #TractogramAngularError.cpp FiberDirectionExtraction.cpp PeakExtraction.cpp PeaksAngularError.cpp MultishellMethods.cpp - FiberFoxProcessing.cpp + #FiberFoxProcessing.cpp ExportShImage.cpp NetworkCreation.cpp NetworkStatistics.cpp ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingUserManual.dox index 97a399a1ca..16d262a6f1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingUserManual.dox @@ -1,140 +1,143 @@ /** \page org_mitk_gui_qt_diffusionimaging MITK Diffusion Imaging (MITK-DI) This module provides means to diffusion weighted image reconstruction, visualization and quantification. Diffusion tensors as well as different q-ball reconstruction schemes are supported. Q-ball imaging aims at recovering more detailed information about the orientations of fibers from diffusion MRI measurements and, in particular, to resolve the orientations of crossing fibers. Available sections: - \ref QmitkDiffusionImagingUserManualIssues - \ref QmitkDiffusionImagingUserManualPreprocessing - \ref QmitkDiffusionImagingUserManualTensorReconstruction - \ref QmitkDiffusionImagingUserManualQBallReconstruction - \ref QmitkDiffusionImagingUserManualDicomImport - \ref QmitkDiffusionImagingUserManualFslImport - \ref QmitkDiffusionImagingUserManualQuantification - \ref QmitkDiffusionImagingUserManualVisualizationSettings - \ref QmitkDiffusionImagingUserManualReferences - \ref QmitkDiffusionImagingUserManualTechnicalDetail - \ref QmitkDiffusionImagingUserManualSubManuals \section QmitkDiffusionImagingUserManualIssues Known Issues \li Dicom Import: The dicom import has so far only been implemented for Siemens dicom images. MITK-DI is capable of reading the nrrd format, which is documented elsewhere [1, 2]. These files can be created by combining the raw image data with a corresponding textual header file. The file extension should be changed from *.nrrd to *.dwi or from *.nhdr to *.hdwi respectively in order to let MITK-DI recognize the diffusion related header information provided in the files. \section QmitkDiffusionImagingUserManualPreprocessing Preprocessing The preprocessing view gives an overview over the important features of a diffusion weighted image like the number of gradient directions, b-value and the measurement frame. Additionally it allows the extraction of the B0 image, reduction of gradient directions and the generation of a binary brain mask. The image volume can be modified by applying a new mesurement frame, which is useful if the measurement frame is not set correctly in the image header, or by averaging redundant gradient directions. \image html prepro1.png Preprocessing \section QmitkDiffusionImagingUserManualTensorReconstruction Tensor Reconstruction The tensor reconstruction view allows ITK based tensor reconstruction [3]. The advanced settings for ITK reconstruction let you configure a manual threshold on the non-diffusion weighted image. All voxels below this threshold will not be reconstructed and left blank. It is also possible to check for negative eigenvalues. The according voxels are also left blank. \image html tensor1.png ITK tensor reconstruction A few seconds (depending on the image size) after the reconstruction button is hit, a colored image should appear in the main window. \image html tensor4.png Tensor image after reconstruction To assess the quality of the tensor fit it has been proposed to calculate the model residual [9]. This calculates the residual between the measured signal and the signal predicted by the model. Large residuals indicate an inadequacy of the model or the presence of artefacts in the signal intensity (noise, head motion, etc.). To use this option: Select a DWI dataset, estimate a tensor, select both the DWI node and the tensor node in the datamanager and press Residual Image Calculation. MITK-Diffusion can show the residual for every voxel averaged over all volumes or (in the plot widget) summarized per volume or for every slice in every volume. Clicking in the widget where the residual is shown per slice will automatically let the cross-hair jump to that position in the DWI dataset. If Percentage of outliers is checked, the per volume plot will show the percentage of outliers per volume. Otherwise it will show the mean together with the first and third quantile of residuals. See [9] for more information. \image html residuals.png The residual widget The view also allows the generation of artificial diffusion weighted or Q-Ball images from the selected tensor image. The ODFs of the Q-Ball image are directly initialized from the tensor values and afterwards normalized. The diffusion weighted image is estimated using the l2-norm image of the tensor image as B0. The gradient images are afterwards generated using the standard tensor equation. \section QmitkDiffusionImagingUserManualQBallReconstruction Q-Ball Reconstruction The q-ball reonstruction view implements a variety of reconstruction methods. The different reconstruction methods are described in the following: \li Numerical: The original, numerical q-ball reconstruction presented by Tuch et al. [5] \li Standard (SH): Descoteaux's reconstruction based on spherical harmonic basis functions [6] \li Solid Angle (SH): Aganj's reconstruction with solid angle consideration [7] \li ADC-profile only: The ADC-profile reconstructed with spherical harmonic basis functions \li Raw signal only: The raw signal reconstructed with spherical harmonic basis functions \image html qballs1.png The q-ball resonstruction view B0 threshold works the same as in tensor reconstruction. The maximum l-level configures the size of the spherical harmonics basis. Larger l-values (e.g. l=8) allow higher levels of detail, lower levels are more stable against noise (e.g. l=4). Lambda is a regularisation parameter. Set it to 0 for no regularisation. lambda = 0.006 has proven to be a stable choice under various settings. \image html qballs2.png Advanced q-ball reconstruction settings This is how a q-ball image should initially look after reconstruction. Standard q-balls feature a relatively low GFA and thus appear rather dark. Adjust the level-window to solve this. \image html qballs3.png q-ball image after reconstruction \section QmitkDiffusionImagingUserManualDicomImport Dicom Import The dicom import does not cover all hardware manufacturers but only Siemens dicom images. MITK-DI is also capable of reading the nrrd format, which is documented elsewhere [1, 2]. These files can be created by combining the raw image data with a corresponding textual header file. The file extension should be changed from *.nrrd to *.dwi or from *.nhdr to *.hdwi respectively in order to let MITK-DI recognize the diffusion related header information provided in the files. In case your dicom images are readable by MITK-DI, select one or more input dicom folders and click import. Each input folder must only contain DICOM-images that can be combined into one vector-valued 3D output volume. Different patients must be loaded from different input-folders. The folders must not contain other acquisitions (e.g. T1,T2,localizer). In case many imports are performed at once, it is recommended to set the the optional output folder argument. This prevents the images from being kept in memory. \image html dicom1.png Dicom import The option "Average duplicate gradients" accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "blur radius" > 0 is configured. \section QmitkDiffusionImagingUserManualFslImport FSL Import FSL diffusion data can be imported with MITK Diffusion. FSL diffusion datasets consist of 3 files: a nifty file (filename.nii.gz or filename.nii), a bvecs file (filename.bvecs), which is a text file containing the gradient vectors, and a bvals file (filename.bvecs), containing the b-values. Due to the system that selects suitable file readers, MITK will not recognize these files as diffusion datasets. In order to make MITK recognize it as diffusion, the extension must be changed from .nii.gz to .fslgz (so the new name is filename.fslgz) or from filename.nii to filename.fsl. The bvecs and bvals files have to be renamed as well(to filename.fsl.bvecs/filenames.fsl.bvecs or to filename.fslgz.bvecs/filename.fslgz.bvals). MITK can also save diffusion weighted images in FSL format. To do this the extension of the new file should be changed to .fsl or .fslgz upon saving the file. \image html fslsave.png Save a dwi dataset as fsl \section QmitkDiffusionImagingUserManualQuantification Quantification The quantification view allows the derivation of different scalar anisotropy measures for the reconstructed tensors (Fractional Anisotropy, Relative Anisotropy, Axial Diffusivity, Radial Diffusivity) or q-balls (Generalized Fractional Anisotropy). \image html quantification.png Anisotropy quantification \section QmitkDiffusionImagingUserManualVisualizationSettings ODF Visualization Setting In this small view, the visualization of ODFs and diffusion images can be configured. Depending on the selected image in the data storage, different options are shown here. For tensor or q-ball images, the visibility of glyphs in the different render windows (T)ransversal, (S)agittal, and (C)oronal can be configured here. The maximal number of glyphs to display can also be configured here for. This is usefull to keep the system response time during rendering feasible. The other options configure normalization and scaling of the glyphs. In diffusion images, a slider lets you choose the desired image channel from the vector of images (each gradient direction one image) for rendering. Furthermore reinit can be performed and texture interpolation toggled. This is how a visualization with activated glyphs should look like: \image html visualization3.png Q-ball image with ODF glyph visibility toggled ON \section QmitkDiffusionImagingUserManualReferences References 1. http://teem.sourceforge.net/nrrd/format.html 2. http://www.cmake.org/Wiki/Getting_Started_with_the_NRRD_Format 3. C.F.Westin, S.E.Maier, H.Mamata, A.Nabavi, F.A.Jolesz, R.Kikinis, "Processing and visualization for Diffusion tensor MRI", Medical image Analysis, 2002, pp 93-108 5. Tuch, D.S., 2004. Q-ball imaging. Magn Reson Med 52, 1358-1372. 6. Descoteaux, M., Angelino, E., Fitzgibbons, S., Deriche, R., 2007. Regularized, fast, and robust analytical Q-ball imaging. Magn Reson Med 58, 497-510. 7. Aganj, I., Lenglet, C., Sapiro, G., 2009. ODF reconstruction in q-ball imaging with solid angle consideration. Proceedings of the Sixth IEEE International Symposium on Biomedical Imaging Boston, MA. 8. Goh, A., Lenglet, C., Thompson, P.M., Vidal, R., 2009. Estimating Orientation Distribution Functions with Probability Density Constraints and Spatial Regularity. Med Image Comput Comput Assist Interv Int Conf Med Image Comput Comput Assist Interv LNCS 5761, 877 ff. 9. J.-D. Tournier, S. Mori, A. Leemans., 2011. Diffusion Tensor Imaging and Beyond. Magn Reson Med 65, 1532-1556. \section QmitkDiffusionImagingUserManualTechnicalDetail Technical Information for Developers The diffusion imaging module uses additional properties beside the ones in use in other modules, for further information see \ref DiffusionImagingPropertiesPage . \section QmitkDiffusionImagingUserManualSubManuals Manuals of componentes The MITK Diffusion tools consist of further components, which have their own documentation, see: \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_gibbstracking \li \subpage org_mitk_views_odfdetails \li \subpage org_mitk_views_partialvolumeanalysisview \li \subpage org_mitk_views_screenshotmaker \li \subpage org_mitk_views_stochasticfibertracking \li \subpage org_mitk_views_ivim \li \subpage org_mitk_diffusionimagingapp_perspectives_connectomics \li \subpage org_mitk_views_tractbasedspatialstatistics + \li \subpage org_mitk_views_fiberextraction + \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_odfmaximaextraction \li \subpage org_mitk_views_streamlinetracking \li \subpage org_mitk_views_fiberfoxview + \li \subpage org_mitk_views_fieldmapgenerator */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberExtractionViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberExtractionViewUserManual.dox new file mode 100644 index 0000000000..df6577f4a5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberExtractionViewUserManual.dox @@ -0,0 +1,9 @@ +/** +\page org_mitk_views_fiberextraction Fiber Extraction View + +This view provides tools to extract subbundles from a given fiber bundle. + +Place ROIs in the 2D render widgets (cricles or polygons) and extract fibers from the bundle that pass through these ROIs by selecting the according ROI and fiber bundle in the datamanger and starting the extraction. The ROIs can be combined via logical operations. All fibers that pass through the thus generated composite ROI are extracted. The extraction can also be performed using 3D ROIs represented as binary mask images. In this extraction method, the logical operations are not implemented at the moment. + +The selected fiber bundle can be smoothed by interpolating the fiber points using Kochanek splines with the specified number of points per cm. +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox index 6f1f6d6963..75e8530197 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberProcessingViewUserManual.dox @@ -1,23 +1,19 @@ /** \page org_mitk_views_fiberprocessing Fiber Processing View -This view provides everything needed to process fiber bundles. - -\image html fiberprocessing.png The Fiber Processing View - -Fiber extraction: -Place ROIs in the 2D render widgets (cricles or polygons) and extract fibers from the bundle that pass through these ROIs by selecting the according ROI and fiber bundle in the datamanger and starting the extraction. The ROIs can be combined via logical operations. All fibers that pass through the thus generated composite ROI are extracted. The extraction can also be performed using 3D ROIs represented as closed surface meshes. In this extraction method, the logical operations are not implemented at the moment. - -The selected fiber bundle can be smoothed by interpolating the fiber points using Kochanek splines with the specified number of points per cm. - -If a float image with pixel values between 0 and 1 is selcted, the fiber bundle can be colored according to the pixel values. +This view provides tools to modify and postprocess the selected fiber bundle as well as additional methods such as TDI. Generation of additional data from fiber bundles: \li Tract density image: generate a 2D heatmap from a fiber bundle \li Binary envelope: generate a binary image from a fiber bundle \li Fiber bundle image: generate a 2D rgba image representation of the fiber bundle -\li Fiber endings image: generate a 2D binary image showing the locations of fiber endpoints +\li Fiber endings image: generate a 2D image showing the locations of fiber endpoints \li Fiber endings pointset: generate a poinset containing the locations of fiber endpoints +Fiber bundle postprocessing: +\li The selected fiber bundle can be smoothed by interpolating the fiber points using Kochanek splines. +\li The fiber bundle can be pruned using a length or curvature threshold. +\li The fiber bundle can be mirrored in aqll three dimensions. +If a float image with pixel values between 0 and 1 is selcted, the fiber bundle can be colored according to the pixel values (e.g. using an FA image). */ 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 30e1922e3a..cb0d30503e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox @@ -1,116 +1,115 @@ /** \page org_mitk_views_fiberfoxview Fiberfox This view provides the user interface for Fiberfox [1,2,3], 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, susceptibility distortions and motion artifacts. 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: 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 Volume Fractions: Output a double image for each compartment. The voxel values correspond to the volume fraction of the respective compartment. 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". 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 Noise: Add Rician or Chi-Square distributed noise with the specified variance to the signal. \li Spikes: Add signal spikes to the k-space signal resulting in stripe artifacts across the corresponding image slice. \li Aliasing: Aliasing artifacts occur if the FOV in phase direction is smaller than the imaged object. The parameter defines the percentage by which the FOV is shrunk. \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. The "Fieldmap Generator" view provides an interface to generate simple artificial frequency maps. \li Motion Artifacts: To simulate motion artifacts, the fiber configuration is moved between the signal simulation of the individual gradient volumes. The motion can be performed randomly, where the parameters are used to define the +/- maximum of the corresponding motion, or linearly, where the parameters define the maximum rotation/translation around/along the corresponding axis at the and of the simulated acquisition. \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. \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, Frederik B. Laun, Bram Stieltjes, and Klaus H. Fritzsche: Fiberfox: Facilitating the creation of realistic white matter software phantoms, Magn Reson Med, Accepted for publication. +[1] Peter F. Neher, Frederik B. Laun, Bram Stieltjes, and Klaus H. Fritzsche: Fiberfox: Facilitating the creation of realistic white matter software phantoms, Magn Reson Med, DOI: 10.1002/mrm.25045. [2] Peter F. Neher, Frederik B. Laun, Bram Stieltjes, and Klaus H. Fritzsche: Fiberfox: An extensible system for generating realistic white matter software phantoms, MICCAI CDMRI Workshop, Nagoya; 09/2013 [3] Peter F. Neher, Bram Stieltjes, Frederik B. Laun, Hans-Peter Meinzer, and Klaus H. Fritzsche: Fiberfox: Fiberfox: A novel tool to generate software phantoms of complex fiber geometries, ISMRM, Salt Lake City; 04/2013 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFieldmapGeneratorViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFieldmapGeneratorViewUserManual.dox new file mode 100644 index 0000000000..ae16bdf3ab --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFieldmapGeneratorViewUserManual.dox @@ -0,0 +1,16 @@ +/** +\page org_mitk_views_fieldmapgenerator Fieldmap Generator View + +This view allows the creation of artificial frequency maps used by Fiberfox to introduce distortions into diffusion weighted images. The generated images can contain a linear frequency gradient and/or multiple 3D gaussian shaped field inhomogeneities. + +Example: +\li Select a reference image with the combo box. The generated fieldmap will feature the same geometry as the selected image. +\li Move the crosshair to the any position in the image and click "Place Field Source". +\li A position marker will appear in the render windows and in the datamanager, which indicates the position of a 3D gaussian field distortion that will be introduced upon clicking "Generate Fieldmap". +\li The strength and variance of the placed sources can be modified by selecting the corresponding data node in the data manager and adjusting the parameters in the lower part of the view (below "Edit Selected Source"). +\li To introduce an (additional) linear frequency gradient, specify the gradient below "Add Gradient". +\li To finally generate the fieldmap, press "Generate Fieldmap". + +\image html fieldmapGenerator.png The Fieldmap Generator View. The render window shows a diffusion weighted image of the brain superimposed by a frequency map with two 3D gaussian field inhomogeneities (red). + +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox index 8424ea110f..4bd210e205 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkGibbsTrackingViewUserManual.dox @@ -1,44 +1,44 @@ /** \page org_mitk_views_gibbstracking Gibbs Tracking View This view provides the user interface for the Gibbs Tracking algorithm, a global fiber tracking algorithm, originally proposed by Reisert et.al. [1]. Available sections: - \ref QmitkGibbsTrackingUserManualInputData - \ref QmitkGibbsTrackingUserManualParameters - \ref QmitkGibbsTrackingUserManualTrackingSurveillance - \ref QmitkGibbsTrackingUserManualReferences \image html gibbstrackingview.png The Gibbs Tracking View \section QmitkGibbsTrackingUserManualInputData Input Data Mandatory Input: -\li One Q-Ball image selected in the datamanager +\li One Q-Ball or tensor image selected in the datamanager Optional Input: \li Mask Image: Float image used as probability mask for the generation of fiber segments. Usually used as binary brain mask to reduce the searchspace of the algorithm and to avoid fibers resulting from noise outside of the brain. \section QmitkGibbsTrackingUserManualParameters Q-Ball Reconstruction \li Number of iterations: More iterations causes the algorithm to be more stable but also to take longer to finish the tracking. Rcommended: 10⁷-10⁹ iterations. \li Particle length/width/weight controlling the contribution of each particle to the model M \li Start and end temperature controlling how fast the process reaches a stable state. (usually no change needed) \li Weighting between the internal (affinity of the model to long and straigt fibers) and external energy (affinity of the model towards the data). (usually no change needed). \li Minimum fiber length constraint (in mm). Shorter fibers are discarded after the tracking. The automatic selection of parameters for the particle length/width and weight are determined directly from the input image using information about the image spacing and GFA. \image html gibbstrackingviewadvanced.png Advanced Tracking Parameters \section QmitkGibbsTrackingUserManualTrackingSurveillance Surveilance of the tracking process -Once started, the tracking can be monitored via the textual output that informs about the tracking progress and several stats of the current state of the algorithm. +Once started, the tracking can be monitored via the textual output that informs about the tracking progress and several stats of the current state of the algorithm. If enabled, the intermediate tracking results are displayed in the renderwindows each second. This live visualization should usually be disabled for performance reasons. It can be turned on and off during the tracking process via the according checkbox. The button next to this checkbox allows the visualization of only the next iteration step. \section QmitkGibbsTrackingUserManualReferences References [1] Reisert, M., Mader, I., Anastasopoulos, C., Weigel, M., Schnell, S., Kiselev, V.: Global fiber reconstruction becomes practical. Neuroimage 54 (2011) 955-962 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox index 41cb736484..812a4aad90 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox @@ -1,51 +1,49 @@ /** \page org_mitk_views_odfmaximaextraction Peak Extraction View This view provides the user interface to extract the peaks of tensors and the spherical harmonic representation of Q-Balls. Available sections: - \ref OdfMaxUserManualInputData - \ref OdfMaxUserManualOutputData - \ref OdfMaxUserManualMethods - \ref OdfMaxUserManualParameters - \ref OdfMaxUserManualReferences -\image html peakextractionview.png Peak Extraction View - \section OdfMaxUserManualInputData Input Data Mandatory Input: \li DTI image or image containing the spherical harmonic coefficients. The SH coefficient images can be obtain from the Q-Ball reconstruction view by enabling the checkbox in the advanced options. Optional Input: \li Binary mask to define the extraction area. \section OdfMaxUserManualOutputData Output Data \li Vector field: 3D representation of the resulting peaks. Only for visualization purposes (the peaks are scaled additionally to the specified normalization to improve the visualization)! \li #Directions per Voxel: Image containing the number of extracted peaks per voxel as image value. \li Direction Images: One image for each of the extracted peaks per voxel. Each voxel contains one direction vector as image value. Use this output for evaluation purposes of the extracted peaks. \section OdfMaxUserManualMethods Peak Extraction Methods \li If a tensor image is used as input, the output is simply the largest eigenvector of each voxel. \li The finite differences extraction uses a higly sampled version of the image ODFs, extracts all local maxima and clusters the resulting directions that point in a similar direction. \li For details about the analytical method (experimental) please refer to [1]. -\image html peaks.png Peaks extracted from the ODFs of a crossing Phantom using the finite differences method. +\image html crossingmaxima.png Peaks of a fiber crossing extracted using finite differences method. \section OdfMaxUserManualParameters Input Parameters \li Vector normalization method (no normalization, maximum normalization of the vecors of one voxel and independent normalization of each vecor). \li SH Order: Specify the order of the spherical harmonic coefficients. \li Maximum number of peaks to extract. If more peaks are found only the largest are kept. \li Threshold to discard small peaks. Value relative to the largest peak of the respective voxel. \li Absolute threshold on the peak size. To evaluate this threshold the peaks are additionally weighted by their GFA (low GFA voxels are more likely to be discarded). This threshold is only used for the finite differences extraction method. \section OdfMaxUserManualReferences References [1] Aganj et al. Proceedings of the Thirteenth International Conference on Medical Image Computing and Computer Assisted Intervention 2010 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox index e6fd7bdd84..8dbd1e69db 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkStreamlineTrackingViewUserManual.dox @@ -1,40 +1,41 @@ /** \page org_mitk_views_streamlinetracking Streamline Tracking View -This view provides the user interface for basic streamline fiber tractography on diffusion tensor images. FACT and TEND tracking methods are available. +This view provides the user interface for basic streamline fiber tractography on diffusion tensor images (single and multi-tensor tracking). FACT and TEND tracking methods are available. Available sections: - \ref StrTrackUserManualInputData - \ref StrTrackUserManualParameters - \ref StrTrackUserManualReferences \image html streamlinetrackingview.png Streamline Tracking View \section StrTrackUserManualInputData Input Data Mandatory Input: -\li One DTI Image image selected in the datamanager +\li One or multiple DTI Image images selected in the datamanager. Optional Input: +\li FA image used to determine streamline termination. If no image is specified, the FA image is automatically calculated from the input tensor images. If multiple tensor images are used as input, it is recommended to provide such an FA image since the FA maps calculated from the individual input tensor images can not provide a suitable termination criterion. \li Binary mask used to define the seed voxels. If no seed mask is specified, the whole image volume is seeded. \li Binary mask used to constrain the generated streamlines. Streamlines can not leave the mask area. \section StrTrackUserManualParameters Input Parameters \li FA Threshold: If the streamline reaches a position with an FA value lower than the speciefied threshold, it is not tracked any further. \li Min. Curvature Radius: If the streamline has a higher curvature than specified, it is not tracked any further. It is defined as the radius of the circle specified by three successive streamline positions. \li f and g values to balance between FACT [1] and TEND [2,3] tracking. For further information please refer to [2,3] \li Step Size: The algorithm proceeds along the streamline with a fixed stepsize. Default is 0.1*minSpacing. \li Min. Tract Length: Shorter fibers are discarded. \li Seeds per voxel: If set to 1, the seed is defined as the voxel center. If > 1 the seeds are distributet randomly inside the voxel. -By default the image values are not interpolated. Enable according checkbox to use trilinear interpolation of the tensors as well as the FA values. Keep in mind that in the noninterpolated case, the TEND term is only applied once per voxel. In the interpolated case the TEND term is applied at each integration step which results in much higher curvatures and has to be compensated by an according choice of f and g. +By default the image values are not interpolated. Enable corresponding checkbox to use trilinear interpolation of the tensors as well as the FA values. Keep in mind that in the noninterpolated case, the TEND term is only applied once per voxel. In the interpolated case the TEND term is applied at each integration step which results in much higher curvatures and has to be compensated by an according choice of f and g. \section StrTrackUserManualReferences References [1] Mori et al. Annals Neurology 1999\n [2] Weinstein et al. Proceedings of IEEE Visualization 1999\n [3] Lazar et al. Human Brain Mapping 2003\n */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/crossingmaxima.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/crossingmaxima.png new file mode 100644 index 0000000000..699b6f7f1b Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/crossingmaxima.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fiberprocessing.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fiberprocessing.png deleted file mode 100644 index bc8e88b655..0000000000 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fiberprocessing.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fieldmapGenerator.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fieldmapGenerator.png new file mode 100644 index 0000000000..b7fa09ea61 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/fieldmapGenerator.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peakextractionview.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peakextractionview.png deleted file mode 100644 index 6ad1211464..0000000000 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peakextractionview.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peaks.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peaks.png deleted file mode 100644 index 41afdf8b59..0000000000 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/peaks.png and /dev/null differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/streamlinetrackingview.png b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/streamlinetrackingview.png index a673154547..f93c8a0bb4 100644 Binary files a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/streamlinetrackingview.png and b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/streamlinetrackingview.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h index b0544e16f6..76c0ad0c49 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberExtractionView.h @@ -1,175 +1,175 @@ /*=================================================================== 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 QmitkFiberExtractionView_h #define QmitkFiberExtractionView_h #include #include "ui_QmitkFiberExtractionViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! -\brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles, generate images from the selected bundle and much more. +\brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles and much more. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberExtractionView : public QmitkFunctionality { // 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: typedef itk::Image< unsigned char, 3 > itkUCharImageType; static const std::string VIEW_ID; QmitkFiberExtractionView(); virtual ~QmitkFiberExtractionView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void OnDrawCircle(); ///< add circle interactors etc. void OnDrawPolygon(); ///< add circle interactors etc. void DoFiberExtraction(); ///< Extract fibers from selected bundle void GenerateAndComposite(); void GenerateOrComposite(); void GenerateNotComposite(); void DoRemoveOutsideMask(); void DoRemoveInsideMask(); void JoinBundles(); ///< merge selected fiber bundles void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection. void GenerateRoiImage(); ///< generate binary image of selected planar figures. void ExtractPassingMask(); ///< extract all fibers passing the selected surface mesh void ExtractEndingInMask(); ///< extract all fibers passing the selected surface mesh virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = NULL, mitk::BaseProperty *property = NULL ); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberExtractionViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** Connection from VTK to ITK */ template void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template < typename TPixel, unsigned int VImageDimension > void InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ); template < typename TPixel, unsigned int VImageDimension > void InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex ); void GenerateStats(); ///< generate statistics of selected fiber bundles void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection int m_CircleCounter; ///< used for data node naming int m_PolygonCounter; ///< used for data node naming std::vector m_SelectedFB; ///< selected fiber bundle nodes std::vector m_SelectedPF; ///< selected planar figure nodes std::vector m_SelectedSurfaces; mitk::Image::Pointer m_SelectedImage; mitk::Image::Pointer m_InternalImage; mitk::PlanarFigure::Pointer m_PlanarFigure; itkUCharImageType::Pointer m_InternalImageMask3D; itkUCharImageType::Pointer m_PlanarFigureImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations mitk::DataNode::Pointer m_MaskImageNode; mitk::DataNode::Pointer m_LastAddedPf; void AddCompositeToDatastorage(mitk::PlanarFigureComposite::Pointer, mitk::DataNode::Pointer); void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int ); void CompositeExtraction(mitk::DataNode::Pointer node, mitk::Image* image); mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute); mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h index b9a9aa22dd..cccc42e14a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberProcessingView.h @@ -1,154 +1,154 @@ /*=================================================================== 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 QmitkFiberProcessingView_h #define QmitkFiberProcessingView_h #include #include "ui_QmitkFiberProcessingViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! -\brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, join and subtract bundles, generate images from the selected bundle and much more. +\brief View to process fiber bundles. Supplies methods to generate images from the selected bundle and much more. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFiberProcessingView : public QmitkFunctionality { // 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: typedef itk::Image< unsigned char, 3 > itkUCharImageType; static const std::string VIEW_ID; QmitkFiberProcessingView(); virtual ~QmitkFiberProcessingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); virtual void Activated(); protected slots: void PruneBundle(); ///< remove too short/too long fibers void MirrorFibers(); ///< mirror bundle on the specified plane void ProcessSelectedBundles(); ///< start selected operation on fiber bundle (e.g. tract density image generation) void ResampleSelectedBundles(); ///< smooth fiber bundle using the specified number of sampling points per cm. void DoImageColorCoding(); ///< color fibers by selected scalar image void ApplyCurvatureThreshold(); ///< remove/split fibers with a too high curvature threshold protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFiberProcessingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** Connection from VTK to ITK */ template void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer) { importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback()); importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback()); importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback()); importer->SetSpacingCallback(exporter->GetSpacingCallback()); importer->SetOriginCallback(exporter->GetOriginCallback()); importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback()); importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback()); importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback()); importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback()); importer->SetDataExtentCallback(exporter->GetDataExtentCallback()); importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback()); importer->SetCallbackUserData(exporter->GetCallbackUserData()); } template < typename TPixel, unsigned int VImageDimension > void InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName ); template < typename TPixel, unsigned int VImageDimension > void InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::Geometry3D* planegeo3D, int additionalIndex ); void GenerateStats(); ///< generate statistics of selected fiber bundles void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection std::vector m_SelectedFB; ///< selected fiber bundle nodes mitk::Image::Pointer m_SelectedImage; float m_UpsamplingFactor; ///< upsampling factor for all image generations std::vector m_SelectedSurfaces; mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundleX::Pointer fib, bool binary, bool absolute); mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundleX::Pointer fib); mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundleX::Pointer fib); }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED 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 ce5da412c9..894a65f467 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,2343 +1,2229 @@ /*=================================================================== 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 "usModuleRegistry.h" #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ switch (m_FilterType) { case 0: m_View->m_TractsToDwiFilter->Update(); break; case 1: m_View->m_ArtifactsToDwiFilter->Update(); break; } } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImage( NULL ) , m_OutputPath("") , m_Worker(this) , m_ThreadIsRunning(false) { m_Worker.moveToThread(&m_Thread); connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run())); connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread())); connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread())); m_SimulationTimer = new QTimer(this); } void QmitkFiberfoxView::KillThread() { MITK_INFO << "Aborting DWI simulation."; switch (m_Worker.m_FilterType) { case 0: m_TractsToDwiFilter->SetAbortGenerateData(true); break; case 1: m_ArtifactsToDwiFilter->SetAbortGenerateData(true); break; } } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); - m_ImageGenParametersBackup = m_ImageGenParameters; m_Controls->m_AbortSimulationButton->setVisible(true); m_Controls->m_GenerateImageButton->setVisible(false); m_Controls->m_SimulationStatusText->setVisible(true); m_ThreadIsRunning = true; } void QmitkFiberfoxView::AfterThread() { UpdateSimulationStatus(); m_SimulationTimer->stop(); m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_GenerateImageButton->setVisible(true); //m_Controls->m_SimulationStatusText->setVisible(false); m_ThreadIsRunning = false; + FiberfoxParameters parameters; mitk::DiffusionImage::Pointer mitkImage = mitk::DiffusionImage::New(); switch (m_Worker.m_FilterType) { case 0: { if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } + parameters = m_TractsToDwiFilter->GetParameters(); + mitkImage->SetVectorImage( m_TractsToDwiFilter->GetOutput() ); - mitkImage->SetB_Value(m_ImageGenParametersBackup.m_Bvalue); - mitkImage->SetDirections(m_ImageGenParametersBackup.m_GradientDirections); + mitkImage->SetB_Value(parameters.m_Bvalue); + mitkImage->SetDirections(parameters.GetGradientDirections()); mitkImage->InitializeFromVectorImage(); - m_ImageGenParametersBackup.m_ResultNode->SetData( mitkImage ); + parameters.m_ResultNode->SetData( mitkImage ); - m_ImageGenParametersBackup.m_ResultNode->SetName(m_ImageGenParametersBackup.m_ParentNode->GetName() - +"_D"+QString::number(m_ImageGenParametersBackup.m_ImageRegion.GetSize(0)).toStdString() - +"-"+QString::number(m_ImageGenParametersBackup.m_ImageRegion.GetSize(1)).toStdString() - +"-"+QString::number(m_ImageGenParametersBackup.m_ImageRegion.GetSize(2)).toStdString() - +"_S"+QString::number(m_ImageGenParametersBackup.m_ImageSpacing[0]).toStdString() - +"-"+QString::number(m_ImageGenParametersBackup.m_ImageSpacing[1]).toStdString() - +"-"+QString::number(m_ImageGenParametersBackup.m_ImageSpacing[2]).toStdString() - +"_b"+QString::number(m_ImageGenParametersBackup.m_Bvalue).toStdString() - +"_"+m_ImageGenParametersBackup.m_SignalModelString - +m_ImageGenParametersBackup.m_ArtifactModelString); + parameters.m_ResultNode->SetName(parameters.m_ParentNode->GetName() + +"_D"+QString::number(parameters.m_ImageRegion.GetSize(0)).toStdString() + +"-"+QString::number(parameters.m_ImageRegion.GetSize(1)).toStdString() + +"-"+QString::number(parameters.m_ImageRegion.GetSize(2)).toStdString() + +"_S"+QString::number(parameters.m_ImageSpacing[0]).toStdString() + +"-"+QString::number(parameters.m_ImageSpacing[1]).toStdString() + +"-"+QString::number(parameters.m_ImageSpacing[2]).toStdString() + +"_b"+QString::number(parameters.m_Bvalue).toStdString() + +"_"+parameters.m_SignalModelString + +parameters.m_ArtifactModelString); - GetDataStorage()->Add(m_ImageGenParametersBackup.m_ResultNode, m_ImageGenParametersBackup.m_ParentNode); + GetDataStorage()->Add(parameters.m_ResultNode, parameters.m_ParentNode); - m_ImageGenParametersBackup.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); + parameters.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_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_ImageGenParametersBackup.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); - GetDataStorage()->Add(node, m_ImageGenParametersBackup.m_ParentNode); + node->SetName(parameters.m_ParentNode->GetName()+"_CompartmentVolume-"+QString::number(k).toStdString()); + GetDataStorage()->Add(node, parameters.m_ParentNode); } } + m_TractsToDwiFilter = NULL; break; } case 1: { if (m_ArtifactsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } - mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(m_ImageGenParametersBackup.m_ParentNode->GetData()); + parameters = m_ArtifactsToDwiFilter->GetParameters().CopyParameters(); + + mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(parameters.m_ParentNode->GetData()); mitkImage = mitk::DiffusionImage::New(); mitkImage->SetVectorImage( m_ArtifactsToDwiFilter->GetOutput() ); mitkImage->SetB_Value(diffImg->GetB_Value()); mitkImage->SetDirections(diffImg->GetDirections()); mitkImage->InitializeFromVectorImage(); - m_ImageGenParametersBackup.m_ResultNode->SetData( mitkImage ); - m_ImageGenParametersBackup.m_ResultNode->SetName(m_ImageGenParametersBackup.m_ParentNode->GetName()+m_ImageGenParameters.m_ArtifactModelString); - GetDataStorage()->Add(m_ImageGenParametersBackup.m_ResultNode, m_ImageGenParametersBackup.m_ParentNode); + parameters.m_ResultNode->SetData( mitkImage ); + parameters.m_ResultNode->SetName(parameters.m_ParentNode->GetName()+parameters.m_ArtifactModelString); + GetDataStorage()->Add(parameters.m_ResultNode, parameters.m_ParentNode); + m_ArtifactsToDwiFilter = NULL; break; } } - mitk::BaseData::Pointer basedata = m_ImageGenParametersBackup.m_ResultNode->GetData(); + mitk::BaseData::Pointer basedata = parameters.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } - if (!m_ImageGenParametersBackup.m_OutputPath.empty()) + if (!parameters.m_OutputPath.empty()) { try{ QString status("Saving output image to "); - status += QString(m_ImageGenParametersBackup.m_OutputPath.c_str()); - status += m_ImageGenParametersBackup.m_ResultNode->GetName().c_str(); + status += QString(parameters.m_OutputPath.c_str()); + status += parameters.m_ResultNode->GetName().c_str(); status += ".dwi"; m_Controls->m_SimulationStatusText->append(status); mitk::NrrdDiffusionImageWriter::Pointer writer = NrrdDiffusionImageWriter::New(); - writer->SetFileName(m_ImageGenParametersBackup.m_OutputPath+m_ImageGenParametersBackup.m_ResultNode->GetName()+".dwi"); + writer->SetFileName(parameters.m_OutputPath+parameters.m_ResultNode->GetName()+".dwi"); writer->SetInput(mitkImage); writer->Update(); m_Controls->m_SimulationStatusText->append("File saved successfully."); } catch (itk::ExceptionObject &e) { QString status("Exception during DWI writing: "); status += e.GetDescription(); m_Controls->m_SimulationStatusText->append(status); } catch (...) { m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!"); } } - m_ImageGenParameters.m_FrequencyMap = NULL; - m_ImageGenParametersBackup.m_FrequencyMap = NULL; - m_TractsToDwiFilter = NULL; + parameters.m_FrequencyMap = NULL; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText; switch (m_Worker.m_FilterType) { case 0: statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); break; case 1: statusText = QString(m_ArtifactsToDwiFilter->GetStatusText().c_str()); break; } if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); statusText = "
"+statusText+"
"; m_Controls->m_SimulationStatusText->setText(statusText); } } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { delete m_SimulationTimer; } 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_NoiseFrame->setVisible(false); m_Controls->m_GhostFrame->setVisible(false); m_Controls->m_DistortionsFrame->setVisible(false); m_Controls->m_EddyFrame->setVisible(false); m_Controls->m_SpikeFrame->setVisible(false); m_Controls->m_AliasingFrame->setVisible(false); m_Controls->m_MotionArtifactFrame->setVisible(false); m_ParameterFile = QDir::currentPath()+"/param.ffp"; m_Controls->m_AbortSimulationButton->setVisible(false); m_Controls->m_SimulationStatusText->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( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) ); connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread())); 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_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_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int))); connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int))); connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(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())); connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath())); } } -void QmitkFiberfoxView::UpdateImageParameters() +template< class ScalarType > +FiberfoxParameters< ScalarType > QmitkFiberfoxView::UpdateImageParameters() { - m_ImageGenParameters.m_NonFiberModelList.clear(); - m_ImageGenParameters.m_FiberModelList.clear(); - m_ImageGenParameters.m_SignalModelString = ""; - m_ImageGenParameters.m_ArtifactModelString = ""; - m_ImageGenParameters.m_ResultNode = mitk::DataNode::New(); - m_ImageGenParameters.m_FrequencyMap = NULL; - m_ImageGenParameters.m_GradientDirections.clear(); - m_ImageGenParameters.m_Spikes = 0; - m_ImageGenParameters.m_SpikeAmplitude = 1; - m_ImageGenParameters.m_Wrap = 1; - m_ImageGenParameters.m_OutputPath = m_OutputPath; + FiberfoxParameters< ScalarType > parameters; + parameters.m_OutputPath = m_OutputPath; + parameters.m_MaskImage = m_ItkMaskImage; if (m_SelectedDWI.IsNotNull()) // use parameters of selected DWI { mitk::DiffusionImage::Pointer dwi = dynamic_cast*>(m_SelectedDWI->GetData()); - m_ImageGenParameters.m_ImageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); - m_ImageGenParameters.m_ImageSpacing = dwi->GetVectorImage()->GetSpacing(); - m_ImageGenParameters.m_ImageOrigin = dwi->GetVectorImage()->GetOrigin(); - m_ImageGenParameters.m_ImageDirection = dwi->GetVectorImage()->GetDirection(); - m_ImageGenParameters.m_Bvalue = dwi->GetB_Value(); - mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = dwi->GetDirections(); - - m_ImageGenParameters.m_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.m_GradientDirections.push_back(g); - if (dirs->at(i).magnitude()>0.0001) - m_ImageGenParameters.m_NumGradients++; - } + parameters.m_ImageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); + parameters.m_ImageSpacing = dwi->GetVectorImage()->GetSpacing(); + parameters.m_ImageOrigin = dwi->GetVectorImage()->GetOrigin(); + parameters.m_ImageDirection = dwi->GetVectorImage()->GetDirection(); + parameters.m_Bvalue = dwi->GetB_Value(); + parameters.SetGradienDirections(dwi->GetDirections()); } 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.m_ImageRegion = itkImg->GetLargestPossibleRegion(); - m_ImageGenParameters.m_ImageSpacing = itkImg->GetSpacing(); - m_ImageGenParameters.m_ImageOrigin = itkImg->GetOrigin(); - m_ImageGenParameters.m_ImageDirection = itkImg->GetDirection(); - - m_ImageGenParameters.m_NumGradients = m_Controls->m_NumGradientsBox->value(); - m_ImageGenParameters.m_GradientDirections = GenerateHalfShell(m_Controls->m_NumGradientsBox->value()); - m_ImageGenParameters.m_Bvalue = m_Controls->m_BvalueBox->value(); + parameters.m_ImageRegion = itkImg->GetLargestPossibleRegion(); + parameters.m_ImageSpacing = itkImg->GetSpacing(); + parameters.m_ImageOrigin = itkImg->GetOrigin(); + parameters.m_ImageDirection = itkImg->GetDirection(); + parameters.SetNumWeightedGradients(m_Controls->m_NumGradientsBox->value()); + parameters.m_Bvalue = m_Controls->m_BvalueBox->value(); } else // use GUI parameters { - m_ImageGenParameters.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); - m_ImageGenParameters.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); - m_ImageGenParameters.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); - m_ImageGenParameters.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); - m_ImageGenParameters.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); - m_ImageGenParameters.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); - m_ImageGenParameters.m_ImageOrigin[0] = m_ImageGenParameters.m_ImageSpacing[0]/2; - m_ImageGenParameters.m_ImageOrigin[1] = m_ImageGenParameters.m_ImageSpacing[1]/2; - m_ImageGenParameters.m_ImageOrigin[2] = m_ImageGenParameters.m_ImageSpacing[2]/2; - m_ImageGenParameters.m_ImageDirection.SetIdentity(); - - m_ImageGenParameters.m_NumGradients = m_Controls->m_NumGradientsBox->value(); - m_ImageGenParameters.m_GradientDirections = GenerateHalfShell(m_Controls->m_NumGradientsBox->value());; - m_ImageGenParameters.m_Bvalue = m_Controls->m_BvalueBox->value(); + parameters.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); + parameters.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); + parameters.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); + parameters.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); + parameters.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); + parameters.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); + parameters.m_ImageOrigin[0] = parameters.m_ImageSpacing[0]/2; + parameters.m_ImageOrigin[1] = parameters.m_ImageSpacing[1]/2; + parameters.m_ImageOrigin[2] = parameters.m_ImageSpacing[2]/2; + parameters.m_ImageDirection.SetIdentity(); + parameters.SetNumWeightedGradients(m_Controls->m_NumGradientsBox->value()); + parameters.m_Bvalue = m_Controls->m_BvalueBox->value(); + parameters.GenerateGradientHalfShell(); } // signal relaxation - m_ImageGenParameters.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); - if (m_ImageGenParameters.m_DoSimulateRelaxation && m_SelectedBundles.size()>0 ) - m_ImageGenParameters.m_ArtifactModelString += "_RELAX"; + parameters.m_DoSimulateRelaxation = m_Controls->m_RelaxationBox->isChecked(); + if (parameters.m_DoSimulateRelaxation && m_SelectedBundles.size()>0 ) + parameters.m_ArtifactModelString += "_RELAX"; // N/2 ghosts if (m_Controls->m_AddGhosts->isChecked()) { - m_ImageGenParameters.m_ArtifactModelString += "_GHOST"; - m_ImageGenParameters.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(m_ImageGenParameters.m_KspaceLineOffset)); + parameters.m_ArtifactModelString += "_GHOST"; + parameters.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); + parameters.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_KspaceLineOffset)); } else - m_ImageGenParameters.m_KspaceLineOffset = 0; + parameters.m_KspaceLineOffset = 0; // Aliasing if (m_Controls->m_AddAliasing->isChecked()) { - m_ImageGenParameters.m_ArtifactModelString += "_ALIASING"; - m_ImageGenParameters.m_Wrap = (100-m_Controls->m_WrapBox->value())/100; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); + parameters.m_ArtifactModelString += "_ALIASING"; + parameters.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; + parameters.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Motion - m_ImageGenParameters.m_DoAddMotion = m_Controls->m_AddMotion->isChecked(); - m_ImageGenParameters.m_RandomMotion = m_Controls->m_RandomMotion->isChecked(); - m_ImageGenParameters.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); - m_ImageGenParameters.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); - m_ImageGenParameters.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); - m_ImageGenParameters.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); - m_ImageGenParameters.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); - m_ImageGenParameters.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); + parameters.m_DoAddMotion = m_Controls->m_AddMotion->isChecked(); + parameters.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); + parameters.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); + parameters.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); + parameters.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); + parameters.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); + parameters.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); + parameters.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); if ( m_Controls->m_AddMotion->isChecked() && m_SelectedBundles.size()>0 ) { - m_ImageGenParameters.m_ArtifactModelString += "_MOTION"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(m_ImageGenParameters.m_RandomMotion)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(m_ImageGenParameters.m_Translation[0])); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(m_ImageGenParameters.m_Translation[1])); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(m_ImageGenParameters.m_Translation[2])); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(m_ImageGenParameters.m_Rotation[0])); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(m_ImageGenParameters.m_Rotation[1])); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(m_ImageGenParameters.m_Rotation[2])); + parameters.m_ArtifactModelString += "_MOTION"; + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_DoRandomizeMotion)); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_Translation[0])); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_Translation[1])); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_Translation[2])); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_Rotation[0])); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_Rotation[1])); + parameters.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_Rotation[2])); } // other imaging parameters - m_ImageGenParameters.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); - m_ImageGenParameters.m_tInhom = m_Controls->m_T2starBox->value(); - m_ImageGenParameters.m_tEcho = m_Controls->m_TEbox->value(); - m_ImageGenParameters.m_Repetitions = m_Controls->m_RepetitionsBox->value(); - m_ImageGenParameters.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); - m_ImageGenParameters.m_InterpolationShrink = m_Controls->m_InterpolationShrink->value(); - m_ImageGenParameters.m_AxonRadius = m_Controls->m_FiberRadius->value(); - m_ImageGenParameters.m_SignalScale = m_Controls->m_SignalScaleBox->value(); + parameters.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); + parameters.m_tInhom = m_Controls->m_T2starBox->value(); + parameters.m_tEcho = m_Controls->m_TEbox->value(); + parameters.m_Repetitions = m_Controls->m_RepetitionsBox->value(); + parameters.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); + parameters.m_AxonRadius = m_Controls->m_FiberRadius->value(); + parameters.m_SignalScale = m_Controls->m_SignalScaleBox->value(); if (m_Controls->m_AddSpikes->isChecked()) { - m_ImageGenParameters.m_Spikes = m_Controls->m_SpikeNumBox->value(); - m_ImageGenParameters.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); - m_ImageGenParameters.m_ArtifactModelString += "_SPIKES"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(m_ImageGenParameters.m_Spikes)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(m_ImageGenParameters.m_SpikeAmplitude)); + parameters.m_Spikes = m_Controls->m_SpikeNumBox->value(); + parameters.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); + parameters.m_ArtifactModelString += "_SPIKES"; + parameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_Spikes)); + parameters.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SpikeAmplitude)); } // adjust echo time if needed - if ( m_ImageGenParameters.m_tEcho < m_ImageGenParameters.m_ImageRegion.GetSize(1)*m_ImageGenParameters.m_tLine ) + if ( parameters.m_tEcho < parameters.m_ImageRegion.GetSize(1)*parameters.m_tLine ) { - this->m_Controls->m_TEbox->setValue( m_ImageGenParameters.m_ImageRegion.GetSize(1)*m_ImageGenParameters.m_tLine ); - m_ImageGenParameters.m_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.m_tEcho)+" ms"); + this->m_Controls->m_TEbox->setValue( parameters.m_ImageRegion.GetSize(1)*parameters.m_tLine ); + parameters.m_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(parameters.m_tEcho)+" ms"); } // rician noise if (m_Controls->m_AddNoise->isChecked()) { - if (m_ImageGenParameters.m_NoiseModel!=NULL) - delete m_ImageGenParameters.m_NoiseModel; - if (m_ImageGenParameters.m_NoiseModelShort!=NULL) - delete m_ImageGenParameters.m_NoiseModelShort; - double noiseVariance = m_Controls->m_NoiseLevel->value(); { switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { - mitk::RicianNoiseModel* rician = new mitk::RicianNoiseModel(); - rician->SetNoiseVariance(noiseVariance); - m_ImageGenParameters.m_NoiseModel = rician; - m_ImageGenParameters.m_ArtifactModelString += "_RICIAN-"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); - break; - } - case 1: - { - mitk::ChiSquareNoiseModel* chiSquare = new mitk::ChiSquareNoiseModel(); - chiSquare->SetDOF(noiseVariance/2); - m_ImageGenParameters.m_NoiseModel = chiSquare; - m_ImageGenParameters.m_ArtifactModelString += "_CHISQUARED-"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); - break; - } - default: - { - mitk::RicianNoiseModel* rician = new mitk::RicianNoiseModel(); - rician->SetNoiseVariance(noiseVariance); - m_ImageGenParameters.m_NoiseModel = rician; - m_ImageGenParameters.m_ArtifactModelString += "_RICIAN-"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); - } - } - } - { - switch (m_Controls->m_NoiseDistributionBox->currentIndex()) - { - case 0: - { - mitk::RicianNoiseModel* rician = new mitk::RicianNoiseModel(); - rician->SetNoiseVariance(noiseVariance); - m_ImageGenParameters.m_NoiseModelShort = rician; + parameters.m_NoiseModel = new mitk::RicianNoiseModel(); + parameters.m_ArtifactModelString += "_RICIAN-"; + parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); break; } case 1: { - mitk::ChiSquareNoiseModel* chiSquare = new mitk::ChiSquareNoiseModel(); - chiSquare->SetDOF(noiseVariance/2); - m_ImageGenParameters.m_NoiseModelShort = chiSquare; + parameters.m_NoiseModel = new mitk::ChiSquareNoiseModel(); + parameters.m_ArtifactModelString += "_CHISQUARED-"; + parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); break; } default: { - mitk::RicianNoiseModel* rician = new mitk::RicianNoiseModel(); - rician->SetNoiseVariance(noiseVariance); - m_ImageGenParameters.m_NoiseModelShort = rician; + parameters.m_NoiseModel = new mitk::RicianNoiseModel(); + parameters.m_ArtifactModelString += "_RICIAN-"; + parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); } } } - m_ImageGenParameters.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); - } - else - { - if (m_ImageGenParameters.m_NoiseModel!=NULL) - { - delete m_ImageGenParameters.m_NoiseModel; - m_ImageGenParameters.m_NoiseModel = NULL; - } - if (m_ImageGenParameters.m_NoiseModelShort!=NULL) - { - delete m_ImageGenParameters.m_NoiseModelShort; - m_ImageGenParameters.m_NoiseModelShort = NULL; - } + parameters.m_NoiseModel->SetNoiseVariance(noiseVariance); + parameters.m_ArtifactModelString += QString::number(noiseVariance).toStdString(); + parameters.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); } // gibbs ringing - m_ImageGenParameters.m_AddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); + parameters.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); - m_ImageGenParameters.m_ArtifactModelString += "_RINGING"; + parameters.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); + parameters.m_ArtifactModelString += "_RINGING"; } // adjusting line readout time to the adapted image size needed for the DFT - int y = m_ImageGenParameters.m_ImageRegion.GetSize(1); + int y = parameters.m_ImageRegion.GetSize(1); if ( y%2 == 1 ) y += 1; - if ( y>m_ImageGenParameters.m_ImageRegion.GetSize(1) ) - m_ImageGenParameters.m_tLine *= (double)m_ImageGenParameters.m_ImageRegion.GetSize(1)/y; + if ( y>parameters.m_ImageRegion.GetSize(1) ) + parameters.m_tLine *= (double)parameters.m_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.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && - m_ImageGenParameters.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && - m_ImageGenParameters.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) + if (parameters.m_ImageRegion.GetSize(0)==itkImg->GetLargestPossibleRegion().GetSize(0) && + parameters.m_ImageRegion.GetSize(1)==itkImg->GetLargestPossibleRegion().GetSize(1) && + parameters.m_ImageRegion.GetSize(2)==itkImg->GetLargestPossibleRegion().GetSize(2)) { - m_ImageGenParameters.m_FrequencyMap = itkImg; - m_ImageGenParameters.m_ArtifactModelString += "_DISTORTED"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); + parameters.m_FrequencyMap = itkImg; + parameters.m_ArtifactModelString += "_DISTORTED"; + parameters.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } } - m_ImageGenParameters.m_DoSimulateEddyCurrents = m_Controls->m_AddEddy->isChecked(); - m_ImageGenParameters.m_EddyStrength = 0; + parameters.m_EddyStrength = 0; if (m_Controls->m_AddEddy->isChecked()) { - m_ImageGenParameters.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); - m_ImageGenParameters.m_ArtifactModelString += "_EDDY"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(m_ImageGenParameters.m_EddyStrength)); + parameters.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); + parameters.m_ArtifactModelString += "_EDDY"; + parameters.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_EddyStrength)); } // signal models - m_ImageGenParameters.m_Comp3Weight = 1; - m_ImageGenParameters.m_Comp4Weight = 0; + double m_Comp3Weight = 1; + double m_Comp4Weight = 0; if (m_Controls->m_Compartment4Box->currentIndex()>0) { - m_ImageGenParameters.m_Comp4Weight = m_Controls->m_Comp4FractionBox->value(); - m_ImageGenParameters.m_Comp3Weight -= m_ImageGenParameters.m_Comp4Weight; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.weight", DoubleProperty::New(m_ImageGenParameters.m_Comp3Weight)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.weight", DoubleProperty::New(m_ImageGenParameters.m_Comp4Weight)); + m_Comp4Weight = m_Controls->m_Comp4FractionBox->value(); + m_Comp3Weight -= m_Comp4Weight; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.weight", DoubleProperty::New(m_Comp3Weight)); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.weight", DoubleProperty::New(m_Comp4Weight)); } // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: - m_StickModel1.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_StickModel1.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_StickModel1.SetGradientList(parameters.GetGradientDirections()); + m_StickModel1.SetBvalue(parameters.m_Bvalue); m_StickModel1.SetDiffusivity(m_Controls->m_StickWidget1->GetD()); m_StickModel1.SetT2(m_Controls->m_StickWidget1->GetT2()); - m_ImageGenParameters.m_FiberModelList.push_back(&m_StickModel1); - m_ImageGenParameters.m_SignalModelString += "Stick"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_StickModel1.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_StickModel1); + parameters.m_SignalModelString += "Stick"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_StickModel1.GetT2()) ); break; case 1: - m_ZeppelinModel1.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_ZeppelinModel1.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_ZeppelinModel1.SetGradientList(parameters.GetGradientDirections()); + m_ZeppelinModel1.SetBvalue(parameters.m_Bvalue); 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.m_FiberModelList.push_back(&m_ZeppelinModel1); - m_ImageGenParameters.m_SignalModelString += "Zeppelin"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_ZeppelinModel1); + parameters.m_SignalModelString += "Zeppelin"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) ); break; case 2: - m_TensorModel1.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_TensorModel1.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_TensorModel1.SetGradientList(parameters.GetGradientDirections()); + m_TensorModel1.SetBvalue(parameters.m_Bvalue); 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.m_FiberModelList.push_back(&m_TensorModel1); - m_ImageGenParameters.m_SignalModelString += "Tensor"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(m_ZeppelinModel1.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_TensorModel1); + parameters.m_SignalModelString += "Tensor"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); + parameters.m_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.m_GradientDirections); - m_StickModel2.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_StickModel2.SetGradientList(parameters.GetGradientDirections()); + m_StickModel2.SetBvalue(parameters.m_Bvalue); m_StickModel2.SetDiffusivity(m_Controls->m_StickWidget2->GetD()); m_StickModel2.SetT2(m_Controls->m_StickWidget2->GetT2()); - m_ImageGenParameters.m_FiberModelList.push_back(&m_StickModel2); - m_ImageGenParameters.m_SignalModelString += "Stick"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_StickModel2.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_StickModel2); + parameters.m_SignalModelString += "Stick"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_StickModel2.GetT2()) ); break; case 2: - m_ZeppelinModel2.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_ZeppelinModel2.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_ZeppelinModel2.SetGradientList(parameters.GetGradientDirections()); + m_ZeppelinModel2.SetBvalue(parameters.m_Bvalue); 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.m_FiberModelList.push_back(&m_ZeppelinModel2); - m_ImageGenParameters.m_SignalModelString += "Zeppelin"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_ZeppelinModel2); + parameters.m_SignalModelString += "Zeppelin"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) ); break; case 3: - m_TensorModel2.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_TensorModel2.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_TensorModel2.SetGradientList(parameters.GetGradientDirections()); + m_TensorModel2.SetBvalue(parameters.m_Bvalue); 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.m_FiberModelList.push_back(&m_TensorModel2); - m_ImageGenParameters.m_SignalModelString += "Tensor"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(m_ZeppelinModel2.GetT2()) ); + parameters.m_FiberModelList.push_back(&m_TensorModel2); + parameters.m_SignalModelString += "Tensor"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); + parameters.m_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.m_GradientDirections); - m_BallModel1.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_BallModel1.SetGradientList(parameters.GetGradientDirections()); + m_BallModel1.SetBvalue(parameters.m_Bvalue); m_BallModel1.SetDiffusivity(m_Controls->m_BallWidget1->GetD()); m_BallModel1.SetT2(m_Controls->m_BallWidget1->GetT2()); - m_BallModel1.SetWeight(m_ImageGenParameters.m_Comp3Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_BallModel1); - m_ImageGenParameters.m_SignalModelString += "Ball"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_BallModel1.GetT2()) ); + m_BallModel1.SetWeight(m_Comp3Weight); + parameters.m_NonFiberModelList.push_back(&m_BallModel1); + parameters.m_SignalModelString += "Ball"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_BallModel1.GetT2()) ); break; case 1: - m_AstrosticksModel1.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_AstrosticksModel1.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_AstrosticksModel1.SetGradientList(parameters.GetGradientDirections()); + m_AstrosticksModel1.SetBvalue(parameters.m_Bvalue); 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.m_Comp3Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_AstrosticksModel1); - m_ImageGenParameters.m_SignalModelString += "Astrosticks"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_AstrosticksModel1.GetT2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); + m_AstrosticksModel1.SetWeight(m_Comp3Weight); + parameters.m_NonFiberModelList.push_back(&m_AstrosticksModel1); + parameters.m_SignalModelString += "Astrosticks"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_AstrosticksModel1.GetT2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; case 2: - m_DotModel1.SetGradientList(m_ImageGenParameters.m_GradientDirections); + m_DotModel1.SetGradientList(parameters.GetGradientDirections()); m_DotModel1.SetT2(m_Controls->m_DotWidget1->GetT2()); - m_DotModel1.SetWeight(m_ImageGenParameters.m_Comp3Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_DotModel1); - m_ImageGenParameters.m_SignalModelString += "Dot"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(m_DotModel1.GetT2()) ); + m_DotModel1.SetWeight(m_Comp3Weight); + parameters.m_NonFiberModelList.push_back(&m_DotModel1); + parameters.m_SignalModelString += "Dot"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); + parameters.m_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.m_GradientDirections); - m_BallModel2.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_BallModel2.SetGradientList(parameters.GetGradientDirections()); + m_BallModel2.SetBvalue(parameters.m_Bvalue); m_BallModel2.SetDiffusivity(m_Controls->m_BallWidget2->GetD()); m_BallModel2.SetT2(m_Controls->m_BallWidget2->GetT2()); - m_BallModel2.SetWeight(m_ImageGenParameters.m_Comp4Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_BallModel2); - m_ImageGenParameters.m_SignalModelString += "Ball"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_BallModel2.GetT2()) ); + m_BallModel2.SetWeight(m_Comp4Weight); + parameters.m_NonFiberModelList.push_back(&m_BallModel2); + parameters.m_SignalModelString += "Ball"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_BallModel2.GetT2()) ); break; case 2: - m_AstrosticksModel2.SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_AstrosticksModel2.SetBvalue(m_ImageGenParameters.m_Bvalue); + m_AstrosticksModel2.SetGradientList(parameters.GetGradientDirections()); + m_AstrosticksModel2.SetBvalue(parameters.m_Bvalue); 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.m_Comp4Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_AstrosticksModel2); - m_ImageGenParameters.m_SignalModelString += "Astrosticks"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_AstrosticksModel2.GetT2()) ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); + m_AstrosticksModel2.SetWeight(m_Comp4Weight); + parameters.m_NonFiberModelList.push_back(&m_AstrosticksModel2); + parameters.m_SignalModelString += "Astrosticks"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_AstrosticksModel2.GetT2()) ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); break; case 3: - m_DotModel2.SetGradientList(m_ImageGenParameters.m_GradientDirections); + m_DotModel2.SetGradientList(parameters.GetGradientDirections()); m_DotModel2.SetT2(m_Controls->m_DotWidget2->GetT2()); - m_DotModel2.SetWeight(m_ImageGenParameters.m_Comp4Weight); - m_ImageGenParameters.m_NonFiberModelList.push_back(&m_DotModel2); - m_ImageGenParameters.m_SignalModelString += "Dot"; - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_DotModel2.GetT2()) ); + m_DotModel2.SetWeight(m_Comp4Weight); + parameters.m_NonFiberModelList.push_back(&m_DotModel2); + parameters.m_SignalModelString += "Dot"; + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); + parameters.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(m_DotModel2.GetT2()) ); break; } - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.InterpolationShrink", IntProperty::New(m_ImageGenParameters.m_InterpolationShrink)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(m_ImageGenParameters.m_SignalScale)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(m_ImageGenParameters.m_AxonRadius)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(m_ImageGenParameters.m_tInhom)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(m_ImageGenParameters.m_tLine)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(m_ImageGenParameters.m_tEcho)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(m_ImageGenParameters.m_Repetitions)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(m_ImageGenParameters.m_Bvalue)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(m_ImageGenParameters.m_DoDisablePartialVolume)); - m_ImageGenParameters.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(m_ImageGenParameters.m_DoSimulateRelaxation)); - m_ImageGenParameters.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); + parameters.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalScale)); + parameters.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_AxonRadius)); + parameters.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_tInhom)); + parameters.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_tLine)); + parameters.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_tEcho)); + parameters.m_ResultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(parameters.m_Repetitions)); + parameters.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_Bvalue)); + parameters.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_DoDisablePartialVolume)); + parameters.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_DoSimulateRelaxation)); + parameters.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); + + return parameters; } void QmitkFiberfoxView::SaveParameters() { - UpdateImageParameters(); + FiberfoxParameters ffParamaters = UpdateImageParameters(); QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; if(!filename.endsWith(".ffp")) filename += ".ffp"; m_ParameterFile = filename; 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.m_Rotation.x", m_Controls->m_XrotBox->value()); parameters.put("fiberfox.fibers.m_Rotation.y", m_Controls->m_YrotBox->value()); parameters.put("fiberfox.fibers.m_Rotation.z", m_Controls->m_ZrotBox->value()); parameters.put("fiberfox.fibers.m_Translation.x", m_Controls->m_XtransBox->value()); parameters.put("fiberfox.fibers.m_Translation.y", m_Controls->m_YtransBox->value()); parameters.put("fiberfox.fibers.m_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.m_ImageRegion.GetSize(0)); - parameters.put("fiberfox.image.basic.size.y", m_ImageGenParameters.m_ImageRegion.GetSize(1)); - parameters.put("fiberfox.image.basic.size.z", m_ImageGenParameters.m_ImageRegion.GetSize(2)); - parameters.put("fiberfox.image.basic.spacing.x", m_ImageGenParameters.m_ImageSpacing[0]); - parameters.put("fiberfox.image.basic.spacing.y", m_ImageGenParameters.m_ImageSpacing[1]); - parameters.put("fiberfox.image.basic.spacing.z", m_ImageGenParameters.m_ImageSpacing[2]); - parameters.put("fiberfox.image.basic.numgradients", m_ImageGenParameters.m_NumGradients); - parameters.put("fiberfox.image.basic.bvalue", m_ImageGenParameters.m_Bvalue); + parameters.put("fiberfox.image.basic.size.x", ffParamaters.m_ImageRegion.GetSize(0)); + parameters.put("fiberfox.image.basic.size.y", ffParamaters.m_ImageRegion.GetSize(1)); + parameters.put("fiberfox.image.basic.size.z", ffParamaters.m_ImageRegion.GetSize(2)); + parameters.put("fiberfox.image.basic.spacing.x", ffParamaters.m_ImageSpacing[0]); + parameters.put("fiberfox.image.basic.spacing.y", ffParamaters.m_ImageSpacing[1]); + parameters.put("fiberfox.image.basic.spacing.z", ffParamaters.m_ImageSpacing[2]); + parameters.put("fiberfox.image.basic.numgradients", ffParamaters.GetNumWeightedVolumes()); + parameters.put("fiberfox.image.basic.bvalue", ffParamaters.m_Bvalue); parameters.put("fiberfox.image.showadvanced", m_Controls->m_AdvancedOptionsBox_2->isChecked()); - parameters.put("fiberfox.image.repetitions", m_ImageGenParameters.m_Repetitions); - parameters.put("fiberfox.image.signalScale", m_ImageGenParameters.m_SignalScale); - parameters.put("fiberfox.image.tEcho", m_ImageGenParameters.m_tEcho); + parameters.put("fiberfox.image.repetitions", ffParamaters.m_Repetitions); + parameters.put("fiberfox.image.signalScale", ffParamaters.m_SignalScale); + parameters.put("fiberfox.image.tEcho", ffParamaters.m_tEcho); parameters.put("fiberfox.image.tLine", m_Controls->m_LineReadoutTimeBox->value()); - parameters.put("fiberfox.image.tInhom", m_ImageGenParameters.m_tInhom); - parameters.put("fiberfox.image.axonRadius", m_ImageGenParameters.m_AxonRadius); - parameters.put("fiberfox.image.interpolationShrink", m_ImageGenParameters.m_InterpolationShrink); - parameters.put("fiberfox.image.doSimulateRelaxation", m_ImageGenParameters.m_DoSimulateRelaxation); - parameters.put("fiberfox.image.doDisablePartialVolume", m_ImageGenParameters.m_DoDisablePartialVolume); + parameters.put("fiberfox.image.tInhom", ffParamaters.m_tInhom); + parameters.put("fiberfox.image.axonRadius", ffParamaters.m_AxonRadius); + parameters.put("fiberfox.image.doSimulateRelaxation", ffParamaters.m_DoSimulateRelaxation); + parameters.put("fiberfox.image.doDisablePartialVolume", ffParamaters.m_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.noisedistribution", m_Controls->m_NoiseDistributionBox->currentIndex()); 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.m_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.m_EddyStrength", m_Controls->m_EddyGradientStrength->value()); parameters.put("fiberfox.image.artifacts.addringing", m_Controls->m_AddGibbsRinging->isChecked()); parameters.put("fiberfox.image.artifacts.addspikes", m_Controls->m_AddSpikes->isChecked()); parameters.put("fiberfox.image.artifacts.m_Spikesnum", m_Controls->m_SpikeNumBox->value()); parameters.put("fiberfox.image.artifacts.m_Spikesscale", m_Controls->m_SpikeScaleBox->value()); parameters.put("fiberfox.image.artifacts.addaliasing", m_Controls->m_AddAliasing->isChecked()); parameters.put("fiberfox.image.artifacts.aliasingfactor", m_Controls->m_WrapBox->value()); parameters.put("fiberfox.image.artifacts.m_DoAddMotion", m_Controls->m_AddMotion->isChecked()); parameters.put("fiberfox.image.artifacts.m_RandomMotion", m_Controls->m_RandomMotion->isChecked()); parameters.put("fiberfox.image.artifacts.m_Translation0", m_Controls->m_MaxTranslationBoxX->value()); parameters.put("fiberfox.image.artifacts.m_Translation1", m_Controls->m_MaxTranslationBoxY->value()); parameters.put("fiberfox.image.artifacts.m_Translation2", m_Controls->m_MaxTranslationBoxZ->value()); parameters.put("fiberfox.image.artifacts.m_Rotation0", m_Controls->m_MaxRotationBoxX->value()); parameters.put("fiberfox.image.artifacts.m_Rotation1", m_Controls->m_MaxRotationBoxY->value()); parameters.put("fiberfox.image.artifacts.m_Rotation2", m_Controls->m_MaxRotationBoxZ->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"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; 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_NoiseDistributionBox->setCurrentIndex(v1.second.get("artifacts.noisedistribution")); 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.m_KspaceLineOffset")); m_Controls->m_AddAliasing->setChecked(v1.second.get("artifacts.addaliasing")); m_Controls->m_WrapBox->setValue(v1.second.get("artifacts.aliasingfactor")); m_Controls->m_AddDistortions->setChecked(v1.second.get("artifacts.distortions")); m_Controls->m_AddSpikes->setChecked(v1.second.get("artifacts.addspikes")); m_Controls->m_SpikeNumBox->setValue(v1.second.get("artifacts.m_Spikesnum")); m_Controls->m_SpikeScaleBox->setValue(v1.second.get("artifacts.m_Spikesscale")); m_Controls->m_AddEddy->setChecked(v1.second.get("artifacts.addeddy")); m_Controls->m_EddyGradientStrength->setValue(v1.second.get("artifacts.m_EddyStrength")); m_Controls->m_AddGibbsRinging->setChecked(v1.second.get("artifacts.addringing")); m_Controls->m_AddMotion->setChecked(v1.second.get("artifacts.m_DoAddMotion")); m_Controls->m_RandomMotion->setChecked(v1.second.get("artifacts.m_RandomMotion")); m_Controls->m_MaxTranslationBoxX->setValue(v1.second.get("artifacts.m_Translation0")); m_Controls->m_MaxTranslationBoxY->setValue(v1.second.get("artifacts.m_Translation1")); m_Controls->m_MaxTranslationBoxZ->setValue(v1.second.get("artifacts.m_Translation2")); m_Controls->m_MaxRotationBoxX->setValue(v1.second.get("artifacts.m_Rotation0")); m_Controls->m_MaxRotationBoxY->setValue(v1.second.get("artifacts.m_Rotation1")); m_Controls->m_MaxRotationBoxZ->setValue(v1.second.get("artifacts.m_Rotation2")); 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::OnAddMotion(int value) { if (value>0) m_Controls->m_MotionArtifactFrame->setVisible(true); else m_Controls->m_MotionArtifactFrame->setVisible(false); } void QmitkFiberfoxView::OnAddAliasing(int value) { if (value>0) m_Controls->m_AliasingFrame->setVisible(true); else m_Controls->m_AliasingFrame->setVisible(false); } void QmitkFiberfoxView::OnAddSpikes(int value) { if (value>0) m_Controls->m_SpikeFrame->setVisible(true); else m_Controls->m_SpikeFrame->setVisible(false); } 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::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); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "PlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } 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 (unsigned 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() { if (m_SelectedBundles.empty() && m_SelectedDWI.IsNull()) { 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(m_ImageGenParameters.m_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()->RequestUpdateAll(); } UpdateGui(); } else if (!m_SelectedBundles.empty()) SimulateImageFromFibers(m_SelectedBundles.at(0)); else if (m_SelectedDWI.IsNotNull()) SimulateForExistingDwi(m_SelectedDWI); } void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { if (!dynamic_cast*>(imageNode->GetData())) return; - UpdateImageParameters(); + FiberfoxParameters parameters = UpdateImageParameters(); - if (m_ImageGenParameters.m_NoiseModel==NULL && - m_ImageGenParameters.m_Spikes==0 && - m_ImageGenParameters.m_FrequencyMap.IsNull() && - m_ImageGenParameters.m_KspaceLineOffset<=0.000001 && - !m_ImageGenParameters.m_AddGibbsRinging && - !m_ImageGenParameters.m_DoSimulateEddyCurrents && - m_ImageGenParameters.m_Wrap>0.999) + if (parameters.m_NoiseModel==NULL && + parameters.m_Spikes==0 && + parameters.m_FrequencyMap.IsNull() && + parameters.m_KspaceLineOffset<=0.000001 && + !parameters.m_DoAddGibbsRinging && + !(parameters.m_EddyStrength>0) && + parameters.m_CroppingFactor>0.999) { QMessageBox::information( NULL, "Simulation cancelled", "No valid artifact enabled! Motion artifacts and relaxation effects can NOT be added to an existing diffusion weighted image."); return; } mitk::DiffusionImage::Pointer diffImg = dynamic_cast*>(imageNode->GetData()); m_ArtifactsToDwiFilter = itk::AddArtifactsToDwiImageFilter< short >::New(); m_ArtifactsToDwiFilter->SetInput(diffImg->GetVectorImage()); - m_ArtifactsToDwiFilter->SettLine(m_ImageGenParameters.m_tLine); - m_ArtifactsToDwiFilter->SetkOffset(m_ImageGenParameters.m_KspaceLineOffset); - m_ArtifactsToDwiFilter->SetNoiseModel(m_ImageGenParameters.m_NoiseModelShort); - m_ArtifactsToDwiFilter->SetGradientList(m_ImageGenParameters.m_GradientDirections); - m_ArtifactsToDwiFilter->SetTE(m_ImageGenParameters.m_tEcho); - m_ArtifactsToDwiFilter->SetSimulateEddyCurrents(m_ImageGenParameters.m_DoSimulateEddyCurrents); - m_ArtifactsToDwiFilter->SetEddyGradientStrength(m_ImageGenParameters.m_EddyStrength); - m_ArtifactsToDwiFilter->SetAddGibbsRinging(m_ImageGenParameters.m_AddGibbsRinging); - m_ArtifactsToDwiFilter->SetFrequencyMap(m_ImageGenParameters.m_FrequencyMap); - m_ArtifactsToDwiFilter->SetSpikeAmplitude(m_ImageGenParameters.m_SpikeAmplitude); - m_ArtifactsToDwiFilter->SetSpikes(m_ImageGenParameters.m_Spikes); - m_ArtifactsToDwiFilter->SetWrap(m_ImageGenParameters.m_Wrap); - m_ImageGenParameters.m_ParentNode = imageNode; + parameters.m_ParentNode = imageNode; + m_ArtifactsToDwiFilter->SetParameters(parameters); m_Worker.m_FilterType = 1; m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { mitk::FiberBundleX::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) return; - UpdateImageParameters(); + FiberfoxParameters parameters = UpdateImageParameters(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); - m_TractsToDwiFilter->SetSimulateEddyCurrents(m_ImageGenParameters.m_DoSimulateEddyCurrents); - m_TractsToDwiFilter->SetEddyGradientStrength(m_ImageGenParameters.m_EddyStrength); - m_TractsToDwiFilter->SetAddGibbsRinging(m_ImageGenParameters.m_AddGibbsRinging); - m_TractsToDwiFilter->SetSimulateRelaxation(m_ImageGenParameters.m_DoSimulateRelaxation); - m_TractsToDwiFilter->SetImageRegion(m_ImageGenParameters.m_ImageRegion); - m_TractsToDwiFilter->SetSpacing(m_ImageGenParameters.m_ImageSpacing); - m_TractsToDwiFilter->SetOrigin(m_ImageGenParameters.m_ImageOrigin); - m_TractsToDwiFilter->SetDirectionMatrix(m_ImageGenParameters.m_ImageDirection); + parameters.m_ParentNode = fiberNode; + m_TractsToDwiFilter->SetParameters(parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); - m_TractsToDwiFilter->SetFiberModels(m_ImageGenParameters.m_FiberModelList); - m_TractsToDwiFilter->SetNonFiberModels(m_ImageGenParameters.m_NonFiberModelList); - m_TractsToDwiFilter->SetNoiseModel(m_ImageGenParameters.m_NoiseModel); - m_TractsToDwiFilter->SetkOffset(m_ImageGenParameters.m_KspaceLineOffset); - m_TractsToDwiFilter->SettLine(m_ImageGenParameters.m_tLine); - m_TractsToDwiFilter->SettInhom(m_ImageGenParameters.m_tInhom); - m_TractsToDwiFilter->SetTE(m_ImageGenParameters.m_tEcho); - m_TractsToDwiFilter->SetNumberOfRepetitions(m_ImageGenParameters.m_Repetitions); - m_TractsToDwiFilter->SetEnforcePureFiberVoxels(m_ImageGenParameters.m_DoDisablePartialVolume); - m_TractsToDwiFilter->SetInterpolationShrink(m_ImageGenParameters.m_InterpolationShrink); - m_TractsToDwiFilter->SetFiberRadius(m_ImageGenParameters.m_AxonRadius); - m_TractsToDwiFilter->SetSignalScale(m_ImageGenParameters.m_SignalScale); - if (m_ImageGenParameters.m_InterpolationShrink>0) - m_TractsToDwiFilter->SetUseInterpolation(true); - m_TractsToDwiFilter->SetTissueMask(m_ImageGenParameters.m_MaskImage); - m_TractsToDwiFilter->SetFrequencyMap(m_ImageGenParameters.m_FrequencyMap); - m_TractsToDwiFilter->SetSpikeAmplitude(m_ImageGenParameters.m_SpikeAmplitude); - m_TractsToDwiFilter->SetSpikes(m_ImageGenParameters.m_Spikes); - m_TractsToDwiFilter->SetWrap(m_ImageGenParameters.m_Wrap); - m_TractsToDwiFilter->SetAddMotionArtifact(m_ImageGenParameters.m_DoAddMotion); - m_TractsToDwiFilter->SetMaxTranslation(m_ImageGenParameters.m_Translation); - m_TractsToDwiFilter->SetMaxRotation(m_ImageGenParameters.m_Rotation); - m_TractsToDwiFilter->SetRandomMotion(m_ImageGenParameters.m_RandomMotion); - m_ImageGenParameters.m_ParentNode = fiberNode; m_Worker.m_FilterType = 0; m_Thread.start(QThread::LowestPriority); } 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< double, 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< double, 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< double, 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< double, 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< double, 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< double, 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< double, 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< double, 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_ImageGenParameters.m_MaskImage.IsNotNull() || m_SelectedImage.IsNotNull()) + if (m_ItkMaskImage.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_ImageGenParameters.m_MaskImage = NULL; m_SelectedBundles.clear(); m_SelectedImage = NULL; m_SelectedDWI = NULL; + m_ItkMaskImage = 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; mitk::Image::Pointer image = dynamic_cast(node->GetData()); bool isbinary = false; node->GetPropertyValue("binary", isbinary); if (isbinary) { - mitk::CastToItkImage(image, m_ImageGenParameters.m_MaskImage); + mitk::CastToItkImage(image, m_ItkMaskImage); 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 (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); 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->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "PlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } 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(); } void QmitkFiberfoxView::SetOutputPath() { // SELECT FOLDER DIALOG m_OutputPath = QFileDialog::getExistingDirectory(NULL, "Save images to...", QString(m_OutputPath.c_str())).toStdString(); if (m_OutputPath.empty()) m_Controls->m_SavePathEdit->setText("-"); else { m_OutputPath += "/"; m_Controls->m_SavePathEdit->setText(QString(m_OutputPath.c_str())); } } 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 fc218dc4f2..e36fb3cb77 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h @@ -1,224 +1,225 @@ /*=================================================================== 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 #include #include #include #include #include #include /*! -\brief View for fiber based diffusion software phantoms (Fiberfox). - +\brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. \sa QmitkFunctionality \ingroup Functionalities */ // Forward Qt class declarations using namespace std; class QmitkFiberfoxView; class QmitkFiberfoxWorker : public QObject { Q_OBJECT public: QmitkFiberfoxWorker(QmitkFiberfoxView* view); int m_FilterType; public slots: void run(); private: QmitkFiberfoxView* m_View; }; 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(); protected slots: - void SetOutputPath(); - void LoadParameters(); - void SaveParameters(); + void SetOutputPath(); ///< path where image is automatically saved to after the simulation is finished + void LoadParameters(); ///< load fiberfox parameters + void SaveParameters(); ///< save fiberfox parameters void BeforeThread(); void AfterThread(); - void KillThread(); - void UpdateSimulationStatus(); - - 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 KillThread(); ///< abort simulation + void UpdateSimulationStatus(); ///< print simulation progress and satus messages + + 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(); ///< start image simulation + 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 signal model for compartment 1 + void Comp2ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 2 + void Comp3ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 3 + void Comp4ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 4 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 OnConstantRadius(int value); + + /** update GUI elements */ void OnAddNoise(int value); void OnAddGhosts(int value); void OnAddDistortions(int value); void OnAddEddy(int value); void OnAddSpikes(int value); void OnAddAliasing(int value); void OnAddMotion(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 SimulateForExistingDwi(mitk::DataNode* imageNode); - void SimulateImageFromFibers(mitk::DataNode* fiberNode); - void UpdateImageParameters(); ///< update iamge generation paaremeter struct - void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection + void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image + void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image + template< class ScalarType > FiberfoxParameters< ScalarType > UpdateImageParameters(); ///< update fiberfox paramater object (template parameter defines noise model type) + 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 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; }; - FiberfoxParameters m_ImageGenParameters; - FiberfoxParameters m_ImageGenParametersBackup; - std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData 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; + ItkUcharImgType::Pointer m_ItkMaskImage; - // intra and inter axonal compartments + /** 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 + /** 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; - QString m_ParameterFile; - string m_OutputPath; + QString m_ParameterFile; ///< parameter file name + string m_OutputPath; ///< image save path // GUI thread QmitkFiberfoxWorker m_Worker; ///< runs filter QThread m_Thread; ///< worker thread - itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; - itk::AddArtifactsToDwiImageFilter< short >::Pointer m_ArtifactsToDwiFilter; bool m_ThreadIsRunning; QTimer* m_SimulationTimer; QTime m_SimulationTime; QString m_SimulationStatusText; + /** Image filters that do all the simulations. */ + itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; + itk::AddArtifactsToDwiImageFilter< short >::Pointer m_ArtifactsToDwiFilter; + friend class QmitkFiberfoxWorker; }; 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 ebc46cd06a..3a508fbb46 100755 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,3065 +1,3041 @@ QmitkFiberfoxViewControls 0 0 435 2274 Form Load Parameters :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico 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 :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico Operations false Join Bundles :/QmitkDiffusionImaging/general_icons/plus.ico:/QmitkDiffusionImaging/general_icons/plus.ico QFrame::NoFrame QFrame::Raised 0 0 0 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 Copy Bundles :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico false Transform Selection :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Fiber Options QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 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 0 0 0 6 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false Generate Fibers :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico QFrame::NoFrame QFrame::Raised 0 0 0 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 0 0 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 0 0 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 Tissue Mask: false <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> true Fiber Bundle: false <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Save path: false QFrame::NoFrame QFrame::Raised 0 0 0 0 0 - ... Noise and other Artifacts Qt::Horizontal Add Noise false Add ringing artifacts occuring at strong edges in the image. Add Gibbs Ringing false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Shrink FOV (%): false Shrink FOV by this percentage. 1 0.000000000000000 90.000000000000000 0.100000000000000 25.000000000000000 Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 0 0 0 Num. Spikes: The number of randomly occurring signal spikes. 1 Spike amplitude relative to the largest signal amplitude of the corresponding k-space slice. 0.100000000000000 0.100000000000000 Scale: !!!EXPERIMENTAL!!! Add Eddy Current Effects false Add Spikes false QFrame::NoFrame QFrame::Raised 0 0 0 0 Variance: Variance of selected noise distribution. 4 0.000000000000000 999999999.000000000000000 0.001000000000000 50.000000000000000 Distribution: Noise distribution Rician Chi-squared Add N/2 Ghosts false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 Frequency Map: false Select image specifying the frequency inhomogeneities (in Hz). Qt::Horizontal Qt::Horizontal Qt::Horizontal true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 6 0 0 Toggle between random movement and linear movement. Randomize motion true Rotation 0 9 0 0 Degree: false x false Axis: false Maximum rotation around x-axis. 1 360.000000000000000 1.000000000000000 0.000000000000000 Maximum rotation around z-axis. 1 360.000000000000000 1.000000000000000 15.000000000000000 y false z false Maximum rotation around y-axis. 1 360.000000000000000 1.000000000000000 0.000000000000000 Translation 0 0 0 Distance: false x false y false Axis: false z false Maximum translation along x-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along y-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Maximum translation along z-axis. 1 1000.000000000000000 1.000000000000000 0.000000000000000 Add Motion Artifacts false Add Distortions false Add Aliasing false true QFrame::NoFrame QFrame::Raised 6 0 0 0 0 K-Space Line Offset: false A larger offset increases the inensity of the ghost image. 3 1.000000000000000 0.010000000000000 0.250000000000000 true QFrame::NoFrame QFrame::Raised QFormLayout::AllNonFixedFieldsGrow 6 0 0 0 0 Magnitude: false Maximum magnitude of eddy current induced magnetic field inhomogeneities (in mT). 5 1000.000000000000000 0.001000000000000 0.005000000000000 color: rgb(255, 0, 0); Experimental! Qt::Horizontal Qt::Horizontal Image Settings QFrame::NoFrame QFrame::Raised 0 0 0 0 6 - + + + + TE in milliseconds + + + 1 + + + 10000 + + + 1 + + + 100 + + + + <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 + Signal Scale: 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> + <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 + + + + + + + Repetitions: + + + + + + + T2* relaxation time (in milliseconds). + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + 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> + <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </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> - - - 0 - - - 10000 - - - 0 - - - - - - - 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 0 0 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 0 0 0 6 Gradient Directions: Number of gradient directions distributed over the half sphere. - 1 + 0 10000 1 30 b-Value: false b-value in mm/s² 0 10000 100 1000 Advanced Options true <html><head/><body><p>Start DWI generation from selected fiber bundle.</p><p>If no fiber bundle but an existing diffusion weighted image is selected, the enabled artifacts are added to this image.</p><p>If neither a fiber bundle nor a diffusion weighted image is selected, a grayscale image containing a simple gradient is generated.</p></body></html> Start Simulation :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico Intra-axonal Compartment Select signal model for intra-axonal compartment. Stick Model Zeppelin Model Tensor Model true Stop current simulation. Abort Simulation :/QmitkDiffusionImaging/general_icons/abort.ico:/QmitkDiffusionImaging/general_icons/abort.ico 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 0 0 0 Weighting factor between the two extra-axonal compartments. 1.000000000000000 0.100000000000000 0.300000000000000 Compartment Fraction: Qt::Vertical 20 40 Inter-axonal Compartment Select signal model for intra-axonal compartment. -- Stick Model Zeppelin Model Tensor Model 8 true Save Parameters :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico 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_RelaxationBox m_EnforcePureFiberVoxelsBox m_VolumeFractionsBox m_Compartment1Box m_Compartment2Box m_Compartment3Box m_Compartment4Box m_Comp4FractionBox m_AddNoise m_NoiseLevel m_AddSpikes m_SpikeNumBox m_SpikeScaleBox m_AddGhosts m_kOffsetBox m_AddAliasing m_WrapBox m_AddDistortions m_FrequencyMapBox m_AddMotion m_RandomMotion m_MaxRotationBoxX m_MaxRotationBoxY m_MaxRotationBoxZ m_MaxTranslationBoxX m_MaxTranslationBoxY m_MaxTranslationBoxZ m_AddEddy m_EddyGradientStrength m_AddGibbsRinging m_SaveParametersButton m_LoadParametersButton tabWidget
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.h index fa93f52bde..085c639d9f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFieldmapGeneratorView.h @@ -1,81 +1,82 @@ /*=================================================================== 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 _QMITKQmitkFieldmapGeneratorView_H_INCLUDED #define _QMITKQmitkFieldmapGeneratorView_H_INCLUDED #include #include #include "ui_QmitkFieldmapGeneratorViewControls.h" #include #include /*! - \brief View displaying details of the orientation distribution function in the voxel at the current crosshair position. + \brief Generate float image with artificial frequency maps used by Fiberfox. Simulates additional frequencies at (possibly multiple) positions based on 3D gaussians with the specified variance and amplitude and/or as a linear gradient in the image. +* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkFieldmapGeneratorView : public QmitkFunctionality { // 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 std::string VIEW_ID; QmitkFieldmapGeneratorView(); virtual ~QmitkFieldmapGeneratorView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); void OnSliceChanged(const itk::EventObject& e); protected slots: void GenerateFieldmap(); void PlaceFieldSource(); void OnVarianceChanged(double value); void OnHeightChanged(double value); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkFieldmapGeneratorViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; /** observer flags */ int m_SliceObserverTag1; int m_SliceObserverTag2; int m_SliceObserverTag3; int m_PropertyObserverTag; mitk::Point3D m_WorldPoint; mitk::DataNode::Pointer m_SelectedSource; }; #endif // _QmitkFieldmapGeneratorView_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h index 118a270370..fb4407ab0f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkStreamlineTrackingView.h @@ -1,90 +1,90 @@ /*=================================================================== 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 QmitkStreamlineTrackingView_h #define QmitkStreamlineTrackingView_h #include #include "ui_QmitkStreamlineTrackingViewControls.h" #include #include #include #include #include /*! -\brief View for deterministic streamline fiber tracking. +\brief View for tensor based deterministic streamline fiber tracking. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkStreamlineTrackingView : public QmitkFunctionality { // 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 std::string VIEW_ID; typedef itk::Image< unsigned char, 3 > ItkUCharImageType; typedef itk::Image< float, 3 > ItkFloatImageType; QmitkStreamlineTrackingView(); virtual ~QmitkStreamlineTrackingView(); virtual void CreateQtPartControl(QWidget *parent); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); protected slots: void DoFiberTracking(); ///< start fiber tracking protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( std::vector nodes ); Ui::QmitkStreamlineTrackingViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; protected slots: /** update labels if parameters have changed */ void OnSeedsPerVoxelChanged(int value); void OnMinTractLengthChanged(int value); void OnFaThresholdChanged(int value); void OnAngularThresholdChanged(int value); void OnfChanged(int value); void OngChanged(int value); void OnStepsizeChanged(int value); private: mitk::Image::Pointer m_MaskImage; ///< abort tracking if leaving mask mitk::Image::Pointer m_SeedRoi; ///< binary image defining seed voxels for tracking process std::vector< mitk::DataNode::Pointer > m_TensorImageNodes; ///< input images std::vector< mitk::TensorImage::Pointer > m_TensorImages; ///< input image datanode }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED