diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkAddArtifactsToDwiImageFilter.cpp index 980796961a..0ea00e425a 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_EddyGradientStrength(0.0) - , m_SimulateEddyCurrents(false) - , 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_Wrap<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_Wrap); 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_Wrap<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< int > 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< 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/itkKspaceImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.cpp index 376f921a67..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_tLine(1) , m_kOffset(0) , m_FrequencyMap(NULL) , m_SimulateRelaxation(true) - , m_SimulateEddyCurrents(false) , m_Tau(70) , m_EddyGradientMagnitude(30) , m_IsBaseline(true) - , m_SignalScale(1) + , m_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..f80d616398 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkKspaceImageFilter.h @@ -1,130 +1,124 @@ /*=================================================================== 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. */ 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( Tau, double) ///< eddy current decay constant 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 ) + itkSetMacro( EddyGradientMagnitude, double) ///< in T/m 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 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/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 12acaee9d2..993b9c70d6 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,989 +1,886 @@ /*=================================================================== 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< 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); 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 (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 (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_Wrap); + 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 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 (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_Wrap<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_Wrap<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 (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 e75a6b5208..4b3a9fcb4d 100755 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,172 +1,103 @@ /*=================================================================== 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. */ 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 ) + itkTypeMacro( TractsToDWIImageFilter, ImageSource ) // 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 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 ) + void SetParameters( FiberfoxParameters param ){ m_Parameters = param; } + FiberfoxParameters GetParameters(){ return m_Parameters; } + // output - std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions(){ return m_VolumeFractions; } + std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel + { 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); - itk::Vector m_Spacing; ///< output image spacing + mitk::FiberfoxParameters m_Parameters; + 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) - ItkDoubleImgType::Pointer m_FrequencyMap; ///< map of the B0 inhomogeneities - double m_kOffset; - double m_tLine; - double m_TE; - double m_tInhom; - FiberBundleType m_FiberBundle; ///< input fiber bundle - DiffusionModelList m_FiberModels; ///< generate signal of fiber compartments - DiffusionModelList m_NonFiberModels; ///< generate signal of non-fiber compartments - NoiseModelType* m_NoiseModel; ///< generates the noise added to the image values - 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; - mitk::LevelWindow m_LevelWindow; - bool m_UseInterpolation; - std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; ///< one double image for each compartment containing the corresponding volume fraction per voxel - bool m_SimulateRelaxation; - bool m_SimulateEddyCurrents; - double m_EddyGradientStrength; - int m_Spikes; - double m_SpikeAmplitude; - double m_Wrap; - VectorType m_MaxTranslation; - VectorType m_MaxRotation; - bool m_AddMotionArtifact; - bool m_RandomMotion; + FiberBundleType m_FiberBundle; + mitk::LevelWindow m_LevelWindow; + std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions; 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 425c2b9952..18cce5ed37 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_AddGibbsRinging(false) +#include +#include +#include +#include +#include + +template< class ScalarType > +mitk::FiberfoxParameters< ScalarType >::FiberfoxParameters() + : m_DoAddGibbsRinging(false) , m_ArtifactModelString("") , m_AxonRadius(0) , m_Bvalue(1000) - , m_Comp3Weight(1) - , m_Comp4Weight(0) , m_DoAddMotion(false) , m_DoDisablePartialVolume(false) - , m_DoSimulateEddyCurrents(false) , m_DoSimulateRelaxation(true) , m_EddyStrength(0) - , m_InterpolationShrink(0) , m_KspaceLineOffset(0) , m_NumGradients(6) + , m_NumBaseline(1) , m_OutputPath("") - , m_RandomMotion(true) + , m_DoRandomizeMotion(true) , m_Repetitions(1) , m_SignalModelString("") , m_SignalScale(100) , m_SpikeAmplitude(1) , m_Spikes(0) , m_tEcho(100) , m_tInhom(50) , m_tLine(1) , m_Wrap(1) , m_MaskImage(NULL) , m_FrequencyMap(NULL) , m_NoiseModel(NULL) - , m_NoiseModelShort(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; + + GenerateHalfShell(); +} + +template< class ScalarType > +mitk::FiberfoxParameters< ScalarType >::~FiberfoxParameters() +{ + // if (m_NoiseModel!=NULL) + // delete m_NoiseModel; +} + +template< class ScalarType > +void mitk::FiberfoxParameters< ScalarType >::GenerateHalfShell() +{ + 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; +} + +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; } -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 > +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; + GenerateHalfShell(); +} + +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"); + GenerateHalfShell(); + 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_Wrap = (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_Wrap; + 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..e3f05ce6d4 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h @@ -1,99 +1,174 @@ /*=================================================================== 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 * */ -class FiberTracking_EXPORT FiberfoxParameters +template< class ScalarType > +class FiberfoxParameters { public: 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(); + 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_Wrap = m_Wrap; + 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; itk::Vector m_ImageSpacing; itk::Point m_ImageOrigin; itk::Matrix m_ImageDirection; - unsigned int m_NumGradients; - double m_Bvalue; + + /** Other acquisitions parameters */ 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; + double m_Bvalue; + + /** 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; double m_SpikeAmplitude; + double m_KspaceLineOffset; + double m_EddyStrength; double m_Wrap; - itk::Vector m_Translation; - itk::Vector m_Rotation; + bool m_DoAddGibbsRinging; 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; + bool m_DoRandomizeMotion; + itk::Vector m_Translation; + itk::Vector m_Rotation; + NoiseModelType* m_NoiseModel; ItkDoubleImgType::Pointer m_FrequencyMap; ItkUcharImgType::Pointer m_MaskImage; + + /** Output parameters */ mitk::DataNode::Pointer m_ResultNode; mitk::DataNode::Pointer m_ParentNode; - - string m_SignalModelString; - string m_ArtifactModelString; - string m_OutputPath; + string m_SignalModelString; + string m_ArtifactModelString; + string m_OutputPath; void PrintSelf(); + void LoadParameters(string filename); + void GenerateHalfShell(); + + 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); + void SetGradienDirections(GradientListType gradientList); + void SetGradienDirections(mitk::DiffusionImage::GradientDirectionContainerType::Pointer gradientList); protected: -}; + unsigned int m_NumBaseline; + unsigned int m_NumGradients; + GradientListType m_GradientDirections; +}; } +#include "mitkFiberfoxParameters.cpp" + #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkChiSquareNoiseModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkChiSquareNoiseModel.h index a6d5f91d89..cabf3fb1f1 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkChiSquareNoiseModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkChiSquareNoiseModel.h @@ -1,58 +1,58 @@ /*=================================================================== 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_ChiSquareNoiseModel_H #define _MITK_ChiSquareNoiseModel_H #include #include namespace mitk { /** * \brief Implementation of noise following a rician 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 SetNoiseVariance(double var){ m_Distribution = boost::random::chi_squared_distribution(var/2); } + double GetNoiseVariance(){ return m_Distribution.n()*2; } void SetSeed(int seed); 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 a3b046bc3a..d23efcbf17 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(){} ~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. **/ 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 7fbdcf119f..0f524f54e2 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(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(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/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp b/Modules/DiffusionImaging/FiberTracking/Testing/mitkFiberfoxAddArtifactsToDwiTest.cpp index b0afe6cc25..cafa23bcfb 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; 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..508f77dc22 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_SignalScale = 1000; StartSimulation(parameters, fiberBundle, aliasing, argv[10]); // Eddy currents parameters.m_Wrap = 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 6f29af6080..ea686a3d08 100755 --- a/Modules/DiffusionImaging/MiniApps/CMakeLists.txt +++ b/Modules/DiffusionImaging/MiniApps/CMakeLists.txt @@ -1,69 +1,69 @@ OPTION(BUILD_DiffusionMiniApps "Build commandline tools for diffusion" OFF) IF(BUILD_DiffusionMiniApps OR MITK_BUILD_ALL_APPS) # include necessary modules here MITK_CHECK_MODULE(_RESULT DiffusionCore FiberTracking ) IF(_RESULT) MESSAGE("Warning: DiffusionMiniApps is missing ${_RESULT}") ELSE(_RESULT) MITK_USE_MODULE( DiffusionCore FiberTracking ) # needed include directories INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${ALL_INCLUDE_DIRECTORIES}) 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 ) ENDIF() MITK_INSTALL_TARGETS(EXECUTABLES mitkDiffusionMiniApps ) ENDIF(BUILD_DiffusionMiniApps OR MITK_BUILD_ALL_APPS) 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/QmitkFiberfoxViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkFiberfoxViewUserManual.dox index 30e1922e3a..631610fb52 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 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. [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/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index ce5da412c9..b21a218e1f 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.GenerateHalfShell(); } // 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_Wrap = (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_Wrap>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..1a40009c25 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,224 @@ /*=================================================================== 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). \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; 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