diff --git a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp index 7a1f49a791..a3b3cea799 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkOdfMaximaExtractionFilter.cpp @@ -1,358 +1,358 @@ /*=================================================================== 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 __itkOdfMaximaExtractionFilter_cpp #define __itkOdfMaximaExtractionFilter_cpp #include "itkOdfMaximaExtractionFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace boost::math; namespace itk { static bool CompareVectors(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2) { return (v1.magnitude()>v2.magnitude()); } template< class PixelType, int ShOrder, int NrOdfDirections > OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::OdfMaximaExtractionFilter() : m_NormalizationMethod(MAX_VEC_NORM) , m_MaxNumPeaks(2) , m_RelativePeakThreshold(0.4) , m_AbsolutePeakThreshold(0) , m_AngularThreshold(0.9) , m_NumCoeffs((ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder) , m_Toolkit(MRTRIX) , m_FlipX(false) , m_FlipY(false) , m_FlipZ(false) , m_ApplyDirectionMatrix(false) , m_ScaleByGfa(false) , m_Iterations(10) { this->SetNumberOfRequiredInputs(1); } template< class PixelType, int ShOrder, int NrOdfDirections > double OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::FindCandidatePeaks(OdfType& odf, double thr, std::vector< DirectionType >& container) { double gfa = 1.0; if (m_ScaleByGfa) gfa = odf.GetGeneralizedFractionalAnisotropy(); //Find the peaks using a finite difference method bool flag = true; vnl_vector_fixed< bool, NrOdfDirections > used; used.fill(false); //Find the peaks for (int i=0; ithr && gfa*val>m_AbsolutePeakThreshold) // limit to one hemisphere ??? + if (val>thr*0.9 && gfa*val>m_AbsolutePeakThreshold*0.9) { flag = true; std::vector< int > neighbours = odf.GetNeighbors(i); for (unsigned int j=0; j void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::BeforeThreadedGenerateData() { typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) ); itk::Vector spacing = ShCoeffImage->GetSpacing(); double minSpacing = spacing[0]; if (spacing[1]GetOrigin(); itk::Matrix direction = ShCoeffImage->GetDirection(); ImageRegion<3> imageRegion = ShCoeffImage->GetLargestPossibleRegion(); if (m_MaskImage.IsNotNull()) { origin = m_MaskImage->GetOrigin(); direction = m_MaskImage->GetDirection(); imageRegion = m_MaskImage->GetLargestPossibleRegion(); } itk::Vector spacing3 = ShCoeffImage->GetSpacing(); itk::Point origin3 = ShCoeffImage->GetOrigin(); itk::Matrix direction3 = ShCoeffImage->GetDirection(); itk::ImageRegion<3> imageRegion3 = ShCoeffImage->GetLargestPossibleRegion(); itk::Vector spacing4; itk::Point origin4; itk::Matrix direction4; itk::ImageRegion<4> imageRegion4; spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1; origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0; for (int r=0; r<3; r++) for (int c=0; c<3; c++) direction4[r][c] = direction3[r][c]; direction4[3][3] = 1; imageRegion4.SetSize(0, imageRegion3.GetSize()[0]); imageRegion4.SetSize(1, imageRegion3.GetSize()[1]); imageRegion4.SetSize(2, imageRegion3.GetSize()[2]); imageRegion4.SetSize(3, m_MaxNumPeaks*3); m_PeakImage = PeakImageType::New(); m_PeakImage->SetSpacing( spacing4 ); m_PeakImage->SetOrigin( origin4 ); m_PeakImage->SetDirection( direction4 ); m_PeakImage->SetRegions( imageRegion4 ); m_PeakImage->Allocate(); m_PeakImage->FillBuffer(0.0); if (m_MaskImage.IsNull()) { m_MaskImage = ItkUcharImgType::New(); m_MaskImage->SetSpacing( spacing ); m_MaskImage->SetOrigin( origin ); m_MaskImage->SetDirection( direction ); m_MaskImage->SetRegions( imageRegion ); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } m_NumDirectionsImage = ItkUcharImgType::New(); m_NumDirectionsImage->SetSpacing( spacing ); m_NumDirectionsImage->SetOrigin( origin ); m_NumDirectionsImage->SetDirection( direction ); m_NumDirectionsImage->SetRegions( imageRegion ); m_NumDirectionsImage->Allocate(); m_NumDirectionsImage->FillBuffer(0); // calculate SH basis OdfType odf; vnl_matrix< double > dir_matrix; dir_matrix.set_size(3, NrOdfDirections); for (int i=0; iSetNumberOfThreads(1); } template< class PixelType, int ShOrder, int NrOdfDirections > void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::AfterThreadedGenerateData() { } template< class PixelType, int ShOrder, int NrOdfDirections > void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections> ::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType threadID ) { typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) ); ImageRegionConstIterator< CoefficientImageType > cit(ShCoeffImage, outputRegionForThread ); OdfType odf; while( !cit.IsAtEnd() ) { typename CoefficientImageType::IndexType idx3 = cit.GetIndex(); if (m_MaskImage->GetPixel(idx3)==0) { ++cit; continue; } CoefficientPixelType c = cit.Get(); vnl_vector coeffs; coeffs.set_size((ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder); for (int j=0; jmax) max = odf[i]; } if (max<0.0001) { ++cit; continue; } std::vector< DirectionType > candidates, final_peaks; - double scale = FindCandidatePeaks(odf, max*m_RelativePeakThreshold*0.9, candidates); // find all local maxima + double scale = FindCandidatePeaks(odf, max*m_RelativePeakThreshold, candidates); // find all local maxima max = 0; for (unsigned int i=0; i x; x.set_size(2); x[0] = spherical[1]; // theta x[1] = spherical[0]; // phi VnlCostFunction cost; if (m_Toolkit==Toolkit::MRTRIX) cost.SetProblem(coeffs, ShOrder, true, max); else cost.SetProblem(coeffs, ShOrder, false, max); vnl_lbfgsb minimizer(cost); minimizer.set_f_tolerance(1e-6); // minimizer.set_trace(true); vnl_vector l; l.set_size(2); l[0] = 0; l[1] = -itk::Math::pi; vnl_vector u; u.set_size(2); u[0] = itk::Math::pi; u[1] = itk::Math::pi; vnl_vector bound_selection; bound_selection.set_size(2); bound_selection.fill(2); minimizer.set_bound_selection(bound_selection); minimizer.set_lower_bound(l); minimizer.set_upper_bound(u); if (m_Iterations>0) minimizer.set_max_function_evals(m_Iterations); minimizer.minimize(x); float v = -minimizer.get_end_error()*scale; candidates[i] = mitk::sh::Sph2Cart(x[0], x[1], v); if (v>max) max = v; } std::sort( candidates.begin(), candidates.end(), CompareVectors ); // sort peaks // kick out directions to close to a larger direction for (unsigned int i=0; im_AngularThreshold && val idx4; idx4[0] = idx3[0]; idx4[1] = idx3[1]; idx4[2] = idx3[2]; // fill output image unsigned int num = final_peaks.size(); if ( num>m_MaxNumPeaks ) num = m_MaxNumPeaks; for (unsigned int i=0; iGetDirection()*dir; if (m_FlipX) dir[0] = -dir[0]; if (m_FlipY) dir[1] = -dir[1]; if (m_FlipZ) dir[2] = -dir[2]; for (unsigned int j = 0; j<3; j++) { idx4[3] = i*3 + j; m_PeakImage->SetPixel(idx4, dir[j]); } } m_NumDirectionsImage->SetPixel(idx3, num); ++cit; } MITK_INFO << "Thread " << threadID << " finished extraction"; } } #endif // __itkOdfMaximaExtractionFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp index 840a193f4e..ead4fce7af 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.cpp @@ -1,239 +1,238 @@ /*=================================================================== 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 __itkibersFromPlanarFiguresFilter_cpp +#define __itkibersFromPlanarFiguresFilter_cpp + #include "itkFibersFromPlanarFiguresFilter.h" -// MITK #include #include #include #include #include #include #include #include #include -// ITK #include #include #include #include -// MISC #include namespace itk{ FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter() { } FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter() { } void FibersFromPlanarFiguresFilter::GeneratePoints() { - Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); - randGen->SetSeed((unsigned int)0); - m_2DPoints.clear(); - unsigned int count = 0; + Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New(); + randGen->SetSeed((unsigned int)0); + m_2DPoints.clear(); + unsigned int count = 0; + + while (count < m_Parameters.m_Density) + { + mitk::Vector2D p; + switch (m_Parameters.m_Distribution) { + case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: + p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); + p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); + break; + default: + p[0] = randGen->GetUniformVariate(-1, 1); + p[1] = randGen->GetUniformVariate(-1, 1); + } - while (count < m_Parameters.m_Density) + if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) { - mitk::Vector2D p; - switch (m_Parameters.m_Distribution) { - case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN: - p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); - p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance); - break; - default: - p[0] = randGen->GetUniformVariate(-1, 1); - p[1] = randGen->GetUniformVariate(-1, 1); - } - - if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1) - { - m_2DPoints.push_back(p); - count++; - } + m_2DPoints.push_back(p); + count++; } + } } void FibersFromPlanarFiguresFilter::GenerateData() { - // check if enough fiducials are available - for (unsigned int i=0; i m_VtkCellArray = vtkSmartPointer::New(); + vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); + + std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); + + std::vector< unsigned int > fliplist; + if (i m_VtkCellArray = vtkSmartPointer::New(); - vtkSmartPointer m_VtkPoints = vtkSmartPointer::New(); - - std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i); - - std::vector< unsigned int > fliplist; - if (i container = vtkSmartPointer::New(); - - mitk::PlanarEllipse::Pointer figure = bundle.at(0); - mitk::Point2D p0 = figure->GetControlPoint(0); - mitk::Point2D p1 = figure->GetControlPoint(1); - mitk::Point2D p2 = figure->GetControlPoint(2); - mitk::Point2D p3 = figure->GetControlPoint(3); - double r1 = p0.EuclideanDistanceTo(p1); - double r2 = p0.EuclideanDistanceTo(p2); - mitk::Vector2D eDir = p1-p0; eDir.Normalize(); - mitk::Vector2D tDir = p3-p0; tDir.Normalize(); - - // apply twist - vnl_matrix_fixed tRot; - tRot[0][0] = tDir[0]; - tRot[1][1] = tRot[0][0]; - tRot[1][0] = sin(acos(tRot[0][0])); - tRot[0][1] = -tRot[1][0]; - if (tDir[1]<0) - tRot.inplace_transpose(); - m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); - - // apply new ellipse shape - vnl_vector_fixed< double, 2 > newP; - newP[0] = m_2DPoints.at(j)[0]; - newP[1] = m_2DPoints.at(j)[1]; - double alpha = acos(eDir[0]); - if (eDir[1]>0) - alpha = 2*itk::Math::pi-alpha; - vnl_matrix_fixed eRot; - eRot[0][0] = cos(alpha); - eRot[1][1] = eRot[0][0]; - eRot[1][0] = sin(alpha); - eRot[0][1] = -eRot[1][0]; - newP = eRot*newP; - newP[0] *= r1; - newP[1] *= r2; - newP = eRot.transpose()*newP; - - p0[0] += newP[0]; - p0[1] += newP[1]; - - const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); - - mitk::Point3D w, wc; - planeGeo->Map(p0, w); - - wc = figure->GetWorldControlPoint(0); - - vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); - container->GetPointIds()->InsertNextId(id); - - vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); - - for (unsigned int k=1; kGetControlPoint(0); - p1 = figure->GetControlPoint(1); - p2 = figure->GetControlPoint(2); - p3 = figure->GetControlPoint(3); - r1 = p0.EuclideanDistanceTo(p1); - r2 = p0.EuclideanDistanceTo(p2); - - eDir = p1-p0; eDir.Normalize(); - mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); - mitk::Vector2D temp; temp.Fill(0); - temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); - - // apply twist - tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; - tRot[1][1] = tRot[0][0]; - tRot[1][0] = sin(acos(tRot[0][0])); - tRot[0][1] = -tRot[1][0]; - if (temp[1]<0) - tRot.inplace_transpose(); - m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); - tDir = tDir2; - - // apply new ellipse shape - newP[0] = m_2DPoints.at(j)[0]; - newP[1] = m_2DPoints.at(j)[1]; - - // calculate normal - mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); - mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); - vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); - wc = figure->GetWorldControlPoint(0); - - // is flip needed? - if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) - newP[0] *= -1; - if (fliplist.at(k)>0) - newP[0] *= -1; - n = n2; - - alpha = acos(eDir[0]); - if (eDir[1]>0) - alpha = 2*itk::Math::pi-alpha; - eRot[0][0] = cos(alpha); - eRot[1][1] = eRot[0][0]; - eRot[1][0] = sin(alpha); - eRot[0][1] = -eRot[1][0]; - newP = eRot*newP; - newP[0] *= r1; - newP[1] *= r2; - newP = eRot.transpose()*newP; - - p0[0] += newP[0]; - p0[1] += newP[1]; - - mitk::Point3D w; - planeGeo->Map(p0, w); - - - vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); - container->GetPointIds()->InsertNextId(id); - } - - m_VtkCellArray->InsertNextCell(container); - } - - vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); - fiberPolyData->SetPoints(m_VtkPoints); - fiberPolyData->SetLines(m_VtkCellArray); - mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); - mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); - m_FiberBundles.push_back(mitkFiberBundle); + vtkSmartPointer container = vtkSmartPointer::New(); + + mitk::PlanarEllipse::Pointer figure = bundle.at(0); + mitk::Point2D p0 = figure->GetControlPoint(0); + mitk::Point2D p1 = figure->GetControlPoint(1); + mitk::Point2D p2 = figure->GetControlPoint(2); + mitk::Point2D p3 = figure->GetControlPoint(3); + double r1 = p0.EuclideanDistanceTo(p1); + double r2 = p0.EuclideanDistanceTo(p2); + mitk::Vector2D eDir = p1-p0; eDir.Normalize(); + mitk::Vector2D tDir = p3-p0; tDir.Normalize(); + + // apply twist + vnl_matrix_fixed tRot; + tRot[0][0] = tDir[0]; + tRot[1][1] = tRot[0][0]; + tRot[1][0] = sin(acos(tRot[0][0])); + tRot[0][1] = -tRot[1][0]; + if (tDir[1]<0) + tRot.inplace_transpose(); + m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); + + // apply new ellipse shape + vnl_vector_fixed< double, 2 > newP; + newP[0] = m_2DPoints.at(j)[0]; + newP[1] = m_2DPoints.at(j)[1]; + double alpha = acos(eDir[0]); + if (eDir[1]>0) + alpha = 2*itk::Math::pi-alpha; + vnl_matrix_fixed eRot; + eRot[0][0] = cos(alpha); + eRot[1][1] = eRot[0][0]; + eRot[1][0] = sin(alpha); + eRot[0][1] = -eRot[1][0]; + newP = eRot*newP; + newP[0] *= r1; + newP[1] *= r2; + newP = eRot.transpose()*newP; + + p0[0] += newP[0]; + p0[1] += newP[1]; + + const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry(); + + mitk::Point3D w, wc; + planeGeo->Map(p0, w); + + wc = figure->GetWorldControlPoint(0); + + vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); + container->GetPointIds()->InsertNextId(id); + + vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl(); + + for (unsigned int k=1; kGetControlPoint(0); + p1 = figure->GetControlPoint(1); + p2 = figure->GetControlPoint(2); + p3 = figure->GetControlPoint(3); + r1 = p0.EuclideanDistanceTo(p1); + r2 = p0.EuclideanDistanceTo(p2); + + eDir = p1-p0; eDir.Normalize(); + mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize(); + mitk::Vector2D temp; temp.Fill(0); + temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector()); + + // apply twist + tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1]; + tRot[1][1] = tRot[0][0]; + tRot[1][0] = sin(acos(tRot[0][0])); + tRot[0][1] = -tRot[1][0]; + if (temp[1]<0) + tRot.inplace_transpose(); + m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector()); + tDir = tDir2; + + // apply new ellipse shape + newP[0] = m_2DPoints.at(j)[0]; + newP[1] = m_2DPoints.at(j)[1]; + + // calculate normal + mitk::PlaneGeometry* planeGeo = const_cast(figure->GetPlaneGeometry()); + mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize(); + vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl(); + wc = figure->GetWorldControlPoint(0); + + // is flip needed? + if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001) + newP[0] *= -1; + if (fliplist.at(k)>0) + newP[0] *= -1; + n = n2; + + alpha = acos(eDir[0]); + if (eDir[1]>0) + alpha = 2*itk::Math::pi-alpha; + eRot[0][0] = cos(alpha); + eRot[1][1] = eRot[0][0]; + eRot[1][0] = sin(alpha); + eRot[0][1] = -eRot[1][0]; + newP = eRot*newP; + newP[0] *= r1; + newP[1] *= r2; + newP = eRot.transpose()*newP; + + p0[0] += newP[0]; + p0[1] += newP[1]; + + mitk::Point3D w; + planeGeo->Map(p0, w); + + + vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer()); + container->GetPointIds()->InsertNextId(id); + } + + m_VtkCellArray->InsertNextCell(container); } -} + vtkSmartPointer fiberPolyData = vtkSmartPointer::New(); + fiberPolyData->SetPoints(m_VtkPoints); + fiberPolyData->SetLines(m_VtkCellArray); + mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData); + mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias); + m_FiberBundles.push_back(mitkFiberBundle); + } } - - +} +#endif // __itkFibersFromPlanarFiguresFilter_cpp diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h index ba03b2ee4a..22693e1730 100644 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkFibersFromPlanarFiguresFilter.h @@ -1,85 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef itkFibersFromPlanarFiguresFilter_h #define itkFibersFromPlanarFiguresFilter_h // MITK #include #include #include // ITK #include // VTK #include #include #include #include #include namespace itk{ /** * \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */ class FibersFromPlanarFiguresFilter : public ProcessObject { public: - typedef FibersFromPlanarFiguresFilter Self; - typedef ProcessObject Superclass; - typedef SmartPointer< Self > Pointer; - typedef SmartPointer< const Self > ConstPointer; - typedef mitk::FiberBundle::Pointer FiberType; - typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; - - itkFactorylessNewMacro(Self) - itkCloneMacro(Self) - itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) - - void Update() override{ - this->GenerateData(); - } - - // input - void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters. - { - m_Parameters = param; - } - - // output - FiberContainerType GetFiberBundles(){ return m_FiberBundles; } + typedef FibersFromPlanarFiguresFilter Self; + typedef ProcessObject Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + typedef mitk::FiberBundle::Pointer FiberType; + typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType; + + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject ) + + void Update() override{ + this->GenerateData(); + } + + // input + void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters. + { + m_Parameters = param; + } + + // output + FiberContainerType GetFiberBundles(){ return m_FiberBundles; } protected: - void GenerateData() override; + void GenerateData() override; - FibersFromPlanarFiguresFilter(); - ~FibersFromPlanarFiguresFilter() override; - void GeneratePoints(); + FibersFromPlanarFiguresFilter(); + ~FibersFromPlanarFiguresFilter() override; + void GeneratePoints(); - FiberContainerType m_FiberBundles; ///< container for the output fiber bundles - std::vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints - FiberGenerationParameters m_Parameters; + FiberContainerType m_FiberBundles; ///< container for the output fiber bundles + std::vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints + FiberGenerationParameters m_Parameters; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkFibersFromPlanarFiguresFilter.cpp" #endif #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp index 96a0bb54f3..f8c20e0a59 100755 --- a/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Fiberfox/itkTractsToDWIImageFilter.cpp @@ -1,1763 +1,1765 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk { template< class PixelType > TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter() : m_StatusText("") , m_UseConstantRandSeed(false) , m_RandGen(itk::Statistics::MersenneTwisterRandomVariateGenerator::New()) { m_RandGen->SetSeed(); m_DoubleInterpolator = itk::LinearInterpolateImageFunction< ItkDoubleImgType, float >::New(); m_NullDir.Fill(0); } template< class PixelType > TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter() { } template< class PixelType > TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >:: SimulateKspaceAcquisition( std::vector< DoubleDwiType::Pointer >& compartment_images ) { unsigned int numFiberCompartments = m_Parameters.m_FiberModelList.size(); // create slice object ImageRegion<2> sliceRegion; sliceRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]); sliceRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]); Vector< double, 2 > sliceSpacing; sliceSpacing[0] = m_WorkingSpacing[0]; sliceSpacing[1] = m_WorkingSpacing[1]; DoubleDwiType::PixelType nullPix; nullPix.SetSize(compartment_images.at(0)->GetVectorLength()); nullPix.Fill(0.0); auto magnitudeDwiImage = DoubleDwiType::New(); magnitudeDwiImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); magnitudeDwiImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); magnitudeDwiImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); magnitudeDwiImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); magnitudeDwiImage->SetVectorLength( compartment_images.at(0)->GetVectorLength() ); magnitudeDwiImage->Allocate(); magnitudeDwiImage->FillBuffer(nullPix); m_PhaseImage = DoubleDwiType::New(); m_PhaseImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_PhaseImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); m_PhaseImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_PhaseImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_PhaseImage->SetVectorLength( compartment_images.at(0)->GetVectorLength() ); m_PhaseImage->Allocate(); m_PhaseImage->FillBuffer(nullPix); m_KspaceImage = DoubleDwiType::New(); m_KspaceImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_KspaceImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin ); m_KspaceImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_KspaceImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_KspaceImage->SetVectorLength( m_Parameters.m_SignalGen.m_NumberOfCoils ); m_KspaceImage->Allocate(); m_KspaceImage->FillBuffer(nullPix); std::vector< unsigned int > spikeVolume; if (m_Parameters.m_Misc.m_DoAddSpikes) for (unsigned int i=0; iGetIntegerVariate()%(compartment_images.at(0)->GetVectorLength())); std::sort (spikeVolume.begin(), spikeVolume.end()); std::reverse (spikeVolume.begin(), spikeVolume.end()); // calculate coil positions double a = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters.m_SignalGen.m_ImageSpacing[0]; double b = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters.m_SignalGen.m_ImageSpacing[1]; double c = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)*m_Parameters.m_SignalGen.m_ImageSpacing[2]; double diagonal = sqrt(a*a+b*b)/1000; // image diagonal in m m_CoilPointset = mitk::PointSet::New(); std::vector< itk::Vector > coilPositions; itk::Vector pos; pos.Fill(0.0); pos[1] = -diagonal/2; itk::Vector center; center[0] = a/2-m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; center[1] = b/2-m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; center[2] = c/2-m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; for (int c=0; cInsertPoint(c, pos*1000 + m_Parameters.m_SignalGen.m_ImageOrigin.GetVectorFromOrigin() + center ); double rz = 360.0/m_Parameters.m_SignalGen.m_NumberOfCoils * itk::Math::pi/180; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; pos.SetVnlVector(rotZ*pos.GetVnlVector()); } PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); unsigned long lastTick = 0; boost::progress_display disp(compartment_images.at(0)->GetVectorLength()*compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)); #pragma omp parallel for for (int g=0; g<(int)compartment_images.at(0)->GetVectorLength(); g++) { if (this->GetAbortGenerateData()) continue; std::vector< unsigned int > spikeSlice; #pragma omp critical while (!spikeVolume.empty() && (int)spikeVolume.back()==g) { spikeSlice.push_back(m_RandGen->GetIntegerVariate()%compartment_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< Float2DImageType::Pointer > compartment_slices; std::vector< float > t2Vector; std::vector< float > t1Vector; 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++) { Float2DImageType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; slice->SetPixel(index2D, compartment_images.at(i)->GetPixel(index3D)[g]); } compartment_slices.push_back(slice); t2Vector.push_back(signalModel->GetT2()); t1Vector.push_back(signalModel->GetT1()); } int numSpikes = 0; while (!spikeSlice.empty() && spikeSlice.back()==z) { numSpikes++; spikeSlice.pop_back(); } int spikeCoil = m_RandGen->GetIntegerVariate()%m_Parameters.m_SignalGen.m_NumberOfCoils; if (this->GetAbortGenerateData()) continue; for (int c=0; c::New(); idft->SetCompartmentImages(compartment_slices); idft->SetT2(t2Vector); idft->SetT1(t1Vector); idft->SetUseConstantRandSeed(m_UseConstantRandSeed); idft->SetParameters(&m_Parameters); idft->SetZ((float)z-(float)( compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2) -compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)%2 ) / 2.0); idft->SetZidx(z); idft->SetCoilPosition(coilPositions.at(c)); idft->SetFiberBundle(m_FiberBundle); idft->SetTranslation(m_Translations.at(g)); idft->SetRotation(m_Rotations.at(g)); idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g)); if (c==spikeCoil) idft->SetSpikesPerSlice(numSpikes); idft->Update(); #pragma omp critical if (c==spikeCoil && numSpikes>0) { m_SpikeLog += "Volume " + boost::lexical_cast(g) + " Coil " + boost::lexical_cast(c) + "\n"; m_SpikeLog += idft->GetSpikeLog(); } Complex2DImageType::Pointer fSlice; fSlice = idft->GetOutput(); // fourier transform slice Complex2DImageType::Pointer newSlice; auto dft = itk::DftImageFilter< Float2DImageType::PixelType >::New(); dft->SetInput(fSlice); dft->SetParameters(m_Parameters); 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; Complex2DImageType::IndexType index2D; index2D[0]=x; index2D[1]=y; Complex2DImageType::PixelType cPix = newSlice->GetPixel(index2D); double magn = sqrt(cPix.real()*cPix.real()+cPix.imag()*cPix.imag()); double phase = 0; if (cPix.real()!=0) phase = atan( cPix.imag()/cPix.real() ); DoubleDwiType::PixelType real_pix = m_OutputImagesReal.at(c)->GetPixel(index3D); real_pix[g] = cPix.real(); m_OutputImagesReal.at(c)->SetPixel(index3D, real_pix); DoubleDwiType::PixelType imag_pix = m_OutputImagesImag.at(c)->GetPixel(index3D); imag_pix[g] = cPix.imag(); m_OutputImagesImag.at(c)->SetPixel(index3D, imag_pix); DoubleDwiType::PixelType dwiPix = magnitudeDwiImage->GetPixel(index3D); DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D); if (m_Parameters.m_SignalGen.m_NumberOfCoils>1) { dwiPix[g] += magn*magn; phasePix[g] += phase*phase; } else { dwiPix[g] = magn; phasePix[g] = phase; } //#pragma omp critical { magnitudeDwiImage->SetPixel(index3D, dwiPix); m_PhaseImage->SetPixel(index3D, phasePix); // k-space image if (g==0) { DoubleDwiType::PixelType kspacePix = m_KspaceImage->GetPixel(index3D); kspacePix[c] = idft->GetKSpaceImage()->GetPixel(index2D); m_KspaceImage->SetPixel(index3D, kspacePix); } } } } if (m_Parameters.m_SignalGen.m_NumberOfCoils>1) { for (int y=0; y(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(1)); y++) for (int x=0; x(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(0)); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; DoubleDwiType::PixelType magPix = magnitudeDwiImage->GetPixel(index3D); magPix[g] = sqrt(magPix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils); DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D); phasePix[g] = sqrt(phasePix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils); //#pragma omp critical { magnitudeDwiImage->SetPixel(index3D, magPix); m_PhaseImage->SetPixel(index3D, phasePix); } } } ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) PrintToLog("*", false, false, false); lastTick = newTick; } } PrintToLog("\n", false); return magnitudeDwiImage; } template< class PixelType > TractsToDWIImageFilter< PixelType >::ItkDoubleImgType::Pointer TractsToDWIImageFilter< PixelType >:: NormalizeInsideMask(ItkDoubleImgType::Pointer image) { double max = itk::NumericTraits< double >::min(); double min = itk::NumericTraits< double >::max(); itk::ImageRegionIterator< ItkDoubleImgType > it(image, image->GetLargestPossibleRegion()); while(!it.IsAtEnd()) { if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && m_Parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0) { it.Set(0.0); ++it; continue; } if (it.Get()>max) max = it.Get(); if (it.Get()::New(); scaler->SetInput(image); scaler->SetShift(-min); scaler->SetScale(1.0/(max-min)); scaler->Update(); return scaler->GetOutput(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::CheckVolumeFractionImages() { m_UseRelativeNonFiberVolumeFractions = false; // check for fiber volume fraction maps unsigned int fibVolImages = 0; for (std::size_t i=0; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for fiber compartment " + boost::lexical_cast(i+1), false); fibVolImages++; } } // check for non-fiber volume fraction maps unsigned int nonfibVolImages = 0; for (std::size_t i=0; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for non-fiber compartment " + boost::lexical_cast(i+1), false); nonfibVolImages++; } } // not all fiber compartments are using volume fraction maps // --> non-fiber volume fractions are assumed to be relative to the // non-fiber volume and not absolute voxel-volume fractions. // this means if two non-fiber compartments are used but only one of them // has an associated volume fraction map, the repesctive other volume fraction map // can be determined as inverse (1-val) of the present volume fraction map- if ( fibVolImages::New(); inverter->SetMaximum(1.0); if ( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNull() && m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNotNull() ) { // m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage( // NormalizeInsideMask( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() ) ); inverter->SetInput( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() ); inverter->Update(); m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage(inverter->GetOutput()); } else if ( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNull() && m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNotNull() ) { // m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage( // NormalizeInsideMask( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() ) ); inverter->SetInput( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() ); inverter->Update(); m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage(inverter->GetOutput()); } else { itkExceptionMacro("Something went wrong in automatically calculating the missing non-fiber volume fraction image!" " Did you use two non fiber compartments but only one volume fraction image?" " Then it should work and this error is really strange."); } m_UseRelativeNonFiberVolumeFractions = true; nonfibVolImages++; } // Up to two fiber compartments are allowed without volume fraction maps since the volume fractions can then be determined automatically if (m_Parameters.m_FiberModelList.size()>2 && fibVolImages!=m_Parameters.m_FiberModelList.size()) itkExceptionMacro("More than two fiber compartment selected but no corresponding volume fraction maps set!"); // One non-fiber compartment is allowed without volume fraction map since the volume fraction can then be determined automatically if (m_Parameters.m_NonFiberModelList.size()>1 && nonfibVolImages!=m_Parameters.m_NonFiberModelList.size()) itkExceptionMacro("More than one non-fiber compartment selected but no volume fraction maps set!"); if (fibVolImages0) { PrintToLog("Not all fiber compartments are using an associated volume fraction image.\n" "Assuming non-fiber volume fraction images to contain values relative to the" " remaining non-fiber volume, not absolute values.", false); m_UseRelativeNonFiberVolumeFractions = true; // itk::ImageFileWriter::Pointer wr = itk::ImageFileWriter::New(); // wr->SetInput(m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage()); // wr->SetFileName("/local/volumefraction.nrrd"); // wr->Update(); } // initialize the images that store the output volume fraction of each compartment m_VolumeFractions.clear(); for (std::size_t i=0; iSetSpacing( m_WorkingSpacing ); doubleImg->SetOrigin( m_WorkingOrigin ); doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleImg->SetLargestPossibleRegion( m_WorkingImageRegion ); doubleImg->SetBufferedRegion( m_WorkingImageRegion ); doubleImg->SetRequestedRegion( m_WorkingImageRegion ); doubleImg->Allocate(); doubleImg->FillBuffer(0); m_VolumeFractions.push_back(doubleImg); } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::InitializeData() { m_Rotations.clear(); m_Translations.clear(); m_MotionLog = ""; m_SpikeLog = ""; // initialize output dwi image m_Parameters.m_SignalGen.m_CroppedRegion = m_Parameters.m_SignalGen.m_ImageRegion; if (m_Parameters.m_Misc.m_DoAddAliasing) m_Parameters.m_SignalGen.m_CroppedRegion.SetSize( 1, m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1) *m_Parameters.m_SignalGen.m_CroppingFactor); itk::Point shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1) -m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_OutputImage = OutputImageType::New(); m_OutputImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); m_OutputImage->SetOrigin( shiftedOrigin ); m_OutputImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_OutputImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); m_OutputImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); m_OutputImage->Allocate(); typename OutputImageType::PixelType temp; temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); temp.Fill(0.0); m_OutputImage->FillBuffer(temp); PrintToLog("Output image spacing: [" + boost::lexical_cast(m_Parameters.m_SignalGen.m_ImageSpacing[0]) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_ImageSpacing[1]) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_ImageSpacing[2]) + "]", false); PrintToLog("Output image size: [" + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(0)) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1)) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(2)) + "]", false); // images containing real and imaginary part of the dMRI signal for each coil m_OutputImagesReal.clear(); m_OutputImagesImag.clear(); for (int i=0; iSetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); outputImageReal->SetOrigin( shiftedOrigin ); outputImageReal->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); outputImageReal->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageReal->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageReal->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageReal->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); outputImageReal->Allocate(); outputImageReal->FillBuffer(temp); m_OutputImagesReal.push_back(outputImageReal); typename DoubleDwiType::Pointer outputImageImag = DoubleDwiType::New(); outputImageImag->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing ); outputImageImag->SetOrigin( shiftedOrigin ); outputImageImag->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); outputImageImag->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageImag->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageImag->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion ); outputImageImag->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); outputImageImag->Allocate(); outputImageImag->FillBuffer(temp); m_OutputImagesImag.push_back(outputImageImag); } // Apply in-plane upsampling for Gibbs ringing artifact double upsampling = 1; if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) upsampling = 2; m_WorkingSpacing = m_Parameters.m_SignalGen.m_ImageSpacing; m_WorkingSpacing[0] /= upsampling; m_WorkingSpacing[1] /= upsampling; m_WorkingImageRegion = m_Parameters.m_SignalGen.m_ImageRegion; m_WorkingImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling); m_WorkingImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling); m_WorkingOrigin = m_Parameters.m_SignalGen.m_ImageOrigin; m_WorkingOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; m_WorkingOrigin[0] += m_WorkingSpacing[0]/2; m_WorkingOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; m_WorkingOrigin[1] += m_WorkingSpacing[1]/2; m_WorkingOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; m_WorkingOrigin[2] += m_WorkingSpacing[2]/2; m_VoxelVolume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2]; PrintToLog("Working image spacing: [" + boost::lexical_cast(m_WorkingSpacing[0]) + "," + boost::lexical_cast(m_WorkingSpacing[1]) + "," + boost::lexical_cast(m_WorkingSpacing[2]) + "]", false); PrintToLog("Working image size: [" + boost::lexical_cast(m_WorkingImageRegion.GetSize(0)) + "," + boost::lexical_cast(m_WorkingImageRegion.GetSize(1)) + "," + boost::lexical_cast(m_WorkingImageRegion.GetSize(2)) + "]", false); // generate double images to store the individual compartment signals m_CompartmentImages.clear(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); for (int i=0; iSetSpacing( m_WorkingSpacing ); doubleDwi->SetOrigin( m_WorkingOrigin ); doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); doubleDwi->SetLargestPossibleRegion( m_WorkingImageRegion ); doubleDwi->SetBufferedRegion( m_WorkingImageRegion ); doubleDwi->SetRequestedRegion( m_WorkingImageRegion ); doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); m_CompartmentImages.push_back(doubleDwi); } if (m_FiberBundle.IsNull() && m_InputImage.IsNotNull()) { m_CompartmentImages.clear(); m_Parameters.m_SignalGen.m_DoAddMotion = false; m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; PrintToLog("Simulating acquisition for input diffusion-weighted image.", false); auto caster = itk::CastImageFilter< OutputImageType, DoubleDwiType >::New(); caster->SetInput(m_InputImage); caster->Update(); if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) { PrintToLog("Upsampling input diffusion-weighted image for Gibbs ringing simulation.", false); auto resampler = itk::ResampleDwiImageFilter< double >::New(); resampler->SetInput(caster->GetOutput()); itk::Vector< double, 3 > samplingFactor; samplingFactor[0] = upsampling; samplingFactor[1] = upsampling; samplingFactor[2] = 1; resampler->SetSamplingFactor(samplingFactor); resampler->SetInterpolation(itk::ResampleDwiImageFilter< double >::Interpolate_WindowedSinc); resampler->Update(); m_CompartmentImages.push_back(resampler->GetOutput()); } else m_CompartmentImages.push_back(caster->GetOutput()); for (unsigned int g=0; gGetLargestPossibleRegion()!=m_WorkingImageRegion) { PrintToLog("Resampling tissue mask", false); // rescale mask image (otherwise there are problems with the resampling) auto rescaler = itk::RescaleIntensityImageFilter::New(); rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); // resample mask image auto resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetSize(m_WorkingImageRegion.GetSize()); resampler->SetOutputSpacing(m_WorkingSpacing); resampler->SetOutputOrigin(m_WorkingOrigin); resampler->SetOutputDirection(m_Parameters.m_SignalGen.m_ImageDirection); resampler->SetOutputStartIndex ( m_WorkingImageRegion.GetIndex() ); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput(); } // resample frequency map if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && m_Parameters.m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion()!=m_WorkingImageRegion) { PrintToLog("Resampling frequency map", false); auto resampler = itk::ResampleImageFilter::New(); resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap); resampler->SetSize(m_WorkingImageRegion.GetSize()); resampler->SetOutputSpacing(m_WorkingSpacing); resampler->SetOutputOrigin(m_WorkingOrigin); resampler->SetOutputDirection(m_Parameters.m_SignalGen.m_ImageDirection); resampler->SetOutputStartIndex ( m_WorkingImageRegion.GetIndex() ); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput(); } m_MaskImageSet = true; if (m_Parameters.m_SignalGen.m_MaskImage.IsNull()) { // no input tissue mask is set -> create default PrintToLog("No tissue mask set", false); m_Parameters.m_SignalGen.m_MaskImage = ItkUcharImgType::New(); m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_WorkingSpacing ); m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_WorkingOrigin ); m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_WorkingImageRegion ); m_Parameters.m_SignalGen.m_MaskImage->Allocate(); m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(100); m_MaskImageSet = false; } else { PrintToLog("Using tissue mask", false); } if (m_Parameters.m_SignalGen.m_DoAddMotion) { if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { PrintToLog("Random motion artifacts:", false); PrintToLog("Maximum rotation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm", false); } else { PrintToLog("Linear motion artifacts:", false); PrintToLog("Maximum rotation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm", false); } } if ( m_Parameters.m_SignalGen.m_MotionVolumes.empty() ) { // no motion in first volume m_Parameters.m_SignalGen.m_MotionVolumes.push_back(false); // motion in all other volumes while ( m_Parameters.m_SignalGen.m_MotionVolumes.size() < m_Parameters.m_SignalGen.GetNumVolumes() ) { m_Parameters.m_SignalGen.m_MotionVolumes.push_back(true); } } // we need to know for every volume if there is motion. if this information is missing, then set corresponding fal to false while ( m_Parameters.m_SignalGen.m_MotionVolumes.size()::New(); duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage); duplicator->Update(); m_TransformedMaskImage = duplicator->GetOutput(); // second upsampling needed for motion artifacts ImageRegion<3> upsampledImageRegion = m_WorkingImageRegion; DoubleVectorType upsampledSpacing = m_WorkingSpacing; upsampledSpacing[0] /= 4; upsampledSpacing[1] /= 4; upsampledSpacing[2] /= 4; upsampledImageRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]*4); upsampledImageRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]*4); upsampledImageRegion.SetSize(2, m_WorkingImageRegion.GetSize()[2]*4); itk::Point upsampledOrigin = m_WorkingOrigin; upsampledOrigin[0] -= m_WorkingSpacing[0]/2; upsampledOrigin[0] += upsampledSpacing[0]/2; upsampledOrigin[1] -= m_WorkingSpacing[1]/2; upsampledOrigin[1] += upsampledSpacing[1]/2; upsampledOrigin[2] -= m_WorkingSpacing[2]/2; upsampledOrigin[2] += upsampledSpacing[2]/2; m_UpsampledMaskImage = ItkUcharImgType::New(); auto upsampler = itk::ResampleImageFilter::New(); upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage); upsampler->SetSize(upsampledImageRegion.GetSize()); upsampler->SetOutputSpacing(upsampledSpacing); upsampler->SetOutputOrigin(upsampledOrigin); auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction::New(); upsampler->SetInterpolator(nn_interpolator); upsampler->Update(); m_UpsampledMaskImage = upsampler->GetOutput(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::InitializeFiberData() { m_mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000; auto caster = itk::CastImageFilter< itk::Image, itk::Image >::New(); caster->SetInput(m_TransformedMaskImage); caster->Update(); vtkSmartPointer weights = m_FiberBundle->GetFiberWeights(); float mean_weight = 0; for (int i=0; iGetSize(); i++) mean_weight += weights->GetValue(i); mean_weight /= weights->GetSize(); if (mean_weight>0.000001) for (int i=0; iGetSize(); i++) m_FiberBundle->SetFiberWeight(i, weights->GetValue(i)/mean_weight); else PrintToLog("\nWarning: streamlines have VERY low weights. Average weight: " + boost::lexical_cast(mean_weight) + ". Possible source of calculation errors.", false, true, true); auto density_calculator = itk::TractDensityImageFilter< itk::Image >::New(); density_calculator->SetFiberBundle(m_FiberBundle); density_calculator->SetInputImage(caster->GetOutput()); density_calculator->SetBinaryOutput(false); density_calculator->SetUseImageGeometry(true); density_calculator->SetOutputAbsoluteValues(true); density_calculator->Update(); double max_density = density_calculator->GetMaxDensity(); double voxel_volume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2]; if (m_mmRadius>0) { std::stringstream stream; stream << std::fixed << setprecision(2) << itk::Math::pi*m_mmRadius*m_mmRadius*max_density; std::string s = stream.str(); PrintToLog("\nMax. fiber volume: " + s + "mm².", false, true, true); { double full_radius = 1000*std::sqrt(voxel_volume/(max_density*itk::Math::pi)); std::stringstream stream; stream << std::fixed << setprecision(2) << full_radius; std::string s = stream.str(); PrintToLog("\nA full fiber voxel corresponds to a fiber radius of ~" + s + "µm, given the current fiber configuration.", false, true, true); } } else { m_mmRadius = std::sqrt(voxel_volume/(max_density*itk::Math::pi)); std::stringstream stream; stream << std::fixed << setprecision(2) << m_mmRadius*1000; std::string s = stream.str(); PrintToLog("\nSetting fiber radius to " + s + "µm to obtain full voxel.", false, true, true); } // a second fiber bundle is needed to store the transformed version of the m_FiberBundleWorkingCopy m_FiberBundleTransformed = m_FiberBundle; } template< class PixelType > bool TractsToDWIImageFilter< PixelType >::PrepareLogFile() { - assert( ! m_Logfile.is_open() ); + if(m_Logfile.is_open()) + m_Logfile.close(); std::string filePath; std::string fileName; // Get directory name: if (m_Parameters.m_Misc.m_OutputPath.size() > 0) { filePath = m_Parameters.m_Misc.m_OutputPath; if( *(--(filePath.cend())) != '/') { filePath.push_back('/'); } } else { filePath = mitk::IOUtil::GetTempPath() + '/'; } // check if directory exists, else use /tmp/: if( itksys::SystemTools::FileIsDirectory( filePath ) ) { while( *(--(filePath.cend())) == '/') { filePath.pop_back(); } filePath = filePath + '/'; } else { filePath = mitk::IOUtil::GetTempPath() + '/'; } // Get file name: if( ! m_Parameters.m_Misc.m_ResultNode->GetName().empty() ) { fileName = m_Parameters.m_Misc.m_ResultNode->GetName(); } else { fileName = ""; } if( ! m_Parameters.m_Misc.m_OutputPrefix.empty() ) { fileName = m_Parameters.m_Misc.m_OutputPrefix + fileName; } else { fileName = "fiberfox"; } // check if file already exists and DO NOT overwrite existing files: std::string NameTest = fileName; int c = 0; while( itksys::SystemTools::FileExists( filePath + '/' + fileName + ".log" ) && c <= std::numeric_limits::max() ) { fileName = NameTest + "_" + boost::lexical_cast(c); ++c; } try { m_Logfile.open( ( filePath + '/' + fileName + ".log" ).c_str() ); } catch (const std::ios_base::failure &fail) { MITK_ERROR << "itkTractsToDWIImageFilter.cpp: Exception " << fail.what() << " while trying to open file" << filePath << '/' << fileName << ".log"; return false; } if ( m_Logfile.is_open() ) { PrintToLog( "Logfile: " + filePath + '/' + fileName + ".log", false ); return true; } else { m_StatusText += "Logfile could not be opened!\n"; MITK_ERROR << "itkTractsToDWIImageFilter.cpp: Logfile could not be opened!"; return false; } } template< class PixelType > void TractsToDWIImageFilter< PixelType >::GenerateData() { PrintToLog("\n**********************************************", false); // prepare logfile if ( ! PrepareLogFile() ) { this->SetAbortGenerateData( true ); return; } PrintToLog("Starting Fiberfox dMRI simulation"); m_TimeProbe.Start(); // check input data if (m_FiberBundle.IsNull() && m_InputImage.IsNull()) itkExceptionMacro("Input fiber bundle and input diffusion-weighted image is nullptr!"); if (m_Parameters.m_FiberModelList.empty() && m_InputImage.IsNull()) itkExceptionMacro("No diffusion model for fiber compartments defined and input diffusion-weighted" " image is nullptr! At least one fiber compartment is necessary to simulate diffusion."); if (m_Parameters.m_NonFiberModelList.empty() && m_InputImage.IsNull()) itkExceptionMacro("No diffusion model for non-fiber compartments defined and input diffusion-weighted" " image is nullptr! At least one non-fiber compartment is necessary to simulate diffusion."); if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) // no partial volume? remove all but first fiber compartment while (m_Parameters.m_FiberModelList.size()>1) m_Parameters.m_FiberModelList.pop_back(); if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) // No upsampling of input image needed if no k-space simulation is performed m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false; if (m_UseConstantRandSeed) // always generate the same random numbers? m_RandGen->SetSeed(0); else m_RandGen->SetSeed(); InitializeData(); if ( m_FiberBundle.IsNotNull() ) // if no fiber bundle is found, we directly proceed to the k-space acquisition simulation { CheckVolumeFractionImages(); InitializeFiberData(); int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); double maxVolume = 0; unsigned long lastTick = 0; int signalModelSeed = m_RandGen->GetIntegerVariate(); PrintToLog("\n", false, false); PrintToLog("Generating " + boost::lexical_cast(numFiberCompartments+numNonFiberCompartments) + "-compartment diffusion-weighted signal."); std::vector< int > bVals = m_Parameters.m_SignalGen.GetBvalues(); PrintToLog("b-values: ", false, false, true); for (auto v : bVals) PrintToLog(boost::lexical_cast(v) + " ", false, false, true); PrintToLog("\nVolumes: " + boost::lexical_cast(m_Parameters.m_SignalGen.GetNumVolumes()), false, true, true); PrintToLog("\n", false, false, true); PrintToLog("\n", false, false, true); unsigned int image_size_x = m_WorkingImageRegion.GetSize(0); unsigned int region_size_y = m_WorkingImageRegion.GetSize(1); unsigned int num_gradients = m_Parameters.m_SignalGen.GetNumVolumes(); int numFibers = m_FiberBundle->GetNumFibers(); boost::progress_display disp(numFibers*num_gradients); if (m_FiberBundle->GetMeanFiberLength()<5.0) omp_set_num_threads(2); PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); for (unsigned int g=0; gSetSeed(signalModelSeed); for (std::size_t i=0; iSetSeed(signalModelSeed); // storing voxel-wise intra-axonal volume in mm³ auto intraAxonalVolumeImage = ItkDoubleImgType::New(); intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing ); intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin ); intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection ); intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion ); intraAxonalVolumeImage->Allocate(); intraAxonalVolumeImage->FillBuffer(0); maxVolume = 0; double* intraAxBuffer = intraAxonalVolumeImage->GetBufferPointer(); if (this->GetAbortGenerateData()) continue; vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData(); // generate fiber signal (if there are any fiber models present) if (!m_Parameters.m_FiberModelList.empty()) { std::vector< double* > buffers; for (unsigned int i=0; iGetBufferPointer()); #pragma omp parallel for for( int i=0; iGetAbortGenerateData()) continue; float fiberWeight = m_FiberBundleTransformed->GetFiberWeight(i); int numPoints = -1; std::vector< itk::Vector > points_copy; #pragma omp critical { vtkCell* cell = fiberPolyData->GetCell(i); numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j))); } if (numPoints<2) continue; double seg_volume = fiberWeight*itk::Math::pi*m_mmRadius*m_mmRadius; for( int j=0; jGetAbortGenerateData()) { j=numPoints; continue; } itk::Vector v = points_copy.at(j); itk::Vector dir = points_copy.at(j+1)-v; if ( dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2] ) continue; dir.Normalize(); itk::Point startVertex = points_copy.at(j); itk::Index<3> startIndex; itk::ContinuousIndex startIndexCont; m_TransformedMaskImage->TransformPhysicalPointToIndex(startVertex, startIndex); m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont); itk::Point endVertex = points_copy.at(j+1); itk::Index<3> endIndex; itk::ContinuousIndex endIndexCont; m_TransformedMaskImage->TransformPhysicalPointToIndex(endVertex, endIndex); m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont); std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(m_WorkingSpacing, startIndex, endIndex, startIndexCont, endIndexCont); // generate signal for each fiber compartment for (int k=0; kSimulateMeasurement(g, dir)*seg_volume; for (std::pair< itk::Index<3>, double > seg : segments) { if (!m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(seg.first) || m_TransformedMaskImage->GetPixel(seg.first)<=0) continue; double seg_signal = seg.second*signal_add; unsigned int linear_index = g + num_gradients*seg.first[0] + num_gradients*image_size_x*seg.first[1] + num_gradients*image_size_x*region_size_y*seg.first[2]; // update dMRI volume #pragma omp atomic buffers[k][linear_index] += seg_signal; // update fiber volume image if (k==0) { linear_index = seg.first[0] + image_size_x*seg.first[1] + image_size_x*region_size_y*seg.first[2]; #pragma omp atomic intraAxBuffer[linear_index] += seg.second*seg_volume; double vol = intraAxBuffer[linear_index]; if (vol>maxVolume) { maxVolume = vol; } } } } } #pragma omp critical { // progress report ++disp; unsigned long newTick = 50*disp.count()/disp.expected_count(); for (unsigned int tick = 0; tick<(newTick-lastTick); ++tick) PrintToLog("*", false, false, false); lastTick = newTick; } } } // axon radius not manually defined --> set fullest voxel (maxVolume) to full fiber voxel double density_correctiony_global = 1.0; if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001) density_correctiony_global = m_VoxelVolume/maxVolume; // generate non-fiber signal ImageRegionIterator it3(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion()); while(!it3.IsAtEnd()) { if (it3.Get()>0) { DoubleDwiType::IndexType index = it3.GetIndex(); double iAxVolume = intraAxonalVolumeImage->GetPixel(index); // get non-transformed point (remove headmotion tranformation) // this point lives in the volume fraction image space itk::Point volume_fraction_point; if ( m_Parameters.m_SignalGen.m_DoAddMotion && m_Parameters.m_SignalGen.m_MotionVolumes[g] ) volume_fraction_point = GetMovedPoint(index, false); else m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, volume_fraction_point); if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) { if (iAxVolume>0.0001) // scale fiber compartment to voxel { DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); pix[g] *= m_VoxelVolume/iAxVolume; m_CompartmentImages.at(0)->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(0)->SetPixel(index, 1); } else { DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); pix[g] = 0; m_CompartmentImages.at(0)->SetPixel(index, pix); SimulateExtraAxonalSignal(index, volume_fraction_point, 0, g); } } else { // manually defined axon radius and voxel overflow --> rescale to voxel volume if ( m_Parameters.m_SignalGen.m_AxonRadius>=0.0001 && iAxVolume>m_VoxelVolume ) { for (int i=0; iGetPixel(index); pix[g] *= m_VoxelVolume/iAxVolume; m_CompartmentImages.at(i)->SetPixel(index, pix); } iAxVolume = m_VoxelVolume; } // if volume fraction image is set use it, otherwise use global scaling factor double density_correction_voxel = density_correctiony_global; if ( m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr && iAxVolume>0.0001 ) { m_DoubleInterpolator->SetInputImage(m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()); double volume_fraction = mitk::imv::GetImageValue(volume_fraction_point, true, m_DoubleInterpolator); if (volume_fraction<0) mitkThrow() << "Volume fraction image (index 1) contains negative values (intra-axonal compartment)!"; density_correction_voxel = m_VoxelVolume*volume_fraction/iAxVolume; // remove iAxVolume sclaing and scale to volume_fraction } else if (m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr) density_correction_voxel = 0.0; // adjust intra-axonal compartment volume by density correction factor DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index); pix[g] *= density_correction_voxel; m_CompartmentImages.at(0)->SetPixel(index, pix); // normalize remaining fiber volume fractions (they are rescaled in SimulateExtraAxonalSignal) if (iAxVolume>0.0001) { for (int i=1; iGetPixel(index); pix[g] /= iAxVolume; m_CompartmentImages.at(i)->SetPixel(index, pix); } } else { for (int i=1; iGetPixel(index); pix[g] = 0; m_CompartmentImages.at(i)->SetPixel(index, pix); } } iAxVolume = density_correction_voxel*iAxVolume; // new intra-axonal volume = old intra-axonal volume * correction factor // simulate other compartments SimulateExtraAxonalSignal(index, volume_fraction_point, iAxVolume, g); } } ++it3; } } PrintToLog("\n", false); } if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } DoubleDwiType::Pointer doubleOutImage; double signalScale = m_Parameters.m_SignalGen.m_SignalScale; if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition ) // do k-space stuff { PrintToLog("\n", false, false); PrintToLog("Simulating k-space acquisition using " +boost::lexical_cast(m_Parameters.m_SignalGen.m_NumberOfCoils) +" coil(s)"); switch (m_Parameters.m_SignalGen.m_AcquisitionType) { case SignalGenerationParameters::SingleShotEpi: { PrintToLog("Acquisition type: single shot EPI", false); break; } case SignalGenerationParameters::SpinEcho: { PrintToLog("Acquisition type: classic spin echo with cartesian k-space trajectory", false); break; } default: { PrintToLog("Acquisition type: single shot EPI", false); break; } } if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation) PrintToLog("Simulating signal relaxation", false); if (m_Parameters.m_SignalGen.m_NoiseVariance>0 && m_Parameters.m_Misc.m_DoAddNoise) PrintToLog("Simulating complex Gaussian noise: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_NoiseVariance), false); if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && m_Parameters.m_Misc.m_DoAddDistortions) PrintToLog("Simulating distortions", false); if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging) PrintToLog("Simulating ringing artifacts", false); if (m_Parameters.m_Misc.m_DoAddEddyCurrents && m_Parameters.m_SignalGen.m_EddyStrength>0) PrintToLog("Simulating eddy currents: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_EddyStrength), false); if (m_Parameters.m_Misc.m_DoAddSpikes && m_Parameters.m_SignalGen.m_Spikes>0) PrintToLog("Simulating spikes: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Spikes), false); if (m_Parameters.m_Misc.m_DoAddAliasing && m_Parameters.m_SignalGen.m_CroppingFactor<1.0) PrintToLog("Simulating aliasing: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppingFactor), false); if (m_Parameters.m_Misc.m_DoAddGhosts && m_Parameters.m_SignalGen.m_KspaceLineOffset>0) PrintToLog("Simulating ghosts: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_KspaceLineOffset), false); doubleOutImage = SimulateKspaceAcquisition(m_CompartmentImages); signalScale = 1; // already scaled in SimulateKspaceAcquisition() } else // don't do k-space stuff, just sum compartments { PrintToLog("Summing compartments"); doubleOutImage = m_CompartmentImages.at(0); for (unsigned int i=1; i::New(); adder->SetInput1(doubleOutImage); adder->SetInput2(m_CompartmentImages.at(i)); adder->Update(); doubleOutImage = adder->GetOutput(); } } if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } PrintToLog("Finalizing image"); if (m_Parameters.m_SignalGen.m_DoAddDrift && m_Parameters.m_SignalGen.m_Drift>0.0) PrintToLog("Adding signal drift: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Drift), false); if (signalScale>1) PrintToLog("Scaling signal", false); if (m_Parameters.m_NoiseModel) PrintToLog("Adding noise: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_NoiseVariance), false); unsigned int window = 0; unsigned int min = itk::NumericTraits::max(); ImageRegionIterator it4 (m_OutputImage, m_OutputImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.m_SignalGen.GetNumVolumes()); boost::progress_display disp2(m_OutputImage->GetLargestPossibleRegion().GetNumberOfPixels()); PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false); PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false); int lastTick = 0; while(!it4.IsAtEnd()) { if (this->GetAbortGenerateData()) { PrintToLog("\n", false, false); PrintToLog("Simulation aborted"); return; } ++disp2; unsigned long newTick = 50*disp2.count()/disp2.expected_count(); for (unsigned long tick = 0; tick<(newTick-lastTick); tick++) PrintToLog("*", false, false, false); lastTick = newTick; typename OutputImageType::IndexType index = it4.GetIndex(); signal = doubleOutImage->GetPixel(index)*signalScale; for (unsigned int i=0; iAddNoise(signal); for (unsigned int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]>window) window = signal[i]; if ( (!m_Parameters.m_SignalGen.IsBaselineIndex(i) || signal.Size()==1) && signal[i]SetNthOutput(0, m_OutputImage); PrintToLog("\n", false); PrintToLog("Finished simulation"); m_TimeProbe.Stop(); if (m_Parameters.m_SignalGen.m_DoAddMotion) { PrintToLog("\nHead motion log:", false); PrintToLog(m_MotionLog, false, false); } if (m_Parameters.m_Misc.m_DoAddSpikes && m_Parameters.m_SignalGen.m_Spikes>0) { PrintToLog("\nSpike log:", false); PrintToLog(m_SpikeLog, false, false); } - if (m_Logfile.is_open()) m_Logfile.close(); + if (m_Logfile.is_open()) + m_Logfile.close(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::PrintToLog(std::string m, bool addTime, bool linebreak, bool stdOut) { // timestamp if (addTime) { m_Logfile << this->GetTime() << " > "; m_StatusText += this->GetTime() + " > "; if (stdOut) std::cout << this->GetTime() << " > "; } // message if (m_Logfile.is_open()) m_Logfile << m; m_StatusText += m; if (stdOut) std::cout << m; // new line if (linebreak) { if (m_Logfile.is_open()) m_Logfile << "\n"; m_StatusText += "\n"; if (stdOut) std::cout << "\n"; } m_Logfile.flush(); } template< class PixelType > void TractsToDWIImageFilter< PixelType >::SimulateMotion(int g) { // is motion artifact enabled? // is the current volume g affected by motion? if ( m_Parameters.m_SignalGen.m_DoAddMotion && m_Parameters.m_SignalGen.m_MotionVolumes[g] && g(m_Parameters.m_SignalGen.GetNumVolumes()) ) { if ( m_Parameters.m_SignalGen.m_DoRandomizeMotion ) { // either undo last transform or work on fresh copy of untransformed fibers m_FiberBundleTransformed = m_FiberBundle->GetDeepCopy(); m_Rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2) -m_Parameters.m_SignalGen.m_Rotation[0]; m_Rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2) -m_Parameters.m_SignalGen.m_Rotation[1]; m_Rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2) -m_Parameters.m_SignalGen.m_Rotation[2]; m_Translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2) -m_Parameters.m_SignalGen.m_Translation[0]; m_Translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2) -m_Parameters.m_SignalGen.m_Translation[1]; m_Translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2) -m_Parameters.m_SignalGen.m_Translation[2]; } else { m_Rotation = m_Parameters.m_SignalGen.m_Rotation / m_NumMotionVolumes; m_Translation = m_Parameters.m_SignalGen.m_Translation / m_NumMotionVolumes; m_MotionCounter++; } // move mask image if (m_MaskImageSet) { ImageRegionIterator maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion()); m_TransformedMaskImage->FillBuffer(0); while(!maskIt.IsAtEnd()) { if (maskIt.Get()<=0) { ++maskIt; continue; } DoubleDwiType::IndexType index = maskIt.GetIndex(); m_TransformedMaskImage->TransformPhysicalPointToIndex(GetMovedPoint(index, true), index); if (m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(index)) m_TransformedMaskImage->SetPixel(index,100); ++maskIt; } } if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { m_Rotations.push_back(m_Rotation); m_Translations.push_back(m_Translation); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]) + "," + boost::lexical_cast(m_Rotation[1]) + "," + boost::lexical_cast(m_Rotation[2]) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]) + "," + boost::lexical_cast(m_Translation[1]) + "," + boost::lexical_cast(m_Translation[2]) + "\n"; } else { m_Rotations.push_back(m_Rotation*m_MotionCounter); m_Translations.push_back(m_Translation*m_MotionCounter); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]*m_MotionCounter) + "," + boost::lexical_cast(m_Rotation[1]*m_MotionCounter) + "," + boost::lexical_cast(m_Rotation[2]*m_MotionCounter) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]*m_MotionCounter) + "," + boost::lexical_cast(m_Translation[1]*m_MotionCounter) + "," + boost::lexical_cast(m_Translation[2]*m_MotionCounter) + "\n"; } m_FiberBundleTransformed->TransformFibers(m_Rotation[0],m_Rotation[1],m_Rotation[2],m_Translation[0],m_Translation[1],m_Translation[2]); } else { m_Rotation.Fill(0.0); m_Translation.Fill(0.0); m_Rotations.push_back(m_Rotation); m_Translations.push_back(m_Translation); m_MotionLog += boost::lexical_cast(g) + " rotation: " + boost::lexical_cast(m_Rotation[0]) + "," + boost::lexical_cast(m_Rotation[1]) + "," + boost::lexical_cast(m_Rotation[2]) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translation[0]) + "," + boost::lexical_cast(m_Translation[1]) + "," + boost::lexical_cast(m_Translation[2]) + "\n"; } } template< class PixelType > itk::Point TractsToDWIImageFilter< PixelType >::GetMovedPoint(itk::Index<3>& index, bool forward) { itk::Point transformed_point; if (forward) { m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, transformed_point); if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { transformed_point = m_FiberBundle->TransformPoint(transformed_point.GetVnlVector(), m_Rotation[0],m_Rotation[1],m_Rotation[2], m_Translation[0],m_Translation[1],m_Translation[2]); } else { transformed_point = m_FiberBundle->TransformPoint(transformed_point.GetVnlVector(), m_Rotation[0]*m_MotionCounter,m_Rotation[1]*m_MotionCounter,m_Rotation[2]*m_MotionCounter, m_Translation[0]*m_MotionCounter,m_Translation[1]*m_MotionCounter,m_Translation[2]*m_MotionCounter); } } else { m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, transformed_point); if (m_Parameters.m_SignalGen.m_DoRandomizeMotion) { transformed_point = m_FiberBundle->TransformPoint( transformed_point.GetVnlVector(), -m_Rotation[0], -m_Rotation[1], -m_Rotation[2], -m_Translation[0], -m_Translation[1], -m_Translation[2] ); } else { transformed_point = m_FiberBundle->TransformPoint( transformed_point.GetVnlVector(), -m_Rotation[0]*m_MotionCounter, -m_Rotation[1]*m_MotionCounter, -m_Rotation[2]*m_MotionCounter, -m_Translation[0]*m_MotionCounter, -m_Translation[1]*m_MotionCounter, -m_Translation[2]*m_MotionCounter ); } } return transformed_point; } template< class PixelType > void TractsToDWIImageFilter< PixelType >:: SimulateExtraAxonalSignal(ItkUcharImgType::IndexType& index, itk::Point& volume_fraction_point, double intraAxonalVolume, int g) { int numFiberCompartments = m_Parameters.m_FiberModelList.size(); int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size(); if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) { // simulate signal for largest non-fiber compartment int max_compartment_index = 0; double max_fraction = 0; if (numNonFiberCompartments>1) { for (int i=0; iSetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); double compartment_fraction = mitk::imv::GetImageValue(volume_fraction_point, true, m_DoubleInterpolator); if (compartment_fraction<0) mitkThrow() << "Volume fraction image (index " << i << ") contains values less than zero!"; if (compartment_fraction>max_fraction) { max_fraction = compartment_fraction; max_compartment_index = i; } } } DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(max_compartment_index+numFiberCompartments); DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); pix[g] += m_Parameters.m_NonFiberModelList[max_compartment_index]->SimulateMeasurement(g, m_NullDir)*m_VoxelVolume; doubleDwi->SetPixel(index, pix); if (g==0) m_VolumeFractions.at(max_compartment_index+numFiberCompartments)->SetPixel(index, 1); } else { std::vector< double > fractions; if (g==0) m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume); double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume; // non-fiber volume if (extraAxonalVolume<0) { if (extraAxonalVolume<-0.001) MITK_ERROR << "Corrupted intra-axonal signal voxel detected. Fiber volume larger voxel volume! " << m_VoxelVolume << "<" << intraAxonalVolume; extraAxonalVolume = 0; } double interAxonalVolume = 0; if (numFiberCompartments>1) interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment double nonFiberVolume = extraAxonalVolume - interAxonalVolume; // rest of compartment if (nonFiberVolume<0) { if (nonFiberVolume<-0.001) MITK_ERROR << "Corrupted signal voxel detected. Fiber volume larger voxel volume!"; nonFiberVolume = 0; interAxonalVolume = extraAxonalVolume; } double compartmentSum = intraAxonalVolume; fractions.push_back(intraAxonalVolume/m_VoxelVolume); // rescale extra-axonal fiber signal for (int i=1; iGetVolumeFractionImage()!=nullptr) { m_DoubleInterpolator->SetInputImage(m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()); interAxonalVolume = mitk::imv::GetImageValue(volume_fraction_point, true, m_DoubleInterpolator)*m_VoxelVolume; if (interAxonalVolume<0) mitkThrow() << "Volume fraction image (index " << i+1 << ") contains negative values!"; } DoubleDwiType::PixelType pix = m_CompartmentImages.at(i)->GetPixel(index); pix[g] *= interAxonalVolume; m_CompartmentImages.at(i)->SetPixel(index, pix); compartmentSum += interAxonalVolume; fractions.push_back(interAxonalVolume/m_VoxelVolume); if (g==0) m_VolumeFractions.at(i)->SetPixel(index, interAxonalVolume/m_VoxelVolume); } for (int i=0; iGetVolumeFractionImage()!=nullptr) { m_DoubleInterpolator->SetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); volume = mitk::imv::GetImageValue(volume_fraction_point, true, m_DoubleInterpolator)*m_VoxelVolume; if (volume<0) mitkThrow() << "Volume fraction image (index " << numFiberCompartments+i+1 << ") contains negative values (non-fiber compartment)!"; if (m_UseRelativeNonFiberVolumeFractions) volume *= nonFiberVolume/m_VoxelVolume; } DoubleDwiType::PixelType pix = m_CompartmentImages.at(i+numFiberCompartments)->GetPixel(index); pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g, m_NullDir)*volume; m_CompartmentImages.at(i+numFiberCompartments)->SetPixel(index, pix); compartmentSum += volume; fractions.push_back(volume/m_VoxelVolume); if (g==0) m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, volume/m_VoxelVolume); } if (compartmentSum/m_VoxelVolume>1.05) { MITK_ERROR << "Compartments do not sum to 1 in voxel " << index << " (" << compartmentSum/m_VoxelVolume << ")"; for (auto val : fractions) MITK_ERROR << val; } } } 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 > double TractsToDWIImageFilter< PixelType >::RoundToNearest(double num) { return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5); } template< class PixelType > std::string TractsToDWIImageFilter< PixelType >::GetTime() { m_TimeProbe.Stop(); unsigned long total = RoundToNearest(m_TimeProbe.GetTotal()); 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)); m_TimeProbe.Start(); return out; } } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp index 30777b4b0e..0790febc01 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.cpp @@ -1,1019 +1,1044 @@ /*=================================================================== 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. ===================================================================*/ #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include #include #include #include #include mitk::FiberfoxParameters::FiberfoxParameters() : m_NoiseModel(nullptr) { + mitk::StickModel* model_aniso = new mitk::StickModel(); + model_aniso->m_CompartmentId = 1; + m_FiberModelList.push_back(model_aniso); + mitk::BallModel* model_iso = new mitk::BallModel(); + model_iso->m_CompartmentId = 3; + m_NonFiberModelList.push_back(model_iso); } mitk::FiberfoxParameters::FiberfoxParameters(const mitk::FiberfoxParameters& params) : m_NoiseModel(nullptr) { m_FiberGen = params.m_FiberGen; m_SignalGen = params.m_SignalGen; m_Misc = params.m_Misc; if (params.m_NoiseModel!=nullptr) { if (dynamic_cast*>(params.m_NoiseModel.get())) m_NoiseModel = std::make_shared< mitk::RicianNoiseModel<> >(); else if (dynamic_cast*>(params.m_NoiseModel.get())) m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel<> >(); m_NoiseModel->SetNoiseVariance(params.m_NoiseModel->GetNoiseVariance()); } for (unsigned int i=0; i* outModel = nullptr; mitk::DiffusionSignalModel<>* signalModel = nullptr; if (i*>(signalModel)) outModel = new mitk::StickModel<>(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::TensorModel<>(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::RawShModel<>(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::BallModel<>(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::AstroStickModel<>(dynamic_cast*>(signalModel)); else if (dynamic_cast*>(signalModel)) outModel = new mitk::DotModel<>(dynamic_cast*>(signalModel)); if (i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*itk::Math::pi); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i mitk::SignalGenerationParameters::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; } unsigned int mitk::SignalGenerationParameters::GetFirstBaselineIndex() { for( unsigned int i=0; im_GradientDirections.size(); i++) if (m_GradientDirections.at(i).GetNorm()<0.0001) return i; return -1; } bool mitk::SignalGenerationParameters::IsBaselineIndex(unsigned int idx) { if (m_GradientDirections.size()>idx && m_GradientDirections.at(idx).GetNorm()<0.0001) return true; return false; } unsigned int mitk::SignalGenerationParameters::GetNumWeightedVolumes() { return m_NumGradients; } unsigned int mitk::SignalGenerationParameters::GetNumBaselineVolumes() { return m_NumBaseline; } unsigned int mitk::SignalGenerationParameters::GetNumVolumes() { return m_GradientDirections.size(); } mitk::SignalGenerationParameters::GradientListType mitk::SignalGenerationParameters::GetGradientDirections() { return m_GradientDirections; } mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::SignalGenerationParameters::GetItkGradientContainer() { int c = 0; mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer out = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New(); for (auto g : m_GradientDirections) { mitk::DiffusionPropertyHelper::GradientDirectionType vnl_dir; vnl_dir[0] = g[0]; vnl_dir[1] = g[1]; vnl_dir[2] = g[2]; out->InsertElement(c, vnl_dir); ++c; } return out; } mitk::SignalGenerationParameters::GradientType mitk::SignalGenerationParameters::GetGradientDirection(unsigned int i) { return m_GradientDirections.at(i); } void mitk::SignalGenerationParameters::SetNumWeightedVolumes(int numGradients) { m_NumGradients = numGradients; GenerateGradientHalfShell(); } std::vector< int > mitk::SignalGenerationParameters::GetBvalues() { std::vector< int > bVals; for( GradientType g : m_GradientDirections) { float norm = g.GetNorm(); int bVal = std::round(norm*norm*m_Bvalue); if ( std::find(bVals.begin(), bVals.end(), bVal) == bVals.end() ) bVals.push_back(bVal); } return bVals; } double mitk::SignalGenerationParameters::GetBvalue() { return m_Bvalue; } void mitk::SignalGenerationParameters::SetGradienDirections(GradientListType gradientList) { m_GradientDirections = gradientList; m_NumGradients = 0; m_NumBaseline = 0; for( unsigned int i=0; im_GradientDirections.size(); i++) { float norm = m_GradientDirections.at(i).GetNorm(); if (norm>0.0001) m_NumGradients++; else m_NumBaseline++; } } void mitk::SignalGenerationParameters::SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::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); float norm = m_GradientDirections.at(i).GetNorm(); if (norm>0.0001) m_NumGradients++; else m_NumBaseline++; } } void mitk::FiberfoxParameters::SaveParameters(std::string filename) { if(filename.empty()) return; if(".ffp"!=filename.substr(filename.size()-4, 4)) filename += ".ffp"; const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, nullptr ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } boost::property_tree::ptree parameters; // fiber generation parameters parameters.put("fiberfox.fibers.distribution", m_FiberGen.m_Distribution); parameters.put("fiberfox.fibers.variance", m_FiberGen.m_Variance); parameters.put("fiberfox.fibers.density", m_FiberGen.m_Density); parameters.put("fiberfox.fibers.spline.sampling", m_FiberGen.m_Sampling); parameters.put("fiberfox.fibers.spline.tension", m_FiberGen.m_Tension); parameters.put("fiberfox.fibers.spline.continuity", m_FiberGen.m_Continuity); parameters.put("fiberfox.fibers.spline.bias", m_FiberGen.m_Bias); parameters.put("fiberfox.fibers.rotation.x", m_FiberGen.m_Rotation[0]); parameters.put("fiberfox.fibers.rotation.y", m_FiberGen.m_Rotation[1]); parameters.put("fiberfox.fibers.rotation.z", m_FiberGen.m_Rotation[2]); parameters.put("fiberfox.fibers.translation.x", m_FiberGen.m_Translation[0]); parameters.put("fiberfox.fibers.translation.y", m_FiberGen.m_Translation[1]); parameters.put("fiberfox.fibers.translation.z", m_FiberGen.m_Translation[2]); parameters.put("fiberfox.fibers.scale.x", m_FiberGen.m_Scale[0]); parameters.put("fiberfox.fibers.scale.y", m_FiberGen.m_Scale[1]); parameters.put("fiberfox.fibers.scale.z", m_FiberGen.m_Scale[2]); // image generation parameters parameters.put("fiberfox.image.basic.size.x", m_SignalGen.m_ImageRegion.GetSize(0)); parameters.put("fiberfox.image.basic.size.y", m_SignalGen.m_ImageRegion.GetSize(1)); parameters.put("fiberfox.image.basic.size.z", m_SignalGen.m_ImageRegion.GetSize(2)); parameters.put("fiberfox.image.basic.spacing.x", m_SignalGen.m_ImageSpacing[0]); parameters.put("fiberfox.image.basic.spacing.y", m_SignalGen.m_ImageSpacing[1]); parameters.put("fiberfox.image.basic.spacing.z", m_SignalGen.m_ImageSpacing[2]); parameters.put("fiberfox.image.basic.origin.x", m_SignalGen.m_ImageOrigin[0]); parameters.put("fiberfox.image.basic.origin.y", m_SignalGen.m_ImageOrigin[1]); parameters.put("fiberfox.image.basic.origin.z", m_SignalGen.m_ImageOrigin[2]); parameters.put("fiberfox.image.basic.direction.d1", m_SignalGen.m_ImageDirection[0][0]); parameters.put("fiberfox.image.basic.direction.d2", m_SignalGen.m_ImageDirection[0][1]); parameters.put("fiberfox.image.basic.direction.d3", m_SignalGen.m_ImageDirection[0][2]); parameters.put("fiberfox.image.basic.direction.d4", m_SignalGen.m_ImageDirection[1][0]); parameters.put("fiberfox.image.basic.direction.d5", m_SignalGen.m_ImageDirection[1][1]); parameters.put("fiberfox.image.basic.direction.d6", m_SignalGen.m_ImageDirection[1][2]); parameters.put("fiberfox.image.basic.direction.d7", m_SignalGen.m_ImageDirection[2][0]); parameters.put("fiberfox.image.basic.direction.d8", m_SignalGen.m_ImageDirection[2][1]); parameters.put("fiberfox.image.basic.direction.d9", m_SignalGen.m_ImageDirection[2][2]); mitk::gradients::WriteBvalsBvecs(filename+".bvals", filename+".bvecs", m_SignalGen.GetItkGradientContainer(), m_SignalGen.m_Bvalue); parameters.put("fiberfox.image.acquisitiontype", m_SignalGen.m_AcquisitionType); parameters.put("fiberfox.image.coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile); parameters.put("fiberfox.image.numberofcoils", m_SignalGen.m_NumberOfCoils); parameters.put("fiberfox.image.reversephase", m_SignalGen.m_ReversePhase); parameters.put("fiberfox.image.partialfourier", m_SignalGen.m_PartialFourier); parameters.put("fiberfox.image.noisevariance", m_SignalGen.m_NoiseVariance); parameters.put("fiberfox.image.trep", m_SignalGen.m_tRep); parameters.put("fiberfox.image.signalScale", m_SignalGen.m_SignalScale); parameters.put("fiberfox.image.tEcho", m_SignalGen.m_tEcho); parameters.put("fiberfox.image.tLine", m_SignalGen.m_tLine); parameters.put("fiberfox.image.tInhom", m_SignalGen.m_tInhom); parameters.put("fiberfox.image.simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition); parameters.put("fiberfox.image.axonRadius", m_SignalGen.m_AxonRadius); parameters.put("fiberfox.image.doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation); parameters.put("fiberfox.image.doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume); parameters.put("fiberfox.image.artifacts.spikesnum", m_SignalGen.m_Spikes); parameters.put("fiberfox.image.artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude); parameters.put("fiberfox.image.artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset); parameters.put("fiberfox.image.artifacts.eddyStrength", m_SignalGen.m_EddyStrength); parameters.put("fiberfox.image.artifacts.eddyTau", m_SignalGen.m_Tau); parameters.put("fiberfox.image.artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor); parameters.put("fiberfox.image.artifacts.drift", m_SignalGen.m_Drift); parameters.put("fiberfox.image.artifacts.doAddMotion", m_SignalGen.m_DoAddMotion); parameters.put("fiberfox.image.artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion); parameters.put("fiberfox.image.artifacts.translation0", m_SignalGen.m_Translation[0]); parameters.put("fiberfox.image.artifacts.translation1", m_SignalGen.m_Translation[1]); parameters.put("fiberfox.image.artifacts.translation2", m_SignalGen.m_Translation[2]); parameters.put("fiberfox.image.artifacts.rotation0", m_SignalGen.m_Rotation[0]); parameters.put("fiberfox.image.artifacts.rotation1", m_SignalGen.m_Rotation[1]); parameters.put("fiberfox.image.artifacts.rotation2", m_SignalGen.m_Rotation[2]); parameters.put("fiberfox.image.artifacts.motionvolumes", m_Misc.m_MotionVolumesBox); parameters.put("fiberfox.image.artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging); parameters.put("fiberfox.image.artifacts.addnoise", m_Misc.m_DoAddNoise); parameters.put("fiberfox.image.artifacts.addghosts", m_Misc.m_DoAddGhosts); parameters.put("fiberfox.image.artifacts.addaliasing", m_Misc.m_DoAddAliasing); parameters.put("fiberfox.image.artifacts.addspikes", m_Misc.m_DoAddSpikes); parameters.put("fiberfox.image.artifacts.addeddycurrents", m_Misc.m_DoAddEddyCurrents); parameters.put("fiberfox.image.artifacts.doAddDistortions", m_Misc.m_DoAddDistortions); parameters.put("fiberfox.image.artifacts.doAddDrift", m_SignalGen.m_DoAddDrift); parameters.put("fiberfox.image.outputvolumefractions", m_Misc.m_CheckOutputVolumeFractionsBox); parameters.put("fiberfox.image.showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox); parameters.put("fiberfox.image.signalmodelstring", m_Misc.m_SignalModelString); parameters.put("fiberfox.image.artifactmodelstring", m_Misc.m_ArtifactModelString); parameters.put("fiberfox.image.outpath", m_Misc.m_OutputPath); parameters.put("fiberfox.fibers.realtime", m_Misc.m_CheckRealTimeFibersBox); parameters.put("fiberfox.fibers.showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox); parameters.put("fiberfox.fibers.constantradius", m_Misc.m_CheckConstantRadiusBox); parameters.put("fiberfox.fibers.includeFiducials", m_Misc.m_CheckIncludeFiducialsBox); if (m_NoiseModel!=nullptr) { parameters.put("fiberfox.image.artifacts.noisevariance", m_NoiseModel->GetNoiseVariance()); if (dynamic_cast*>(m_NoiseModel.get())) parameters.put("fiberfox.image.artifacts.noisetype", "rice"); else if (dynamic_cast*>(m_NoiseModel.get())) parameters.put("fiberfox.image.artifacts.noisetype", "chisquare"); } for (std::size_t i=0; i* signalModel = nullptr; if (i(i)+".type", "fiber"); } else { signalModel = m_NonFiberModelList.at(i-m_FiberModelList.size()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".type", "non-fiber"); } if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "stick"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d", model->GetDiffusivity()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t2", model->GetT2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "tensor"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d1", model->GetDiffusivity1()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d2", model->GetDiffusivity2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d3", model->GetDiffusivity3()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t2", model->GetT2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "prototype"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".minFA", model->GetFaRange().first); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".maxFA", model->GetFaRange().second); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".minADC", model->GetAdcRange().first); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".maxADC", model->GetAdcRange().second); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".maxNumSamples", model->GetMaxNumKernels()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".numSamples", model->GetNumberOfKernels()); int shOrder = model->GetShOrder(); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".numCoeffs", (shOrder*shOrder + shOrder + 2)/2 + shOrder); for (unsigned int j=0; jGetNumberOfKernels(); j++) { vnl_vector< double > coeffs = model->GetCoefficients(j); for (unsigned int k=0; k(i)+".kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k), coeffs[k]); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".kernels."+boost::lexical_cast(j)+".B0", model->GetBaselineSignal(j)); } } else if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "ball"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d", model->GetDiffusivity()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t2", model->GetT2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t1", model->GetT1()); } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "astrosticks"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".d", model->GetDiffusivity()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t2", model->GetT2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t1", model->GetT1()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".randomize", model->GetRandomizeSticks()); } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".model", "dot"); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t2", model->GetT2()); parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".t1", model->GetT1()); } if (signalModel!=nullptr) { parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast(i)+".ID", signalModel->m_CompartmentId); if (signalModel->GetVolumeFractionImage().IsNotNull()) { try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); writer->SetFileName(filename+"_VOLUME"+boost::lexical_cast(signalModel->m_CompartmentId)+".nii.gz"); writer->SetInput(signalModel->GetVolumeFractionImage()); writer->Update(); MITK_INFO << "Volume fraction image for compartment "+boost::lexical_cast(signalModel->m_CompartmentId)+" saved."; } catch(...) { } } } } boost::property_tree::xml_writer_settings writerSettings(' ', 2); boost::property_tree::xml_parser::write_xml(filename, parameters, std::locale(), writerSettings); try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); writer->SetFileName(filename+"_FMAP.nii.gz"); writer->SetInput(m_SignalGen.m_FrequencyMap); writer->Update(); } catch(...) { MITK_INFO << "No frequency map saved."; } try{ itk::ImageFileWriter::Pointer writer = itk::ImageFileWriter::New(); writer->SetFileName(filename+"_MASK.nii.gz"); writer->SetInput(m_SignalGen.m_MaskImage); writer->Update(); } catch(...) { MITK_INFO << "No mask image saved."; } setlocale(LC_ALL, currLocale.c_str()); } template< class ParameterType > ParameterType mitk::FiberfoxParameters::ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential) { try { return v.second.get(tag); } catch (...) { if (essential) { mitkThrow() << "Parameter file corrupted. Essential tag is missing: '" << tag << "'"; } if (tag!="artifacts.noisetype") { MITK_INFO << "Tag '" << tag << "' not found. Using default value '" << defaultValue << "'."; m_MissingTags += "\n- "; m_MissingTags += tag; } return defaultValue; } } void mitk::FiberfoxParameters::UpdateSignalModels() { for (mitk::DiffusionSignalModel<>* m : m_FiberModelList) { m->SetGradientList(m_SignalGen.m_GradientDirections); m->SetBvalue(m_SignalGen.m_Bvalue); } for (mitk::DiffusionSignalModel<>* m : m_NonFiberModelList) { m->SetGradientList(m_SignalGen.m_GradientDirections); m->SetBvalue(m_SignalGen.m_Bvalue); } } void mitk::FiberfoxParameters::SetNumWeightedVolumes(int numGradients) { m_SignalGen.SetNumWeightedVolumes(numGradients); UpdateSignalModels(); } void mitk::FiberfoxParameters::SetGradienDirections(mitk::SignalGenerationParameters::GradientListType gradientList) { m_SignalGen.SetGradienDirections(gradientList); UpdateSignalModels(); } void mitk::FiberfoxParameters::SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList) { m_SignalGen.SetGradienDirections(gradientList); UpdateSignalModels(); } void mitk::FiberfoxParameters::SetBvalue(double Bvalue) { m_SignalGen.m_Bvalue = Bvalue; UpdateSignalModels(); } void mitk::FiberfoxParameters::GenerateGradientHalfShell() { m_SignalGen.GenerateGradientHalfShell(); UpdateSignalModels(); } void mitk::FiberfoxParameters::LoadParameters(std::string filename) { srand(time(0)); m_MissingTags = ""; if(filename.empty()) { return; } const std::string& locale = "C"; const std::string& currLocale = setlocale( LC_ALL, nullptr ); if ( locale.compare(currLocale)!=0 ) { try { setlocale(LC_ALL, locale.c_str()); } catch(...) { MITK_INFO << "Could not set locale " << locale; } } boost::property_tree::ptree parameterTree; boost::property_tree::xml_parser::read_xml( filename, parameterTree ); m_FiberModelList.clear(); m_NonFiberModelList.clear(); if (m_NoiseModel) { m_NoiseModel = nullptr; } BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameterTree.get_child("fiberfox") ) { if( v1.first == "fibers" ) { m_Misc.m_CheckRealTimeFibersBox = ReadVal(v1,"realtime", m_Misc.m_CheckRealTimeFibersBox); m_Misc.m_CheckAdvancedFiberOptionsBox = ReadVal(v1,"showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox); m_Misc.m_CheckConstantRadiusBox = ReadVal(v1,"constantradius", m_Misc.m_CheckConstantRadiusBox); m_Misc.m_CheckIncludeFiducialsBox = ReadVal(v1,"includeFiducials", m_Misc.m_CheckIncludeFiducialsBox); switch (ReadVal(v1,"distribution", 0)) { case 0: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } m_FiberGen.m_Variance = ReadVal(v1,"variance", m_FiberGen.m_Variance); m_FiberGen.m_Density = ReadVal(v1,"density", m_FiberGen.m_Density); m_FiberGen.m_Sampling = ReadVal(v1,"spline.sampling", m_FiberGen.m_Sampling); m_FiberGen.m_Tension = ReadVal(v1,"spline.tension", m_FiberGen.m_Tension); m_FiberGen.m_Continuity = ReadVal(v1,"spline.continuity", m_FiberGen.m_Continuity); m_FiberGen.m_Bias = ReadVal(v1,"spline.bias", m_FiberGen.m_Bias); m_FiberGen.m_Rotation[0] = ReadVal(v1,"rotation.x", m_FiberGen.m_Rotation[0]); m_FiberGen.m_Rotation[1] = ReadVal(v1,"rotation.y", m_FiberGen.m_Rotation[1]); m_FiberGen.m_Rotation[2] = ReadVal(v1,"rotation.z", m_FiberGen.m_Rotation[2]); m_FiberGen.m_Translation[0] = ReadVal(v1,"translation.x", m_FiberGen.m_Translation[0]); m_FiberGen.m_Translation[1] = ReadVal(v1,"translation.y", m_FiberGen.m_Translation[1]); m_FiberGen.m_Translation[2] = ReadVal(v1,"translation.z", m_FiberGen.m_Translation[2]); m_FiberGen.m_Scale[0] = ReadVal(v1,"scale.x", m_FiberGen.m_Scale[0]); m_FiberGen.m_Scale[1] = ReadVal(v1,"scale.y", m_FiberGen.m_Scale[1]); m_FiberGen.m_Scale[2] = ReadVal(v1,"scale.z", m_FiberGen.m_Scale[2]); } else if ( v1.first == "image" ) { m_Misc.m_SignalModelString = ReadVal(v1,"signalmodelstring", m_Misc.m_SignalModelString); m_Misc.m_ArtifactModelString = ReadVal(v1,"artifactmodelstring", m_Misc.m_ArtifactModelString); m_Misc.m_OutputPath = ReadVal(v1,"outpath", m_Misc.m_OutputPath); m_Misc.m_CheckOutputVolumeFractionsBox = ReadVal(v1,"outputvolumefractions", m_Misc.m_CheckOutputVolumeFractionsBox); m_Misc.m_CheckAdvancedSignalOptionsBox = ReadVal(v1,"showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox); m_Misc.m_DoAddDistortions = ReadVal(v1,"artifacts.doAddDistortions", m_Misc.m_DoAddDistortions); m_Misc.m_DoAddNoise = ReadVal(v1,"artifacts.addnoise", m_Misc.m_DoAddNoise); m_Misc.m_DoAddGhosts = ReadVal(v1,"artifacts.addghosts", m_Misc.m_DoAddGhosts); m_Misc.m_DoAddAliasing = ReadVal(v1,"artifacts.addaliasing", m_Misc.m_DoAddAliasing); m_Misc.m_DoAddSpikes = ReadVal(v1,"artifacts.addspikes", m_Misc.m_DoAddSpikes); m_Misc.m_DoAddEddyCurrents = ReadVal(v1,"artifacts.addeddycurrents", m_Misc.m_DoAddEddyCurrents); m_SignalGen.m_ImageRegion.SetSize(0, ReadVal(v1,"basic.size.x",m_SignalGen.m_ImageRegion.GetSize(0))); m_SignalGen.m_ImageRegion.SetSize(1, ReadVal(v1,"basic.size.y",m_SignalGen.m_ImageRegion.GetSize(1))); m_SignalGen.m_ImageRegion.SetSize(2, ReadVal(v1,"basic.size.z",m_SignalGen.m_ImageRegion.GetSize(2))); m_SignalGen.m_ImageSpacing[0] = ReadVal(v1,"basic.spacing.x",m_SignalGen.m_ImageSpacing[0]); m_SignalGen.m_ImageSpacing[1] = ReadVal(v1,"basic.spacing.y",m_SignalGen.m_ImageSpacing[1]); m_SignalGen.m_ImageSpacing[2] = ReadVal(v1,"basic.spacing.z",m_SignalGen.m_ImageSpacing[2]); m_SignalGen.m_ImageOrigin[0] = ReadVal(v1,"basic.origin.x",m_SignalGen.m_ImageOrigin[0]); m_SignalGen.m_ImageOrigin[1] = ReadVal(v1,"basic.origin.y",m_SignalGen.m_ImageOrigin[1]); m_SignalGen.m_ImageOrigin[2] = ReadVal(v1,"basic.origin.z",m_SignalGen.m_ImageOrigin[2]); int i = 0; int j = 0; for(auto v : v1.second.get_child("basic.direction")) { m_SignalGen.m_ImageDirection[i][j] = boost::lexical_cast(v.second.data()); ++j; if (j==3) { j = 0; ++i; } } m_SignalGen.m_AcquisitionType = (SignalGenerationParameters::AcquisitionType)ReadVal(v1,"acquisitiontype", m_SignalGen.m_AcquisitionType); m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)ReadVal(v1,"coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile); m_SignalGen.m_NumberOfCoils = ReadVal(v1,"numberofcoils", m_SignalGen.m_NumberOfCoils); m_SignalGen.m_ReversePhase = ReadVal(v1,"reversephase", m_SignalGen.m_ReversePhase); m_SignalGen.m_PartialFourier = ReadVal(v1,"partialfourier", m_SignalGen.m_PartialFourier); m_SignalGen.m_NoiseVariance = ReadVal(v1,"noisevariance", m_SignalGen.m_NoiseVariance); m_SignalGen.m_tRep = ReadVal(v1,"trep", m_SignalGen.m_tRep); m_SignalGen.m_SignalScale = ReadVal(v1,"signalScale", m_SignalGen.m_SignalScale); m_SignalGen.m_tEcho = ReadVal(v1,"tEcho", m_SignalGen.m_tEcho); m_SignalGen.m_tLine = ReadVal(v1,"tLine", m_SignalGen.m_tLine); m_SignalGen.m_tInhom = ReadVal(v1,"tInhom", m_SignalGen.m_tInhom); m_SignalGen.m_SimulateKspaceAcquisition = ReadVal(v1,"simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition); m_SignalGen.m_AxonRadius = ReadVal(v1,"axonRadius", m_SignalGen.m_AxonRadius); m_SignalGen.m_Spikes = ReadVal(v1,"artifacts.spikesnum", m_SignalGen.m_Spikes); m_SignalGen.m_SpikeAmplitude = ReadVal(v1,"artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude); m_SignalGen.m_KspaceLineOffset = ReadVal(v1,"artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset); m_SignalGen.m_EddyStrength = ReadVal(v1,"artifacts.eddyStrength", m_SignalGen.m_EddyStrength); m_SignalGen.m_Tau = ReadVal(v1,"artifacts.eddyTau", m_SignalGen.m_Tau); m_SignalGen.m_CroppingFactor = ReadVal(v1,"artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor); m_SignalGen.m_Drift = ReadVal(v1,"artifacts.drift", m_SignalGen.m_Drift); m_SignalGen.m_DoAddGibbsRinging = ReadVal(v1,"artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging); m_SignalGen.m_DoSimulateRelaxation = ReadVal(v1,"doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation); m_SignalGen.m_DoDisablePartialVolume = ReadVal(v1,"doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume); m_SignalGen.m_DoAddMotion = ReadVal(v1,"artifacts.doAddMotion", m_SignalGen.m_DoAddMotion); m_SignalGen.m_DoRandomizeMotion = ReadVal(v1,"artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion); m_SignalGen.m_DoAddDrift = ReadVal(v1,"artifacts.doAddDrift", m_SignalGen.m_DoAddDrift); m_SignalGen.m_Translation[0] = ReadVal(v1,"artifacts.translation0", m_SignalGen.m_Translation[0]); m_SignalGen.m_Translation[1] = ReadVal(v1,"artifacts.translation1", m_SignalGen.m_Translation[1]); m_SignalGen.m_Translation[2] = ReadVal(v1,"artifacts.translation2", m_SignalGen.m_Translation[2]); m_SignalGen.m_Rotation[0] = ReadVal(v1,"artifacts.rotation0", m_SignalGen.m_Rotation[0]); m_SignalGen.m_Rotation[1] = ReadVal(v1,"artifacts.rotation1", m_SignalGen.m_Rotation[1]); m_SignalGen.m_Rotation[2] = ReadVal(v1,"artifacts.rotation2", m_SignalGen.m_Rotation[2]); if (itksys::SystemTools::FileExists(filename+".bvals") && itksys::SystemTools::FileExists(filename+".bvecs")) { - m_SignalGen.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(filename+".bvals", filename+".bvecs", m_SignalGen.m_Bvalue) ); + m_Misc.m_BvalsFile = filename+".bvals"; + m_Misc.m_BvecsFile = filename+".bvecs"; + m_SignalGen.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Misc.m_BvalsFile, m_Misc.m_BvecsFile, m_SignalGen.m_Bvalue) ); } else { m_SignalGen.m_Bvalue = ReadVal(v1,"bvalue", m_SignalGen.m_Bvalue); SignalGenerationParameters::GradientListType gradients; try { BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("gradients") ) { SignalGenerationParameters::GradientType g; g[0] = ReadVal(v2,"x",0); g[1] = ReadVal(v2,"y",0); g[2] = ReadVal(v2,"z",0); gradients.push_back(g); } } catch(...) { MITK_INFO << "WARNING: Fiberfox parameters without any gradient directions loaded."; } m_SignalGen.SetGradienDirections(gradients); } m_Misc.m_MotionVolumesBox = ReadVal(v1,"artifacts.motionvolumes", m_Misc.m_MotionVolumesBox); m_SignalGen.m_MotionVolumes.clear(); if ( m_Misc.m_MotionVolumesBox == "random" ) { m_SignalGen.m_MotionVolumes.push_back(0); for ( size_t i=1; i < m_SignalGen.GetNumVolumes(); ++i ) { m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) ); } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case m_Misc.m_MotionVolumesBox == \"random\"."; } else if ( ! m_Misc.m_MotionVolumesBox.empty() ) { std::stringstream stream( m_Misc.m_MotionVolumesBox ); std::vector numbers; int nummer = std::numeric_limits::max(); while( stream >> nummer ) { if( nummer < std::numeric_limits::max() ) { numbers.push_back( nummer ); } } // If a list of negative numbers is given: if( *(std::min_element( numbers.begin(), numbers.end() )) < 0 && *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0 { for ( size_t i=0; i(m_SignalGen.GetNumVolumes()) && -number >= 0 ) m_SignalGen.m_MotionVolumes.at(-number) = false; } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of negative numbers."; } // If a list of positive numbers is given: else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0 && *(std::max_element( numbers.begin(), numbers.end() )) >= 0 ) { for ( size_t i=0; i(m_SignalGen.GetNumVolumes()) && number >= 0) m_SignalGen.m_MotionVolumes.at(number) = true; } MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of positive numbers."; } else { MITK_WARN << "mitkFiberfoxParameters.cpp: Inconsistent list of numbers in m_MotionVolumesBox."; break; } } else { MITK_WARN << "mitkFiberfoxParameters.cpp: Cannot make sense of string in m_MotionVolumesBox."; break; } try { if (ReadVal(v1,"artifacts.noisetype","")=="rice") { m_NoiseModel = std::make_shared< mitk::RicianNoiseModel<> >(); m_NoiseModel->SetNoiseVariance(ReadVal(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance())); } } catch(...) { MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()"; // throw; } try { if (ReadVal(v1,"artifacts.noisetype","")=="chisquare") { m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel<> >(); m_NoiseModel->SetNoiseVariance(ReadVal(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance())); } } catch(...) { MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()"; // throw; } BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("compartments") ) { mitk::DiffusionSignalModel<>* signalModel = nullptr; std::string model = ReadVal(v2,"model","",true); if (model=="stick") { mitk::StickModel<>* model = new mitk::StickModel<>(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="tensor") { mitk::TensorModel<>* model = new mitk::TensorModel<>(); model->SetDiffusivity1(ReadVal(v2,"d1",model->GetDiffusivity1())); model->SetDiffusivity2(ReadVal(v2,"d2",model->GetDiffusivity2())); model->SetDiffusivity3(ReadVal(v2,"d3",model->GetDiffusivity3())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="ball") { mitk::BallModel<>* model = new mitk::BallModel<>(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->m_CompartmentId = ReadVal(v2,"ID",0,true); if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="astrosticks") { mitk::AstroStickModel<>* model = new AstroStickModel<>(); model->SetDiffusivity(ReadVal(v2,"d",model->GetDiffusivity())); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->SetBvalue(m_SignalGen.m_Bvalue); model->SetRandomizeSticks(ReadVal(v2,"randomize",model->GetRandomizeSticks())); model->m_CompartmentId = ReadVal(v2,"ID",0,true); if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="dot") { mitk::DotModel<>* model = new mitk::DotModel<>(); model->SetT2(ReadVal(v2,"t2",model->GetT2())); model->SetT1(ReadVal(v2,"t1",model->GetT1())); model->m_CompartmentId = ReadVal(v2,"ID",0,true); if (ReadVal(v2,"type","",true)=="fiber") m_FiberModelList.push_back(model); else if (ReadVal(v2,"type","",true)=="non-fiber") m_NonFiberModelList.push_back(model); signalModel = model; } else if (model=="prototype") { mitk::RawShModel<>* model = new mitk::RawShModel<>(); model->SetMaxNumKernels(ReadVal(v2,"maxNumSamples",model->GetMaxNumKernels())); model->SetFaRange(ReadVal(v2,"minFA",model->GetFaRange().first), ReadVal(v2,"maxFA",model->GetFaRange().second)); model->SetAdcRange(ReadVal(v2,"minADC",model->GetAdcRange().first), ReadVal(v2,"maxADC",model->GetAdcRange().second)); model->m_CompartmentId = ReadVal(v2,"ID",0,true); unsigned int numCoeffs = ReadVal(v2,"numCoeffs",0,true); unsigned int numSamples = ReadVal(v2,"numSamples",0,true); for (unsigned int j=0; j coeffs(numCoeffs); for (unsigned int k=0; k(v2,"kernels."+boost::lexical_cast(j)+".coeffs."+boost::lexical_cast(k),0,true); } model->SetShCoefficients( coeffs, ReadVal(v2,"kernels."+boost::lexical_cast(j)+".B0",0,true) ); } if (ReadVal(v2,"type","",true)=="fiber") { m_FiberModelList.push_back(model); } else if (ReadVal(v2,"type","",true)=="non-fiber") { m_NonFiberModelList.push_back(model); } // else ? signalModel = model; } if (signalModel!=nullptr) { try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); if ( itksys::SystemTools::FileExists(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nii.gz") ) reader->SetFileName(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nii.gz"); else if ( itksys::SystemTools::FileExists(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nii") ) reader->SetFileName(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nii"); else reader->SetFileName(filename+"_VOLUME"+ReadVal(v2,"ID","")+".nrrd"); reader->Update(); signalModel->SetVolumeFractionImage(reader->GetOutput()); MITK_INFO << "Volume fraction image loaded for compartment " << signalModel->m_CompartmentId; } catch(...) { MITK_INFO << "No volume fraction image found for compartment " << signalModel->m_CompartmentId; } } } } else { } } UpdateSignalModels(); try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); reader->SetFileName(filename+"_FMAP.nrrd"); if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii.gz") ) reader->SetFileName(filename+"_FMAP.nii.gz"); else if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii") ) reader->SetFileName(filename+"_FMAP.nii"); else reader->SetFileName(filename+"_FMAP.nrrd"); reader->Update(); m_SignalGen.m_FrequencyMap = reader->GetOutput(); MITK_INFO << "Frequency map loaded."; } catch(...) { MITK_INFO << "No frequency map found."; } try { itk::ImageFileReader::Pointer reader = itk::ImageFileReader::New(); if ( itksys::SystemTools::FileExists(filename+"_MASK.nii.gz") ) reader->SetFileName(filename+"_MASK.nii.gz"); else if ( itksys::SystemTools::FileExists(filename+"_MASK.nii") ) reader->SetFileName(filename+"_MASK.nii"); else reader->SetFileName(filename+"_MASK.nrrd"); reader->Update(); m_SignalGen.m_MaskImage = reader->GetOutput(); m_SignalGen.m_ImageRegion = m_SignalGen.m_MaskImage->GetLargestPossibleRegion(); m_SignalGen.m_ImageSpacing = m_SignalGen.m_MaskImage->GetSpacing(); m_SignalGen.m_ImageOrigin = m_SignalGen.m_MaskImage->GetOrigin(); m_SignalGen.m_ImageDirection = m_SignalGen.m_MaskImage->GetDirection(); MITK_INFO << "Mask image loaded."; } catch(...) { MITK_INFO << "No mask image found."; } setlocale(LC_ALL, currLocale.c_str()); } void mitk::FiberfoxParameters::PrintSelf() { MITK_INFO << "Not implemented :("; } diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h index 48c2093104..2ca404962e 100644 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/mitkFiberfoxParameters.h @@ -1,319 +1,326 @@ /*=================================================================== 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 #include #include #include #include #include #include #include #include #include #include namespace mitk { class MITKFIBERTRACKING_EXPORT FiberfoxParameters; /** Signal generation */ class MITKFIBERTRACKING_EXPORT SignalGenerationParameters { friend FiberfoxParameters; public: typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; typedef itk::Vector GradientType; typedef std::vector GradientListType; enum CoilSensitivityProfile : int { COIL_CONSTANT, COIL_LINEAR, COIL_EXPONENTIAL }; enum AcquisitionType : int { SingleShotEpi, SpinEcho }; SignalGenerationParameters() : m_AcquisitionType(SignalGenerationParameters::SingleShotEpi) , m_SignalScale(100) , m_tEcho(100) , m_tRep(4000) , m_tLine(1) , m_tInhom(50) , m_ReversePhase(false) , m_PartialFourier(1.0) , m_NoiseVariance(0.001) , m_NumberOfCoils(1) , m_CoilSensitivityProfile(SignalGenerationParameters::COIL_CONSTANT) , m_SimulateKspaceAcquisition(false) , m_AxonRadius(0) , m_DoDisablePartialVolume(false) , m_Spikes(0) , m_SpikeAmplitude(1) , m_KspaceLineOffset(0) , m_EddyStrength(300) , m_Tau(70) , m_CroppingFactor(1) , m_Drift(0.06) , m_DoAddGibbsRinging(false) , m_DoSimulateRelaxation(true) , m_DoAddMotion(false) , m_DoRandomizeMotion(true) , m_DoAddDrift(false) , m_FrequencyMap(nullptr) , m_MaskImage(nullptr) , m_Bvalue(1000) { m_ImageRegion.SetSize(0, 12); m_ImageRegion.SetSize(1, 12); m_ImageRegion.SetSize(2, 3); m_ImageSpacing.Fill(2.0); m_ImageOrigin.Fill(0.0); m_ImageDirection.SetIdentity(); m_Translation.Fill(0.0); m_Rotation.Fill(0.0); SetNumWeightedVolumes(6); } /** input/output image specifications */ itk::ImageRegion<3> m_CroppedRegion; ///< Image size with reduced FOV. itk::ImageRegion<3> m_ImageRegion; ///< Image size. itk::Vector m_ImageSpacing; ///< Image voxel size. itk::Point m_ImageOrigin; ///< Image origin. itk::Matrix m_ImageDirection; ///< Image rotation matrix. /** Other acquisitions parameters */ AcquisitionType m_AcquisitionType; ///< determines k-space trajectory and maximum echo position(s) float m_SignalScale; ///< Scaling factor for output signal (before noise is added). float m_tEcho; ///< Echo time TE. float m_tRep; ///< Echo time TR. float m_tLine; ///< k-space line readout time (dwell time). float m_tInhom; ///< T2' bool m_ReversePhase; ///< If true, the phase readout direction will be inverted (-y instead of y) float m_PartialFourier; ///< Partial fourier factor (0.5-1) float m_NoiseVariance; ///< Variance of complex gaussian noise int m_NumberOfCoils; ///< Number of coils in multi-coil acquisition CoilSensitivityProfile m_CoilSensitivityProfile; ///< Choose between constant, linear or exponential sensitivity profile of the used coils bool m_SimulateKspaceAcquisition;///< Flag to enable/disable k-space acquisition simulation double m_AxonRadius; ///< Determines compartment volume fractions (0 == automatic axon radius estimation) bool m_DoDisablePartialVolume; ///< Disable partial volume effects. Each voxel is either all fiber or all non-fiber. /** Artifacts and other effects */ unsigned int m_Spikes; ///< Number of spikes randomly appearing in the image float m_SpikeAmplitude; ///< amplitude of spikes relative to the largest signal intensity (magnitude of complex) float m_KspaceLineOffset; ///< Causes N/2 ghosts. Larger offset means stronger ghost. float m_EddyStrength; ///< Strength of eddy current induced gradients in mT/m. float m_Tau; ///< Eddy current decay constant (in ms) float m_CroppingFactor; ///< FOV size in y-direction is multiplied by this factor. Causes aliasing artifacts. float m_Drift; ///< Global signal decrease by the end of the acquisition. bool m_DoAddGibbsRinging; ///< Add Gibbs ringing artifact bool m_DoSimulateRelaxation; ///< Add T2 relaxation effects bool m_DoAddMotion; ///< Enable motion artifacts. bool m_DoRandomizeMotion; ///< Toggles between random and linear motion. bool m_DoAddDrift; ///< Add quadratic signal drift. std::vector< bool > m_MotionVolumes; ///< Indicates the image volumes that are affected by motion ///< with positive numbers, inverted logic with negative numbers. itk::Vector m_Translation; ///< Maximum translational motion. itk::Vector m_Rotation; ///< Maximum rotational motion. ItkFloatImgType::Pointer m_FrequencyMap; ///< If != nullptr, distortions are added to the image using this frequency map. ItkUcharImgType::Pointer m_MaskImage; ///< Signal is only genrated inside of the mask image. std::vector< int > GetBaselineIndices(); ///< Returns list of nun-diffusion-weighted image volume indices unsigned int GetFirstBaselineIndex(); ///< Returns index of first non-diffusion-weighted image volume bool IsBaselineIndex(unsigned int idx); ///< Checks if image volume with given index is non-diffusion-weighted volume or not. unsigned int GetNumWeightedVolumes(); ///< Get number of diffusion-weighted image volumes unsigned int GetNumBaselineVolumes(); ///< Get number of non-diffusion-weighted image volumes unsigned int GetNumVolumes(); ///< Get number of baseline and diffusion-weighted image volumes GradientListType GetGradientDirections(); ///< Return gradient direction container mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer GetItkGradientContainer(); GradientType GetGradientDirection(unsigned int i); std::vector< int > GetBvalues(); ///< Returns a vector with all unique b-values (determined by the gradient magnitudes) double GetBvalue(); protected: unsigned int m_NumGradients; ///< Number of diffusion-weighted image volumes. unsigned int m_NumBaseline; ///< Number of non-diffusion-weighted image volumes. GradientListType m_GradientDirections; ///< Total number of image volumes. double m_Bvalue; ///< Acquisition b-value void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards. void SetGradienDirections(GradientListType gradientList); void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList); void GenerateGradientHalfShell(); ///< Generates half shell of gradient directions (with m_NumGradients non-zero directions) }; /** Fiber generation */ class MITKFIBERTRACKING_EXPORT FiberGenerationParameters { public: enum FiberDistribution { DISTRIBUTE_UNIFORM, // distribute fibers uniformly in the ROIs DISTRIBUTE_GAUSSIAN // distribute fibers using a 2D gaussian }; typedef std::vector< std::vector< mitk::PlanarEllipse::Pointer > > FiducialListType; typedef std::vector< std::vector< unsigned int > > FlipListType; FiberGenerationParameters() : m_Distribution(DISTRIBUTE_UNIFORM) , m_Density(100) , m_Variance(100) , m_Sampling(1) , m_Tension(0) , m_Continuity(0) , m_Bias(0) { m_Rotation.Fill(0.0); m_Translation.Fill(0.0); m_Scale.Fill(1.0); } FiberDistribution m_Distribution; unsigned int m_Density; double m_Variance; double m_Sampling; double m_Tension; double m_Continuity; double m_Bias; mitk::Vector3D m_Rotation; mitk::Vector3D m_Translation; mitk::Vector3D m_Scale; FlipListType m_FlipList; ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting) FiducialListType m_Fiducials; ///< container of the planar ellipses used as fiducials for the fiber generation process }; /** GUI persistence, input, output, ... */ class MITKFIBERTRACKING_EXPORT MiscFiberfoxParameters { public: MiscFiberfoxParameters() : m_ResultNode(DataNode::New()) , m_ParentNode(nullptr) , m_SignalModelString("") , m_ArtifactModelString("") , m_OutputPath("/tmp/") , m_OutputPrefix("fiberfox") + , m_AfterSimulationMessage("") + , m_BvalsFile("") + , m_BvecsFile("") , m_CheckOutputVolumeFractionsBox(false) , m_CheckAdvancedSignalOptionsBox(false) , m_DoAddNoise(false) , m_DoAddGhosts(false) , m_DoAddAliasing(false) , m_DoAddSpikes(false) , m_DoAddEddyCurrents(false) , m_DoAddDistortions(false) , m_MotionVolumesBox("random") , m_CheckRealTimeFibersBox(true) , m_CheckAdvancedFiberOptionsBox(false) , m_CheckConstantRadiusBox(false) , m_CheckIncludeFiducialsBox(true) {} DataNode::Pointer m_ResultNode; ///< Stores resulting image. DataNode::Pointer m_ParentNode; ///< Parent node of result node. std::string m_SignalModelString; ///< Appendet to the name of the result node std::string m_ArtifactModelString; ///< Appendet to the name of the result node std::string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished. std::string m_OutputPrefix; /** Prefix for filename of output files and logfile. */ std::string m_AfterSimulationMessage; ///< Store messages that are displayed after the simulation has finished (e.g. warnings, automatic parameter adjustments etc.) + std::string m_BvalsFile; + std::string m_BvecsFile; /** member variables that store the check-state of GUI checkboxes */ // image generation bool m_CheckOutputVolumeFractionsBox; bool m_CheckAdvancedSignalOptionsBox; bool m_DoAddNoise; bool m_DoAddGhosts; bool m_DoAddAliasing; bool m_DoAddSpikes; bool m_DoAddEddyCurrents; bool m_DoAddDistortions; std::string m_MotionVolumesBox; // fiber generation bool m_CheckRealTimeFibersBox; bool m_CheckAdvancedFiberOptionsBox; bool m_CheckConstantRadiusBox; bool m_CheckIncludeFiducialsBox; }; /** * \brief Datastructure to manage the Fiberfox signal generation parameters. * */ class MITKFIBERTRACKING_EXPORT FiberfoxParameters { public: typedef itk::Image ItkFloatImgType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkUcharImgType; typedef DiffusionSignalModel DiffusionModelType; typedef std::vector< DiffusionModelType* > DiffusionModelListType; typedef DiffusionNoiseModel NoiseModelType; FiberfoxParameters(); FiberfoxParameters(const FiberfoxParameters ¶ms); ~FiberfoxParameters(); /** Not templated parameters */ FiberGenerationParameters m_FiberGen; ///< Fiber generation parameters SignalGenerationParameters m_SignalGen; ///< Signal generation parameters MiscFiberfoxParameters m_Misc; ///< GUI realted and I/O parameters /** Templated parameters */ DiffusionModelListType m_FiberModelList; ///< Intra- and inter-axonal compartments. DiffusionModelListType m_NonFiberModelList; ///< Extra-axonal compartments. std::shared_ptr< NoiseModelType > m_NoiseModel; ///< If != nullptr, noise is added to the image. void GenerateGradientHalfShell(); void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards. void SetGradienDirections(mitk::SignalGenerationParameters::GradientListType gradientList); void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList); void SetBvalue(double Bvalue); void UpdateSignalModels(); + void ClearFiberParameters(); + void ClearSignalParameters(); void PrintSelf(); ///< Print parameters to stdout. void SaveParameters(std::string filename); ///< Save image generation parameters to .ffp file. void LoadParameters(std::string filename); ///< Load image generation parameters from .ffp file. template< class ParameterType > ParameterType ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential=false); std::string m_MissingTags; }; } #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberGenerationViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberGenerationViewUserManual.dox new file mode 100644 index 0000000000..894b666b06 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberGenerationViewUserManual.dox @@ -0,0 +1,70 @@ +/** +\page org_mitk_views_fibergenerationview Fiber Generator + +This view provides the user interface for defining artificial white matter fibers. +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 can be simulated using the Fiberfox View. + +Available sections: + - \ref QmitkFiberGenerationViewUserManualFiberDefinition + - \ref QmitkFiberGenerationViewUserManualKnownIssues + - \ref QmitkFiberGenerationViewUserManualReferences + +\section QmitkFiberGenerationViewUserManualFiberDefinition 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. + +\imageMacro{Fiberfox-Fiducial.png, "Fig. 1: 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.",10} + +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 Fiber Distribution: Specifies if the fiber distribution inside the bundle follows a uniform or normal distribution. +\li \# Fibers: Specifies the number of fibers that will be generated for the selected bundle. +\li Advanced Options: Show/hide advanced options +\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 the selected 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. + +\imageMacro{FiberfoxExamples.png, "Fig. 2: 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.",4} + +\section QmitkFiberGenerationViewUserManualKnownIssues Known Issues + +\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: https://phabricator.mitk.org/maniphest/ +\section QmitkFiberGenerationViewUserManualReferences References + +[1] Neher, P.F., Laun, F.B., Stieltjes, B., Maier-Hein, K.H., 2014. Fiberfox: facilitating the creation of realistic white matter software phantoms. Magn Reson Med 72, 1460–1470. doi:10.1002/mrm.25045 + +[2] Neher, P.F., Laun, F.Neher, P.F., Stieltjes, B., Laun, F.B., Meinzer, H.-P., Fritzsche, K.H., 2013. Fiberfox: A novel tool to generate software phantoms of complex fiber geometries, in: Proceedings of International Society of Magnetic Resonance in Medicine. + +[3] Neher, P.F., Stieltjes, B., Laun, F.B., Meinzer, H.-P., Fritzsche, K.H., 2013. Fiberfox: A novel tool to generate software phantoms of complex fiber geometries, in: Proceedings of International Society of Magnetic Resonance in Medicine. + +[4] Hering, J., Neher, P.F., Meinzer, H.-P., Maier-Hein, K.H., 2014. Construction of ground-truth data for head motion correction in diffusion MRI, in: Proceedings of International Society of Magnetic Resonance in Medicine. + +[5] Maier-Hein, Klaus, Neher, Peter, Houde, Jean-Christophe, Caruyer, Emmanuel, Daducci, Alessandro, Dyrby, Tim, … Descoteaux, Maxime. (2015). Tractography Challenge ISMRM 2015 Data [Data set]. Zenodo. http://doi.org/10.5281/zenodo.572345 + +[6] Maier-Hein, Klaus, Neher, Peter, Houde, Jean-Christophe, Caruyer, Emmanuel, Daducci, Alessandro, Dyrby, Tim, … Descoteaux, Maxime. (2017). Tractography Challenge ISMRM 2015 High-resolution Data [Data set]. Zenodo. http://doi.org/10.5281/zenodo.579933 + +*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberfoxViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberfoxViewUserManual.dox index 981d333f71..5573d1700f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberfoxViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/documentation/UserManual/QmitkFiberfoxViewUserManual.dox @@ -1,149 +1,104 @@ /** \page org_mitk_views_fiberfoxview Fiberfox DW-MRI Simulation -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. -Instead of using manually created artificial fiber bundles, fibers obtained in any other way, e.g. using fiber tractography, can be used to simulate the signal (Example: ISMRM Tractography Challenge). +This view provides the user interface for Fiberfox [1,2,3], an interactive simulation tool diffusion-weighted MR images. +A diffusion-weighted signal is simulated from arbitrary input fibers using a flexible combination of various diffusion models. +It is possible to use manually created artificial fiber bundles (see Fiber Generator View) or fibers obtained in any other way, e.g. using fiber tractography, to simulate the signal (Example: ISMRM Tractography Challenge). The simulation can be modified using specified acquisition settings such as gradient direction, b-value, image size, image resolution, echo time, and much more. Additionally it enables the simulation of magnetic resonance artifacts including thermal noise, Gibbs ringing, N/2 ghosting, aliasing, susceptibility distortions, eddy currents and motion artifacts. The employed parameters can be saved and loaded as xml file with the ending ".ffp" (Fiberfox parameters). It is furthermore possible to add artifacts to an already existing diffusion-weighted image. Available sections: - - \ref QmitkFiberfoxViewUserManualFiberDefinition - \ref QmitkFiberfoxViewUserManualSignalGeneration - - \ref QmitkFiberfoxViewUserManualKnownIssues - \ref QmitkFiberfoxViewUserManualReferences -\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. - -\imageMacro{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.",10} - -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 Fiber Distribution: Specifies if the fiber distribution inside the bundle follows a uniform or normal distribution. -\li \# Fibers: Specifies the number of fibers that will be generated for the selected bundle. -\li Advanced Options: Show/hide advanced options -\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 the selected 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. - \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 "Fiber Bundle" combobox 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 and other effects induced by the acquisiton (ghosts etc.). If a save path is specified, the simualted image will be saved at this location. Eventually generated log files (e.g. recording the head motion) are also saved at this location. If not path is specified, the simualted image will only appear in the data manager and has to be saved manually. Logfiles are then saved in the system specific temp directory. If no fiber bundle but a diffusion-weighted image is selected, the specified artifacts are added to the selected image. In this mode, signal relaxation is disabled since multiple compartments are not available and the input image alrady contains relaxation effects. Also, introducing head motion is not possible since this qould require a contrast change in the weighted volumes. 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 Acquisition Type: the default acquisition type is a single shot EPI, which acquires a complete k-space slice with one echo. Alternatively, a standard spin echo sequence can be chosen that uses a cartesian k-space sampling scheme and acquires one k-space line with one echo. \li Signal Scale: Additional scaling factor for the signal in each voxel. The default value of 100 results in a maximum signal amplitude of 800 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 Number of Channels: Specify the number of coil elements used for the acquisition. The coil elements are circularly arranged around the objects z-axis. Currently the coil distance to the currently imaged object slice in z-direction is not taken into account, so the coil basically seems to move with the currently imaged slice along the z-axis. The signals obtained from the individual coil elements are combined using a sum of squares approach. Beware that the simulation time scales linearly with the number of coils! \li Coil Sensitivity: Using multiple acquisition channels only makes sense if the coil elements have a non-constant sensitivity profile. At the moment linearly as well as exponantially decreasing coil sensitivities are implemented. Using a constant coil sensitivity, the signal received by each coil element is equal regardless of the distance to the coil. In case of a non-constant sensitivity profile the received signal intensities decrease with increasing distance from the coil element. Using a linear profile, about 50% of the signal originating from the slice center is received. In case of an exponential coil sensitivity, only about 32% of the signal originating from the slice center is received. \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 Repetition Time TR: Time between two 90° RF pulses. Important for T1 contrast (use short TE and TR for strong T1 weighting). \li Dwell 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 (T2'): 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 Reverse Phase Encoding Direction: Switch anterior-posterior and posterior-anterior phase encoding. \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 Additional Images: 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. \li Prototype Signal: EXPERIMENTAL FEATURE!!! The signal is not generated from a parametric model but a prototype signal is sampled from the selected diffusion-weighted image. Parameters: The number of prototype signals that are used for the signal generation (at each fiber position one is picked randomly) and the constraining diffusion parameters for a voxel signal to be included in the list. For a fiber signal one would for example probably select a high FA and for a CSF voxel a low FA. For a detailed description of the individual 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 T1 and T2 signal relaxation constants (in ms). This constants are not relevant if the prototype signal model is used, since in this case signal relaxation is disabled. Furthermore, it is possible to specify a volume fraction map for each compartment: \li The volume fraction maps for compartment 1 and 2 (fiber compartments) are optional. If they are not specified, the corresponding volume fractions are directly determined from the fiber bundle. Additionally, it is assumed that in this case all volume fraction maps of the non-fiber compartments contain values relative to the remaining non-fiber volume, not absolute fractions of the complete voxel volume. This ensures that the automatically determined fiber volumes and the map-defined non-fiber volumes sum up to 1 in each voxel. \li If one non-fiber compartment is used but no corresponding volume fraction map is specified, the corresponding volume is automatically set to the remaining volume (voxel volume - fiber volume). \li If four compartments are used, at least one of the extra axonal compartment volume fraction maps has to be specified. The second one can be automatically determined from the respective other (1-f). If this is the case, the non-fiber volume information is again regarded as relative to the available non-fiber volume. Noise and Artifacts: \li Noise: Add Rician or Chi-Square distributed noise with the specified variance to the signal. \li Spikes: Add signal spikes to the k-space signal resulting in stripe artifacts across the corresponding image slice. \li Aliasing: Aliasing artifacts occur if the FOV in phase direction is smaller than the imaged object. The parameter defines the percentage by which the FOV is shrunk. \li N/2 Ghosts: Specify the offset between successive lines in k-space. This offset causes ghost images in distance N/2 in phase direction due to the alternating EPI readout directions. \li Distortions: Simulate distortions due to magnetic field inhomogeneities. This is achieved by adding an additional phase during the readout process. The input is a frequency map specifying the inhomogeneities. The "Fieldmap Generator" view provides an interface to generate simple artificial frequency maps. To egnerate realistic distortions for an in vivo like dataset we recommend using a frequency map acquired during a real MR scan or one estimated with tools such as FSL TOPUP. \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: Eddy current induced magnetic field gradient (in mT/m) at the beginning of the k-space readout. A spatially linear eddy current profile in the direction of the respective diffusion-weighting gradient is used. The eddy current induced gradient decays with a time constant τ=70ms. \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. -\imageMacro{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.",4} - -\imageMacro{FiberfoxWholebrain.png, "Fig. 4: Realistic simulation of a whole brain dataset with multiple artifacts.",4} - -\section QmitkFiberfoxViewUserManualKnownIssues Known Issues +\imageMacro{FiberfoxWholebrain.png, "Fig. 1: Realistic simulation of a whole brain dataset with multiple artifacts.",4} -\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: https://phabricator.mitk.org/maniphest/ \section QmitkFiberfoxViewUserManualReferences References [1] Neher, P.F., Laun, F.B., Stieltjes, B., Maier-Hein, K.H., 2014. Fiberfox: facilitating the creation of realistic white matter software phantoms. Magn Reson Med 72, 1460–1470. doi:10.1002/mrm.25045 [2] Neher, P.F., Laun, F.Neher, P.F., Stieltjes, B., Laun, F.B., Meinzer, H.-P., Fritzsche, K.H., 2013. Fiberfox: A novel tool to generate software phantoms of complex fiber geometries, in: Proceedings of International Society of Magnetic Resonance in Medicine. [3] Neher, P.F., Stieltjes, B., Laun, F.B., Meinzer, H.-P., Fritzsche, K.H., 2013. Fiberfox: A novel tool to generate software phantoms of complex fiber geometries, in: Proceedings of International Society of Magnetic Resonance in Medicine. [4] Hering, J., Neher, P.F., Meinzer, H.-P., Maier-Hein, K.H., 2014. Construction of ground-truth data for head motion correction in diffusion MRI, in: Proceedings of International Society of Magnetic Resonance in Medicine. [5] Maier-Hein, Klaus, Neher, Peter, Houde, Jean-Christophe, Caruyer, Emmanuel, Daducci, Alessandro, Dyrby, Tim, … Descoteaux, Maxime. (2015). Tractography Challenge ISMRM 2015 Data [Data set]. Zenodo. http://doi.org/10.5281/zenodo.572345 [6] Maier-Hein, Klaus, Neher, Peter, Houde, Jean-Christophe, Caruyer, Emmanuel, Daducci, Alessandro, Dyrby, Tim, … Descoteaux, Maxime. (2017). Tractography Challenge ISMRM 2015 High-resolution Data [Data set]. Zenodo. http://doi.org/10.5281/zenodo.579933 */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/files.cmake b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/files.cmake index 639205bf3c..1e35e55a6c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/files.cmake +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/files.cmake @@ -1,69 +1,73 @@ set(SRC_CPP_FILES QmitkTensorModelParametersWidget.cpp QmitkZeppelinModelParametersWidget.cpp QmitkStickModelParametersWidget.cpp QmitkDotModelParametersWidget.cpp QmitkBallModelParametersWidget.cpp QmitkAstrosticksModelParametersWidget.cpp QmitkPrototypeSignalParametersWidget.cpp ) set(INTERNAL_CPP_FILES QmitkFiberfoxView.cpp QmitkFieldmapGeneratorView.cpp + QmitkFiberGenerationView.cpp mitkPluginActivator.cpp Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp ) set(UI_FILES src/internal/QmitkFiberfoxViewControls.ui src/internal/QmitkFieldmapGeneratorViewControls.ui + src/internal/QmitkFiberGenerationViewControls.ui src/QmitkTensorModelParametersWidgetControls.ui src/QmitkZeppelinModelParametersWidgetControls.ui src/QmitkStickModelParametersWidgetControls.ui src/QmitkDotModelParametersWidgetControls.ui src/QmitkBallModelParametersWidgetControls.ui src/QmitkAstrosticksModelParametersWidgetControls.ui src/QmitkPrototypeSignalParametersWidgetControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkFiberfoxView.h src/internal/QmitkFieldmapGeneratorView.h + src/internal/QmitkFiberGenerationView.h src/QmitkTensorModelParametersWidget.h src/QmitkZeppelinModelParametersWidget.h src/QmitkStickModelParametersWidget.h src/QmitkDotModelParametersWidget.h src/QmitkBallModelParametersWidget.h src/QmitkAstrosticksModelParametersWidget.h src/QmitkPrototypeSignalParametersWidget.h src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h ) set(CACHED_RESOURCE_FILES plugin.xml resources/phantom.png resources/syntheticdata.png resources/fieldmap.png + resources/models.png ) set(QRC_FILES resources/QmitkDiffusionImaging.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/plugin.xml b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/plugin.xml index 74b185b36f..eaeb743a2a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/plugin.xml +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/plugin.xml @@ -1,68 +1,76 @@ + icon="resources/models.png"> Diffusion weighted MRI data simulation tool. + + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/QmitkDiffusionImaging.qrc b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/QmitkDiffusionImaging.qrc index c357fa85e7..3bd9ee335f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/QmitkDiffusionImaging.qrc +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/QmitkDiffusionImaging.qrc @@ -1,29 +1,30 @@ circle.png general_icons/download.ico general_icons/play.ico general_icons/plus.ico general_icons/refresh.ico general_icons/right.ico general_icons/save.ico general_icons/undo.ico general_icons/upload.ico general_icons/abort.ico general_icons/copy1.ico general_icons/copy2.ico general_icons/cut.ico general_icons/deny1.ico general_icons/deny2.ico general_icons/down.ico general_icons/left.ico general_icons/magn_minus.ico general_icons/magn_plus.ico general_icons/search.ico general_icons/stop.ico general_icons/up.ico general_icons/help.ico general_icons/pencil.ico general_icons/edit.ico + models.png diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/models.png b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/models.png new file mode 100644 index 0000000000..3c3a066bf2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/resources/models.png differ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp index 239c0e8c75..cd88f9b3d0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp @@ -1,49 +1,50 @@ /*=================================================================== 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 "QmitkDIAppSyntheticDataGenerationPerspective.h" #include "berryIViewLayout.h" void QmitkDIAppSyntheticDataGenerationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout) { ///////////////////////////////////////////////////// // all di-app perspectives should have the following: ///////////////////////////////////////////////////// QString editorArea = layout->GetEditorArea(); layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false); layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea); layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager"); berry::IFolderLayout::Pointer left = layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview"); layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false); ///////////////////////////////////////////// // here goes the perspective specific stuff ///////////////////////////////////////////// left->AddView("org.mitk.views.fiberfoxview"); + left->AddView("org.mitk.views.fibergenerationview"); left->AddView("org.mitk.views.fieldmapgenerator"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp new file mode 100644 index 0000000000..084cf4ada5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp @@ -0,0 +1,1015 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkFiberGenerationView.h" + +// MITK +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define RAPIDXML_NO_EXCEPTIONS +#include +#include +#include +#include +#include "usModuleRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mitkNodePredicateDataType.h" +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + + +const std::string QmitkFiberGenerationView::VIEW_ID = "org.mitk.views.fibergenerationview"; + +QmitkFiberGenerationView::QmitkFiberGenerationView() + : QmitkAbstractView() + , m_Controls( 0 ) + , m_SelectedImageNode( nullptr ) +{ + +} + +// Destructor +QmitkFiberGenerationView::~QmitkFiberGenerationView() +{ +} + +void QmitkFiberGenerationView::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::QmitkFiberGenerationViewControls; + m_Controls->setupUi( parent ); + + m_ParameterFile = QDir::currentPath()+"/param.ffp"; + 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_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_AdvancedOptionsBox, 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())); + + } + UpdateGui(); +} + +void QmitkFiberGenerationView::UpdateParametersFromGui() +{ + m_Parameters.ClearFiberParameters(); + m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); + + switch(m_Controls->m_DistributionBox->currentIndex()) + { + case 0: + m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; + break; + case 1: + m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; + break; + default: + m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; + } + m_Parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); + m_Parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); + m_Parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); + m_Parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); + m_Parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); + m_Parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); + m_Parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); + m_Parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); + m_Parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); + m_Parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); + m_Parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); + m_Parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); + m_Parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); + m_Parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); + m_Parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); + + m_Parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); + m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); + m_Parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); + m_Parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); +} + +void QmitkFiberGenerationView::SaveParameters(QString filename) +{ + UpdateParametersFromGui(); + m_Parameters.SaveParameters(filename.toStdString()); + m_ParameterFile = filename; +} + +void QmitkFiberGenerationView::SaveParameters() +{ + QString filename = QFileDialog::getSaveFileName( + 0, + tr("Save Parameters"), + m_ParameterFile, + tr("Fiberfox Parameters (*.ffp)") ); + + SaveParameters(filename); +} + +void QmitkFiberGenerationView::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; + m_Parameters.LoadParameters(filename.toStdString()); + + if (m_Parameters.m_MissingTags.size()>0) + { + QString missing("Parameter file might be corrupted. The following parameters could not be read: "); + missing += QString(m_Parameters.m_MissingTags.c_str()); + missing += "\nDefault values have been assigned to the missing parameters."; + QMessageBox::information( nullptr, "Warning!", missing); + } + + m_Controls->m_RealTimeFibers->setChecked(m_Parameters.m_Misc.m_CheckRealTimeFibersBox); + m_Controls->m_AdvancedOptionsBox->setChecked(m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); + m_Controls->m_IncludeFiducials->setChecked(m_Parameters.m_Misc.m_CheckIncludeFiducialsBox); + m_Controls->m_ConstantRadiusBox->setChecked(m_Parameters.m_Misc.m_CheckConstantRadiusBox); + + m_Controls->m_DistributionBox->setCurrentIndex(m_Parameters.m_FiberGen.m_Distribution); + m_Controls->m_VarianceBox->setValue(m_Parameters.m_FiberGen.m_Variance); + m_Controls->m_FiberDensityBox->setValue(m_Parameters.m_FiberGen.m_Density); + m_Controls->m_FiberSamplingBox->setValue(m_Parameters.m_FiberGen.m_Sampling); + m_Controls->m_TensionBox->setValue(m_Parameters.m_FiberGen.m_Tension); + m_Controls->m_ContinuityBox->setValue(m_Parameters.m_FiberGen.m_Continuity); + m_Controls->m_BiasBox->setValue(m_Parameters.m_FiberGen.m_Bias); + m_Controls->m_XrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[0]); + m_Controls->m_YrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[1]); + m_Controls->m_ZrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[2]); + m_Controls->m_XtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[0]); + m_Controls->m_YtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[1]); + m_Controls->m_ZtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[2]); + m_Controls->m_XscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[0]); + m_Controls->m_YscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[1]); + m_Controls->m_ZscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[2]); +} + +void QmitkFiberGenerationView::ShowAdvancedOptions(int state) +{ + if (state) + { + m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); + m_Controls->m_AdvancedOptionsBox->setChecked(true); + } + else + { + m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); + m_Controls->m_AdvancedOptionsBox->setChecked(false); + } +} + +void QmitkFiberGenerationView::OnConstantRadius(int value) +{ + if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::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 QmitkFiberGenerationView::OnVarianceChanged(double) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::OnFiberDensityChanged(int) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::OnFiberSamplingChanged(double) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::OnTensionChanged(double) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::OnContinuityChanged(double) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::OnBiasChanged(double) +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::AlignOnGrid() +{ + for (unsigned 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::BaseGeometry::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(unsigned 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::BaseGeometry::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(unsigned 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::BaseGeometry::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 QmitkFiberGenerationView::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(); +} + +void QmitkFiberGenerationView::OnAddBundle() +{ + if (m_SelectedImageNode.IsNull()) + return; + + mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); + + mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::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_SelectedImageNode); +} + +void QmitkFiberGenerationView::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 ); + node->SetBoolProperty("planarfigure.3drendering", true); + node->SetBoolProperty("planarfigure.3drendering.fill", true); + + 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( "MitkPlanarFigure" ); + figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); + figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); + figureInteractor->SetDataNode( node ); + } + + UpdateGui(); + GetDataStorage()->Add(node, m_SelectedBundles.at(0)); +} + +bool QmitkFiberGenerationView::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; + } + + UpdateParametersFromGui(); + + for (unsigned 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); + std::sort(childVector.begin(), childVector.end(), CompareLayer); + + std::vector< mitk::PlanarEllipse::Pointer > fib; + std::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); + ellipse->Modified(); + } + else + { + v.Normalize(); + v *= radius; + ellipse->SetControlPoint(1, c+v); + ellipse->Modified(); + } + } + 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) + { + m_Parameters.m_FiberGen.m_Fiducials.push_back(fib); + m_Parameters.m_FiberGen.m_FlipList.push_back(flip); + } + else if (fib.size()>0) + m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + + itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); + filter->SetParameters(m_Parameters.m_FiberGen); + filter->Update(); + std::vector< mitk::FiberBundle::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 QmitkFiberGenerationView::ApplyTransform() +{ + std::vector< mitk::DataNode::Pointer > selectedBundles; + for(unsigned 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()) + { + for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) + { + mitk::FiberBundle::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::BaseGeometry* 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()*itk::Math::pi/180; + double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; + double z = m_Controls->m_ZrotBox->value()*itk::Math::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); + + pe->Modified(); + } + } + } + } + } + else + { + for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); + mitk::BaseGeometry* 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()*itk::Math::pi/180; + double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; + double z = m_Controls->m_ZrotBox->value()*itk::Math::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()); + pe->Modified(); + } + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); + } + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkFiberGenerationView::CopyBundles() +{ + if ( m_SelectedBundles.size()<1 ){ + QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); + MITK_WARN("QmitkFiberGenerationView") << "Select at least one fiber bundle!"; + return; + } + + for (std::vector::const_iterator it = m_SelectedBundles.begin(); 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::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); + mitk::FiberBundle::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 = dynamic_cast(fiducialNode->GetData())->Clone(); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + newNode->SetData(pe); + newNode->SetName(fiducialNode->GetName()); + newNode->SetBoolProperty("planarfigure.3drendering", true); + GetDataStorage()->Add(newNode, fbNode); + + } + } + } + } + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkFiberGenerationView::JoinBundles() +{ + if ( m_SelectedBundles.size()<2 ){ + QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); + MITK_WARN("QmitkFiberGenerationView") << "Select at least two fiber bundles!"; + return; + } + + std::vector::const_iterator it = m_SelectedBundles.begin(); + mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); + QString name(""); + name += QString((*it)->GetName().c_str()); + ++it; + for (; 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 QmitkFiberGenerationView::UpdateGui() +{ + 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_JoinBundlesButton->setEnabled(false); + m_Controls->m_AlignOnGrid->setEnabled(false); + + // Fiber generation gui + if (m_SelectedFiducial.IsNotNull()) + { + m_Controls->m_TransformBundlesButton->setEnabled(true); + m_Controls->m_FlipButton->setEnabled(true); + m_Controls->m_AlignOnGrid->setEnabled(true); + } + + if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) + { + m_Controls->m_CircleButton->setEnabled(true); + m_Controls->m_FiberGenMessage->setVisible(false); + } + if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) + m_Controls->m_AlignOnGrid->setEnabled(true); + + if (!m_SelectedBundles.empty()) + { + m_Controls->m_TransformBundlesButton->setEnabled(true); + m_Controls->m_CopyBundlesButton->setEnabled(true); + m_Controls->m_GenerateFibersButton->setEnabled(true); + + if (m_SelectedBundles.size()>1) + m_Controls->m_JoinBundlesButton->setEnabled(true); + } +} + +void QmitkFiberGenerationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) +{ + m_SelectedBundles2.clear(); + m_SelectedImages.clear(); + m_SelectedFiducials.clear(); + m_SelectedFiducial = nullptr; + m_SelectedBundles.clear(); + m_SelectedImageNode = nullptr; + + // iterate all selected objects, adjust warning visibility + for( int i=0; i(node->GetData()) ) + { + m_SelectedImages.push_back(node); + m_SelectedImageNode = node; + } + 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::FiberBundle::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 QmitkFiberGenerationView::EnableCrosshairNavigation() +{ + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); +} + +void QmitkFiberGenerationView::DisableCrosshairNavigation() +{ +} + +void QmitkFiberGenerationView::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 QmitkFiberGenerationView::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( "MitkPlanarFigure" ); + 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< QmitkFiberGenerationView > SimpleCommandType; + // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); + // initializationCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureInitialized ); + // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); + + // add observer for event when figure is picked (selected) + typedef itk::MemberCommand< QmitkFiberGenerationView > MemberCommandType; + MemberCommandType::Pointer selectCommand = MemberCommandType::New(); + selectCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::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, &QmitkFiberGenerationView::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, &QmitkFiberGenerationView::EnableCrosshairNavigation); + data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); + + m_DataNodeToPlanarFigureData[nonConstNode] = data; + } +} + +void QmitkFiberGenerationView::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 QmitkFiberGenerationView::SetFocus() +{ + m_Controls->m_CircleButton->setFocus(); +} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h similarity index 60% copy from Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h copy to Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h index 772becedcf..adbff9b243 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h @@ -1,214 +1,146 @@ /*=================================================================== 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 "ui_QmitkFiberGenerationViewControls.h" #include #include #include #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include -/*! -\brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. -*/ -// Forward Qt class declarations - -class QmitkFiberfoxView; - -class QmitkFiberfoxWorker : public QObject -{ - Q_OBJECT - -public: - - QmitkFiberfoxWorker(QmitkFiberfoxView* view); - -public slots: - - void run(); - -private: - - QmitkFiberfoxView* m_View; -}; - -class QmitkFiberfoxView : public QmitkAbstractView +class QmitkFiberGenerationView : 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 std::string VIEW_ID; - QmitkFiberfoxView(); - virtual ~QmitkFiberfoxView(); + QmitkFiberGenerationView(); + virtual ~QmitkFiberGenerationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; - typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; - typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; - typedef itk::Vector GradientType; - typedef std::vector GradientListType; - typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; - template std::vector > MakeGradientList(); - protected slots: - 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(); ///< abort simulation - void UpdateSimulationStatus(); ///< print simulation progress and satus messages + void LoadParameters(); ///< load FiberGeneration parameters + void SaveParameters(); ///< save FiberGeneration parameters 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 OnAddDrift(int value); - void OnMaskSelected(int value); - void OnFibSelected(int value); - void OnTemplateSelected(int value); - protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere - - Ui::QmitkFiberfoxViewControls* m_Controls; + Ui::QmitkFiberGenerationViewControls* m_Controls; - void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image - void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image - FiberfoxParameters UpdateImageParameters(bool all=true, bool save=false); ///< update fiberfox paramater object + void UpdateParametersFromGui(); 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 ) override; ///< add observers void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers void SaveParameters(QString filename); + static bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j); /** 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; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImageNode; std::vector< mitk::DataNode::Pointer > m_SelectedBundles; std::vector< mitk::DataNode::Pointer > m_SelectedBundles2; std::vector< mitk::DataNode::Pointer > m_SelectedFiducials; std::vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name - - // GUI thread - QmitkFiberfoxWorker m_Worker; ///< runs filter - QThread m_Thread; ///< worker thread - bool m_ThreadIsRunning; - QTimer* m_SimulationTimer; - QTime m_SimulationTime; - QString m_SimulationStatusText; - - /** Image filters that do all the simulations. */ - itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; - - friend class QmitkFiberfoxWorker; + FiberfoxParameters m_Parameters; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui new file mode 100644 index 0000000000..1313ab8379 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui @@ -0,0 +1,1154 @@ + + + QmitkFiberGenerationViewControls + + + + 0 + 0 + 463 + 1017 + + + + Form + + + + + + + + + QGroupBox { + background-color: transparent; +} + + + Fiducial Options + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + 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. + + + QCommandLinkButton:disabled { + border: none; +} + + + Align With Grid + + + + :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico + + + + + + + + + + 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 + + + + + + + QGroupBox { + background-color: transparent; +} + + + Fiber Options + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + 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 + + + QCommandLinkButton:disabled { + border: none; +} + + + 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/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico + + + + 32 + 32 + + + + false + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Load Parameters + + + + :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico + + + + + + + + + + Save Parameters + + + + :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico + + + + + + + QGroupBox { + background-color: transparent; +} + + + Operations + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + false + + + QCommandLinkButton:disabled { + border: none; +} + + + 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. + + + 3 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Axis: + + + false + + + + + + + Rotation angle (in degree) around y-axis. + + + 3 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Translation: + + + false + + + + + + + Translation (in mm) in direction of the z-axis. + + + 3 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + Translation (in mm) in direction of the y-axis. + + + 3 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + X + + + false + + + + + + + + + + + + + + + + Rotation: + + + false + + + + + + + + + + + + + + + + Z + + + false + + + + + + + Rotation angle (in degree) around z-axis. + + + 3 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + Translation (in mm) in direction of the x-axis. + + + 3 + + + -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 + + + QCommandLinkButton:disabled { + border: none; +} + + + Copy Bundles + + + + :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico + + + + + + + false + + + QCommandLinkButton:disabled { + border: none; +} + + + 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 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 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_SaveParametersButton + m_LoadParametersButton + + + + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp index 082c740951..a1bbc8189a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp @@ -1,2903 +1,2125 @@ /*=================================================================== 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. ===================================================================*/ // 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 #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view) : m_View(view) { } void QmitkFiberfoxWorker::run() { try{ m_View->m_TractsToDwiFilter->Update(); } catch( ... ) { } m_View->m_Thread.quit(); } const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImageNode( nullptr ) , 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."; m_TractsToDwiFilter->SetAbortGenerateData(true); m_Controls->m_AbortSimulationButton->setEnabled(false); m_Controls->m_AbortSimulationButton->setText("Aborting simulation ..."); } void QmitkFiberfoxView::BeforeThread() { m_SimulationTime = QTime::currentTime(); m_SimulationTimer->start(100); 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_AbortSimulationButton->setEnabled(true); m_Controls->m_AbortSimulationButton->setText("Abort simulation"); m_Controls->m_GenerateImageButton->setVisible(true); m_ThreadIsRunning = false; QString statusText; FiberfoxParameters parameters; mitk::Image::Pointer mitkImage = mitk::Image::New(); statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (m_TractsToDwiFilter->GetAbortGenerateData()) { MITK_INFO << "Simulation aborted."; return; } parameters = m_TractsToDwiFilter->GetParameters(); mitkImage = mitk::GrabItkImageMemory( m_TractsToDwiFilter->GetOutput() ); mitk::DiffusionPropertyHelper::SetGradientContainer(mitkImage, parameters.m_SignalGen.GetItkGradientContainer()); mitk::DiffusionPropertyHelper::SetReferenceBValue(mitkImage, parameters.m_SignalGen.GetBvalue()); mitk::DiffusionPropertyHelper::InitializeImage( mitkImage ); parameters.m_Misc.m_ResultNode->SetData( mitkImage ); GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode); parameters.m_Misc.m_ResultNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New(m_TractsToDwiFilter->GetLevelWindow()) ); if (m_Controls->m_VolumeFractionsBox->isChecked()) { if (m_TractsToDwiFilter->GetPhaseImage().IsNotNull()) { mitk::Image::Pointer phaseImage = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkPhase = m_TractsToDwiFilter->GetPhaseImage(); phaseImage = mitk::GrabItkImageMemory( itkPhase.GetPointer() ); mitk::DataNode::Pointer phaseNode = mitk::DataNode::New(); phaseNode->SetData( phaseImage ); phaseNode->SetName("Phase Image"); GetDataStorage()->Add(phaseNode, parameters.m_Misc.m_ResultNode); } if (m_TractsToDwiFilter->GetKspaceImage().IsNotNull()) { mitk::Image::Pointer image = mitk::Image::New(); itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkImage = m_TractsToDwiFilter->GetKspaceImage(); image = mitk::GrabItkImageMemory( itkImage.GetPointer() ); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("k-Space"); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(m_TractsToDwiFilter->GetCoilPointset()); node->SetName("Coil Positions"); node->SetProperty("pointsize", mitk::FloatProperty::New(parameters.m_SignalGen.m_ImageSpacing[0]/4)); node->SetProperty("color", mitk::ColorProperty::New(0, 1, 0)); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } int c = 1; std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_real = m_TractsToDwiFilter->GetOutputImagesReal(); for (auto real : output_real) { mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(real.GetPointer()); image->SetVolume(real->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Coil-"+QString::number(c).toStdString()+"-real"); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); ++c; } c = 1; std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_imag = m_TractsToDwiFilter->GetOutputImagesImag(); for (auto imag : output_imag) { mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(imag.GetPointer()); image->SetVolume(imag->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Coil-"+QString::number(c).toStdString()+"-imag"); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); ++c; } std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions(); for (unsigned 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("CompartmentVolume-"+QString::number(k).toStdString()); GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode); } } m_TractsToDwiFilter = nullptr; if (parameters.m_Misc.m_AfterSimulationMessage.size()>0) QMessageBox::information( nullptr, "Warning", parameters.m_Misc.m_AfterSimulationMessage.c_str()); mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } if (!parameters.m_Misc.m_OutputPath.empty()) { try{ QString outputFileName(parameters.m_Misc.m_OutputPath.c_str()); outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str(); outputFileName.replace(QString("."), QString("_")); SaveParameters(outputFileName+".ffp"); outputFileName += ".dwi"; QString status("Saving output image to "); status += outputFileName; m_Controls->m_SimulationStatusText->append(status); mitk::IOUtil::Save(mitkImage, outputFileName.toStdString()); 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!"); } } parameters.m_SignalGen.m_FrequencyMap = nullptr; } void QmitkFiberfoxView::UpdateSimulationStatus() { QString statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str()); if (QString::compare(m_SimulationStatusText,statusText)!=0) { m_Controls->m_SimulationStatusText->clear(); m_Controls->m_SimulationStatusText->setText(statusText); QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar(); vScrollBar->triggerAction(QScrollBar::SliderToMaximum); } } // 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_BallWidget2->SetT1(4500); m_Controls->m_AstrosticksWidget1->setVisible(false); m_Controls->m_AstrosticksWidget2->setVisible(false); m_Controls->m_AstrosticksWidget2->SetT1(4500); m_Controls->m_DotWidget1->setVisible(false); m_Controls->m_DotWidget2->setVisible(false); m_Controls->m_DotWidget2->SetT1(4500); m_Controls->m_PrototypeWidget1->setVisible(false); m_Controls->m_PrototypeWidget2->setVisible(false); m_Controls->m_PrototypeWidget3->setVisible(false); m_Controls->m_PrototypeWidget4->setVisible(false); m_Controls->m_PrototypeWidget3->SetMinFa(0.0); m_Controls->m_PrototypeWidget3->SetMaxFa(0.15); m_Controls->m_PrototypeWidget4->SetMinFa(0.0); m_Controls->m_PrototypeWidget4->SetMaxFa(0.15); m_Controls->m_PrototypeWidget3->SetMinAdc(0.0); m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001); m_Controls->m_PrototypeWidget4->SetMinAdc(0.003); m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004); m_Controls->m_Comp2FractionFrame->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_Controls->m_DriftFrame->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()); m_Controls->m_Comp1VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp2VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp3VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TemplateComboBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_FiberBundleComboBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isFiberBundle = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isMitkImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New( ); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("Odfmage"); mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti); isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isOdf); mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage); mitk::NodePredicateAnd::Pointer isNonDiffMitkImage = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isBinaryMitkImage = mitk::NodePredicateAnd::New( isNonDiffMitkImage, isBinaryPredicate ); m_Controls->m_FrequencyMapBox->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp1VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp1VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp2VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp2VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp3VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp3VolumeFraction->SetZeroEntryText("--"); m_Controls->m_Comp4VolumeFraction->SetPredicate(isNonDiffMitkImage); m_Controls->m_Comp4VolumeFraction->SetZeroEntryText("--"); m_Controls->m_MaskComboBox->SetPredicate(isBinaryMitkImage); m_Controls->m_MaskComboBox->SetZeroEntryText("--"); m_Controls->m_TemplateComboBox->SetPredicate(isMitkImage); m_Controls->m_TemplateComboBox->SetZeroEntryText("--"); m_Controls->m_FiberBundleComboBox->SetPredicate(isFiberBundle); m_Controls->m_FiberBundleComboBox->SetZeroEntryText("--"); QFont font; font.setFamily("Courier"); font.setStyleHint(QFont::Monospace); font.setFixedPitch(true); font.setPointSize(7); m_Controls->m_SimulationStatusText->setFont(font); 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_AddDrift, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDrift(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_UseBvalsBvecsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(OnBvalsBvecsCheck(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())); + connect((QObject*) m_Controls->m_LoadBvalsButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetBvalsEdit())); + connect((QObject*) m_Controls->m_LoadBvecsButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetBvecsEdit())); connect((QObject*) m_Controls->m_MaskComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnMaskSelected(int))); connect((QObject*) m_Controls->m_TemplateComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnTemplateSelected(int))); connect((QObject*) m_Controls->m_FiberBundleComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnFibSelected(int))); } + UpdateGui(); } void QmitkFiberfoxView::OnMaskSelected(int ) { UpdateGui(); } void QmitkFiberfoxView::OnTemplateSelected(int ) { UpdateGui(); } void QmitkFiberfoxView::OnFibSelected(int ) { UpdateGui(); } -FiberfoxParameters QmitkFiberfoxView::UpdateImageParameters(bool all, bool save) +void QmitkFiberfoxView::OnBvalsBvecsCheck(int ) { - FiberfoxParameters parameters; - parameters.m_Misc.m_OutputPath = ""; - parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); - parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); - parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); - parameters.m_Misc.m_AfterSimulationMessage = ""; + UpdateGui(); +} + +void QmitkFiberfoxView::UpdateParametersFromGui() +{ + m_Parameters.ClearSignalParameters(); + m_Parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked(); + m_Parameters.m_Misc.m_CheckOutputVolumeFractionsBox = m_Controls->m_VolumeFractionsBox->isChecked(); std::string outputPath = m_Controls->m_SavePathEdit->text().toStdString(); if (outputPath.compare("-")!=0) { - parameters.m_Misc.m_OutputPath = outputPath; - parameters.m_Misc.m_OutputPath += "/"; + m_Parameters.m_Misc.m_OutputPath = outputPath; + m_Parameters.m_Misc.m_OutputPath += "/"; } - - switch(m_Controls->m_DistributionBox->currentIndex()) - { - case 0: - parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; - break; - case 1: - parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; - break; - default: - parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; - } - parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); - parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); - parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); - parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); - parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); - parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); - parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); - parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); - parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); - parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); - parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); - parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); - parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); - parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); - parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); - - if (!all) - return parameters; - if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mitkMaskImage = dynamic_cast(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData()); - mitk::CastToItkImage(mitkMaskImage, parameters.m_SignalGen.m_MaskImage); + mitk::CastToItkImage(mitkMaskImage, m_Parameters.m_SignalGen.m_MaskImage); itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); - duplicator->SetInputImage(parameters.m_SignalGen.m_MaskImage); + duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage); duplicator->Update(); - parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); + m_Parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput(); } if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) // use parameters of selected DWI { mitk::Image::Pointer dwi = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); - parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); - parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); - parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); - parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); - parameters.SetBvalue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); - parameters.SetGradienDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi)); + m_Parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion(); + m_Parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing(); + m_Parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin(); + m_Parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection(); + m_Parameters.SetBvalue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); + m_Parameters.SetGradienDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi)); } else if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image { mitk::Image::Pointer img = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New(); CastToItkImage< itk::Image< float, 3 > >(img, itkImg); - parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); - parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); - parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); - parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); - parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); - parameters.SetBvalue(m_Controls->m_BvalueBox->value()); + m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); + m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); + m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); + m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); + + if (m_Controls->m_UseBvalsBvecsBox->isChecked()) + { + double bval; + m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) ); + m_Parameters.SetBvalue(bval); + } + else + { + m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); + m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value()); + m_Parameters.GenerateGradientHalfShell(); + } } - else if (parameters.m_SignalGen.m_MaskImage.IsNotNull()) // use geometry of mask image + else if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull()) // use geometry of mask image { - ItkUcharImgType::Pointer itkImg = parameters.m_SignalGen.m_MaskImage; - parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); - parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); - parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); - parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); - parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); - parameters.SetBvalue(m_Controls->m_BvalueBox->value()); + ItkUcharImgType::Pointer itkImg = m_Parameters.m_SignalGen.m_MaskImage; + m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); + m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); + m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); + m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); + + if (m_Controls->m_UseBvalsBvecsBox->isChecked()) + { + double bval; + m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) ); + m_Parameters.SetBvalue(bval); + } + else + { + m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); + m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value()); + m_Parameters.GenerateGradientHalfShell(); + } } else // use GUI parameters { - parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); - parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); - parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); - parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); - parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); - parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); - parameters.m_SignalGen.m_ImageOrigin[0] = parameters.m_SignalGen.m_ImageSpacing[0]/2; - parameters.m_SignalGen.m_ImageOrigin[1] = parameters.m_SignalGen.m_ImageSpacing[1]/2; - parameters.m_SignalGen.m_ImageOrigin[2] = parameters.m_SignalGen.m_ImageSpacing[2]/2; - parameters.m_SignalGen.m_ImageDirection.SetIdentity(); - parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); - parameters.SetBvalue(m_Controls->m_BvalueBox->value()); - parameters.GenerateGradientHalfShell(); + m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value()); + m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value()); + m_Parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value()); + m_Parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value(); + m_Parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value(); + m_Parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value(); + m_Parameters.m_SignalGen.m_ImageOrigin[0] = m_Parameters.m_SignalGen.m_ImageSpacing[0]/2; + m_Parameters.m_SignalGen.m_ImageOrigin[1] = m_Parameters.m_SignalGen.m_ImageSpacing[1]/2; + m_Parameters.m_SignalGen.m_ImageOrigin[2] = m_Parameters.m_SignalGen.m_ImageSpacing[2]/2; + m_Parameters.m_SignalGen.m_ImageDirection.SetIdentity(); + + if (m_Controls->m_UseBvalsBvecsBox->isChecked()) + { + double bval; + m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) ); + m_Parameters.SetBvalue(bval); + } + else + { + m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value()); + m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value()); + m_Parameters.GenerateGradientHalfShell(); + } } // signal relaxation - parameters.m_SignalGen.m_DoSimulateRelaxation = false; - if (m_Controls->m_RelaxationBox->isChecked() && (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() || save) ) + m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; + if (m_Controls->m_RelaxationBox->isChecked()) { - parameters.m_SignalGen.m_DoSimulateRelaxation = true; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(true)); - parameters.m_Misc.m_ArtifactModelString += "_RELAX"; + m_Parameters.m_SignalGen.m_DoSimulateRelaxation = true; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(true)); + m_Parameters.m_Misc.m_ArtifactModelString += "_RELAX"; } - parameters.m_SignalGen.m_SimulateKspaceAcquisition = parameters.m_SignalGen.m_DoSimulateRelaxation; + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = m_Parameters.m_SignalGen.m_DoSimulateRelaxation; // N/2 ghosts - parameters.m_Misc.m_DoAddGhosts = m_Controls->m_AddGhosts->isChecked(); - parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); + m_Parameters.m_Misc.m_DoAddGhosts = m_Controls->m_AddGhosts->isChecked(); + m_Parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value(); if (m_Controls->m_AddGhosts->isChecked()) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_GHOST"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(parameters.m_SignalGen.m_KspaceLineOffset)); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_GHOST"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(m_Parameters.m_SignalGen.m_KspaceLineOffset)); } // Aliasing - parameters.m_Misc.m_DoAddAliasing = m_Controls->m_AddAliasing->isChecked(); - parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; + m_Parameters.m_Misc.m_DoAddAliasing = m_Controls->m_AddAliasing->isChecked(); + m_Parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100; if (m_Controls->m_AddAliasing->isChecked()) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_ALIASING"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value())); } // Spikes - parameters.m_Misc.m_DoAddSpikes = m_Controls->m_AddSpikes->isChecked(); - parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); - parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); + m_Parameters.m_Misc.m_DoAddSpikes = m_Controls->m_AddSpikes->isChecked(); + m_Parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value(); + m_Parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value(); if (m_Controls->m_AddSpikes->isChecked()) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(parameters.m_SignalGen.m_Spikes)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(parameters.m_SignalGen.m_SpikeAmplitude)); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_SPIKES"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(m_Parameters.m_SignalGen.m_Spikes)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(m_Parameters.m_SignalGen.m_SpikeAmplitude)); } // Drift - parameters.m_SignalGen.m_DoAddDrift = m_Controls->m_AddDrift->isChecked(); - parameters.m_SignalGen.m_Drift = m_Controls->m_DriftFactor->value()/100; + m_Parameters.m_SignalGen.m_DoAddDrift = m_Controls->m_AddDrift->isChecked(); + m_Parameters.m_SignalGen.m_Drift = m_Controls->m_DriftFactor->value()/100; if (m_Controls->m_AddDrift->isChecked()) { - parameters.m_Misc.m_ArtifactModelString += "_DRIFT"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Drift", FloatProperty::New(parameters.m_SignalGen.m_Drift)); + m_Parameters.m_Misc.m_ArtifactModelString += "_DRIFT"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Drift", FloatProperty::New(m_Parameters.m_SignalGen.m_Drift)); } // gibbs ringing - parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); + m_Parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked(); if (m_Controls->m_AddGibbsRinging->isChecked()) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); - parameters.m_Misc.m_ArtifactModelString += "_RINGING"; + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true)); + m_Parameters.m_Misc.m_ArtifactModelString += "_RINGING"; } // add distortions - parameters.m_Misc.m_DoAddDistortions = m_Controls->m_AddDistortions->isChecked(); + m_Parameters.m_Misc.m_DoAddDistortions = m_Controls->m_AddDistortions->isChecked(); 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()); ItkFloatImgType::Pointer itkImg = ItkFloatImgType::New(); CastToItkImage< ItkFloatImgType >(img, itkImg); if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) // use geometry of frequency map { - parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); - parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); - parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); - parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); + m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion(); + m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing(); + m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin(); + m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection(); } - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; itk::ImageDuplicator::Pointer duplicator = itk::ImageDuplicator::New(); duplicator->SetInputImage(itkImg); duplicator->Update(); - parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); - parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); + m_Parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput(); + m_Parameters.m_Misc.m_ArtifactModelString += "_DISTORTED"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true)); } - parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); - parameters.m_Misc.m_DoAddEddyCurrents = m_Controls->m_AddEddy->isChecked(); + m_Parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value(); + m_Parameters.m_Misc.m_DoAddEddyCurrents = m_Controls->m_AddEddy->isChecked(); if (m_Controls->m_AddEddy->isChecked()) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_EDDY"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(parameters.m_SignalGen.m_EddyStrength)); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_EDDY"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(m_Parameters.m_SignalGen.m_EddyStrength)); } // Motion - parameters.m_SignalGen.m_DoAddMotion = false; - parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); - parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); - parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); - parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); - parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); - parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); - parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); - parameters.m_SignalGen.m_MotionVolumes.clear(); - parameters.m_Misc.m_MotionVolumesBox = m_Controls->m_MotionVolumesBox->text().toStdString(); - - if ( m_Controls->m_AddMotion->isChecked() && (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull() || save) ) - { - parameters.m_SignalGen.m_DoAddMotion = true; - parameters.m_Misc.m_ArtifactModelString += "_MOTION"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(parameters.m_SignalGen.m_DoRandomizeMotion)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(parameters.m_SignalGen.m_Translation[0])); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(parameters.m_SignalGen.m_Translation[1])); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(parameters.m_SignalGen.m_Translation[2])); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[0])); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[1])); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(parameters.m_SignalGen.m_Rotation[2])); - - if ( parameters.m_Misc.m_MotionVolumesBox == "random" ) + m_Parameters.m_SignalGen.m_DoAddMotion = false; + m_Parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked(); + m_Parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value(); + m_Parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value(); + m_Parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value(); + m_Parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value(); + m_Parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value(); + m_Parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value(); + m_Parameters.m_SignalGen.m_MotionVolumes.clear(); + m_Parameters.m_Misc.m_MotionVolumesBox = m_Controls->m_MotionVolumesBox->text().toStdString(); + + if ( m_Controls->m_AddMotion->isChecked()) + { + m_Parameters.m_SignalGen.m_DoAddMotion = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_MOTION"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(m_Parameters.m_SignalGen.m_DoRandomizeMotion)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[0])); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[1])); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[2])); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[0])); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[1])); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[2])); + + if ( m_Parameters.m_Misc.m_MotionVolumesBox == "random" ) { - for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) + for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i ) { - parameters.m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) ); + m_Parameters.m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) ); } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case m_Misc.m_MotionVolumesBox == \"random\"."; } - else if ( ! parameters.m_Misc.m_MotionVolumesBox.empty() ) + else if ( ! m_Parameters.m_Misc.m_MotionVolumesBox.empty() ) { - std::stringstream stream( parameters.m_Misc.m_MotionVolumesBox ); + std::stringstream stream( m_Parameters.m_Misc.m_MotionVolumesBox ); std::vector numbers; int number = std::numeric_limits::max(); while( stream >> number ) { if( number < std::numeric_limits::max() ) { numbers.push_back( number ); } } // If a list of negative numbers is given: if( *(std::min_element( numbers.begin(), numbers.end() )) < 0 && *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0 { - for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) + for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i ) { - parameters.m_SignalGen.m_MotionVolumes.push_back( true ); + m_Parameters.m_SignalGen.m_MotionVolumes.push_back( true ); } // set all true except those given. for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter ) { - if ( -(*iter) < (int)parameters.m_SignalGen.GetNumVolumes() && -(*iter) >= 0 ) + if ( -(*iter) < (int)m_Parameters.m_SignalGen.GetNumVolumes() && -(*iter) >= 0 ) { - parameters.m_SignalGen.m_MotionVolumes.at( -(*iter) ) = false; + m_Parameters.m_SignalGen.m_MotionVolumes.at( -(*iter) ) = false; } } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of negative numbers."; } // If a list of positive numbers is given: else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0 && *(std::max_element( numbers.begin(), numbers.end() )) >= 0 ) { - for ( size_t i=0; i < parameters.m_SignalGen.GetNumVolumes(); ++i ) + for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i ) { - parameters.m_SignalGen.m_MotionVolumes.push_back( false ); + m_Parameters.m_SignalGen.m_MotionVolumes.push_back( false ); } // set all false except those given. for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter ) { - if ( *iter < (int)parameters.m_SignalGen.GetNumVolumes() && *iter >= 0 ) + if ( *iter < (int)m_Parameters.m_SignalGen.GetNumVolumes() && *iter >= 0 ) { - parameters.m_SignalGen.m_MotionVolumes.at( *iter ) = true; + m_Parameters.m_SignalGen.m_MotionVolumes.at( *iter ) = true; } } MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of positive numbers."; } else { MITK_ERROR << "QmitkFiberfoxView.cpp: Inconsistent list of numbers in m_MotionVolumesBox."; } } else { - MITK_WARN << "QmitkFiberfoxView.cpp: Unrecognised parameters.m_Misc.m_MotionVolumesBox: " << parameters.m_Misc.m_MotionVolumesBox; - parameters.m_Misc.m_MotionVolumesBox = "random"; // set default. - for (unsigned int i=0; im_AcquisitionTypeBox->currentIndex(); - parameters.m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)m_Controls->m_CoilSensBox->currentIndex(); - parameters.m_SignalGen.m_NumberOfCoils = m_Controls->m_NumCoilsBox->value(); - parameters.m_SignalGen.m_PartialFourier = m_Controls->m_PartialFourier->value(); - parameters.m_SignalGen.m_ReversePhase = m_Controls->m_ReversePhaseBox->isChecked(); - parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); - parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); - parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); - parameters.m_SignalGen.m_tRep = m_Controls->m_TRbox->value(); - parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); - parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); - parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); - - double voxelVolume = parameters.m_SignalGen.m_ImageSpacing[0] - * parameters.m_SignalGen.m_ImageSpacing[1] - * parameters.m_SignalGen.m_ImageSpacing[2]; - - if ( parameters.m_SignalGen.m_SignalScale*voxelVolume > itk::NumericTraits::max()*0.75 ) - { - parameters.m_SignalGen.m_SignalScale = itk::NumericTraits::max()*0.75/voxelVolume; - m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); + m_Parameters.m_SignalGen.m_AcquisitionType = (SignalGenerationParameters::AcquisitionType)m_Controls->m_AcquisitionTypeBox->currentIndex(); + m_Parameters.m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)m_Controls->m_CoilSensBox->currentIndex(); + m_Parameters.m_SignalGen.m_NumberOfCoils = m_Controls->m_NumCoilsBox->value(); + m_Parameters.m_SignalGen.m_PartialFourier = m_Controls->m_PartialFourier->value(); + m_Parameters.m_SignalGen.m_ReversePhase = m_Controls->m_ReversePhaseBox->isChecked(); + m_Parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value(); + m_Parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value(); + m_Parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value(); + m_Parameters.m_SignalGen.m_tRep = m_Controls->m_TRbox->value(); + m_Parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked(); + m_Parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value(); + m_Parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value(); + + double voxelVolume = m_Parameters.m_SignalGen.m_ImageSpacing[0] + * m_Parameters.m_SignalGen.m_ImageSpacing[1] + * m_Parameters.m_SignalGen.m_ImageSpacing[2]; + + if ( m_Parameters.m_SignalGen.m_SignalScale*voxelVolume > itk::NumericTraits::max()*0.75 ) + { + m_Parameters.m_SignalGen.m_SignalScale = itk::NumericTraits::max()*0.75/voxelVolume; + m_Controls->m_SignalScaleBox->setValue(m_Parameters.m_SignalGen.m_SignalScale); QMessageBox::information( nullptr, "Warning", "Maximum signal exceeding data type limits. Automatically adjusted to " - + QString::number(parameters.m_SignalGen.m_SignalScale) + + QString::number(m_Parameters.m_SignalGen.m_SignalScale) + " to obtain a maximum signal of 75% of the data type maximum." " Relaxation and other effects that affect the signal intensities are not accounted for."); } // Noise - parameters.m_Misc.m_DoAddNoise = m_Controls->m_AddNoise->isChecked(); - parameters.m_SignalGen.m_NoiseVariance = m_Controls->m_NoiseLevel->value(); + m_Parameters.m_Misc.m_DoAddNoise = m_Controls->m_AddNoise->isChecked(); + m_Parameters.m_SignalGen.m_NoiseVariance = m_Controls->m_NoiseLevel->value(); if (m_Controls->m_AddNoise->isChecked()) { switch (m_Controls->m_NoiseDistributionBox->currentIndex()) { case 0: { - if (parameters.m_SignalGen.m_NoiseVariance>0) + if (m_Parameters.m_SignalGen.m_NoiseVariance>0) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); } break; } case 1: { - if (parameters.m_SignalGen.m_NoiseVariance>0) + if (m_Parameters.m_SignalGen.m_NoiseVariance>0) { - parameters.m_NoiseModel = std::make_shared< mitk::RicianNoiseModel >(); - parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); - parameters.m_NoiseModel->SetNoiseVariance(parameters.m_SignalGen.m_NoiseVariance); + m_Parameters.m_NoiseModel = std::make_shared< mitk::RicianNoiseModel >(); + m_Parameters.m_Misc.m_ArtifactModelString += "_RICIAN-"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician")); + m_Parameters.m_NoiseModel->SetNoiseVariance(m_Parameters.m_SignalGen.m_NoiseVariance); } break; } case 2: { - if (parameters.m_SignalGen.m_NoiseVariance>0) + if (m_Parameters.m_SignalGen.m_NoiseVariance>0) { - parameters.m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel >(); - parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); - parameters.m_NoiseModel->SetNoiseVariance(parameters.m_SignalGen.m_NoiseVariance); + m_Parameters.m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel >(); + m_Parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared")); + m_Parameters.m_NoiseModel->SetNoiseVariance(m_Parameters.m_SignalGen.m_NoiseVariance); } break; } default: { - if (parameters.m_SignalGen.m_NoiseVariance>0) + if (m_Parameters.m_SignalGen.m_NoiseVariance>0) { - parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; - parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); + m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true; + m_Parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian")); } break; } } - if (parameters.m_SignalGen.m_NoiseVariance>0) + if (m_Parameters.m_SignalGen.m_NoiseVariance>0) { - parameters.m_Misc.m_ArtifactModelString += QString::number(parameters.m_SignalGen.m_NoiseVariance).toStdString(); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(parameters.m_SignalGen.m_NoiseVariance)); + m_Parameters.m_Misc.m_ArtifactModelString += QString::number(m_Parameters.m_SignalGen.m_NoiseVariance).toStdString(); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(m_Parameters.m_SignalGen.m_NoiseVariance)); } } // signal models { // compartment 1 switch (m_Controls->m_Compartment1Box->currentIndex()) { case 0: { mitk::StickModel* model = new mitk::StickModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_StickWidget1->GetD()); model->SetT2(m_Controls->m_StickWidget1->GetT2()); model->SetT1(m_Controls->m_StickWidget1->GetT1()); model->m_CompartmentId = 1; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Stick"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Stick"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::TensorModel* model = new mitk::TensorModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2()); model->SetT1(m_Controls->m_ZeppelinWidget1->GetT1()); model->m_CompartmentId = 1; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Zeppelin"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Zeppelin"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3()); model->SetT2(m_Controls->m_TensorWidget1->GetT2()); model->SetT1(m_Controls->m_TensorWidget1->GetT1()); model->m_CompartmentId = 1; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Tensor"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Tensor"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); - parameters.m_SignalGen.m_DoSimulateRelaxation = false; - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc()); model->m_CompartmentId = 1; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Prototype"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Prototype"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") ); break; } } if (m_Controls->m_Comp1VolumeFraction->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp1VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); - parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); + m_Parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } // compartment 2 switch (m_Controls->m_Compartment2Box->currentIndex()) { case 0: break; case 1: { mitk::StickModel* model = new mitk::StickModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_StickWidget2->GetD()); model->SetT2(m_Controls->m_StickWidget2->GetT2()); model->SetT1(m_Controls->m_StickWidget2->GetT1()); model->m_CompartmentId = 2; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Stick"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Stick"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::TensorModel* model = new mitk::TensorModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2()); model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2()); model->SetT1(m_Controls->m_ZeppelinWidget2->GetT1()); model->m_CompartmentId = 2; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Zeppelin"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Zeppelin"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::TensorModel* model = new mitk::TensorModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1()); model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2()); model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3()); model->SetT2(m_Controls->m_TensorWidget2->GetT2()); model->SetT1(m_Controls->m_TensorWidget2->GetT1()); model->m_CompartmentId = 2; - parameters.m_FiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Tensor"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_FiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Tensor"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) ); break; } } - if (m_Controls->m_Comp2VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_FiberModelList.size()==2) + if (m_Controls->m_Comp2VolumeFraction->GetSelectedNode().IsNotNull() && m_Parameters.m_FiberModelList.size()==2) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp2VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); - parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); + m_Parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } // compartment 3 switch (m_Controls->m_Compartment3Box->currentIndex()) { case 0: { mitk::BallModel* model = new mitk::BallModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_BallWidget1->GetD()); model->SetT2(m_Controls->m_BallWidget1->GetT2()); model->SetT1(m_Controls->m_BallWidget1->GetT1()); model->m_CompartmentId = 3; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Ball"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Ball"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 1: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2()); model->SetT1(m_Controls->m_AstrosticksWidget1->GetT1()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()); model->m_CompartmentId = 3; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Astrosticks"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Astrosticks"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) ); break; } case 2: { mitk::DotModel* model = new mitk::DotModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget1->GetT2()); model->SetT1(m_Controls->m_DotWidget1->GetT1()); model->m_CompartmentId = 3; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Dot"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Dot"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) ); break; } case 3: { mitk::RawShModel* model = new mitk::RawShModel(); - parameters.m_SignalGen.m_DoSimulateRelaxation = false; - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc()); model->m_CompartmentId = 3; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Prototype"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Prototype"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") ); break; } } if (m_Controls->m_Comp3VolumeFraction->GetSelectedNode().IsNotNull()) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp3VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage); - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); + m_Parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage); } switch (m_Controls->m_Compartment4Box->currentIndex()) { case 0: break; case 1: { mitk::BallModel* model = new mitk::BallModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_BallWidget2->GetD()); model->SetT2(m_Controls->m_BallWidget2->GetT2()); model->SetT1(m_Controls->m_BallWidget2->GetT1()); model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Ball"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Ball"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 2: { mitk::AstroStickModel* model = new mitk::AstroStickModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); - model->SetBvalue(parameters.m_SignalGen.GetBvalue()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); + model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue()); model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD()); model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2()); model->SetT1(m_Controls->m_AstrosticksWidget2->GetT1()); model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()); model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Astrosticks"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Astrosticks"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) ); break; } case 3: { mitk::DotModel* model = new mitk::DotModel(); - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); model->SetT2(m_Controls->m_DotWidget2->GetT2()); model->SetT1(m_Controls->m_DotWidget2->GetT1()); model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Dot"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Dot"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) ); break; } case 4: { mitk::RawShModel* model = new mitk::RawShModel(); - parameters.m_SignalGen.m_DoSimulateRelaxation = false; - model->SetGradientList(parameters.m_SignalGen.GetGradientDirections()); + m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false; + model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections()); model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples()); model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa()); model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc()); model->m_CompartmentId = 4; - parameters.m_NonFiberModelList.push_back(model); - parameters.m_Misc.m_SignalModelString += "Prototype"; - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); + m_Parameters.m_NonFiberModelList.push_back(model); + m_Parameters.m_Misc.m_SignalModelString += "Prototype"; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") ); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") ); break; } } - if (m_Controls->m_Comp4VolumeFraction->GetSelectedNode().IsNotNull() && parameters.m_NonFiberModelList.size()==2) + if (m_Controls->m_Comp4VolumeFraction->GetSelectedNode().IsNotNull() && m_Parameters.m_NonFiberModelList.size()==2) { mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode(); ItkDoubleImgType::Pointer compVolumeImage = ItkDoubleImgType::New(); mitk::Image* img = dynamic_cast(volumeNode->GetData()); CastToItkImage< ItkDoubleImgType >(img, compVolumeImage); - parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(compVolumeImage); + m_Parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(compVolumeImage); } } - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(parameters.m_SignalGen.m_SignalScale)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(parameters.m_SignalGen.m_AxonRadius)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(parameters.m_SignalGen.m_tInhom)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(parameters.m_SignalGen.m_tLine)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(parameters.m_SignalGen.m_tEcho)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(parameters.m_SignalGen.GetBvalue())); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(parameters.m_SignalGen.m_DoDisablePartialVolume)); - parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(parameters.m_SignalGen.m_DoSimulateRelaxation)); - parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); - - parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); - parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); - parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); - parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); - - return parameters; + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(m_Parameters.m_SignalGen.m_SignalScale)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(m_Parameters.m_SignalGen.m_AxonRadius)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(m_Parameters.m_SignalGen.m_tInhom)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(m_Parameters.m_SignalGen.m_tLine)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(m_Parameters.m_SignalGen.m_tEcho)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(m_Parameters.m_SignalGen.GetBvalue())); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(m_Parameters.m_SignalGen.m_DoDisablePartialVolume)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(m_Parameters.m_SignalGen.m_DoSimulateRelaxation)); + m_Parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false)); } void QmitkFiberfoxView::SaveParameters(QString filename) { - FiberfoxParameters ffParamaters = UpdateImageParameters(true, true); - std::vector< int > bVals = ffParamaters.m_SignalGen.GetBvalues(); + UpdateParametersFromGui(); + std::vector< int > bVals = m_Parameters.m_SignalGen.GetBvalues(); std::cout << "b-values: "; for (auto v : bVals) std::cout << v << " "; std::cout << std::endl; bool ok = true; bool first = true; bool dosampling = false; mitk::Image::Pointer diffImg = nullptr; itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr; ItkDoubleImgType::Pointer adcImage = nullptr; - for (unsigned int i=0; i* model = nullptr; - if (i* >(ffParamaters.m_FiberModelList.at(i)); + model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_FiberModelList.at(i)); } else { - model = dynamic_cast< mitk::RawShModel<>* >(ffParamaters.m_NonFiberModelList.at(i-ffParamaters.m_FiberModelList.size())); + model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_NonFiberModelList.at(i-m_Parameters.m_FiberModelList.size())); } if ( model!=nullptr && model->GetNumberOfKernels() <= 0 ) { if (first==true) { if ( QMessageBox::question(nullptr, "Prototype signal sampling", "Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes ) dosampling = true; first = false; if ( dosampling && (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) ) { QMessageBox::information(nullptr, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from."); return; } else if (dosampling) { diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg)); adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } } typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg)); adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); adcFilter->Update(); adcImage = adcFilter->GetOutput(); if (dosampling && diffImg.IsNotNull()) { - ok = model->SampleKernels(diffImg, ffParamaters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); + ok = model->SampleKernels(diffImg, m_Parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) { QMessageBox::information( nullptr, "Parameter file not saved", "No valid prototype signals could be sampled."); return; } } } } - ffParamaters.SaveParameters(filename.toStdString()); + m_Parameters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberfoxView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); SaveParameters(filename); } 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; + m_Parameters.LoadParameters(filename.toStdString()); - FiberfoxParameters parameters = UpdateImageParameters(); - parameters.LoadParameters(filename.toStdString()); - - if (parameters.m_MissingTags.size()>0) + if (m_Parameters.m_MissingTags.size()>0) { QString missing("Parameter file might be corrupted. The following parameters could not be read: "); - missing += QString(parameters.m_MissingTags.c_str()); + missing += QString(m_Parameters.m_MissingTags.c_str()); missing += "\nDefault values have been assigned to the missing parameters."; QMessageBox::information( nullptr, "Warning!", missing); } - m_Controls->m_RealTimeFibers->setChecked(parameters.m_Misc.m_CheckRealTimeFibersBox); - m_Controls->m_AdvancedOptionsBox->setChecked(parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); - m_Controls->m_IncludeFiducials->setChecked(parameters.m_Misc.m_CheckIncludeFiducialsBox); - m_Controls->m_ConstantRadiusBox->setChecked(parameters.m_Misc.m_CheckConstantRadiusBox); - - m_Controls->m_DistributionBox->setCurrentIndex(parameters.m_FiberGen.m_Distribution); - m_Controls->m_VarianceBox->setValue(parameters.m_FiberGen.m_Variance); - m_Controls->m_FiberDensityBox->setValue(parameters.m_FiberGen.m_Density); - m_Controls->m_FiberSamplingBox->setValue(parameters.m_FiberGen.m_Sampling); - m_Controls->m_TensionBox->setValue(parameters.m_FiberGen.m_Tension); - m_Controls->m_ContinuityBox->setValue(parameters.m_FiberGen.m_Continuity); - m_Controls->m_BiasBox->setValue(parameters.m_FiberGen.m_Bias); - m_Controls->m_XrotBox->setValue(parameters.m_FiberGen.m_Rotation[0]); - m_Controls->m_YrotBox->setValue(parameters.m_FiberGen.m_Rotation[1]); - m_Controls->m_ZrotBox->setValue(parameters.m_FiberGen.m_Rotation[2]); - m_Controls->m_XtransBox->setValue(parameters.m_FiberGen.m_Translation[0]); - m_Controls->m_YtransBox->setValue(parameters.m_FiberGen.m_Translation[1]); - m_Controls->m_ZtransBox->setValue(parameters.m_FiberGen.m_Translation[2]); - m_Controls->m_XscaleBox->setValue(parameters.m_FiberGen.m_Scale[0]); - m_Controls->m_YscaleBox->setValue(parameters.m_FiberGen.m_Scale[1]); - m_Controls->m_ZscaleBox->setValue(parameters.m_FiberGen.m_Scale[2]); - // image generation parameters - m_Controls->m_SizeX->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(0)); - m_Controls->m_SizeY->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(1)); - m_Controls->m_SizeZ->setValue(parameters.m_SignalGen.m_ImageRegion.GetSize(2)); - m_Controls->m_SpacingX->setValue(parameters.m_SignalGen.m_ImageSpacing[0]); - m_Controls->m_SpacingY->setValue(parameters.m_SignalGen.m_ImageSpacing[1]); - m_Controls->m_SpacingZ->setValue(parameters.m_SignalGen.m_ImageSpacing[2]); - m_Controls->m_NumGradientsBox->setValue(parameters.m_SignalGen.GetNumWeightedVolumes()); - m_Controls->m_BvalueBox->setValue(parameters.m_SignalGen.GetBvalue()); - m_Controls->m_SignalScaleBox->setValue(parameters.m_SignalGen.m_SignalScale); - m_Controls->m_TEbox->setValue(parameters.m_SignalGen.m_tEcho); - m_Controls->m_LineReadoutTimeBox->setValue(parameters.m_SignalGen.m_tLine); - m_Controls->m_T2starBox->setValue(parameters.m_SignalGen.m_tInhom); - m_Controls->m_FiberRadius->setValue(parameters.m_SignalGen.m_AxonRadius); - m_Controls->m_RelaxationBox->setChecked(parameters.m_SignalGen.m_DoSimulateRelaxation); - m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(parameters.m_SignalGen.m_DoDisablePartialVolume); - m_Controls->m_ReversePhaseBox->setChecked(parameters.m_SignalGen.m_ReversePhase); - m_Controls->m_PartialFourier->setValue(parameters.m_SignalGen.m_PartialFourier); - m_Controls->m_TRbox->setValue(parameters.m_SignalGen.m_tRep); - m_Controls->m_NumCoilsBox->setValue(parameters.m_SignalGen.m_NumberOfCoils); - m_Controls->m_CoilSensBox->setCurrentIndex(parameters.m_SignalGen.m_CoilSensitivityProfile); - m_Controls->m_AcquisitionTypeBox->setCurrentIndex(parameters.m_SignalGen.m_AcquisitionType); - - if (parameters.m_NoiseModel!=nullptr) + m_Controls->m_SizeX->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)); + m_Controls->m_SizeY->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)); + m_Controls->m_SizeZ->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)); + m_Controls->m_SpacingX->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[0]); + m_Controls->m_SpacingY->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[1]); + m_Controls->m_SpacingZ->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[2]); + m_Controls->m_NumGradientsBox->setValue(m_Parameters.m_SignalGen.GetNumWeightedVolumes()); + m_Controls->m_BvalueBox->setValue(m_Parameters.m_SignalGen.GetBvalue()); + m_Controls->m_SignalScaleBox->setValue(m_Parameters.m_SignalGen.m_SignalScale); + m_Controls->m_TEbox->setValue(m_Parameters.m_SignalGen.m_tEcho); + m_Controls->m_LineReadoutTimeBox->setValue(m_Parameters.m_SignalGen.m_tLine); + m_Controls->m_T2starBox->setValue(m_Parameters.m_SignalGen.m_tInhom); + m_Controls->m_FiberRadius->setValue(m_Parameters.m_SignalGen.m_AxonRadius); + m_Controls->m_RelaxationBox->setChecked(m_Parameters.m_SignalGen.m_DoSimulateRelaxation); + m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(m_Parameters.m_SignalGen.m_DoDisablePartialVolume); + m_Controls->m_ReversePhaseBox->setChecked(m_Parameters.m_SignalGen.m_ReversePhase); + m_Controls->m_PartialFourier->setValue(m_Parameters.m_SignalGen.m_PartialFourier); + m_Controls->m_TRbox->setValue(m_Parameters.m_SignalGen.m_tRep); + m_Controls->m_NumCoilsBox->setValue(m_Parameters.m_SignalGen.m_NumberOfCoils); + m_Controls->m_CoilSensBox->setCurrentIndex(m_Parameters.m_SignalGen.m_CoilSensitivityProfile); + m_Controls->m_AcquisitionTypeBox->setCurrentIndex(m_Parameters.m_SignalGen.m_AcquisitionType); + + if (!m_Parameters.m_Misc.m_BvalsFile.empty()) + { + m_Controls->m_UseBvalsBvecsBox->setChecked(true); + m_Controls->m_LoadBvalsEdit->setText(QString(m_Parameters.m_Misc.m_BvalsFile.c_str())); + } + else + m_Controls->m_LoadBvalsEdit->setText("-"); + + if (!m_Parameters.m_Misc.m_BvecsFile.empty()) + { + m_Controls->m_UseBvalsBvecsBox->setChecked(true); + m_Controls->m_LoadBvecsEdit->setText(QString(m_Parameters.m_Misc.m_BvecsFile.c_str())); + } + else + m_Controls->m_LoadBvecsEdit->setText("-"); + + if (m_Parameters.m_NoiseModel!=nullptr) { - m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_DoAddNoise); - if (dynamic_cast*>(parameters.m_NoiseModel.get())) + m_Controls->m_AddNoise->setChecked(m_Parameters.m_Misc.m_DoAddNoise); + if (dynamic_cast*>(m_Parameters.m_NoiseModel.get())) { m_Controls->m_NoiseDistributionBox->setCurrentIndex(0); } - else if (dynamic_cast*>(parameters.m_NoiseModel.get())) + else if (dynamic_cast*>(m_Parameters.m_NoiseModel.get())) { m_Controls->m_NoiseDistributionBox->setCurrentIndex(1); } - m_Controls->m_NoiseLevel->setValue(parameters.m_NoiseModel->GetNoiseVariance()); + m_Controls->m_NoiseLevel->setValue(m_Parameters.m_NoiseModel->GetNoiseVariance()); } else { - m_Controls->m_AddNoise->setChecked(parameters.m_Misc.m_DoAddNoise); - m_Controls->m_NoiseLevel->setValue(parameters.m_SignalGen.m_NoiseVariance); - } - - m_Controls->m_VolumeFractionsBox->setChecked(parameters.m_Misc.m_CheckOutputVolumeFractionsBox); - m_Controls->m_AdvancedOptionsBox_2->setChecked(parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); - m_Controls->m_AddGhosts->setChecked(parameters.m_Misc.m_DoAddGhosts); - m_Controls->m_AddAliasing->setChecked(parameters.m_Misc.m_DoAddAliasing); - m_Controls->m_AddDistortions->setChecked(parameters.m_Misc.m_DoAddDistortions); - m_Controls->m_AddSpikes->setChecked(parameters.m_Misc.m_DoAddSpikes); - m_Controls->m_AddEddy->setChecked(parameters.m_Misc.m_DoAddEddyCurrents); - m_Controls->m_AddDrift->setChecked(parameters.m_SignalGen.m_DoAddDrift); - - m_Controls->m_kOffsetBox->setValue(parameters.m_SignalGen.m_KspaceLineOffset); - m_Controls->m_WrapBox->setValue(100*(1-parameters.m_SignalGen.m_CroppingFactor)); - m_Controls->m_DriftFactor->setValue(100*parameters.m_SignalGen.m_Drift); - m_Controls->m_SpikeNumBox->setValue(parameters.m_SignalGen.m_Spikes); - m_Controls->m_SpikeScaleBox->setValue(parameters.m_SignalGen.m_SpikeAmplitude); - m_Controls->m_EddyGradientStrength->setValue(parameters.m_SignalGen.m_EddyStrength); - m_Controls->m_AddGibbsRinging->setChecked(parameters.m_SignalGen.m_DoAddGibbsRinging); - m_Controls->m_AddMotion->setChecked(parameters.m_SignalGen.m_DoAddMotion); - m_Controls->m_RandomMotion->setChecked(parameters.m_SignalGen.m_DoRandomizeMotion); - m_Controls->m_MotionVolumesBox->setText(QString(parameters.m_Misc.m_MotionVolumesBox.c_str())); - - m_Controls->m_MaxTranslationBoxX->setValue(parameters.m_SignalGen.m_Translation[0]); - m_Controls->m_MaxTranslationBoxY->setValue(parameters.m_SignalGen.m_Translation[1]); - m_Controls->m_MaxTranslationBoxZ->setValue(parameters.m_SignalGen.m_Translation[2]); - m_Controls->m_MaxRotationBoxX->setValue(parameters.m_SignalGen.m_Rotation[0]); - m_Controls->m_MaxRotationBoxY->setValue(parameters.m_SignalGen.m_Rotation[1]); - m_Controls->m_MaxRotationBoxZ->setValue(parameters.m_SignalGen.m_Rotation[2]); + m_Controls->m_AddNoise->setChecked(m_Parameters.m_Misc.m_DoAddNoise); + m_Controls->m_NoiseLevel->setValue(m_Parameters.m_SignalGen.m_NoiseVariance); + } + + m_Controls->m_VolumeFractionsBox->setChecked(m_Parameters.m_Misc.m_CheckOutputVolumeFractionsBox); + m_Controls->m_AdvancedOptionsBox_2->setChecked(m_Parameters.m_Misc.m_CheckAdvancedSignalOptionsBox); + m_Controls->m_AddGhosts->setChecked(m_Parameters.m_Misc.m_DoAddGhosts); + m_Controls->m_AddAliasing->setChecked(m_Parameters.m_Misc.m_DoAddAliasing); + m_Controls->m_AddDistortions->setChecked(m_Parameters.m_Misc.m_DoAddDistortions); + m_Controls->m_AddSpikes->setChecked(m_Parameters.m_Misc.m_DoAddSpikes); + m_Controls->m_AddEddy->setChecked(m_Parameters.m_Misc.m_DoAddEddyCurrents); + m_Controls->m_AddDrift->setChecked(m_Parameters.m_SignalGen.m_DoAddDrift); + + m_Controls->m_kOffsetBox->setValue(m_Parameters.m_SignalGen.m_KspaceLineOffset); + m_Controls->m_WrapBox->setValue(100*(1-m_Parameters.m_SignalGen.m_CroppingFactor)); + m_Controls->m_DriftFactor->setValue(100*m_Parameters.m_SignalGen.m_Drift); + m_Controls->m_SpikeNumBox->setValue(m_Parameters.m_SignalGen.m_Spikes); + m_Controls->m_SpikeScaleBox->setValue(m_Parameters.m_SignalGen.m_SpikeAmplitude); + m_Controls->m_EddyGradientStrength->setValue(m_Parameters.m_SignalGen.m_EddyStrength); + m_Controls->m_AddGibbsRinging->setChecked(m_Parameters.m_SignalGen.m_DoAddGibbsRinging); + m_Controls->m_AddMotion->setChecked(m_Parameters.m_SignalGen.m_DoAddMotion); + m_Controls->m_RandomMotion->setChecked(m_Parameters.m_SignalGen.m_DoRandomizeMotion); + m_Controls->m_MotionVolumesBox->setText(QString(m_Parameters.m_Misc.m_MotionVolumesBox.c_str())); + + m_Controls->m_MaxTranslationBoxX->setValue(m_Parameters.m_SignalGen.m_Translation[0]); + m_Controls->m_MaxTranslationBoxY->setValue(m_Parameters.m_SignalGen.m_Translation[1]); + m_Controls->m_MaxTranslationBoxZ->setValue(m_Parameters.m_SignalGen.m_Translation[2]); + m_Controls->m_MaxRotationBoxX->setValue(m_Parameters.m_SignalGen.m_Rotation[0]); + m_Controls->m_MaxRotationBoxY->setValue(m_Parameters.m_SignalGen.m_Rotation[1]); + m_Controls->m_MaxRotationBoxZ->setValue(m_Parameters.m_SignalGen.m_Rotation[2]); m_Controls->m_Compartment1Box->setCurrentIndex(0); m_Controls->m_Compartment2Box->setCurrentIndex(0); m_Controls->m_Compartment3Box->setCurrentIndex(0); m_Controls->m_Compartment4Box->setCurrentIndex(0); - for (unsigned int i=0; i* signalModel = nullptr; - if (iGetVolumeFractionImage().IsNotNull() ) { compVolNode = mitk::DataNode::New(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(signalModel->GetVolumeFractionImage().GetPointer()); image->SetVolume(signalModel->GetVolumeFractionImage()->GetBufferPointer()); compVolNode->SetData( image ); compVolNode->SetName("Compartment volume "+QString::number(signalModel->m_CompartmentId).toStdString()); GetDataStorage()->Add(compVolNode); } switch (signalModel->m_CompartmentId) { case 1: { if (compVolNode.IsNotNull()) m_Controls->m_Comp1VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget1->SetT2(model->GetT2()); m_Controls->m_StickWidget1->SetT1(model->GetT1()); m_Controls->m_StickWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment1Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget1->SetT2(model->GetT2()); m_Controls->m_TensorWidget1->SetT1(model->GetT1()); m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment1Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment1Box->setCurrentIndex(3); break; } break; } case 2: { if (compVolNode.IsNotNull()) m_Controls->m_Comp2VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::StickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_StickWidget2->SetT2(model->GetT2()); m_Controls->m_StickWidget2->SetT1(model->GetT1()); m_Controls->m_StickWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment2Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::TensorModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_TensorWidget2->SetT2(model->GetT2()); m_Controls->m_TensorWidget2->SetT1(model->GetT1()); m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1()); m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2()); m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3()); m_Controls->m_Compartment2Box->setCurrentIndex(3); break; } break; } case 3: { if (compVolNode.IsNotNull()) m_Controls->m_Comp3VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget1->SetT2(model->GetT2()); m_Controls->m_BallWidget1->SetT1(model->GetT1()); m_Controls->m_BallWidget1->SetD(model->GetDiffusivity()); m_Controls->m_Compartment3Box->setCurrentIndex(0); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget1->SetT1(model->GetT1()); m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment3Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget1->SetT2(model->GetT2()); m_Controls->m_DotWidget1->SetT1(model->GetT1()); m_Controls->m_Compartment3Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment3Box->setCurrentIndex(3); break; } break; } case 4: { if (compVolNode.IsNotNull()) m_Controls->m_Comp4VolumeFraction->SetSelectedNode(compVolNode); if (dynamic_cast*>(signalModel)) { mitk::BallModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_BallWidget2->SetT2(model->GetT2()); m_Controls->m_BallWidget2->SetT1(model->GetT1()); m_Controls->m_BallWidget2->SetD(model->GetDiffusivity()); m_Controls->m_Compartment4Box->setCurrentIndex(1); break; } else if (dynamic_cast*>(signalModel)) { mitk::AstroStickModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2()); m_Controls->m_AstrosticksWidget2->SetT1(model->GetT1()); m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity()); m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks()); m_Controls->m_Compartment4Box->setCurrentIndex(2); break; } else if (dynamic_cast*>(signalModel)) { mitk::DotModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_DotWidget2->SetT2(model->GetT2()); m_Controls->m_DotWidget2->SetT1(model->GetT1()); m_Controls->m_Compartment4Box->setCurrentIndex(3); break; } else if (dynamic_cast*>(signalModel)) { mitk::RawShModel<>* model = dynamic_cast*>(signalModel); m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels()); m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first); m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second); m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first); m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second); m_Controls->m_Compartment4Box->setCurrentIndex(4); break; } break; } } } - if ( parameters.m_SignalGen.m_MaskImage ) + if ( m_Parameters.m_SignalGen.m_MaskImage ) { mitk::Image::Pointer image = mitk::Image::New(); - image->InitializeByItk(parameters.m_SignalGen.m_MaskImage.GetPointer()); - image->SetVolume(parameters.m_SignalGen.m_MaskImage->GetBufferPointer()); + image->InitializeByItk(m_Parameters.m_SignalGen.m_MaskImage.GetPointer()); + image->SetVolume(m_Parameters.m_SignalGen.m_MaskImage->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Tissue mask"); GetDataStorage()->Add(node); m_Controls->m_MaskComboBox->SetSelectedNode(node); } - if ( parameters.m_SignalGen.m_FrequencyMap ) + if ( m_Parameters.m_SignalGen.m_FrequencyMap ) { mitk::Image::Pointer image = mitk::Image::New(); - image->InitializeByItk(parameters.m_SignalGen.m_FrequencyMap.GetPointer()); - image->SetVolume(parameters.m_SignalGen.m_FrequencyMap->GetBufferPointer()); + image->InitializeByItk(m_Parameters.m_SignalGen.m_FrequencyMap.GetPointer()); + image->SetVolume(m_Parameters.m_SignalGen.m_FrequencyMap->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Frequency map"); GetDataStorage()->Add(node); m_Controls->m_FrequencyMapBox->SetSelectedNode(node); } } 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); m_Controls->m_PrototypeWidget1->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; case 3: m_Controls->m_PrototypeWidget1->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); m_Controls->m_Comp2FractionFrame->setVisible(false); switch (index) { case 0: break; case 1: m_Controls->m_StickWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 2: m_Controls->m_ZeppelinWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->setVisible(true); break; case 3: m_Controls->m_TensorWidget2->setVisible(true); m_Controls->m_Comp2FractionFrame->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); m_Controls->m_PrototypeWidget3->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; case 3: m_Controls->m_PrototypeWidget3->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_PrototypeWidget4->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; case 4: m_Controls->m_PrototypeWidget4->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::OnAddDrift(int value) { if (value>0) m_Controls->m_DriftFrame->setVisible(true); else m_Controls->m_DriftFrame->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) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::OnFiberDensityChanged(int) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::OnFiberSamplingChanged(double) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::OnTensionChanged(double) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::OnContinuityChanged(double) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::OnBiasChanged(double) -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::AlignOnGrid() -{ - for (unsigned 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::BaseGeometry::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(unsigned 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::BaseGeometry::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(unsigned 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::BaseGeometry::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*itk::Math::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_SelectedImageNode.IsNull()) - return; - - mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); - - mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::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_SelectedImageNode); -} - -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 ); - node->SetBoolProperty("planarfigure.3drendering", true); - node->SetBoolProperty("planarfigure.3drendering.fill", true); - - 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( "MitkPlanarFigure" ); - 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; - } - - FiberfoxParameters parameters = UpdateImageParameters(false); - - for (unsigned 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); - std::sort(childVector.begin(), childVector.end(), CompareLayer); - - std::vector< mitk::PlanarEllipse::Pointer > fib; - std::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); - ellipse->Modified(); - } - else - { - v.Normalize(); - v *= radius; - ellipse->SetControlPoint(1, c+v); - ellipse->Modified(); - } - } - 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) - { - parameters.m_FiberGen.m_Fiducials.push_back(fib); - parameters.m_FiberGen.m_FlipList.push_back(flip); - } - else if (fib.size()>0) - m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - } - - itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); - filter->SetParameters(parameters.m_FiberGen); - filter->Update(); - std::vector< mitk::FiberBundle::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_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) { 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::Point3D origin; origin[0] = m_Controls->m_SpacingX->value()/2; origin[1] = m_Controls->m_SpacingY->value()/2; origin[2] = m_Controls->m_SpacingZ->value()/2; image->SetOrigin(origin); 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_SelectedImageNode = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); - QMessageBox::information(nullptr, "Template image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image. A template image with the specified geometry has been generated that can be used to draw artificial fibers (see tab 'Fiber Definition')."); + QMessageBox::information(nullptr, "Template image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image. A template image with the specified geometry has been generated that can be used to draw artificial fibers (see view 'Fiber Generator')."); } else if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull()) SimulateImageFromFibers(m_Controls->m_FiberBundleComboBox->GetSelectedNode()); else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode()) ) SimulateForExistingDwi(m_Controls->m_TemplateComboBox->GetSelectedNode()); else QMessageBox::information(nullptr, "No image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image."); } +void QmitkFiberfoxView::SetFocus() +{ +} + void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode) { bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(imageNode->GetData())) ); if ( !isDiffusionImage ) { return; } - FiberfoxParameters parameters = UpdateImageParameters(); + UpdateParametersFromGui(); mitk::Image::Pointer diffImg = dynamic_cast(imageNode->GetData()); ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); - parameters.m_Misc.m_ParentNode = imageNode; - parameters.m_SignalGen.m_SignalScale = 1; - - parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() - +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() - +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() - +"_b"+QString::number(parameters.m_SignalGen.GetBvalue()).toStdString() - +"_"+parameters.m_Misc.m_SignalModelString - +parameters.m_Misc.m_ArtifactModelString); - - m_TractsToDwiFilter->SetParameters(parameters); + m_Parameters.m_Misc.m_ParentNode = imageNode; + m_Parameters.m_SignalGen.m_SignalScale = 1; + + m_Parameters.m_Misc.m_ResultNode->SetName(m_Parameters.m_Misc.m_ParentNode->GetName() + +"_D"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() + +"_S"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() + +"_b"+QString::number(m_Parameters.m_SignalGen.GetBvalue()).toStdString() + +"_"+m_Parameters.m_Misc.m_SignalModelString + +m_Parameters.m_Misc.m_ArtifactModelString); + + m_TractsToDwiFilter->SetParameters(m_Parameters); m_TractsToDwiFilter->SetInputImage(itkVectorImagePointer); m_Thread.start(QThread::LowestPriority); } void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode) { mitk::FiberBundle::Pointer fiberBundle = dynamic_cast(fiberNode->GetData()); if (fiberBundle->GetNumFibers()<=0) { return; } - FiberfoxParameters parameters = UpdateImageParameters(); + UpdateParametersFromGui(); m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New(); - parameters.m_Misc.m_ParentNode = fiberNode; - - parameters.m_Misc.m_ResultNode->SetName(parameters.m_Misc.m_ParentNode->GetName() - +"_D"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() - +"_S"+QString::number(parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() - +"-"+QString::number(parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() - +"_b"+QString::number(parameters.m_SignalGen.GetBvalue()).toStdString() - +"_"+parameters.m_Misc.m_SignalModelString - +parameters.m_Misc.m_ArtifactModelString); + m_Parameters.m_Misc.m_ParentNode = fiberNode; + + m_Parameters.m_Misc.m_ResultNode->SetName(m_Parameters.m_Misc.m_ParentNode->GetName() + +"_D"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)).toStdString() + +"_S"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[0]).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[1]).toStdString() + +"-"+QString::number(m_Parameters.m_SignalGen.m_ImageSpacing[2]).toStdString() + +"_b"+QString::number(m_Parameters.m_SignalGen.GetBvalue()).toStdString() + +"_"+m_Parameters.m_Misc.m_SignalModelString + +m_Parameters.m_Misc.m_ArtifactModelString); if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast (m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) { bool first = true; bool ok = true; mitk::Image::Pointer diffImg = dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()); itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr; const int shOrder = 2; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter QballFilterType; QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr; ItkDoubleImgType::Pointer adcImage = nullptr; - for (unsigned int i=0; i* model = nullptr; - if (i* >(parameters.m_FiberModelList.at(i)); + if (i* >(m_Parameters.m_FiberModelList.at(i)); else - model = dynamic_cast< mitk::RawShModel<>* >(parameters.m_NonFiberModelList.at(i-parameters.m_FiberModelList.size())); + model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_NonFiberModelList.at(i-m_Parameters.m_FiberModelList.size())); if (model!=0 && model->GetNumberOfKernels()<=0) { if (first==true) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(diffImg, itkVectorImagePointer); typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); filter->Update(); tensorImage = filter->GetOutput(); QballFilterType::Pointer qballfilter = QballFilterType::New(); qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer ); qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); qballfilter->SetLambda(0.006); qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL); qballfilter->Update(); itkFeatureImage = qballfilter->GetCoefficientImage(); itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New(); adcFilter->SetInput( itkVectorImagePointer ); adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg)); adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg)); adcFilter->Update(); adcImage = adcFilter->GetOutput(); } - ok = model->SampleKernels(diffImg, parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); + ok = model->SampleKernels(diffImg, m_Parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage); if (!ok) break; } } if (!ok) { QMessageBox::information( nullptr, "Simulation cancelled", "No valid prototype signals could be sampled."); return; } } else if ( m_Controls->m_Compartment1Box->currentIndex()==3 || m_Controls->m_Compartment3Box->currentIndex()==3 || m_Controls->m_Compartment4Box->currentIndex()==4 ) { QMessageBox::information( nullptr, "Simulation cancelled", "Prototype signal but no diffusion-weighted image selected to sample signal from."); return; } - m_TractsToDwiFilter->SetParameters(parameters); + m_TractsToDwiFilter->SetParameters(m_Parameters); m_TractsToDwiFilter->SetFiberBundle(fiberBundle); m_Thread.start(QThread::LowestPriority); } -void QmitkFiberfoxView::ApplyTransform() +void QmitkFiberfoxView::SetBvalsEdit() { - std::vector< mitk::DataNode::Pointer > selectedBundles; - for(unsigned 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()) - { - for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) - { - mitk::FiberBundle::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()); + // SELECT FOLDER DIALOG + std::string filename; + filename = QFileDialog::getOpenFileName(nullptr, "Select bvals file", QString(filename.c_str())).toStdString(); - // 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::BaseGeometry* 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()*itk::Math::pi/180; - double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; - double z = m_Controls->m_ZrotBox->value()*itk::Math::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); - - pe->Modified(); - } - } - } - } - } + if (filename.empty()) + m_Controls->m_LoadBvalsEdit->setText("-"); else - { - for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); - mitk::BaseGeometry* 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()*itk::Math::pi/180; - double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; - double z = m_Controls->m_ZrotBox->value()*itk::Math::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()); - pe->Modified(); - } - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); - } - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + m_Controls->m_LoadBvalsEdit->setText(QString(filename.c_str())); } -void QmitkFiberfoxView::CopyBundles() +void QmitkFiberfoxView::SetBvecsEdit() { - if ( m_SelectedBundles.size()<1 ){ - QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); - MITK_WARN("QmitkFiberFoxView") << "Select at least one fiber bundle!"; - return; - } - - for (std::vector::const_iterator it = m_SelectedBundles.begin(); 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::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); - mitk::FiberBundle::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 = dynamic_cast(fiducialNode->GetData())->Clone(); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - newNode->SetData(pe); - newNode->SetName(fiducialNode->GetName()); - newNode->SetBoolProperty("planarfigure.3drendering", true); - GetDataStorage()->Add(newNode, fbNode); + // SELECT FOLDER DIALOG + std::string filename; + filename = QFileDialog::getOpenFileName(nullptr, "Select bvecs file", QString(filename.c_str())).toStdString(); - } - } - } - } - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + if (filename.empty()) + m_Controls->m_LoadBvecsEdit->setText("-"); + else + m_Controls->m_LoadBvecsEdit->setText(QString(filename.c_str())); } -void QmitkFiberfoxView::JoinBundles() +void QmitkFiberfoxView::SetOutputPath() { - if ( m_SelectedBundles.size()<2 ){ - QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); - MITK_WARN("QmitkFiberFoxView") << "Select at least two fiber bundles!"; - return; - } + // SELECT FOLDER DIALOG + std::string outputPath; + outputPath = QFileDialog::getExistingDirectory(nullptr, "Save images to...", QString(outputPath.c_str())).toStdString(); - std::vector::const_iterator it = m_SelectedBundles.begin(); - mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); - QString name(""); - name += QString((*it)->GetName().c_str()); - ++it; - for (; it!=m_SelectedBundles.end(); ++it) + if (outputPath.empty()) + m_Controls->m_SavePathEdit->setText("-"); + else { - newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); - name += "+"+QString((*it)->GetName().c_str()); + outputPath += "/"; + m_Controls->m_SavePathEdit->setText(QString(outputPath.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_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); - - // Fiber generation gui - if (m_SelectedFiducial.IsNotNull()) - { - m_Controls->m_TransformBundlesButton->setEnabled(true); - m_Controls->m_FlipButton->setEnabled(true); - m_Controls->m_AlignOnGrid->setEnabled(true); - } - if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) - { - m_Controls->m_CircleButton->setEnabled(true); - m_Controls->m_FiberGenMessage->setVisible(false); - } - if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) - m_Controls->m_AlignOnGrid->setEnabled(true); - - if (!m_SelectedBundles.empty()) - { - m_Controls->m_TransformBundlesButton->setEnabled(true); - m_Controls->m_CopyBundlesButton->setEnabled(true); - m_Controls->m_GenerateFibersButton->setEnabled(true); - - if (m_SelectedBundles.size()>1) - m_Controls->m_JoinBundlesButton->setEnabled(true); - } + m_Controls->m_LoadGradientsFrame->setVisible(false); + m_Controls->m_GenerateGradientsFrame->setVisible(false); + if (m_Controls->m_UseBvalsBvecsBox->isChecked()) + m_Controls->m_LoadGradientsFrame->setVisible(true); + else + m_Controls->m_GenerateGradientsFrame->setVisible(true); // Signal generation gui if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull() || m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) { 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); - } -} - -void QmitkFiberfoxView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) -{ - m_SelectedBundles2.clear(); - m_SelectedImages.clear(); - m_SelectedFiducials.clear(); - m_SelectedFiducial = nullptr; - m_SelectedBundles.clear(); - m_SelectedImageNode = nullptr; - - // iterate all selected objects, adjust warning visibility - for( int i=0; i(node->GetData()) ) - { - m_SelectedImages.push_back(node); - m_SelectedImageNode = node; - } - 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::FiberBundle::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() -{ - if (m_Controls->m_RealTimeFibers->isChecked()) - GenerateFibers(); -} - -void QmitkFiberfoxView::DisableCrosshairNavigation() -{ -} - -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( "MitkPlanarFigure" ); - 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 - std::string outputPath; - outputPath = QFileDialog::getExistingDirectory(nullptr, "Save images to...", QString(outputPath.c_str())).toStdString(); - - if (outputPath.empty()) - m_Controls->m_SavePathEdit->setText("-"); - else - { - outputPath += "/"; - m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str())); + m_Controls->m_LoadGradientsFrame->setVisible(false); + m_Controls->m_GenerateGradientsFrame->setVisible(false); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h index 772becedcf..3d9ea22d68 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h @@ -1,214 +1,171 @@ /*=================================================================== 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 #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details. */ // Forward Qt class declarations class QmitkFiberfoxView; class QmitkFiberfoxWorker : public QObject { Q_OBJECT public: QmitkFiberfoxWorker(QmitkFiberfoxView* view); 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 std::string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef itk::Vector GradientType; typedef std::vector GradientListType; typedef itk::VectorImage< short, 3 > ItkDwiType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; template std::vector > MakeGradientList(); protected slots: 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 SetBvalsEdit(); + void SetBvecsEdit(); void BeforeThread(); void AfterThread(); 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 OnAddDrift(int value); void OnMaskSelected(int value); void OnFibSelected(int value); void OnTemplateSelected(int value); + void OnBvalsBvecsCheck(int value); protected: - /// \brief called by QmitkAbstractView when DataManager's selection has changed - virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image - FiberfoxParameters UpdateImageParameters(bool all=true, bool save=false); ///< update fiberfox paramater object + void UpdateParametersFromGui(); ///< update fiberfox paramater object 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 ) override; ///< add observers - void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers + void SaveParameters(QString filename); - /** 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; - }; - - std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData - mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse + mitk::DataNode::Pointer m_SelectedImageNode; - std::vector< mitk::DataNode::Pointer > m_SelectedBundles; - std::vector< mitk::DataNode::Pointer > m_SelectedBundles2; - std::vector< mitk::DataNode::Pointer > m_SelectedFiducials; - std::vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name // GUI thread QmitkFiberfoxWorker m_Worker; ///< runs filter QThread m_Thread; ///< worker thread bool m_ThreadIsRunning; QTimer* m_SimulationTimer; QTime m_SimulationTime; QString m_SimulationStatusText; /** Image filters that do all the simulations. */ itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter; friend class QmitkFiberfoxWorker; + FiberfoxParameters m_Parameters; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui index 86c0a1f394..c9f768a18c 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxViewControls.ui @@ -1,3772 +1,2742 @@ QmitkFiberfoxViewControls 0 0 463 - 875 + 2651 Form - - + + - Load Parameters + Save Parameters - :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico + :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 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 + + + + + + + QGroupBox { + background-color: transparent; +} + + + Input Data + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + - + + + + + + + ... + + + + + + + + + + <html><head/><body><p>Select a binary image to define the area of signal generation. Outside of the mask image only noise will be actively generated.</p></body></html> + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + + + + + + + + + + Fiber Bundle: + + + false + + + + + + + + + + + + + + + + Save path: + + + false + + + + + + + + + + + + + + + + Tissue Mask: + + + false + + + + + + + <html><head/><body><p>Select a fiber bundle to generate the white matter signal from. You can either use the fiber definition tab to manually define an input fiber bundle or you can also use any existing bundle, e.g. yielded by a tractography algorithm.</p></body></html> + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + + + + + + + + + + Template Image: + + + false + + + + + + + <html><head/><body><p>The parameters for the simulation (e.g. spacing, size, diffuison-weighted gradients, b-value) are adopted from this image.</p></body></html> + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + + + + true + + + Stop current simulation. + + + + + + Abort Simulation + + + + :/QmitkDiffusionImaging/general_icons/abort.ico:/QmitkDiffusionImaging/general_icons/abort.ico + + + + + + + + Courier + 7 + + + + true + + + + - + + + QGroupBox { + background-color: transparent; +} + + + Intra-axonal Compartment + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + + + + + + Select signal model for intra-axonal compartment. + + + + Stick Model + + + + + Zeppelin Model + + + + + Tensor Model + + + + + Prototype Signal + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + + + + + + + - Save Parameters + Load Parameters - :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico + :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico - - - - - 75 - true - - + + - + QGroupBox { + background-color: transparent; +} + + + Extra-axonal Compartments - - - - 0 - -1969 - 431 - 2751 - + + + 6 - - Signal Generation - - - - 25 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 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 - - - - - - - QGroupBox { + + 6 + + + 6 + + + 6 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + + + + + + + + + + + Select signal model for extra-axonal compartment. + + + + Ball Model + + + + + Astrosticks Model + + + + + Dot Model + + + + + Prototype Signal + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + + + + + + + + + + + + + + + Select signal model for extra-axonal compartment. + + + + -- + + + + + Ball Model + + + + + Astrosticks Model + + + + + Dot Model + + + + + Prototype Signal + + + + + + + + + + + + + + QGroupBox { background-color: transparent; } - - - Input Data - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - ... - - - - - - - - - - <html><head/><body><p>Select a binary image to define the area of signal generation. Outside of the mask image only noise will be actively generated.</p></body></html> - - - QComboBox::AdjustToMinimumContentsLength - - - - - - - - - - - - - - - - Fiber Bundle: - - - false - - - - - - - - - - - - - - - - Save path: - - - false - - - - - - - - - - - - - - - - Tissue Mask: - - - false - - - - - - - <html><head/><body><p>Select a fiber bundle to generate the white matter signal from. You can either use the fiber definition tab to manually define an input fiber bundle or you can also use any existing bundle, e.g. yielded by a tractography algorithm.</p></body></html> - - - QComboBox::AdjustToMinimumContentsLength - - - - - - - - - - - - - - - - Template Image: - - - false - - - - - - - <html><head/><body><p>The parameters for the simulation (e.g. spacing, size, diffuison-weighted gradients, b-value) are adopted from this image.</p></body></html> - - - QComboBox::AdjustToMinimumContentsLength - - - - - - - - - - true - - - Stop current simulation. - - - - + + + Noise and other Artifacts + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Add Distortions + + + false + + + + + + + Add ringing artifacts occuring at strong edges in the image. + + + Add Gibbs Ringing + + + false + + + + + + + Add Motion Artifacts + + + false + + + + + + + Add Aliasing + + + false + + + + + + + Qt::Horizontal + + + + + + + Add Signal Drift + + + false + + + + + + + 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: + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + 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 + + + + + + + + + + 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 + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Variance: + + + + + + + Variance of selected noise distribution. + + + 10 + + + 0.000000000000000 + + + 999999999.000000000000000 + + + 0.001000000000000 + + + 50.000000000000000 + + + + + + + Distribution: + + + + + + + Noise distribution + + - Abort Simulation - - - - :/QmitkDiffusionImaging/general_icons/abort.ico:/QmitkDiffusionImaging/general_icons/abort.ico + Complex Gaussian - - - - - - - Courier - 7 - - - - true - - - - - - - - - - QGroupBox { + + + + Rician + + + + + + + + + + + + + + Add Eddy Current Effects + + + false + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + 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 + + + + 0 + + + 6 + + + 0 + + + 0 + + + 6 + + + + + Toggle between random movement and linear movement. + + + Randomize motion + + + true + + + + + + + QGroupBox { background-color: transparent; } - - - Extra-axonal Compartments - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Volume Fraction: - - - - - - - - - - - - - - - - - Select signal model for extra-axonal compartment. - - - - Ball Model - + + + Rotation + + + + 6 + + + 9 + + + 6 + + + 6 + + + + + + + + + + + + + + Degree: + + + false + + - - - Astrosticks Model - + + + + + + + + + + + + + x + + + false + + - - - Dot Model - + + + + + + + + + + + + + Axis: + + + false + + - - - Prototype Signal - - - - - - - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Volume Fraction: - - - - - - - Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. - - - - - - - - - - - - - - - - - - - Select signal model for extra-axonal compartment. - - - - -- - + + + + Maximum rotation around x-axis. + + + 1 + + + -360.000000000000000 + + + 360.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + - - - Ball Model - + + + + Maximum rotation around z-axis. + + + 1 + + + -360.000000000000000 + + + 360.000000000000000 + + + 1.000000000000000 + + + 15.000000000000000 + + - - - Astrosticks Model - + + + + + + + + + + + + + y + + + false + + - - - Dot Model - + + + + + + + + + + + + + z + + + false + + - - - Prototype Signal - + + + + Maximum rotation around y-axis. + + + 1 + + + -360.000000000000000 + + + 360.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + - - - - - - - - - - - - QGroupBox { + + + + + + + QGroupBox { background-color: transparent; } - - - Intra-axonal Compartment - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - - - - - - - - - - Select signal model for intra-axonal compartment. - - - - Stick Model - + + + Translation + + + + 6 + + + 6 + + + 6 + + + + + + + + + + + + + + Distance: + + + false + + - - - Zeppelin Model - + + + + + + + + + + + + + x + + + false + + - - - Tensor Model - + + + + + + + + + + + + + y + + + false + + - - - Prototype Signal - + + + + + + + + + + + + + Axis: + + + false + + - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Volume Fraction: - - - - - - - Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. - - - - - - - - - - - - - QGroupBox { - background-color: transparent; -} - - - Image Settings - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - Advanced Options - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 6 - - - - - Gradient Directions: - - - - - - - Number of gradient directions distributed over the half sphere. - - - 0 - - - 10000 - - - 1 - - - 30 - - - - - - - - - - - - - - - - <html><head/><body><p>b-Value<span style=" font-style:italic;"> [s/mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">]</span>:</p></body></html> - - - false - - - - - - - b-value in s/mm² - - - 0 - - - 10000 - - - 100 - - - 1000 - - - - - - - - - - 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 - - - 6 - - - - - - - - - - - - - - <html><head/><body><p>Number of Channels:</p></body></html> - - - false - - - - - - - TR in milliseconds - - - 1 - - - 999999999 - - - 1 - - - 4000 - - - - - - - Output one image per compartment containing the corresponding volume fractions per voxel. - - - Reverse Phase Encoding Direction - - - false - - - - - - - Signal Scale: - - - - - - - Dwell time (time to read one line in k-space) in ms. - - - 100.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - TE in milliseconds - - - 1 - - - 999999999 - - - 1 - - - 100 - - - - - - - Fiber Radius: - - - - - - - - - - - - - - - - Partial Fourier: - - - false - - - - - - - Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. - - - Disable Partial Volume Effects - - - false - - - - - - - - - - - - - - - - <html><head/><body><p>Coil Sensitivity:</p></body></html> - - - false - - - - - - - Partial fourier factor (0.5-1) - - - 3 - - - 0.500000000000000 - - - 1.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - Output phase image and volume fraction maps. - - - Output Additional Images - - - false - - - - - - - Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). - - - 1 - - - 10000 - - - 1 - - - 50 - - - - - - - - - - - - - - - - <html><head/><body><p>Repetition Time <span style=" font-style:italic;">TR</span>: </p></body></html> - - - false - - - - - - - - Constant - - - - - Linear - - - - - Exponential - - - - - - - - - - - - - - - - - Dwell Time: - - - false - - - - - - - - - - - - - - - - <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> - - - false - - - - - - - <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 - - - - - - - - - - - - - - - - <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> - - - false - - - - - - - TE in milliseconds - - - 1 - - - 10000 - - - 1 - - - 100 - - - - - - - Number of coil elements used for the acquisiton. - - - 1 - - - 128 - - - 1 - - - 1 - - - - - - - Acquisition Type: - - - - - - - - Single Shot EPI - - - - - Spin Echo - - - - - - - - Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. - - - 9999.000000000000000 - - - - - - - - - - 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 - - - 20 - - - - - - - Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. - - - 1 - - - 1000 - - - 1 - - - 20 - - - - - - - Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. - - - 1 - - - 1000 - - - 1 - - - 3 - - - - - - - - - - - - - QGroupBox { - background-color: transparent; -} - - - Inter-axonal Compartment - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - Select signal model for intra-axonal compartment. - - - - -- - + + + + + + + + + + + + + z + + + false + + - - - Stick Model - + + + + Maximum translation along x-axis. + + + 1 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + - - - Zeppelin Model - + + + + Maximum translation along y-axis. + + + 1 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + - - - Tensor Model - + + + + Maximum translation along z-axis. + + + 1 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 1.000000000000000 + + + 0.000000000000000 + + - - - - - - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Volume Fraction: - - - - - - - Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. - - - - - - - - - - - - - QGroupBox { + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Motion volumes: + + + + + + + Type in the volume indices that should be affected by motion (e.g. "0 3 7" whithout quotation marks). Leave blank for motion in all volumes. Type in "random" to randomly select volumes for motion. A list of negative numbers (e.g. -1 -2 -3) excludes volumes (e.g. 1 2 3) selects all remaining volumes. + + + random + + + + + + + + + + + + + Add Noise + + + false + + + + + + + Add Spikes + + + false + + + + + + + true + + + QFrame::NoFrame + + + QFrame::Raised + + + + QFormLayout::AllNonFixedFieldsGrow + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + Gradient: + + + false + + + + + + + Eddy current induced magnetic field gradient (in mT/m). + + + 4 + + + 1000.000000000000000 + + + 0.001000000000000 + + + 0.010000000000000 + + + + + + + + + + Add N/2 Ghosts + + + false + + + + + + + true + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + Signal Reduction (%): + + + false + + + + + + + Global signal in last simulated volume is specified percentage lower than in the first volume. + + + 1 + + + 100.000000000000000 + + + 1.000000000000000 + + + 6.000000000000000 + + + + + + + + + + + + + QGroupBox { background-color: transparent; } + + + Image Settings + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + color: rgb(255, 0, 0); + + + Using geometry of selected image! + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 - - Noise and other Artifacts - - - - 6 - - - 6 - - - 6 - - - 6 - - - + + 6 + + + + + + + + + + + + + + <html><head/><body><p>Number of Channels:</p></body></html> + + + false + + + + + + + TR in milliseconds + + + 1 + + + 999999999 + + + 1 + + + 4000 + + + + + + + Output one image per compartment containing the corresponding volume fractions per voxel. + + + Reverse Phase Encoding Direction + + + false + + + + + + + Signal Scale: + + + + + + + Dwell time (time to read one line in k-space) in ms. + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + TE in milliseconds + + + 1 + + + 999999999 + + + 1 + + + 100 + + + + + + + Fiber Radius: + + + + + + + + + + + + + + + + Partial Fourier: + + + false + + + + + + + Disable partial volume. Treat voxel content as fiber-only if at least one fiber is present. + + + Disable Partial Volume Effects + + + false + + + + + + + + + + + + + + + + <html><head/><body><p>Coil Sensitivity:</p></body></html> + + + false + + + + + + + Partial fourier factor (0.5-1) + + + 3 + + + 0.500000000000000 + + + 1.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + Output phase image and volume fraction maps. + + + Output Additional Images + + + false + + + + + + + Relaxation time due to magnetic field inhomogeneities (T2', in milliseconds). + + + 1 + + + 10000 + + + 1 + + + 50 + + + + + + + + + + + + + + + + <html><head/><body><p>Repetition Time <span style=" font-style:italic;">TR</span>: </p></body></html> + + + false + + + + + + - Add Distortions - - - false - - - - - - - Add ringing artifacts occuring at strong edges in the image. + Constant + + - Add Gibbs Ringing + Linear - - false - - - - - + + - Add Motion Artifacts - - - false - - - - - + Exponential + + + + + + + + + + + + + + + + + Dwell Time: + + + false + + + + + + + + + + + + + + + + <html><head/><body><p><span style=" font-style:italic;">T</span><span style=" font-style:italic; vertical-align:sub;">inhom</span> Relaxation: </p></body></html> + + + false + + + + + + + <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 + + + + + + + + + + + + + + + + <html><head/><body><p>Echo Time <span style=" font-style:italic;">TE</span>: </p></body></html> + + + false + + + + + + + TE in milliseconds + + + 1 + + + 10000 + + + 1 + + + 100 + + + + + + + Number of coil elements used for the acquisiton. + + + 1 + + + 128 + + + 1 + + + 1 + + + + + + + Acquisition Type: + + + + + + - Add Aliasing + Single Shot EPI - - false - - - - - - - Qt::Horizontal - - - - - + + - Add Signal Drift - - - false - - - - - - - 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: - - - - - - - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - - 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 - - - - - - - - - - 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 - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Variance: - - - - - - - Variance of selected noise distribution. - - - 10 - - - 0.000000000000000 - - - 999999999.000000000000000 - - - 0.001000000000000 - - - 50.000000000000000 - - - - - - - Distribution: - - - - - - - Noise distribution - - - - Complex Gaussian - - - - - Rician - - - - - - - - - - - - - - Add Eddy Current Effects - - - false - - - - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - - 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 - - - - 0 - - - 6 - - - 0 - - - 0 - - - 6 - - - - - Toggle between random movement and linear movement. - - - Randomize motion - - - true - - - - - - - QGroupBox { - background-color: transparent; -} - - - Rotation - - - - 6 - - - 9 - - - 6 - - - 6 - - - - - - - - - - - - - - Degree: - - - false - - - - - - - - - - - - - - - - x - - - false - - - - - - - - - - - - - - - - Axis: - - - false - - - - - - - Maximum rotation around x-axis. - - - 1 - - - -360.000000000000000 - - - 360.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - Maximum rotation around z-axis. - - - 1 - - - -360.000000000000000 - - - 360.000000000000000 - - - 1.000000000000000 - - - 15.000000000000000 - - - - - - - - - - - - - - - - y - - - false - - - - - - - - - - - - - - - - z - - - false - - - - - - - Maximum rotation around y-axis. - - - 1 - - - -360.000000000000000 - - - 360.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - - - - QGroupBox { + Spin Echo + + + + + + + + Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. + + + 9999.000000000000000 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 6 + + + + + + + + + + + + + + <html><head/><body><p>b-Value<span style=" font-style:italic;"> [s/mm</span><span style=" font-style:italic; vertical-align:super;">2</span><span style=" font-style:italic;">]</span>:</p></body></html> + + + false + + + + + + + b-value in s/mm² + + + 0 + + + 10000 + + + 100 + + + 1000 + + + + + + + Gradient Directions: + + + + + + + Number of gradient directions distributed over the half sphere. + + + 0 + + + 10000 + + + 1 + + + 30 + + + + + + + + + + Advanced Options + + + + + + + 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 + + + 20 + + + + + + + Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + + + 1 + + + 1000 + + + 1 + + + 20 + + + + + + + Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + + + 1 + + + 1000 + + + 1 + + + 3 + + + + + + + + + + Use bvals/bvecs files + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ... + + + + + + + ... + + + + + + + - + + + false + + + + + + + + + + + + + + + + Bvecs: + + + false + + + + + + + + + + + + + + + + Bvals: + + + false + + + + + + + - + + + false + + + + + + + + + + + + + QGroupBox { background-color: transparent; } - - - Translation - - - - 6 - - - 6 - - - 6 - - - - - - - - - - - - - - Distance: - - - false - - - - - - - - - - - - - - - - x - - - false - - - - - - - - - - - - - - - - y - - - false - - - - - - - - - - - - - - - - Axis: - - - false - - - - - - - - - - - - - - - - z - - - false - - - - - - - Maximum translation along x-axis. - - - 1 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - Maximum translation along y-axis. - - - 1 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - Maximum translation along z-axis. - - - 1 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 1.000000000000000 - - - 0.000000000000000 - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Motion volumes: - - - - - - - Type in the volume indices that should be affected by motion (e.g. "0 3 7" whithout quotation marks). Leave blank for motion in all volumes. Type in "random" to randomly select volumes for motion. A list of negative numbers (e.g. -1 -2 -3) excludes volumes (e.g. 1 2 3) selects all remaining volumes. - - - random - - - - - - - - - - - - - Add Noise - - - false - - - - - - - Add Spikes - - - false - - - - - - - true - - - QFrame::NoFrame - - - QFrame::Raised - - - - QFormLayout::AllNonFixedFieldsGrow - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - - Gradient: - - - false - - - - - - - Eddy current induced magnetic field gradient (in mT/m). - - - 4 - - - 1000.000000000000000 - - - 0.001000000000000 - - - 0.010000000000000 - - - - - - - - - - Add N/2 Ghosts - - - false - - - - - - - true - - - QFrame::NoFrame - - - QFrame::Raised - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - - - Signal Reduction (%): - - - false - - - - - - - Global signal in last simulated volume is specified percentage lower than in the first volume. - - - 1 - - - 100.000000000000000 - - - 1.000000000000000 - - - 6.000000000000000 - - - - - - - - - - - - - - - 0 - 0 - 431 - 954 - + + + Inter-axonal Compartment + + + + 6 + + + 6 + + + 6 - - Fiber Definition - - - - 25 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - color: rgb(255, 0, 0); + + 6 + + + + + Select signal model for intra-axonal compartment. + + + + -- + + - 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. + Stick Model - - Qt::AutoText + + + + Zeppelin Model - - Qt::AlignJustify|Qt::AlignVCenter + + + + Tensor Model - - true + + + + + + + + + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 - - - - - - QGroupBox { - background-color: transparent; -} + + 0 - - Fiducial Options - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - 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. - - - QCommandLinkButton:disabled { - border: none; -} - - - Align With Grid - - - - :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico - - - - - - - - - - QGroupBox { - background-color: transparent; -} + + 0 - - Operations - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - false - - - QCommandLinkButton:disabled { - border: none; -} - - - 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. - - - 3 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Axis: - - - false - - - - - - - Rotation angle (in degree) around y-axis. - - - 3 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - Translation: - - - false - - - - - - - Translation (in mm) in direction of the z-axis. - - - 3 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 0.100000000000000 - - - - - - - Translation (in mm) in direction of the y-axis. - - - 3 - - - -1000.000000000000000 - - - 1000.000000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - X - - - false - - - - - - - - - - - - - - - - Rotation: - - - false - - - - - - - - - - - - - - - - Z - - - false - - - - - - - Rotation angle (in degree) around z-axis. - - - 3 - - - -360.000000000000000 - - - 360.000000000000000 - - - 0.100000000000000 - - - - - - - Translation (in mm) in direction of the x-axis. - - - 3 - - - -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 - - - QCommandLinkButton:disabled { - border: none; -} - - - Copy Bundles - - - - :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico - - - - - - - false - - - QCommandLinkButton:disabled { - border: none; -} - - - 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 - - - - - - - - - - QGroupBox { - background-color: transparent; -} + + 0 - - Fiber Options - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - 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 - - - QCommandLinkButton:disabled { - border: none; -} - - - 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/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico - - - - 32 - 32 - - - - false - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - + + + + Volume Fraction: + + + + + + + Optional! If no volume fraction map for this compartment is set, the corresponding volume fractions are calculated from the input fibers. + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.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
QmitkPrototypeSignalParametersWidget QWidget
QmitkPrototypeSignalParametersWidget.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_FiberBundleComboBox m_MaskComboBox m_TemplateComboBox m_SavePathEdit m_OutputPathButton m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox m_BvalueBox m_AdvancedOptionsBox_2 m_SignalScaleBox m_TEbox m_TRbox m_LineReadoutTimeBox m_PartialFourier m_T2starBox m_FiberRadius m_ReversePhaseBox m_RelaxationBox m_EnforcePureFiberVoxelsBox m_VolumeFractionsBox m_Compartment1Box m_Comp1VolumeFraction m_Compartment2Box m_Comp2VolumeFraction m_Compartment3Box m_Comp3VolumeFraction m_Compartment4Box m_Comp4VolumeFraction m_AddNoise m_NoiseDistributionBox 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 - toolBox
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp index 966622df5d..a63feeaef4 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp @@ -1,44 +1,46 @@ /*=================================================================== 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 "mitkPluginActivator.h" #include "src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h" #include "src/internal/QmitkFiberfoxView.h" +#include "src/internal/QmitkFiberGenerationView.h" #include "src/internal/QmitkFieldmapGeneratorView.h" ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppSyntheticDataGenerationPerspective, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberfoxView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkFieldmapGeneratorView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberGenerationView, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberQuantificationViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberQuantificationViewUserManual.dox index fea03bd0bb..af33fc3fbf 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberQuantificationViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/documentation/UserManual/QmitkFiberQuantificationViewUserManual.dox @@ -1,32 +1,32 @@ /** \page org_mitk_views_fiberquantification Fiber Quantification This view provides tools to derive additional information (such as tract density images and principal fiber direction maps) from tractograms. \section SecFiberQuantInput Input Data - Tractogram: The input streamlines. - Reference Image: The output images will have the same geometry as this reference image (optional). If a reference image with DICOM tags is used, the resulting tract envelope can be saved as DICOM Segmentation Object. \section SecFDI Fiber-derived Images -- Tract density image: Generate a 2D heatmap from a fiber bundle. +- Tract density image: The voxel values correspond to the sum of all fiber segment lengths in the respective voxel. - Normalized TDI: 0-1 normalized version of the TDI. - Binary envelope: Generate a binary segmentation from the input tractogram. - Fiber bundle image: Generate a 2D rgba image representation of the fiber bundle. - Fiber endings image: Generate a 2D image showing the locations of fiber endpoints. - Fiber endings pointset: Generate a poinset containing the locations of fiber endpoints (not recommended for large tractograms). \section SecPD Principal Fiber Directions Calculate the voxel-wise principal fiber directions (fixels) from a tractogram. - Max. Peaks: Maximum number of output directions per voxel. - Angular Threshold: Cluster directions that are close together using the specified threshold (in degree). - Size Threshold: Discard principal directions with a magnitude smaller than the specified threshold. This value is the vector magnitude raltive to the largest vector in the voxel. - Normalization: Normalize the principal fiber directions by the global maximum, the voxel-wise maximum or each direction individually. - Output #Directions per Voxel: Generate an image that contains the number of principal directions per voxel as values. \imageMacro{DirectionExtractionFib.png, "Input fiber bundle",10} \imageMacro{DirectionExtractionPeaks.png, "Output principal fiber directions",10} */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox index 5cdb039c00..6c724bad14 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/documentation/UserManual/QmitkOdfMaximaExtractionViewUserManual.dox @@ -1,9 +1,9 @@ /** \page org_mitk_views_odfmaximaextraction ODF Peak Extraction -This view provides the user interface to extract the principal diffusion direction of tensors and the peaks of spherical harmonic ODFs. +This view provides the user interface to extract the principal diffusion direction of tensors and the peaks of spherical harmonic ODFs using gradient descent optimization. The output peaks can for example be used for streamline tractography. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui index f2164ff799..5c17c07146 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionViewControls.ui @@ -1,470 +1,473 @@ QmitkOdfMaximaExtractionViewControls 0 0 397 848 Form QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; } 25 QFrame::NoFrame QFrame::Raised 0 0 0 0 true Generate ODF image and MITK compatible SH coefficient from other toolkits. Start SH Coefficient Import true Extract ODF peaks using finite differences on the densely sampled ODF surface. Start Peak Extraction Please Select Input Data 6 6 6 6 Select a tensor image or a SH coefficient image (generate using Q-Ball reconstruction view). ShCoeff/DTI: Mask Image: Additional Output QFormLayout::AllNonFixedFieldsGrow 6 6 6 6 Output unsigned char image containing the number of directions per voxel. #Peaks per Voxel false Parameters 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 Vector Normalization: <html><head/><body><p>The vector fields are always coorected for image spacing and using the lagest eigenvalue in case of the tensor peak extraction. This is done for visualizytion purposes. The output direction images are not affected.</p></body></html> 1 No Normalization MAX Normalize Single Vec Normalization true QFrame::NoFrame QFrame::Raised 0 0 0 0 6 true Peak threshold relative to the largest peak per voxel. 3 0.000000000000000 1.000000000000000 0.100000000000000 0.400000000000000 true Max. Peaks: true - Absolute peak threshold (only used for the finite differences method). The value is additionally scaled by 1/GFA. + Absolute threshold on the peak magnitudes. 3 0.000000000000000 1.000000000000000 0.010000000000000 0.030000000000000 true Maximum number of peaks to extract. 1 1000 3 Angular Threshold: - Discard smaller peaks in the defined angle around the maximum peaks that were too far away to be clustered. + Discard peaks that er closer to a larger peak. 0 90 15 Absolute Threshold: Relative Threshold: Scale by GFA: + + Scale ODF values and successively the peaks by the GFA in the respective voxels. + Qt::Vertical 20 259 Spherical Harmonic Convention 6 6 6 6 Define SH coefficient convention (depends on toolkit) 0 MITK/MRtrix FSL QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkDataStorageComboBoxWithSelectNone QComboBox
QmitkDataStorageComboBoxWithSelectNone.h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox index d2052b2ff2..ea0ea8cd86 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/documentation/UserManual/QmitkDiffusionImagingPortalPage.dox @@ -1,48 +1,48 @@ /** \page org_mitk_gui_qt_diffusionimaging MITK Diffusion \tableofcontents MITK Diffusion offers a selection of image analysis methods for dMRI processing. It encompasses the research of the Division of Medical Image Computing of the German Cancer Research Center (DKFZ). \section org_mitk_gui_qt_diffusionimagingComponents Components MITK Diffusion consists of multiple components with their own documentation: \subsection sub1 Data formats, import and export \li \subpage QmitkDiffusionImagingDataImportPage \subsection sub2 Preprocessing and Reconstruction \li \subpage org_mitk_views_diffusionpreprocessing \li \subpage org_mitk_views_simpleregistrationview \li \subpage org_mitk_views_headmotioncorrectionview \li \subpage org_mitk_views_denoisingview \li \subpage org_mitk_views_tensorreconstruction \li \subpage org_mitk_views_qballreconstruction \subsection sub3 Visualization and Quantification \li \subpage org_mitk_views_controlvisualizationpropertiesview \li \subpage org_mitk_views_odfdetails \li \subpage org_mitk_views_odfmaximaextraction \li \subpage org_mitk_views_partialvolumeanalysisview \li \subpage org_mitk_views_diffusionquantification \li \subpage org_mitk_views_ivim \subsection sub4 Fiber Tractography \li \subpage org_mitk_views_streamlinetracking \li \subpage org_mitk_views_gibbstracking \li \subpage org_mitk_views_mlbtview \li \subpage org_mitk_views_fiberprocessing \li \subpage org_mitk_views_fiberquantification \li \subpage org_mitk_views_fiberfit \li \subpage org_mitk_views_fiberclustering \subsection sub5 Fiberfox dMRI Simulation \li \subpage org_mitk_views_fiberfoxview +\li \subpage org_mitk_views_fibergenerationview \li \subpage org_mitk_views_fieldmapgenerator -\subsection sub6 TBSS and Connectomics -\li \subpage org_mitk_views_tractbasedspatialstatistics +\subsection sub6 Connectomics \li \subpage org_mitk_diffusionimagingapp_perspectives_connectomics */