diff --git a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.cpp b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.cpp index 8981cdf042..1243cd100e 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.cpp @@ -1,76 +1,80 @@ /*=================================================================== 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 __itkShToOdfImageFilter_cpp #define __itkShToOdfImageFilter_cpp #include #include #include #include "itkShToOdfImageFilter.h" #include #include namespace itk { template< class PixelType, int ShOrder > ShToOdfImageFilter< PixelType, ShOrder >::ShToOdfImageFilter() : m_Toolkit(Toolkit::MRTRIX) { } template< class PixelType, int ShOrder > -void ShToOdfImageFilter< PixelType, ShOrder >::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) +void ShToOdfImageFilter< PixelType, ShOrder >::BeforeThreadedGenerateData() { CalcShBasis(); +} +template< class PixelType, int ShOrder > +void ShToOdfImageFilter< PixelType, ShOrder >::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) +{ typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput()); typename InputImageType::Pointer inputImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) ); typedef ImageRegionConstIterator< InputImageType > InputIteratorType; InputIteratorType it(inputImage, outputRegionForThread); typedef ImageRegionIterator< OutputImageType > OutputIteratorType; OutputIteratorType oit(outputImage, outputRegionForThread); while(!it.IsAtEnd()) { auto pix = it.Get(); vnl_vector coeffs = pix.GetVnlVector(); OutputPixelType odf = (m_ShBasis * coeffs).data_block(); oit.Set(odf); ++it; ++oit; } } // generate spherical harmonic values of the desired order for each input direction template< class PixelType, int ShOrder > void ShToOdfImageFilter< PixelType, ShOrder >::CalcShBasis() { vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); if (m_Toolkit==Toolkit::MRTRIX) m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, U->as_matrix()); else m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, U->as_matrix(), false); } } #endif // __itkShToOdfImageFilter_cpp diff --git a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.h b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.h index e5b9d72494..dea8d8a8e5 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.h +++ b/Modules/DiffusionImaging/DiffusionCore/include/Algorithms/itkShToOdfImageFilter.h @@ -1,86 +1,87 @@ /*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $ Language: C++ Date: $Date: 2006-03-27 17:01:06 $ Version: $Revision: 1.12 $ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __itkShToOdfImageFilter_h_ #define __itkShToOdfImageFilter_h_ #include #include namespace itk{ /** \class ShToOdfImageFilter */ template< class PixelType, int ShOrder > class ShToOdfImageFilter : public ImageToImageFilter< itk::Image< itk::Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >, itk::Image< itk::Vector,3> > { public: enum Toolkit { ///< SH coefficient convention (depends on toolkit) FSL, MRTRIX }; typedef itk::Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder > InputPixelType; typedef itk::Image InputImageType; typedef typename InputImageType::RegionType InputImageRegionType; typedef itk::Vector OutputPixelType; typedef itk::Image OutputImageType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef ShToOdfImageFilter Self; typedef itk::ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(ShToOdfImageFilter, ImageToImageFilter) itkSetMacro( Toolkit, Toolkit) ///< define SH coefficient convention (depends on toolkit) itkGetMacro( Toolkit, Toolkit) ///< SH coefficient convention (depends on toolkit) + void BeforeThreadedGenerateData(); void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType); protected: ShToOdfImageFilter(); ~ShToOdfImageFilter(){} void CalcShBasis(); vnl_matrix m_ShBasis; Toolkit m_Toolkit; private: }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkShToOdfImageFilter.cpp" #endif #endif //__itkShToOdfImageFilter_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/include/mitkDiffusionFunctionCollection.h b/Modules/DiffusionImaging/DiffusionCore/include/mitkDiffusionFunctionCollection.h index 48ba4b2573..fd76a172f7 100644 --- a/Modules/DiffusionImaging/DiffusionCore/include/mitkDiffusionFunctionCollection.h +++ b/Modules/DiffusionImaging/DiffusionCore/include/mitkDiffusionFunctionCollection.h @@ -1,165 +1,192 @@ /*=================================================================== 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 __mitkDiffusionFunctionCollection_h_ #define __mitkDiffusionFunctionCollection_h_ #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include namespace mitk{ class MITKDIFFUSIONCORE_EXPORT imv { public: static std::vector< std::pair< itk::Index<3>, double > > IntersectImage(const itk::Vector& spacing, itk::Index<3>& si, itk::Index<3>& ei, itk::ContinuousIndex& sf, itk::ContinuousIndex& ef); static itk::Point GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = static_cast(point[0]); itkPoint[1] = static_cast(point[1]); itkPoint[2] = static_cast(point[2]); return itkPoint; } template< class TType > static itk::Point GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = static_cast(point[0]); itkPoint[1] = static_cast(point[1]); itkPoint[2] = static_cast(point[2]); return itkPoint; } template< class TPixelType, class TOutPixelType=TPixelType > static TOutPixelType GetImageValue(const itk::Point& itkP, bool interpolate, typename itk::LinearInterpolateImageFunction< itk::Image< TPixelType, 3 >, float >::Pointer interpolator) { if (interpolator==nullptr) return 0.0; itk::ContinuousIndex< float, 3> cIdx; interpolator->ConvertPointToContinuousIndex(itkP, cIdx); if (interpolator->IsInsideBuffer(cIdx)) { if (interpolate) return interpolator->EvaluateAtContinuousIndex(cIdx); else { itk::Index<3> idx; interpolator->ConvertContinuousIndexToNearestIndex(cIdx, idx); return interpolator->EvaluateAtIndex(idx); } } else return 0.0; } template< class TPixelType=unsigned char > static bool IsInsideMask(const itk::Point& itkP, bool interpolate, typename itk::LinearInterpolateImageFunction< itk::Image< TPixelType, 3 >, float >::Pointer interpolator, float threshold=0.5) { if (interpolator==nullptr) return false; itk::ContinuousIndex< float, 3> cIdx; interpolator->ConvertPointToContinuousIndex(itkP, cIdx); if (interpolator->IsInsideBuffer(cIdx)) { float value = 0.0; if (interpolate) value = interpolator->EvaluateAtContinuousIndex(cIdx); else { itk::Index<3> idx; interpolator->ConvertContinuousIndexToNearestIndex(cIdx, idx); value = interpolator->EvaluateAtIndex(idx); } if (value>=threshold) return true; } return false; } }; class MITKDIFFUSIONCORE_EXPORT convert { public: static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromTensorImage(mitk::Image::Pointer mitkImage); static mitk::OdfImage::Pointer GetOdfFromTensorImage(mitk::Image::Pointer mitkImage); static mitk::TensorImage::ItkTensorImageType::Pointer GetItkTensorFromTensorImage(mitk::Image::Pointer mitkImage); static mitk::PeakImage::ItkPeakImageType::Pointer GetItkPeakFromPeakImage(mitk::Image::Pointer mitkImage); + template + static typename itk::Image< itk::Vector, 3>::Pointer GetItkShFromShImage(mitk::Image::Pointer mitkImage) + { + mitk::ShImage::Pointer mitkShImage = dynamic_cast(mitkImage.GetPointer()); + if (mitkShImage.IsNull()) + mitkThrow() << "Input image is not a SH image!"; + + typename itk::Image< itk::Vector, 3>::Pointer itkvol; + mitk::CastToItkImage(mitkImage, itkvol); + + return itkvol; + } + static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromShImage(mitk::Image::Pointer mitkImage); static mitk::OdfImage::Pointer GetOdfFromShImage(mitk::Image::Pointer mitkImage); static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromOdfImage(mitk::Image::Pointer mitkImage); }; class MITKDIFFUSIONCORE_EXPORT sh { public: static double factorial(int number); static void Cart2Sph(double x, double y, double z, double* spherical); static vnl_vector_fixed Sph2Cart(const double& theta, const double& phi, const double& rad); static double legendre0(int l); static double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart); static double Yj(int m, int k, float theta, float phi, bool mrtrix=true); static vnl_matrix CalcShBasisForDirections(unsigned int sh_order, vnl_matrix U, bool mrtrix=true); static float GetValue(const vnl_vector& coefficients, const int& sh_order, const vnl_vector_fixed& dir, const bool mrtrix); static float GetValue(const vnl_vector &coefficients, const int &sh_order, const double theta, const double phi, const bool mrtrix); + static unsigned int ShOrder(int num_coeffs); + + template + static void SampleOdf(const vnl_vector& coefficients, itk::OrientationDistributionFunction& odf) + { + auto dirs = odf.GetDirections(); + auto basis = CalcShBasisForDirections(ShOrder(coefficients.size()), *dirs); + auto odf_vals = basis * coefficients; + for (unsigned int i=0; i IndiciesVector; typedef mitk::BValueMapProperty::BValueMap BValueMap; typedef DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; public: static GradientDirectionContainerType::Pointer ReadBvalsBvecs(std::string bvals_file, std::string bvecs_file, double& reference_bval); static void WriteBvalsBvecs(std::string bvals_file, std::string bvecs_file, GradientDirectionContainerType::Pointer gradients, double reference_bval); static std::vector GetAllUniqueDirections(const BValueMap &bValueMap, GradientDirectionContainerType *refGradientsContainer ); static bool CheckForDifferingShellDirections(const BValueMap &bValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer); static vnl_matrix ComputeSphericalHarmonicsBasis(const vnl_matrix & QBallReference, const unsigned int & LOrder); static vnl_matrix ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer); static GradientDirectionContainerType::Pointer CreateNormalizedUniqueGradientDirectionContainer(const BValueMap &bValueMap, const GradientDirectionContainerType * origninalGradentcontainer); }; } #endif //__mitkDiffusionFunctionCollection_h_ diff --git a/Modules/DiffusionImaging/DiffusionCore/src/mitkDiffusionFunctionCollection.cpp b/Modules/DiffusionImaging/DiffusionCore/src/mitkDiffusionFunctionCollection.cpp index 953a27ee49..254fe1a463 100644 --- a/Modules/DiffusionImaging/DiffusionCore/src/mitkDiffusionFunctionCollection.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/src/mitkDiffusionFunctionCollection.cpp @@ -1,690 +1,704 @@ /*=================================================================== 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 "mitkDiffusionFunctionCollection.h" #include "mitkNumericTypes.h" #include #include #include #include #include "itkVectorContainer.h" #include "vnl/vnl_vector.h" #include #include #include #include #include -#include -#include #include // Intersect a finite line (with end points p0 and p1) with all of the // cells of a vtkImageData std::vector< std::pair< itk::Index<3>, double > > mitk::imv::IntersectImage(const itk::Vector& spacing, itk::Index<3>& si, itk::Index<3>& ei, itk::ContinuousIndex& sf, itk::ContinuousIndex& ef) { std::vector< std::pair< itk::Index<3>, double > > out; if (si == ei) { double d[3]; for (int i=0; i<3; ++i) d[i] = static_cast(sf[i]-ef[i])*spacing[i]; double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ); out.push_back( std::pair< itk::Index<3>, double >(si, len) ); return out; } double bounds[6]; double entrancePoint[3]; double exitPoint[3]; double startPoint[3]; double endPoint[3]; double t0, t1; for (unsigned int i=0; i<3; ++i) { startPoint[i] = static_cast(sf[i]); endPoint[i] = static_cast(ef[i]); if (si[i]>ei[i]) { auto t = si[i]; si[i] = ei[i]; ei[i] = t; } } for (auto x = si[0]; x<=ei[0]; ++x) for (auto y = si[1]; y<=ei[1]; ++y) for (auto z = si[2]; z<=ei[2]; ++z) { bounds[0] = static_cast(x) - 0.5; bounds[1] = static_cast(x) + 0.5; bounds[2] = static_cast(y) - 0.5; bounds[3] = static_cast(y) + 0.5; bounds[4] = static_cast(z) - 0.5; bounds[5] = static_cast(z) + 0.5; int entryPlane; int exitPlane; int hit = vtkBox::IntersectWithLine(bounds, startPoint, endPoint, t0, t1, entrancePoint, exitPoint, entryPlane, exitPlane); if (hit) { if (entryPlane>=0 && exitPlane>=0) { double d[3]; for (int i=0; i<3; ++i) d[i] = (exitPoint[i] - entrancePoint[i])*spacing[i]; double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ); itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z; out.push_back( std::pair< itk::Index<3>, double >(idx, len) ); } else if (entryPlane>=0) { double d[3]; for (int i=0; i<3; ++i) d[i] = (static_cast(ef[i]) - entrancePoint[i])*spacing[i]; double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ); itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z; out.push_back( std::pair< itk::Index<3>, double >(idx, len) ); } else if (exitPlane>=0) { double d[3]; for (int i=0; i<3; ++i) d[i] = (exitPoint[i]-static_cast(sf[i]))*spacing[i]; double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] ); itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z; out.push_back( std::pair< itk::Index<3>, double >(idx, len) ); } } } return out; } //------------------------- SH-function ------------------------------------ double mitk::sh::factorial(int number) { if(number <= 1) return 1; double result = 1.0; for(int i=1; i<=number; i++) result *= i; return result; } void mitk::sh::Cart2Sph(double x, double y, double z, double *spherical) { double phi, th, rad; rad = sqrt(x*x+y*y+z*z); if( rad < mitk::eps ) { th = itk::Math::pi/2; phi = itk::Math::pi/2; } else { th = acos(z/rad); phi = atan2(y, x); } spherical[0] = phi; spherical[1] = th; spherical[2] = rad; } vnl_vector_fixed mitk::sh::Sph2Cart(const double& theta, const double& phi, const double& rad) { vnl_vector_fixed dir; dir[0] = rad * sin(theta) * cos(phi); dir[1] = rad * sin(theta) * sin(phi); dir[2] = rad * cos(theta); return dir; } double mitk::sh::legendre0(int l) { if( l%2 != 0 ) { return 0; } else { double prod1 = 1.0; for(int i=1;i(::boost::math::spherical_harmonic_r(static_cast(k), -m, theta, phi)); else if (m==0) return static_cast(::boost::math::spherical_harmonic_r(static_cast(k), m, theta, phi)); else return pow(-1.0,m)*sqrt(2.0)*static_cast(::boost::math::spherical_harmonic_i(static_cast(k), m, theta, phi)); } else { double plm = static_cast(::boost::math::legendre_p(k,abs(m),-cos(theta))); double mag = sqrt((2.0*k+1.0)/(4.0*itk::Math::pi)*::boost::math::factorial(k-abs(m))/::boost::math::factorial(k+abs(m)))*plm; if (m>0) return mag*static_cast(cos(m*phi)); else if (m==0) return mag; else return mag*static_cast(sin(-m*phi)); } return 0; } mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromShImage(mitk::Image::Pointer mitkImage) { mitk::ShImage::Pointer mitkShImage = dynamic_cast(mitkImage.GetPointer()); if (mitkShImage.IsNull()) mitkThrow() << "Input image is not a SH image!"; mitk::OdfImage::ItkOdfImageType::Pointer output; switch (mitkShImage->ShOrder()) { case 2: { typedef itk::ShToOdfImageFilter< float, 2 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } case 4: { typedef itk::ShToOdfImageFilter< float, 4 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } case 6: { typedef itk::ShToOdfImageFilter< float, 6 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } case 8: { typedef itk::ShToOdfImageFilter< float, 8 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } case 10: { typedef itk::ShToOdfImageFilter< float, 10 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } case 12: { typedef itk::ShToOdfImageFilter< float, 12 > ShConverterType; typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New(); mitk::CastToItkImage(mitkImage, itkvol); typename ShConverterType::Pointer converter = ShConverterType::New(); converter->SetInput(itkvol); converter->Update(); output = converter->GetOutput(); break; } default: mitkThrow() << "SH orders higher than 12 are not supported!"; } return output; } mitk::OdfImage::Pointer mitk::convert::GetOdfFromShImage(mitk::Image::Pointer mitkImage) { mitk::OdfImage::Pointer image = mitk::OdfImage::New(); auto img = GetItkOdfFromShImage(mitkImage); image->InitializeByItk( img.GetPointer() ); image->SetVolume( img->GetBufferPointer() ); return image; } mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromTensorImage(mitk::Image::Pointer mitkImage) { typedef itk::TensorImageToOdfImageFilter< float, float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( GetItkTensorFromTensorImage(mitkImage) ); filter->Update(); return filter->GetOutput(); } mitk::TensorImage::ItkTensorImageType::Pointer mitk::convert::GetItkTensorFromTensorImage(mitk::Image::Pointer mitkImage) { typedef mitk::ImageToItk< mitk::TensorImage::ItkTensorImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImage); caster->Update(); return caster->GetOutput(); } mitk::PeakImage::ItkPeakImageType::Pointer mitk::convert::GetItkPeakFromPeakImage(mitk::Image::Pointer mitkImage) { typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImage); caster->SetCopyMemFlag(true); caster->Update(); return caster->GetOutput(); } mitk::OdfImage::Pointer mitk::convert::GetOdfFromTensorImage(mitk::Image::Pointer mitkImage) { mitk::OdfImage::Pointer image = mitk::OdfImage::New(); auto img = GetItkOdfFromTensorImage(mitkImage); image->InitializeByItk( img.GetPointer() ); image->SetVolume( img->GetBufferPointer() ); return image; } mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromOdfImage(mitk::Image::Pointer mitkImage) { typedef mitk::ImageToItk< mitk::OdfImage::ItkOdfImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(mitkImage); caster->Update(); return caster->GetOutput(); } vnl_matrix mitk::sh::CalcShBasisForDirections(unsigned int sh_order, vnl_matrix U, bool mrtrix) { vnl_matrix sh_basis = vnl_matrix(U.cols(), (sh_order*sh_order + sh_order + 2)/2 + sh_order ); for(unsigned int i=0; i(sh_order); k+=2) { for(int m=-k; m<=k; m++) { int j = (k*k + k + 2)/2 + m - 1; double phi = U(0,i); double th = U(1,i); sh_basis(i,j) = mitk::sh::Yj(m,k,th,phi, mrtrix); } } } return sh_basis; } +unsigned int mitk::sh::ShOrder(int num_coeffs) +{ + int c=3, d=2-2*num_coeffs; + int D = c*c-4*d; + if (D>0) + { + int s = (-c+static_cast(sqrt(D)))/2; + if (s<0) + s = (-c-static_cast(sqrt(D)))/2; + return static_cast(s); + } + else if (D==0) + return static_cast(-c/2); + return 0; +} + float mitk::sh::GetValue(const vnl_vector &coefficients, const int &sh_order, const double theta, const double phi, const bool mrtrix) { float val = 0; for(int k=0; k<=sh_order; k+=2) { for(int m=-k; m<=k; m++) { unsigned int j = static_cast((k*k + k + 2)/2 + m - 1); val += coefficients[j] * mitk::sh::Yj(m, k, theta, phi, mrtrix); } } return val; } float mitk::sh::GetValue(const vnl_vector &coefficients, const int &sh_order, const vnl_vector_fixed &dir, const bool mrtrix) { double spherical[3]; mitk::sh::Cart2Sph(dir[0], dir[1], dir[2], spherical); float val = 0; for(int k=0; k<=sh_order; k+=2) { for(int m=-k; m<=k; m++) { int j = (k*k + k + 2)/2 + m - 1; val += coefficients[j] * mitk::sh::Yj(m, k, spherical[1], spherical[0], mrtrix); } } return val; } //------------------------- gradients-function ------------------------------------ mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::ReadBvalsBvecs(std::string bvals_file, std::string bvecs_file, double& reference_bval) { mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New(); std::vector bvec_entries; if (!itksys::SystemTools::FileExists(bvecs_file)) mitkThrow() << "bvecs file not existing: " << bvecs_file; else { std::string line; std::ifstream myfile (bvecs_file.c_str()); if (myfile.is_open()) { while (std::getline(myfile, line)) { std::vector strs; boost::split(strs,line,boost::is_any_of("\t \n")); for (auto token : strs) { if (!token.empty()) { try { bvec_entries.push_back(boost::lexical_cast(token)); } catch(...) { mitkThrow() << "Encountered invalid bvecs file entry >" << token << "<"; } } } } myfile.close(); } else { mitkThrow() << "bvecs file could not be opened: " << bvals_file; } } reference_bval = -1; std::vector bval_entries; if (!itksys::SystemTools::FileExists(bvals_file)) mitkThrow() << "bvals file not existing: " << bvals_file; else { std::string line; std::ifstream myfile (bvals_file.c_str()); if (myfile.is_open()) { while (std::getline(myfile, line)) { std::vector strs; boost::split(strs,line,boost::is_any_of("\t \n")); for (auto token : strs) { if (!token.empty()) { try { bval_entries.push_back(boost::lexical_cast(token)); if (bval_entries.back()>reference_bval) reference_bval = bval_entries.back(); } catch(...) { mitkThrow() << "Encountered invalid bvals file entry >" << token << "<"; } } } } myfile.close(); } else { mitkThrow() << "bvals file could not be opened: " << bvals_file; } } for(unsigned int i=0; i 0) { vec.normalize(); vec[0] = sqrt(factor)*vec[0]; vec[1] = sqrt(factor)*vec[1]; vec[2] = sqrt(factor)*vec[2]; } directioncontainer->InsertElement(i,vec); } return directioncontainer; } void mitk::gradients::WriteBvalsBvecs(std::string bvals_file, std::string bvecs_file, GradientDirectionContainerType::Pointer gradients, double reference_bval) { std::ofstream myfile; myfile.open (bvals_file.c_str()); for(unsigned int i=0; iSize(); i++) { double twonorm = gradients->ElementAt(i).two_norm(); myfile << std::round(reference_bval*twonorm*twonorm) << " "; } myfile.close(); std::ofstream myfile2; myfile2.open (bvecs_file.c_str()); for(int j=0; j<3; j++) { for(unsigned int i=0; iSize(); i++) { GradientDirectionType direction = gradients->ElementAt(i); direction.normalize(); myfile2 << direction.get(j) << " "; } myfile2 << std::endl; } } std::vector mitk::gradients::GetAllUniqueDirections(const BValueMap & refBValueMap, GradientDirectionContainerType *refGradientsContainer ) { IndiciesVector directioncontainer; auto mapIterator = refBValueMap.begin(); if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) mapIterator++; //skip bzero Values for( ; mapIterator != refBValueMap.end(); mapIterator++){ IndiciesVector currentShell = mapIterator->second; while(currentShell.size()>0) { unsigned int wntIndex = currentShell.back(); currentShell.pop_back(); auto containerIt = directioncontainer.begin(); bool directionExist = false; while(containerIt != directioncontainer.end()) { if (fabs(dot_product(refGradientsContainer->ElementAt(*containerIt), refGradientsContainer->ElementAt(wntIndex))) > 0.9998) { directionExist = true; break; } containerIt++; } if(!directionExist) { directioncontainer.push_back(wntIndex); } } } return directioncontainer; } bool mitk::gradients::CheckForDifferingShellDirections(const BValueMap & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer) { auto mapIterator = refBValueMap.begin(); if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) mapIterator++; //skip bzero Values for( ; mapIterator != refBValueMap.end(); mapIterator++){ auto mapIterator_2 = refBValueMap.begin(); if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1) mapIterator_2++; //skip bzero Values for( ; mapIterator_2 != refBValueMap.end(); mapIterator_2++){ if(mapIterator_2 == mapIterator) continue; IndiciesVector currentShell = mapIterator->second; IndiciesVector testShell = mapIterator_2->second; for (unsigned int i = 0; i< currentShell.size(); i++) if (fabs(dot_product(refGradientsContainer->ElementAt(currentShell[i]), refGradientsContainer->ElementAt(testShell[i]))) <= 0.9998) { return true; } } } return false; } vnl_matrix mitk::gradients::ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer) { vnl_matrix Q(3, refShell.size()); Q.fill(0.0); for(unsigned int i = 0; i < refShell.size(); i++) { GradientDirectionType dir = refGradientsContainer->ElementAt(refShell[i]); double x = dir.normalize().get(0); double y = dir.normalize().get(1); double z = dir.normalize().get(2); double cart[3]; mitk::sh::Cart2Sph(x,y,z,cart); Q(0,i) = cart[0]; Q(1,i) = cart[1]; Q(2,i) = cart[2]; } return Q; } vnl_matrix mitk::gradients::ComputeSphericalHarmonicsBasis(const vnl_matrix & QBallReference, const unsigned int & LOrder) { vnl_matrix SHBasisOutput(QBallReference.cols(), (LOrder+1)*(LOrder+2)*0.5); SHBasisOutput.fill(0.0); for(unsigned int i=0; i 1){ mapIterator++; //skip bzero Values vnl_vector_fixed vec; vec.fill(0.0); directioncontainer->push_back(vec); } for( ; mapIterator != bValueMap.end(); mapIterator++){ IndiciesVector currentShell = mapIterator->second; while(currentShell.size()>0) { unsigned int wntIndex = currentShell.back(); currentShell.pop_back(); mitk::gradients::GradientDirectionContainerType::Iterator containerIt = directioncontainer->Begin(); bool directionExist = false; while(containerIt != directioncontainer->End()) { if (fabs(dot_product(containerIt.Value(), origninalGradentcontainer->ElementAt(wntIndex))) > 0.9998) { directionExist = true; break; } containerIt++; } if(!directionExist) { GradientDirectionType dir(origninalGradentcontainer->ElementAt(wntIndex)); directioncontainer->push_back(dir.normalize()); } } } return directioncontainer; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp index e29dc6a3a9..74abc75e26 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp @@ -1,350 +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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkTractSegView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkTractSegView::VIEW_ID = "org.mitk.views.tractseg"; QmitkTractSegView::QmitkTractSegView() : QmitkAbstractView() , m_Controls( 0 ) { } // Destructor QmitkTractSegView::~QmitkTractSegView() { } void QmitkTractSegView::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::QmitkTractSegViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(Start()) ); connect( m_Controls->m_OutputBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); this->m_Parent = parent; m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("PeakImage"); m_Controls->m_ImageBox->SetPredicate( isDwi ); UpdateGUI(); } } void QmitkTractSegView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { } void QmitkTractSegView::UpdateGUI() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) m_Controls->m_StartButton->setEnabled(true); else m_Controls->m_StartButton->setEnabled(false); m_Controls->m_CollapseBox->setVisible(true); m_Controls->m_thresholdFrame->setVisible(true); if (m_Controls->m_OutputBox->currentIndex()==3 || m_Controls->m_OutputBox->currentIndex()==1) m_Controls->m_thresholdFrame->setVisible(false); if (m_Controls->m_OutputBox->currentIndex()>0) m_Controls->m_CollapseBox->setVisible(false); } void QmitkTractSegView::SetFocus() { UpdateGUI(); m_Controls->m_StartButton->setFocus(); } void QmitkTractSegView::Start() { std::locale::global(std::locale::classic()); mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer input_image = dynamic_cast(node->GetData()); // get python script as string QString data; QString fileName(":/QmitkDiffusionImaging/tractseg.py"); QFile file(fileName); if(!file.open(QIODevice::ReadOnly)) { qDebug()<<"filenot opened"< m_PythonServiceRef = context->GetServiceReference(); mitk::IPythonService* m_PythonService = dynamic_cast ( context->GetService(m_PythonServiceRef) ); mitk::IPythonService::ForceLoadModule(); typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_image); caster->Update(); mitk::PeakImage::ItkPeakImageType::Pointer itk_peaks = caster->GetOutput(); if (itk_peaks->GetLargestPossibleRegion().GetSize()[3]!=9) { QMessageBox::warning(nullptr, "Error", "TractSeg only works with 3-peak images!", QMessageBox::Ok); return; } itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New(); flipper->SetInput(itk_peaks); flipper->SetFlipX(false); flipper->SetFlipY(false); flipper->SetFlipZ(true); flipper->Update(); itk::FourDToVectorImageFilter< float >::Pointer converter = itk::FourDToVectorImageFilter< float >::New(); converter->SetInputImage(flipper->GetOutput()); converter->GenerateData(); mitk::Image::Pointer mitk_vec_img = mitk::GrabItkImageMemory( converter->GetOutputImage().GetPointer() ); m_PythonService->CopyToPythonAsSimpleItkImage( mitk_vec_img, "in_image"); m_PythonService->Execute("sx=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[0])); m_PythonService->Execute("sy=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[1])); m_PythonService->Execute("sz=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[2])); if (m_PythonService->DoesVariableExist("segmentation")) m_PythonService->Execute("del segmentation"); if(m_Controls->m_ModeBox->currentIndex()==0) m_PythonService->Execute("output_type=\"tract_segmentation\""); else if(m_Controls->m_ModeBox->currentIndex()==1) m_PythonService->Execute("output_type=\"endings_segmentation\""); if(m_Controls->m_OutputBox->currentIndex()==3) m_PythonService->Execute("output_type=\"TOM\""); if (m_Controls->m_CollapseBox->isChecked() && m_Controls->m_OutputBox->currentIndex()==0) m_PythonService->Execute("collapse=True"); else m_PythonService->Execute("collapse=False"); m_PythonService->Execute("get_probs=False"); m_PythonService->Execute("dropout_sampling=False"); if (m_Controls->m_OutputBox->currentIndex()==1) m_PythonService->Execute("get_probs=True"); else if (m_Controls->m_OutputBox->currentIndex()==2) m_PythonService->Execute("dropout_sampling=True"); m_PythonService->Execute("threshold=" + boost::lexical_cast(m_Controls->m_SegThresholdBox->value())); m_PythonService->Execute("verbose=False"); m_PythonService->Execute(data.toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND); // clean up after running script (better way than deleting individual variables?) if(m_PythonService->DoesVariableExist("in_image")) m_PythonService->Execute("del in_image"); if(m_PythonService->DoesVariableExist("collapse")) m_PythonService->Execute("del collapse"); // check for errors if(!m_PythonService->GetVariable("error_string").empty()) { QMessageBox::warning(nullptr, "Error", QString(m_PythonService->GetVariable("error_string").c_str()), QMessageBox::Ok); return; } std::vector small_name_list = {"AF_left", "AF_right", "CA", "CST_left", "CST_right", "CG_left", "CG_right", "ICP_left", "ICP_right", "MCP", "SCP_left", "SCP_right", "ILF_left", "ILF_right", "IFO_left", "IFO_right", "OR_left", "OR_right", "UF_left", "UF_right"}; std::vector large_name_list = {"AF_left", "AF_right", "ATR_left", "ATR_right", "CA", "CC_1", "CC_2", "CC_3", "CC_4", "CC_5", "CC_6", "CC_7","CG_left","CG_right","CST_left","CST_right" ,"MLF_left","MLF_right","FPT_left" ,"FPT_right","FX_left","FX_right","ICP_left","ICP_right","IFO_left","IFO_right" ,"ILF_left" ,"ILF_right","MCP","OR_left","OR_right","POPT_left","POPT_right" ,"SCP_left","SCP_right","SLF_I_left","SLF_I_right","SLF_II_left","SLF_II_right" ,"SLF_III_left","SLF_III_right","STR_left","STR_right","UF_left","UF_right" ,"CC","T_PREF_left","T_PREF_right","T_PREM_left","T_PREM_right","T_PREC_left" ,"T_PREC_right","T_POSTC_left","T_POSTC_right","T_PAR_left","T_PAR_right","T_OCC_left" ,"T_OCC_right","ST_FO_left","ST_FO_right","ST_PREF_left","ST_PREF_right","ST_PREM_left" ,"ST_PREM_right","ST_PREC_left","ST_PREC_right","ST_POSTC_left","ST_POSTC_right" ,"ST_PAR_left","ST_PAR_right","ST_OCC_left","ST_OCC_right"}; if (m_PythonService->DoesVariableExist("segmentation")) { mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("segmentation"); if (!m_Controls->m_CollapseBox->isChecked() || m_Controls->m_OutputBox->currentIndex()>0) { if (m_Controls->m_OutputBox->currentIndex()>0) { itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); mitk::CastToItkImage(out_image, vectorImage); itk::SplitVectorImageFilter::Pointer splitter = itk::SplitVectorImageFilter::New(); splitter->SetInputImage(vectorImage); splitter->GenerateData(); int c = 0; for (auto itk_seg : splitter->GetOutputImages()) { mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData( mitk::GrabItkImageMemory(itk_seg) ); if (m_Controls->m_ModeBox->currentIndex()==0) seg->SetName(large_name_list.at(c)); else seg->SetName(small_name_list.at(c)); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); seg->SetProperty("LookupTable", lut_prop ); mitk::LevelWindow lw; lw.SetRangeMinMax(0.0,1.0); seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(seg, node); ++c; } } else { itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); mitk::CastToItkImage(out_image, vectorImage); itk::SplitVectorImageFilter::Pointer splitter = itk::SplitVectorImageFilter::New(); splitter->SetInputImage(vectorImage); splitter->GenerateData(); int c = 0; for (auto itk_seg : splitter->GetOutputImages()) { mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData( mitk::GrabItkImageMemory(itk_seg) ); if (m_Controls->m_ModeBox->currentIndex()==0) { seg->SetName(large_name_list.at(c)); seg->SetBoolProperty("binary", true); } else { mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::MULTILABEL ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); seg->SetProperty("LookupTable", lut_prop ); mitk::LevelWindow lw; lw.SetRangeMinMax(0,2); seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); seg->SetName(small_name_list.at(c)); } GetDataStorage()->Add(seg, node); ++c; } } } else { mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData(out_image); mitk::LevelWindow lw; if (m_Controls->m_ModeBox->currentIndex()==0) { seg->SetName("TractLabels"); lw.SetRangeMinMax(0, 72); } else { seg->SetName("TractEndpointRegionLabels"); lw.SetRangeMinMax(0, 40); } if (m_Controls->m_OutputBox->currentIndex()==0) { mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::MULTILABEL ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); seg->SetProperty("LookupTable", lut_prop ); seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); } GetDataStorage()->Add(seg, node); } m_PythonService->Execute("del segmentation"); } else { for (int i=0; i<20; ++i) if (m_PythonService->DoesVariableExist("tom" + boost::lexical_cast(i))) { mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("tom" + boost::lexical_cast(i)); itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); mitk::CastToItkImage(out_image, vectorImage); itk::VectorImageToFourDImageFilter< float >::Pointer converter = itk::VectorImageToFourDImageFilter< float >::New(); converter->SetInputImage(vectorImage); converter->GenerateData(); mitk::PeakImage::ItkPeakImageType::Pointer itk_peaks = converter->GetOutputImage(); + itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New(); + flipper->SetInput(itk_peaks); + flipper->SetFlipX(false); + flipper->SetFlipY(false); + flipper->SetFlipZ(true); + flipper->Update(); + itk_peaks = flipper->GetOutput(); + mitk::Image::Pointer mitk_peaks = dynamic_cast(mitk::PeakImage::New().GetPointer()); mitk::CastToMitkImage(itk_peaks, mitk_peaks); mitk_peaks->SetVolume(itk_peaks->GetBufferPointer()); mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData( mitk_peaks ); if (!m_Controls->m_CollapseBox->isChecked()) seg->SetName(small_name_list.at(i) + "_TOM"); else seg->SetName("Collapsed_TOM"); GetDataStorage()->Add(seg, node); m_PythonService->Execute("del tom" + boost::lexical_cast(i)); } } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp index 083513f782..333567d9bd 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp @@ -1,69 +1,39 @@ /*=================================================================== 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 "QmitkODFDetailsWidget.h" #include QmitkODFDetailsWidget::QmitkODFDetailsWidget( QWidget * parent ) : QmitkPlotWidget(parent) { QFrame* canvas = qobject_cast(m_Plot->canvas()); if (canvas) { canvas->setLineWidth(0); canvas->setContentsMargins(0,0,0,0); } auto scale = new QwtLinearScaleEngine(); m_Plot->setAxisScaleEngine(0, scale); m_Plot->setAxisScale ( 0, -0.5, 0.5 ); } QmitkODFDetailsWidget::~QmitkODFDetailsWidget() { } - -void QmitkODFDetailsWidget::SetParameters( itk::OrientationDistributionFunction odf ) -{ - this->Clear(); - - std::vector xVals; - std::vector yVals; - float max = itk::NumericTraits::NonpositiveMin(); - float min = itk::NumericTraits::max(); - - for (int i=0; imax) - max = odf[i]; - if (odf[i]0) - m_Plot->setAxisScale ( 0, 0, max ); - else - m_Plot->setAxisScale ( 0, min, max ); - - int curveId = this->InsertCurve( "ODF Values" ); - this->SetCurveData( curveId, xVals, yVals ); - this->SetCurvePen( curveId, QPen(Qt::blue, 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin) ); - this->Replot(); -} - diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h index a748bc106b..07f8606d01 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h @@ -1,46 +1,74 @@ /*=================================================================== 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 QmitkODFDetailsWidget_H_ #define QmitkODFDetailsWidget_H_ #include "QmitkPlotWidget.h" #include #include /** * \brief Widget for displaying image histograms based on the vtkQtChart * framework */ class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkODFDetailsWidget : public QmitkPlotWidget { Q_OBJECT public: - void SetParameters( itk::OrientationDistributionFunction odf ); + template< unsigned int ODF_SIZE=ODF_SAMPLING_SIZE > + void SetParameters( itk::OrientationDistributionFunction odf ) + { + this->Clear(); + + std::vector xVals; + std::vector yVals; + double max = itk::NumericTraits::NonpositiveMin(); + double min = itk::NumericTraits::max(); + + for (unsigned int i=0; imax) + max = odf[i]; + if (odf[i]0) + m_Plot->setAxisScale ( 0, 0, max ); + else + m_Plot->setAxisScale ( 0, min, max ); + + auto curveId = this->InsertCurve( "ODF Values" ); + this->SetCurveData( curveId, xVals, yVals ); + this->SetCurvePen( curveId, QPen(Qt::blue, 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin) ); + this->Replot(); + } QmitkODFDetailsWidget( QWidget * /*parent = 0 */); virtual ~QmitkODFDetailsWidget(); std::vector m_Vals; private: }; #endif /* QmitkODFDetailsWidget_H_ */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp index 2fd0f35086..9d5a0a6b5d 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp @@ -1,123 +1,44 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkODFRenderWidget.h" #include #include #include #include QmitkODFRenderWidget::QmitkODFRenderWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { //create Layouts QmitkODFRenderWidgetLayout = new QHBoxLayout( this ); //Set Layout to widget this->setLayout(QmitkODFRenderWidgetLayout); //Create RenderWindow m_RenderWindow = new QmitkRenderWindow(this, "odf render widget"); m_RenderWindow->setMaximumSize(300,300); m_RenderWindow->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D ); //m_RenderWindow->SetLayoutIndex( 3 ); QmitkODFRenderWidgetLayout->addWidget( m_RenderWindow ); } QmitkODFRenderWidget::~QmitkODFRenderWidget() { } -void QmitkODFRenderWidget::GenerateODF( itk::OrientationDistributionFunction odf ) -{ - try - { - m_Surface = mitk::Surface::New(); - m_ds = mitk::StandaloneDataStorage::New(); - m_Node = mitk::DataNode::New(); - - vtkPolyData* m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); - - vtkPolyData *polyData = vtkPolyData::New(); - vtkPoints *points = vtkPoints::New(); - vtkFloatArray *scalars = vtkFloatArray::New(); - - for (int i=0; iGetPoints()->GetPoint(i,p); - double val = odf[i]; - - p[0] *= val; - p[1] *= val; - p[2] *= val; - points->InsertPoint(i,p); - - scalars->InsertTuple1(i, 1-val); - } - - polyData->SetPoints(points); - vtkCellArray* polys = m_TemplateOdf->GetPolys(); - polyData->SetPolys(polys); - polyData->GetPointData()->SetScalars(scalars); - - polys->Delete(); - scalars->Delete(); - points->Delete(); - - m_Surface->SetVtkPolyData(polyData); - m_Node->SetData(m_Surface); - - mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); - - // assign an empty vtk lookup table to the odf renderer, it is the same - // the ODF 2D Mapper has - vtkSmartPointer lut = vtkSmartPointer::New(); - mitkLut->SetVtkLookupTable( lut ); - - mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); - mitkLutProp->SetLookupTable(mitkLut); - m_Node->SetProperty( "LookupTable", mitkLutProp ); - - m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(true)); - m_Node->SetProperty("color mode", mitk::BoolProperty::New(true)); - m_Node->SetProperty("material.specularCoefficient", mitk::FloatProperty::New(0.5)); - - m_ds->Add(m_Node); - - m_RenderWindow->GetRenderer()->SetDataStorage( m_ds ); - - // adjust camera to current plane rotation - mitk::PlaneGeometry::ConstPointer worldPlaneGeometry = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetCurrentWorldPlaneGeometry(); - mitk::Vector3D normal = worldPlaneGeometry->GetNormal(); - mitk::Vector3D up = worldPlaneGeometry->GetAxisVector(1); - normal.Normalize(); - up.Normalize(); - - vtkSmartPointer cam = vtkSmartPointer::New(); - const double camPos[3] = {normal[0],normal[1],normal[2]}; - const double camUp[3] = {up[0],up[1],up[2]}; - cam->SetPosition(camPos); - cam->SetViewUp(camUp); - cam->SetParallelProjection(1); - m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetActiveCamera(cam); - m_RenderWindow->update(); - } - catch (...) - { - - } -} diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h index 0af5c9c897..31c2ec4328 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h @@ -1,60 +1,168 @@ /*=================================================================== 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 QmitkODFRenderWidget_H_ #define QmitkODFRenderWidget_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkODFRenderWidget : public QWidget { Q_OBJECT public: - QmitkODFRenderWidget( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + QmitkODFRenderWidget( QWidget* parent = nullptr, Qt::WindowFlags f = nullptr ); virtual ~QmitkODFRenderWidget(); - void GenerateODF( itk::OrientationDistributionFunction odf ); + template + void GenerateODF( itk::OrientationDistributionFunction odf, int normalization, bool dir_color) + { + try + { + switch(normalization) + { + case 0: + odf = odf.MinMaxNormalize(); + break; + case 1: + odf = odf.MaxNormalize(); + break; + case 2: + odf = odf.MaxNormalize(); + break; + default: + odf = odf.MinMaxNormalize(); + } + + m_Surface = mitk::Surface::New(); + m_ds = mitk::StandaloneDataStorage::New(); + m_Node = mitk::DataNode::New(); + + vtkPolyData* m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); + + vtkPolyData *polyData = vtkPolyData::New(); + vtkPoints *points = vtkPoints::New(); + vtkFloatArray *scalars = vtkFloatArray::New(); + + for (unsigned int i=0; iGetPoints()->GetPoint(i,p); + double val = odf[i]; + + p[0] *= val; + p[1] *= val; + p[2] *= val; + points->InsertPoint(i,p); + + scalars->InsertTuple1(i, 1-val); + } + + polyData->SetPoints(points); + vtkCellArray* polys = m_TemplateOdf->GetPolys(); + polyData->SetPolys(polys); + polyData->GetPointData()->SetScalars(scalars); + + polys->Delete(); + scalars->Delete(); + points->Delete(); + + m_Surface->SetVtkPolyData(polyData); + m_Node->SetData(m_Surface); + + mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); + + // assign an empty vtk lookup table to the odf renderer, it is the same + // the ODF 2D Mapper has + vtkSmartPointer lut = vtkSmartPointer::New(); + mitkLut->SetVtkLookupTable( lut ); + + mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); + mitkLutProp->SetLookupTable(mitkLut); + m_Node->SetProperty( "LookupTable", mitkLutProp ); + + m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(true)); + m_Node->SetProperty("color mode", mitk::BoolProperty::New(true)); + m_Node->SetProperty("material.specularCoefficient", mitk::FloatProperty::New(0.5)); + + if (dir_color) + { + m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(false)); + m_Node->SetProperty("color mode", mitk::BoolProperty::New(false)); + vnl_vector_fixed d = odf.GetPrincipalDiffusionDirection(); + mitk::Color c; + c.SetRed(fabs(static_cast(d[0]))); + c.SetGreen(fabs(static_cast(d[1]))); + c.SetBlue(fabs(static_cast(d[2]))); + m_Node->SetColor(c); + } + + m_ds->Add(m_Node); + + m_RenderWindow->GetRenderer()->SetDataStorage( m_ds ); + + // adjust camera to current plane rotation + mitk::PlaneGeometry::ConstPointer worldPlaneGeometry = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetCurrentWorldPlaneGeometry(); + mitk::Vector3D normal = worldPlaneGeometry->GetNormal(); + mitk::Vector3D up = worldPlaneGeometry->GetAxisVector(1); + normal.Normalize(); + up.Normalize(); + + vtkSmartPointer cam = vtkSmartPointer::New(); + const double camPos[3] = {normal[0],normal[1],normal[2]}; + const double camUp[3] = {up[0],up[1],up[2]}; + cam->SetPosition(camPos); + cam->SetViewUp(camUp); + cam->SetParallelProjection(1); + m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetActiveCamera(cam); + m_RenderWindow->update(); + } + catch (...) + { + + } + } protected: QHBoxLayout* QmitkODFRenderWidgetLayout; QmitkRenderWindow* m_RenderWindow; mitk::Surface::Pointer m_Surface; mitk::StandaloneDataStorage::Pointer m_ds; mitk::DataNode::Pointer m_Node; }; #endif /*QmitkODFRenderWidget_H_*/ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp index 8310b75382..26929f079b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp @@ -1,50 +1,51 @@ /*=================================================================== 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 "QmitkQuantificationPerspective.h" #include "berryIViewLayout.h" void QmitkQuantificationPerspective::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.diffusionquantification"); left->AddView("org.mitk.views.imagestatistics"); left->AddView("org.mitk.views.segmentation"); + left->AddView("org.mitk.views.odfdetails"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp index e64a4bb757..68d2b4c969 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp @@ -1,51 +1,52 @@ /*=================================================================== 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 "QmitkReconstructionPerspective.h" #include "berryIViewLayout.h" void QmitkReconstructionPerspective::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.tensorreconstruction"); left->AddView("org.mitk.views.qballreconstruction"); left->AddView("org.mitk.views.odfmaximaextraction"); left->AddView("org.mitk.views.dipyreconstruction"); + left->AddView("org.mitk.views.odfdetails"); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp index 1f4d35d30f..d5792ee0c7 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp @@ -1,606 +1,606 @@ /*=================================================================== 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 "QmitkDiffusionQuantificationView.h" #include "mitkDiffusionImagingConfigure.h" - #include "itkTimeProbe.h" #include "itkImage.h" - #include "mitkNodePredicateDataType.h" #include "mitkDataNodeObject.h" #include "mitkOdfImage.h" #include #include "mitkImageCast.h" #include "mitkStatusBar.h" #include "itkDiffusionOdfGeneralizedFaImageFilter.h" #include "itkShiftScaleImageFilter.h" #include "itkTensorFractionalAnisotropyImageFilter.h" #include "itkTensorRelativeAnisotropyImageFilter.h" #include "itkTensorDerivedMeasurementsFilter.h" - #include "QmitkDataStorageComboBox.h" #include #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" - #include #include #include #include #include #include #include #include - #include #include #include #include #include +#include const std::string QmitkDiffusionQuantificationView::VIEW_ID = "org.mitk.views.diffusionquantification"; QmitkDiffusionQuantificationView::QmitkDiffusionQuantificationView() : QmitkAbstractView(), m_Controls(nullptr) { } QmitkDiffusionQuantificationView::~QmitkDiffusionQuantificationView() { } void QmitkDiffusionQuantificationView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkDiffusionQuantificationViewControls; m_Controls->setupUi(parent); m_Controls->m_BallStickButton->setVisible(false); m_Controls->m_MultiTensorButton->setVisible(false); connect( static_cast(m_Controls->m_GFAButton), SIGNAL(clicked()), this, SLOT(GFA()) ); connect( static_cast(m_Controls->m_FAButton), SIGNAL(clicked()), this, SLOT(FA()) ); connect( static_cast(m_Controls->m_RAButton), SIGNAL(clicked()), this, SLOT(RA()) ); connect( static_cast(m_Controls->m_ADButton), SIGNAL(clicked()), this, SLOT(AD()) ); connect( static_cast(m_Controls->m_RDButton), SIGNAL(clicked()), this, SLOT(RD()) ); connect( static_cast(m_Controls->m_MDButton), SIGNAL(clicked()), this, SLOT(MD()) ); connect( static_cast(m_Controls->m_MdDwiButton), SIGNAL(clicked()), this, SLOT(MD_DWI()) ); connect( static_cast(m_Controls->m_AdcDwiButton), SIGNAL(clicked()), this, SLOT(ADC_DWI()) ); connect( static_cast(m_Controls->m_ClusteringAnisotropy), SIGNAL(clicked()), this, SLOT(ClusterAnisotropy()) ); connect( static_cast(m_Controls->m_BallStickButton), SIGNAL(clicked()), this, SLOT(DoBallStickCalculation()) ); connect( static_cast(m_Controls->m_MultiTensorButton), SIGNAL(clicked()), this, SLOT(DoMultiTensorCalculation()) ); m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isDti = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isOdf = mitk::TNodePredicateDataType::New(); + mitk::TNodePredicateDataType::Pointer isSh = mitk::TNodePredicateDataType::New(); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New(); - m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateOr::New(isDti, mitk::NodePredicateOr::New(isOdf, isDwi)) ); + m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateOr::New(isSh, mitk::NodePredicateOr::New(isDti, mitk::NodePredicateOr::New(isOdf, isDwi))) ); connect( static_cast(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); } } void QmitkDiffusionQuantificationView::SetFocus() { m_Controls->m_ScaleImageValuesBox->setFocus(); } void QmitkDiffusionQuantificationView::UpdateGui() { bool foundOdfVolume = false; bool foundTensorVolume = false; bool foundDwVolume = false; mitk::DataNode::Pointer selNode = m_Controls->m_ImageBox->GetSelectedNode(); - if( selNode.IsNotNull() && dynamic_cast(selNode->GetData()) ) + if( selNode.IsNotNull() && (dynamic_cast(selNode->GetData()) || dynamic_cast(selNode->GetData())) ) foundOdfVolume = true; else if( selNode.IsNotNull() && dynamic_cast(selNode->GetData()) ) foundTensorVolume = true; else if( selNode.IsNotNull()) foundDwVolume = true; m_Controls->m_GFAButton->setEnabled(foundOdfVolume); m_Controls->m_FAButton->setEnabled(foundTensorVolume); m_Controls->m_RAButton->setEnabled(foundTensorVolume); m_Controls->m_ADButton->setEnabled(foundTensorVolume); m_Controls->m_RDButton->setEnabled(foundTensorVolume); m_Controls->m_MDButton->setEnabled(foundTensorVolume); m_Controls->m_ClusteringAnisotropy->setEnabled(foundTensorVolume); m_Controls->m_AdcDwiButton->setEnabled(foundDwVolume); m_Controls->m_MdDwiButton->setEnabled(foundDwVolume); m_Controls->m_BallStickButton->setEnabled(foundDwVolume); m_Controls->m_MultiTensorButton->setEnabled(foundDwVolume); } void QmitkDiffusionQuantificationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& ) { UpdateGui(); } void QmitkDiffusionQuantificationView::ADC_DWI() { DoAdcCalculation(true); } void QmitkDiffusionQuantificationView::MD_DWI() { DoAdcCalculation(false); } void QmitkDiffusionQuantificationView::DoBallStickCalculation() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer image = dynamic_cast(node->GetData()); typedef itk::BallAndSticksImageFilter< short, double > FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(image)); - filter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)); + filter->SetB_value(static_cast(mitk::DiffusionPropertyHelper::GetReferenceBValue(image))); filter->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( filter->GetOutput() ); newImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_f").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); { FilterType::PeakImageType::Pointer itkImg = filter->GetPeakImage(); mitk::Image::Pointer newImage = mitk::Image::New(); CastToMitkImage(itkImg, newImage); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); imageNode->SetName((name+"_Sticks").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } { mitk::Image::Pointer dOut = mitk::GrabItkImageMemory( filter->GetOutDwi().GetPointer() ); mitk::DiffusionPropertyHelper::SetGradientContainer(dOut, mitk::DiffusionPropertyHelper::GetGradientContainer(image) ); mitk::DiffusionPropertyHelper::SetReferenceBValue(dOut, mitk::DiffusionPropertyHelper::GetReferenceBValue(image) ); mitk::DiffusionPropertyHelper::InitializeImage(dOut); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData(dOut); QString name = node->GetName().c_str(); imageNode->SetName((name+"_Estimated-DWI").toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } } } void QmitkDiffusionQuantificationView::DoMultiTensorCalculation() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) // for all items { mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer image = dynamic_cast(node->GetData()); typedef itk::MultiTensorImageFilter< short, double > FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(image)); - filter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)); + filter->SetB_value(static_cast(mitk::DiffusionPropertyHelper::GetReferenceBValue(image))); filter->Update(); typedef mitk::TensorImage::ItkTensorImageType TensorImageType; - for (int i=0; iGetTensorImages().at(i); mitk::TensorImage::Pointer image = mitk::TensorImage::New(); image->InitializeByItk( tensorImage.GetPointer() ); image->SetVolume( tensorImage->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = node->GetName().c_str(); name.append("_Tensor"); name.append(boost::lexical_cast(i).c_str()); imageNode->SetName(name.toStdString().c_str()); GetDataStorage()->Add(imageNode, node); } } } void QmitkDiffusionQuantificationView::DoAdcCalculation(bool fit) { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer image = dynamic_cast(node->GetData()); typedef itk::AdcImageFilter< short, double > FilterType; ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkVectorImagePointer ); filter->SetGradientDirections( mitk::DiffusionPropertyHelper::GetGradientContainer(image) ); - filter->SetB_value( mitk::DiffusionPropertyHelper::GetReferenceBValue(image) ); + filter->SetB_value( static_cast(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)) ); filter->SetFitSignal(fit); filter->Update(); typedef itk::ShiftScaleImageFilter::OutputImageType, itk::AdcImageFilter< short, double >::OutputImageType> ShiftScaleFilterType; ShiftScaleFilterType::Pointer multi = ShiftScaleFilterType::New(); multi->SetShift(0.0); multi->SetScale(m_Controls->m_ScaleImageValuesBox->value()); multi->SetInput(filter->GetOutput()); multi->Update(); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->InitializeByItk( multi->GetOutput() ); newImage->SetVolume( multi->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newImage ); QString name = node->GetName().c_str(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); imageNode->SetProperty("LookupTable", lut_prop ); if (fit) imageNode->SetName((name+"_ADC").toStdString().c_str()); else imageNode->SetName((name+"_MD").toStdString().c_str()); mitk::LevelWindow lw; lw.SetLevelWindow(0.0015, 0.003); imageNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(imageNode, node); } } void QmitkDiffusionQuantificationView::GFA() { OdfQuantify(0); } void QmitkDiffusionQuantificationView::FA() { TensorQuantify(0); } void QmitkDiffusionQuantificationView::RA() { TensorQuantify(1); } void QmitkDiffusionQuantificationView::AD() { TensorQuantify(2); } void QmitkDiffusionQuantificationView::RD() { TensorQuantify(3); } void QmitkDiffusionQuantificationView::ClusterAnisotropy() { TensorQuantify(4); } void QmitkDiffusionQuantificationView::MD() { TensorQuantify(5); } void QmitkDiffusionQuantificationView::OdfQuantify(int method) { OdfQuantification(method); } void QmitkDiffusionQuantificationView::TensorQuantify(int method) { TensorQuantification(method); } void QmitkDiffusionQuantificationView::OdfQuantification(int method) { QString status; if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode(); typedef float TOdfPixelType; typedef itk::Vector OdfVectorType; typedef itk::Image OdfVectorImgType; - mitk::Image* vol = static_cast(node->GetData()); - OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New(); - mitk::CastToItkImage(vol, itkvol); + mitk::Image::Pointer vol = dynamic_cast(node->GetData()); + OdfVectorImgType::Pointer itkvol; + if (dynamic_cast(vol.GetPointer())) + itkvol = mitk::convert::GetItkOdfFromShImage(vol); + else + itkvol = mitk::convert::GetItkOdfFromOdfImage(vol); std::string nodename = node->GetName(); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Computing GFA for %s", nodename.c_str()).toLatin1()); typedef itk::DiffusionOdfGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itkvol); std::string newname; newname.append(nodename); switch(method) { case 0: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); newname.append("GFA"); break; } case 1: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_HIGH_LOW); newname.append("01"); break; } case 2: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_HIGH); newname.append("02"); break; } case 3: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE); newname.append("03"); break; } case 4: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_DECONVOLUTION_COEFFS); newname.append("04"); break; } case 5: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_MAX_NORMALIZED_STANDARD); newname.append("05"); break; } case 6: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_NORMALIZED_ENTROPY); newname.append("06"); break; } case 7: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_NEMATIC_ORDER_PARAMETER); newname.append("07"); break; } case 8: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_LOW_HIGH); newname.append("08"); break; } case 9: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_LOW); newname.append("09"); break; } case 10: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_ODF_VALUE); newname.append("10"); break; } case 11: { gfaFilter->SetComputationMethod(GfaFilterType::GFA_STD_BY_MAX); newname.append("11"); break; } default: { newname.append("0"); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); } } gfaFilter->Update(); typedef itk::Image ImgType; ImgType::Pointer img = ImgType::New(); img->SetSpacing( gfaFilter->GetOutput()->GetSpacing() ); // Set the image spacing img->SetOrigin( gfaFilter->GetOutput()->GetOrigin() ); // Set the image origin img->SetDirection( gfaFilter->GetOutput()->GetDirection() ); // Set the image direction img->SetLargestPossibleRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion()); img->SetBufferedRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion() ); img->Allocate(); itk::ImageRegionIterator ot (img, img->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionConstIterator it (gfaFilter->GetOutput(), gfaFilter->GetOutput()->GetLargestPossibleRegion() ); for (it.GoToBegin(); !it.IsAtEnd(); ++it) { GfaFilterType::OutputImageType::PixelType val = it.Get(); ot.Set(val * m_Controls->m_ScaleImageValuesBox->value()); ++ot; } // GFA TO DATATREE mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( img.GetPointer() ); image->SetVolume( img->GetBufferPointer() ); mitk::DataNode::Pointer new_node=mitk::DataNode::New(); new_node->SetData( image ); new_node->SetProperty( "name", mitk::StringProperty::New(newname) ); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); new_node->SetProperty("LookupTable", lut_prop ); mitk::LevelWindow lw; lw.SetLevelWindow(0.5, 1.0); new_node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(new_node, node); mitk::StatusBar::GetInstance()->DisplayText("Computation complete."); } this->GetRenderWindowPart()->RequestUpdate(); } void QmitkDiffusionQuantificationView::TensorQuantification(int method) { QString status; if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode(); typedef mitk::TensorImage::ScalarPixelType TTensorPixelType; typedef mitk::TensorImage::ItkTensorImageType TensorImageType; mitk::Image* vol = static_cast(node->GetData()); TensorImageType::Pointer itkvol = TensorImageType::New(); mitk::CastToItkImage(vol, itkvol); std::string nodename = node->GetName(); mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Computing FA for %s", nodename.c_str()).toLatin1()); typedef itk::Image< TTensorPixelType, 3 > FAImageType; typedef itk::ShiftScaleImageFilter ShiftScaleFilterType; ShiftScaleFilterType::Pointer multi = ShiftScaleFilterType::New(); multi->SetShift(0.0); multi->SetScale(m_Controls->m_ScaleImageValuesBox->value()); typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; mitk::LevelWindow lw; if(method == 0) //FA { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::FA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_FA").toStdString(); lw.SetLevelWindow(0.5, 1.0); } else if(method == 1) //RA { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::RA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_RA").toStdString(); lw.SetLevelWindow(0.015, 0.03); } else if(method == 2) // AD (Axial diffusivity) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::AD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_AD").toStdString(); lw.SetLevelWindow(0.0015, 0.003); } else if(method == 3) // RD (Radial diffusivity, (Lambda2+Lambda3)/2 { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::RD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_RD").toStdString(); lw.SetLevelWindow(0.0015, 0.003); } else if(method == 4) // 1-(Lambda2+Lambda3)/(2*Lambda1) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::CA); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_CA").toStdString(); lw.SetLevelWindow(0.5, 1.0); } else if(method == 5) // MD (Mean Diffusivity, (Lambda1+Lambda2+Lambda3)/3 ) { MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); measurementsCalculator->SetInput(itkvol.GetPointer() ); measurementsCalculator->SetMeasure(MeasurementsType::MD); measurementsCalculator->Update(); multi->SetInput(measurementsCalculator->GetOutput()); nodename = QString(nodename.c_str()).append("_MD").toStdString(); lw.SetLevelWindow(0.0015, 0.003); } multi->Update(); // FA TO DATATREE mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( multi->GetOutput() ); image->SetVolume( multi->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer new_node=mitk::DataNode::New(); new_node->SetData( image ); new_node->SetProperty( "name", mitk::StringProperty::New(nodename) ); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); lut_prop->SetLookupTable( lut ); new_node->SetProperty("LookupTable", lut_prop ); new_node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); GetDataStorage()->Add(new_node, node); mitk::StatusBar::GetInstance()->DisplayText("Computation complete."); } this->GetRenderWindowPart()->RequestUpdate(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp index 96fee83d4c..c0906f0f77 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp @@ -1,345 +1,405 @@ /*=================================================================== 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 "QmitkODFDetailsView.h" #include #include #include #include #include #include #include #include #include #include - +#include #include - +#include +#include #include const std::string QmitkODFDetailsView::VIEW_ID = "org.mitk.views.odfdetails"; QmitkODFDetailsView::QmitkODFDetailsView() : QmitkAbstractView() - , m_Controls( 0 ) + , m_Controls(nullptr) , m_OdfNormalization(0) , m_ImageNode(nullptr) { - m_VtkActor = vtkActor::New(); - m_VtkMapper = vtkPolyDataMapper::New(); - m_Renderer = vtkRenderer::New(); - m_VtkRenderWindow = vtkRenderWindow::New(); - m_RenderWindowInteractor = vtkRenderWindowInteractor::New(); - m_Camera = vtkCamera::New(); - m_VtkRenderWindow->SetSize(300,300); } QmitkODFDetailsView::~QmitkODFDetailsView() { } void QmitkODFDetailsView::Activated() { } void QmitkODFDetailsView::Deactivated() { } void QmitkODFDetailsView::Visible() { } void QmitkODFDetailsView::Hidden() { } void QmitkODFDetailsView::SetFocus() { this->m_Controls->m_OverviewTextEdit->setFocus(); } void QmitkODFDetailsView::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::QmitkODFDetailsViewControls; m_Controls->setupUi( parent ); m_Controls->m_OdfBox->setVisible(false); m_Controls->m_ODFRenderWidget->setVisible(false); - m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); } } void QmitkODFDetailsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { m_Controls->m_InputData->setTitle("Please Select Input Data"); m_Controls->m_InputImageLabel->setText("mandatory"); m_ImageNode = nullptr; // iterate selection for (mitk::DataNode::Pointer node: nodes) { - if( node.IsNotNull() && (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) ) + if( node.IsNotNull() && (dynamic_cast(node->GetData()) || dynamic_cast(node->GetData()) || dynamic_cast(node->GetData())) ) { m_Controls->m_InputImageLabel->setText(node->GetName().c_str()); m_ImageNode = node; } } UpdateOdf(); if (m_ImageNode.IsNotNull()) { m_Controls->m_InputData->setTitle("Input Data"); } } void QmitkODFDetailsView::UpdateOdf() { try { m_Controls->m_OverviewBox->setVisible(true); if (m_ImageNode.IsNull() || !this->GetRenderWindowPart()) { m_Controls->m_ODFRenderWidget->setVisible(false); m_Controls->m_OdfBox->setVisible(false); m_Controls->m_OverviewBox->setVisible(false); return; } // restore the input image label ( needed in case the last run resulted into an exception ) m_Controls->m_InputImageLabel->setText(m_ImageNode->GetName().c_str()); // ODF Normalization Property mitk::OdfNormalizationMethodProperty* nmp = dynamic_cast(m_ImageNode->GetProperty( "Normalization" )); if(nmp) m_OdfNormalization = nmp->GetNormalization(); - m_TemplateOdf = itk::OrientationDistributionFunction::GetBaseMesh(); - m_OdfTransform = vtkSmartPointer::New(); - m_OdfTransform->Identity(); - m_OdfVals = vtkSmartPointer::New(); - m_OdfSource = vtkSmartPointer::New(); - itk::OrientationDistributionFunction odf; + bool dir_color = false; + m_ImageNode->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", dir_color ); + + bool toggle_tensor = false; + m_ImageNode->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.SwitchTensorView", toggle_tensor ); mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition(); - mitk::Point3D index; + mitk::Point3D cont_index; mitk::Image::Pointer img = dynamic_cast(m_ImageNode->GetData()); - unsigned int *img_dimension = img->GetDimensions(); - img->GetGeometry()->WorldToIndex(world, index); + img->GetGeometry()->WorldToIndex(world, cont_index); + itk::Index<3> index; + index[0] = static_cast(cont_index[0]+0.5); + index[1] = static_cast(cont_index[1]+0.5); + index[2] = static_cast(cont_index[2]+0.5); float sum = 0; float max = itk::NumericTraits::NonpositiveMin(); float min = itk::NumericTraits::max(); QString values; QString overviewText; // check if dynamic_cast successfull and if the crosshair position is inside of the geometry of the ODF data // otherwise possible crash for a scenario with multiple nodes if (dynamic_cast(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) ) { + itk::OrientationDistributionFunction odf; m_Controls->m_ODFRenderWidget->setVisible(true); m_Controls->m_OdfBox->setVisible(true); try { const mitk::OdfImage* Odf_image = dynamic_cast< mitk::OdfImage* >( m_ImageNode->GetData() ); - // get access to the Odf image data with explicitely allowing exceptions if memory locked - mitk::ImageReadAccessor readAccess( Odf_image, Odf_image->GetVolumeData(0), mitk::ImageAccessorBase::ExceptionIfLocked ); - const float* Odf_cPtr = static_cast< const float*>(readAccess.GetData()); - - OdfVectorImgType::IndexType ind; - ind[0] = (int)(index[0]+0.5); - ind[1] = (int)(index[1]+0.5); - ind[2] = (int)(index[2]+0.5); - - // pixel size = ODF_SAMPLING_SIZE - // position offset = standard offset - unsigned int offset_to_data = ODF_SAMPLING_SIZE * (ind[2] * img_dimension[1] * img_dimension[0] + ind[1] * img_dimension[0] + ind[0]); - const float *pixel_data = Odf_cPtr + offset_to_data; + mitk::ImagePixelReadAccessor pixel_read(Odf_image, Odf_image->GetVolumeData(0)); + auto pixel_data = pixel_read.GetPixelByIndex(index); - for (int i=0; i(val))+"\n"; sum += val; if (val>max) max = val; if (val(odf.GetGeneralizedFractionalAnisotropy()))+"\n"; + overviewText += "Sum: "+QString::number(static_cast(sum))+"\n"; + overviewText += "Mean: "+QString::number(static_cast(mean))+"\n"; + overviewText += "Stdev: "+QString::number(static_cast(stdev))+"\n"; + overviewText += "Min: "+QString::number(static_cast(min))+"\n"; + overviewText += "Max: "+QString::number(static_cast(max))+"\n"; vnl_vector_fixed pd = odf.GetDirection(odf.GetPrincipalDiffusionDirectionIndex()); overviewText += "Main Diffusion:\n "+QString::number(pd[0])+"\n "+QString::number(pd[1])+"\n "+QString::number(pd[2])+"\n"; m_Controls->m_OdfValuesTextEdit->setText(values); m_Controls->m_OverviewTextEdit->setVisible(true); + m_Controls->m_ODFDetailsWidget->SetParameters(odf); + m_Controls->m_ODFRenderWidget->GenerateODF(odf, m_OdfNormalization, dir_color); + m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str()); } catch( mitk::Exception &e ) { MITK_WARN << "LOCKED : " << e.what(); m_Controls->m_ODFRenderWidget->setVisible(false); m_Controls->m_OdfBox->setVisible(false); m_Controls->m_OverviewTextEdit->setVisible(false); // reset the selection m_Controls->m_InputImageLabel->setText("Click image to restore rendering!"); } } else if (dynamic_cast(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) ) { + itk::OrientationDistributionFunction odf; m_Controls->m_ODFRenderWidget->setVisible(true); m_Controls->m_OdfBox->setVisible(false); - - const mitk::TensorImage* Odf_image = dynamic_cast< mitk::TensorImage*>(m_ImageNode->GetData()); // pixel access block try { - // get access to the Odf image data with explicitely allowing exceptions if memory locked - mitk::ImageReadAccessor readAccess( Odf_image, Odf_image->GetVolumeData(0), mitk::ImageAccessorBase::ExceptionIfLocked ); - const float* Odf_cPtr = static_cast< const float*>(readAccess.GetData()); - - TensorImageType::IndexType ind; - ind[0] = (int)(index[0]+0.5); - ind[1] = (int)(index[1]+0.5); - ind[2] = (int)(index[2]+0.5); - - // 6 - tensorsize - // remaining computation - standard offset - unsigned int offset_to_data = 6 * (ind[2] * img_dimension[1] * img_dimension[0] + ind[1] * img_dimension[0] + ind[0]); - const float *pixel_data = Odf_cPtr + offset_to_data; - - float tensorelems[6] = { - *(pixel_data ), - *(pixel_data + 1), - *(pixel_data + 2), - *(pixel_data + 3), - *(pixel_data + 4), - *(pixel_data + 5), - }; + mitk::ImagePixelReadAccessor pixel_read(Odf_image, Odf_image->GetVolumeData(0)); + auto tensorelems = pixel_read.GetPixelByIndex(index); TensorPixelType tensor(tensorelems); - odf.InitFromTensor(tensor); + if (!toggle_tensor) + odf.InitFromTensor(tensor); + else + { + odf.InitFromEllipsoid(tensor); + m_OdfNormalization = 1; + } /** Array of eigen-values. */ typedef itk::FixedArray EigenValuesArrayType; /** Matrix of eigen-vectors. */ typedef itk::Matrix EigenVectorsMatrixType; EigenValuesArrayType eigenValues; EigenVectorsMatrixType eigenvectors; - QString pos = QString::number(ind[0])+", "+QString::number(ind[1])+", "+QString::number(ind[2]); + QString pos = QString::number(index[0])+", "+QString::number(index[1])+", "+QString::number(index[2]); overviewText += "Coordinates: "+pos+"\n"; overviewText += "FA: "+QString::number(tensor.GetFractionalAnisotropy())+"\n"; overviewText += "RA: "+QString::number(tensor.GetRelativeAnisotropy())+"\n"; overviewText += "Trace: "+QString::number(tensor.GetTrace())+"\n"; tensor.ComputeEigenAnalysis(eigenValues,eigenvectors); - overviewText += "Eigenvalues:\n "+QString::number(eigenValues[2])+"\n "+QString::number(eigenValues[1])+"\n "+QString::number(eigenValues[0])+"\n"; - overviewText += "Main Diffusion:\n "+QString::number(eigenvectors(2, 0))+"\n "+QString::number(eigenvectors(2, 1))+"\n "+QString::number(eigenvectors(2, 2))+"\n"; - overviewText += "Values:\n "+QString::number(tensorelems[0])+"\n "+QString::number(tensorelems[1])+"\n "+QString::number(tensorelems[2])+"\n "+QString::number(tensorelems[3])+"\n "+QString::number(tensorelems[4])+"\n "+QString::number(tensorelems[5])+"\n "+"\n"; + overviewText += "Eigenvalues:\n "+QString::number(static_cast(eigenValues[2]))+"\n "+QString::number(static_cast(eigenValues[1]))+"\n "+QString::number(static_cast(eigenValues[0]))+"\n"; + overviewText += "Main Diffusion:\n "+QString::number(static_cast(eigenvectors(2, 0)))+"\n "+QString::number(static_cast(eigenvectors(2, 1)))+"\n "+QString::number(static_cast(eigenvectors(2, 2)))+"\n"; + overviewText += "Values:\n "+QString::number(static_cast(tensorelems[0]))+"\n "+QString::number(static_cast(tensorelems[1]))+"\n "+QString::number(static_cast(tensorelems[2]))+"\n "+QString::number(static_cast(tensorelems[3]))+"\n "+QString::number(static_cast(tensorelems[4]))+"\n "+QString::number(static_cast(tensorelems[5]))+"\n "+"\n"; m_Controls->m_OverviewTextEdit->setVisible(true); + + m_Controls->m_ODFDetailsWidget->SetParameters<5000>(odf); + m_Controls->m_ODFRenderWidget->GenerateODF<5000>(odf, m_OdfNormalization, dir_color); + m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str()); } // end pixel access block catch(mitk::Exception &e ) { MITK_WARN << "LOCKED : " << e.what(); m_Controls->m_ODFRenderWidget->setVisible(false); m_Controls->m_OdfBox->setVisible(false); m_Controls->m_OverviewTextEdit->setVisible(false); // reset the selection m_Controls->m_InputImageLabel->setText("Click image to restore rendering!"); } } - else + else if (dynamic_cast(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) ) { - m_Controls->m_ODFRenderWidget->setVisible(false); + itk::OrientationDistributionFunction odf; + m_Controls->m_ODFRenderWidget->setVisible(true); m_Controls->m_OdfBox->setVisible(false); - overviewText += "Please reinit image geometry.\n"; - } - - // proceed only if the render widget is visible which indicates that the - // predecessing computations were successfull - if( m_Controls->m_ODFRenderWidget->isVisible() ) - { - m_Controls->m_ODFDetailsWidget->SetParameters(odf); - switch(m_OdfNormalization) + mitk::ShImage::Pointer Odf_image = dynamic_cast< mitk::ShImage*>(m_ImageNode->GetData()); + mitk::Image::Pointer image = dynamic_cast< mitk::ShImage*>(m_ImageNode->GetData()); + QString coeff_string = ""; + switch (Odf_image->ShOrder()) { - case 0: - odf = odf.MinMaxNormalize(); + case 2: + { + auto img = mitk::convert::GetItkShFromShImage<6>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); break; - case 1: - odf = odf.MaxNormalize(); + } + case 4: + { + auto img = mitk::convert::GetItkShFromShImage<15>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); break; - case 2: - odf = odf.MaxNormalize(); + } + case 6: + { + auto img = mitk::convert::GetItkShFromShImage<28>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); + break; + } + case 8: + { + auto img = mitk::convert::GetItkShFromShImage<45>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); + break; + } + case 10: + { + auto img = mitk::convert::GetItkShFromShImage<66>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); + break; + } + case 12: + { + auto img = mitk::convert::GetItkShFromShImage<91>(image); + auto coeffs = img->GetPixel(index); + for (unsigned int i=0; i(coeffs[i])) + " "; + mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf); break; - default: - odf = odf.MinMaxNormalize(); } + default : + mitkThrow() << "SH order larger 12 not supported"; + } + + for (unsigned int i=0; i(val))+"\n"; + sum += val; + if (val>max) + max = val; + if (valm_ODFRenderWidget->GenerateODF(odf); + float stdev = 0; + for (unsigned int i=0; i(Odf_image->ShOrder()))+"\n"; + overviewText += "Num. Coefficients: "+QString::number(static_cast(Odf_image->NumCoefficients()))+"\n"; + overviewText += "Coefficients: "+coeff_string+"\n"; + overviewText += "GFA: "+QString::number(static_cast(odf.GetGeneralizedFractionalAnisotropy()))+"\n"; + overviewText += "Sum: "+QString::number(static_cast(sum))+"\n"; + overviewText += "Mean: "+QString::number(static_cast(mean))+"\n"; + overviewText += "Stdev: "+QString::number(static_cast(stdev))+"\n"; + overviewText += "Min: "+QString::number(static_cast(min))+"\n"; + overviewText += "Max: "+QString::number(static_cast(max))+"\n"; + vnl_vector_fixed pd = odf.GetDirection(odf.GetPrincipalDiffusionDirectionIndex()); + overviewText += "Main Diffusion:\n "+QString::number(pd[0])+"\n "+QString::number(pd[1])+"\n "+QString::number(pd[2])+"\n"; + + m_Controls->m_OdfValuesTextEdit->setText(values); + m_Controls->m_OverviewTextEdit->setVisible(true); + m_Controls->m_ODFDetailsWidget->SetParameters<5000>(odf); + m_Controls->m_ODFRenderWidget->GenerateODF<5000>(odf, m_OdfNormalization, dir_color); m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str()); } + else + { + m_Controls->m_ODFRenderWidget->setVisible(false); + m_Controls->m_OdfBox->setVisible(false); + overviewText += "Please reinit image geometry.\n"; + } + + } catch(...) { - QMessageBox::critical(0, "Error", "Data could not be analyzed. The image might be corrupted."); + QMessageBox::critical(nullptr, "Error", "Data could not be analyzed. The image might be corrupted."); } } void QmitkODFDetailsView::OnSliceChanged() { UpdateOdf(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h index 26955931f2..8ad5a1020a 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h @@ -1,112 +1,98 @@ /*=================================================================== 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 _QMITKQmitkODFDetailsView_H_INCLUDED #define _QMITKQmitkODFDetailsView_H_INCLUDED #include #include #include "mitkILifecycleAwarePart.h" #include "ui_QmitkODFDetailsViewControls.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*! \brief View displaying details of the orientation distribution function in the voxel at the current crosshair position. */ class QmitkODFDetailsView : public QmitkAbstractView, public mitk::ILifecycleAwarePart { // 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; QmitkODFDetailsView(); virtual ~QmitkODFDetailsView(); typedef mitk::OdfImage::ScalarPixelType TOdfPixelType; typedef mitk::OdfImage::PixelType OdfVectorType; typedef mitk::OdfImage::ItkOdfImageType OdfVectorImgType; typedef mitk::TensorImage::PixelType TensorPixelType; typedef mitk::TensorImage::ItkTensorImageType TensorImageType; virtual void CreateQtPartControl(QWidget *parent) override; protected slots: void OnSliceChanged(); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; virtual void SetFocus() override; virtual void Activated() override; virtual void Deactivated() override; virtual void Visible() override; virtual void Hidden() override; void UpdateOdf(); ///< called if slice position or datamanager selection has changed Ui::QmitkODFDetailsViewControls* m_Controls; - /** ODF related variables like mesh structure, values etc. */ - vtkPolyData* m_TemplateOdf; ///< spherical base mesh - vtkSmartPointer m_OdfTransform; - vtkSmartPointer m_OdfVals; - vtkSmartPointer m_OdfSource; - int m_OdfNormalization; ///< normalization method defined in the visualization view - - /** rendering of the ODF */ - vtkActor* m_VtkActor; - vtkPolyDataMapper* m_VtkMapper; - vtkRenderer* m_Renderer; - vtkRenderWindow* m_VtkRenderWindow; - vtkRenderWindowInteractor* m_RenderWindowInteractor; - vtkCamera* m_Camera; mitk::DataNode::Pointer m_ImageNode; QmitkSliceNavigationListener m_SliceChangeListener; }; #endif // _QmitkODFDetailsView_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui index f25a1adb7b..84a4354f48 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsViewControls.ui @@ -1,259 +1,259 @@ - + QmitkODFDetailsViewControls 0 0 351 734 0 0 QmitkTemplate QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; } 6 9 9 9 9 Please Select Input Data 6 6 6 6 - DTI/ODF: + DTI/ODF/SH: - <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> + <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Overview 6 6 6 6 0 0 0 0 true 0 0 200 200 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 0 ODF Values 6 6 6 6 true 0 0 0 200 Qt::Vertical QSizePolicy::Expanding 20 220 - + QmitkODFDetailsWidget QWidget
QmitkODFDetailsWidget.h
1
QmitkODFRenderWidget QWidget
QmitkODFRenderWidget.h
1
- - -
\ No newline at end of file + + + diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp index d1ddd6c446..b12fb0d210 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp @@ -1,808 +1,808 @@ /*=================================================================== 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 MBILOG_ENABLE_DEBUG #include "QmitkQBallReconstructionView.h" // qt includes #include // itk includes #include "itkTimeProbe.h" // mitk includes #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "QmitkDataStorageComboBox.h" #include "itkDiffusionQballReconstructionImageFilter.h" #include "itkAnalyticalDiffusionQballReconstructionImageFilter.h" #include "itkDiffusionMultiShellQballReconstructionImageFilter.h" #include "itkVectorContainer.h" #include "itkB0ImageExtractionImageFilter.h" #include #include "mitkOdfImage.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include "mitkDiffusionImagingConfigure.h" #include #include "berryIStructuredSelection.h" #include "berryIWorkbenchWindow.h" #include "berryISelectionService.h" #include #include #include #include #include const std::string QmitkQBallReconstructionView::VIEW_ID = "org.mitk.views.qballreconstruction"; typedef float TTensorPixelType; const int QmitkQBallReconstructionView::nrconvkernels = 252; struct QbrShellSelection { typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType; typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType; typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMapType; typedef itk::VectorImage< DiffusionPixelType, 3 > ITKDiffusionImageType; QmitkQBallReconstructionView* m_View; mitk::DataNode * m_Node; std::string m_NodeName; std::vector m_CheckBoxes; QLabel * m_Label; mitk::Image * m_Image; QbrShellSelection(QmitkQBallReconstructionView* view, mitk::DataNode * node) : m_View(view), m_Node(node), m_NodeName(node->GetName()) { m_Image = dynamic_cast (node->GetData()); if(!m_Image) { MITK_ERROR << "QmitkQBallReconstructionView::QbrShellSelection : no image selected"; return; } bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_Node->GetData())) ); if( !isDiffusionImage ) { MITK_ERROR << "QmitkQBallReconstructionView::QbrShellSelection : selected image contains no diffusion information"; return; } GenerateCheckboxes(); } void GenerateCheckboxes() { BValueMapType origMap = mitk::DiffusionPropertyHelper::GetBValueMap(m_Image); BValueMapType::iterator itStart = origMap.begin(); itStart++; BValueMapType::iterator itEnd = origMap.end(); m_Label = new QLabel(m_NodeName.c_str()); m_Label->setVisible(true); m_View->m_Controls->m_QBallSelectionBox->layout()->addWidget(m_Label); for(BValueMapType::iterator it = itStart ; it!= itEnd; it++) { QCheckBox * box = new QCheckBox(QString::number(it->first)); m_View->m_Controls->m_QBallSelectionBox->layout()->addWidget(box); box->setChecked(true); box->setCheckable(true); // box->setVisible(true); m_CheckBoxes.push_back(box); } } void SetVisible(bool vis) { foreach(QCheckBox * box, m_CheckBoxes) { box->setVisible(vis); } } BValueMapType GetBValueSelctionMap() { BValueMapType inputMap = mitk::DiffusionPropertyHelper::GetBValueMap(m_Image); BValueMapType outputMap; unsigned int val = 0; if(inputMap.find(0) == inputMap.end()){ return outputMap; }else{ outputMap[val] = inputMap[val]; } foreach(QCheckBox * box, m_CheckBoxes) { if(box->isChecked()){ val = box->text().toUInt(); outputMap[val] = inputMap[val]; MITK_INFO << val; } } return outputMap; } ~QbrShellSelection() { m_View->m_Controls->m_QBallSelectionBox->layout()->removeWidget(m_Label); delete m_Label; for(std::vector::iterator it = m_CheckBoxes.begin() ; it!= m_CheckBoxes.end(); it++) { m_View->m_Controls->m_QBallSelectionBox->layout()->removeWidget((*it)); delete (*it); } m_CheckBoxes.clear(); } }; QmitkQBallReconstructionView::QmitkQBallReconstructionView() : QmitkAbstractView(), m_Controls(nullptr) { } QmitkQBallReconstructionView::~QmitkQBallReconstructionView() { } void QmitkQBallReconstructionView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkQBallReconstructionViewControls; m_Controls->setupUi(parent); this->CreateConnections(); QStringList items; items << "2" << "4" << "6" << "8" << "10" << "12"; m_Controls->m_QBallReconstructionMaxLLevelComboBox->addItems(items); m_Controls->m_QBallReconstructionMaxLLevelComboBox->setCurrentIndex(1); MethodChoosen(m_Controls->m_QBallReconstructionMethodComboBox->currentIndex()); } } void QmitkQBallReconstructionView::SetFocus() { } void QmitkQBallReconstructionView::CreateConnections() { if ( m_Controls ) { connect( static_cast(m_Controls->m_ButtonStandard), SIGNAL(clicked()), this, SLOT(ReconstructStandard()) ); connect( static_cast(m_Controls->m_QBallReconstructionMethodComboBox), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) ); connect( static_cast(m_Controls->m_QBallReconstructionThreasholdEdit), SIGNAL(valueChanged(int)), this, SLOT(PreviewThreshold(int)) ); connect( static_cast(m_Controls->m_ConvertButton), SIGNAL(clicked()), this, SLOT(ConvertShImage()) ); m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New(); m_Controls->m_ImageBox->SetPredicate( isDwi ); m_Controls->m_ShImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isSh = mitk::TNodePredicateDataType::New(); m_Controls->m_ShImageBox->SetPredicate( isSh ); connect( static_cast(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); connect( static_cast(m_Controls->m_ShImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui())); UpdateGui(); } } void QmitkQBallReconstructionView::ConvertShImage() { if (m_Controls->m_ShImageBox->GetSelectedNode().IsNotNull()) { mitk::Image::Pointer mitkImg = dynamic_cast(m_Controls->m_ShImageBox->GetSelectedNode()->GetData()); auto img = mitk::convert::GetOdfFromShImage(mitkImg); mitk::DataNode::Pointer node= mitk::DataNode::New(); node->SetData( img ); node->SetName(m_Controls->m_ShImageBox->GetSelectedNode()->GetName()); GetDataStorage()->Add(node, m_Controls->m_ShImageBox->GetSelectedNode()); } } void QmitkQBallReconstructionView::UpdateGui() { m_Controls->m_ButtonStandard->setEnabled(false); if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { m_Controls->m_ButtonStandard->setEnabled(true); GenerateShellSelectionUI(m_Controls->m_ImageBox->GetSelectedNode()); } m_Controls->m_ConvertButton->setEnabled(m_Controls->m_ShImageBox->GetSelectedNode().IsNotNull()); } void QmitkQBallReconstructionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& /*nodes*/) { UpdateGui(); } void QmitkQBallReconstructionView::Activated() { } void QmitkQBallReconstructionView::Deactivated() { } void QmitkQBallReconstructionView::Visible() { } void QmitkQBallReconstructionView::Hidden() { } void QmitkQBallReconstructionView::ReconstructStandard() { int index = m_Controls->m_QBallReconstructionMethodComboBox->currentIndex(); switch(index) { case 0: { // Numerical Reconstruct(0,0); break; } case 1: { // Standard Reconstruct(1,0); break; } case 2: { // Solid Angle Reconstruct(1,6); break; } case 3: { // ADC Reconstruct(1,4); break; } case 4: { // Raw Signal Reconstruct(1,5); break; } case 5: { // Q-Ball reconstruction Reconstruct(2,0); break; } } } void QmitkQBallReconstructionView::MethodChoosen(int method) { m_Controls->m_QBallSelectionBox->setHidden(true); - m_Controls->m_OutputCoeffsImage->setHidden(true); + m_Controls->m_OutputOdfImage->setHidden(true); if (method==0) m_Controls->m_ShFrame->setVisible(false); else m_Controls->m_ShFrame->setVisible(true); switch(method) { case 0: m_Controls->m_Description->setText("Numerical recon. (Tuch 2004)"); break; case 1: m_Controls->m_Description->setText("Spherical harmonics recon. (Descoteaux 2007)"); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; case 2: m_Controls->m_Description->setText("SH recon. with solid angle consideration (Aganj 2009)"); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; case 3: m_Controls->m_Description->setText("SH solid angle with non-neg. constraint (Goh 2009)"); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; case 4: m_Controls->m_Description->setText("SH recon. of the plain ADC-profiles"); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; case 5: m_Controls->m_Description->setText("SH recon. of the raw diffusion signal"); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; case 6: m_Controls->m_Description->setText("SH recon. of the multi shell diffusion signal (Aganj 2010)"); m_Controls->m_QBallSelectionBox->setHidden(false); - m_Controls->m_OutputCoeffsImage->setHidden(false); + m_Controls->m_OutputOdfImage->setHidden(false); break; } } void QmitkQBallReconstructionView::Reconstruct(int method, int normalization) { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { if(method == 0) { NumericalQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode(), normalization); } else if(method == 1) { AnalyticalQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode(), normalization); } else if(method == 2) { MultiQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode()); } } } void QmitkQBallReconstructionView::NumericalQBallReconstruction(mitk::DataNode::Pointer node, int normalization) { try { mitk::Image* vols = static_cast(node->GetData()); std::string nodename = node->GetName(); typedef itk::DiffusionQballReconstructionImageFilter QballReconstructionImageFilterType; ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols)); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(vols), itkVectorImagePointer); filter->SetThreshold( static_cast(m_Controls->m_QBallReconstructionThreasholdEdit->value()) ); std::string nodePostfix; switch(normalization) { case 0: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); nodePostfix = "_Numerical_Qball"; break; } case 1: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO_B_VALUE); nodePostfix = "_Numerical_ZeroBvalueNormalization_Qball"; break; } case 2: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO); nodePostfix = "_NumericalQball_ZeroNormalization_Qball"; break; } case 3: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_NONE); nodePostfix = "_NumericalQball_NoNormalization_Qball"; break; } default: { filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD); nodePostfix = "_NumericalQball_Qball"; } } filter->Update(); // ODFs TO DATATREE mitk::OdfImage::Pointer image = mitk::OdfImage::New(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer new_node = mitk::DataNode::New(); new_node->SetData( image ); new_node->SetName(nodename+nodePostfix); mitk::ProgressBar::GetInstance()->Progress(); GetDataStorage()->Add(new_node, node); this->GetRenderWindowPart()->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MITK_INFO << ex ; QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription()); return ; } } void QmitkQBallReconstructionView::AnalyticalQBallReconstruction( mitk::DataNode::Pointer node, int normalization) { try { auto lambda = m_Controls->m_QBallReconstructionLambdaLineEdit->value(); switch(m_Controls->m_QBallReconstructionMaxLLevelComboBox->currentIndex()) { case 0: { TemplatedAnalyticalQBallReconstruction<2>(node, lambda, normalization); break; } case 1: { TemplatedAnalyticalQBallReconstruction<4>(node, lambda, normalization); break; } case 2: { TemplatedAnalyticalQBallReconstruction<6>(node, lambda, normalization); break; } case 3: { TemplatedAnalyticalQBallReconstruction<8>(node, lambda, normalization); break; } case 4: { TemplatedAnalyticalQBallReconstruction<10>(node, lambda, normalization); break; } case 5: { TemplatedAnalyticalQBallReconstruction<12>(node, lambda, normalization); break; } } this->GetRenderWindowPart()->RequestUpdate(); } catch (itk::ExceptionObject &ex) { MITK_INFO << ex; QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription()); return; } } template void QmitkQBallReconstructionView::TemplatedAnalyticalQBallReconstruction(mitk::DataNode* dataNodePointer, double lambda, int normalization) { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); mitk::Image* vols = dynamic_cast(dataNodePointer->GetData()); ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols)); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(vols), itkVectorImagePointer); filter->SetThreshold( static_cast(m_Controls->m_QBallReconstructionThreasholdEdit->value()) ); filter->SetLambda(lambda); std::string nodePostfix; switch(normalization) { case 0: { filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); - nodePostfix = "_SH_Qball"; + nodePostfix = "_Qball"; break; } case 1: { filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO_B_VALUE); - nodePostfix = "_SH_1_Qball"; + nodePostfix = "_1_Qball"; break; } case 2: { filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO); - nodePostfix = "_SH_2_Qball"; + nodePostfix = "_2_Qball"; break; } case 3: { filter->SetNormalizationMethod(FilterType::QBAR_NONE); - nodePostfix = "_SH_3_Qball"; + nodePostfix = "_3_Qball"; break; } case 4: { filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY); nodePostfix = "_AdcProfile"; break; } case 5: { filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL); nodePostfix = "_RawSignal"; break; } case 6: { filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); - nodePostfix = "_SH_CSA_Qball"; + nodePostfix = "_CSA_Qball"; break; } case 7: { filter->SetNormalizationMethod(FilterType::QBAR_NONNEG_SOLID_ANGLE); - nodePostfix = "_SH_NonNegCSA_Qball"; + nodePostfix = "_NonNegCSA_Qball"; break; } default: { filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); } } filter->Update(); - // ODFs TO DATATREE - mitk::OdfImage::Pointer image = mitk::OdfImage::New(); - image->InitializeByItk( filter->GetOutput() ); - image->SetVolume( filter->GetOutput()->GetBufferPointer() ); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( image ); - node->SetName(dataNodePointer->GetName()+nodePostfix); + mitk::Image::Pointer coeffsImage = dynamic_cast(mitk::ShImage::New().GetPointer()); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); - GetDataStorage()->Add(node, dataNodePointer); + mitk::DataNode::Pointer coeffsNode = mitk::DataNode::New(); + coeffsNode->SetData( coeffsImage ); + coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName() + nodePostfix + "_SH") ); + GetDataStorage()->Add(coeffsNode, dataNodePointer); - if(m_Controls->m_OutputCoeffsImage->isChecked()) + // ODFs TO DATATREE + if(m_Controls->m_OutputOdfImage->isChecked()) { - mitk::Image::Pointer coeffsImage = dynamic_cast(mitk::ShImage::New().GetPointer()); - coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); - coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); + mitk::OdfImage::Pointer image = mitk::OdfImage::New(); + image->InitializeByItk( filter->GetOutput() ); + image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + mitk::DataNode::Pointer node=mitk::DataNode::New(); + node->SetData( image ); + node->SetName(dataNodePointer->GetName() + nodePostfix + "_Sampeld"); - mitk::DataNode::Pointer coeffsNode=mitk::DataNode::New(); - coeffsNode->SetData( coeffsImage ); - coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName()+"_SH-Coeffs") ); - GetDataStorage()->Add(coeffsNode, node); + GetDataStorage()->Add(node, coeffsNode); } } void QmitkQBallReconstructionView::MultiQBallReconstruction(mitk::DataNode::Pointer node) { try { auto lambda = m_Controls->m_QBallReconstructionLambdaLineEdit->value(); switch(m_Controls->m_QBallReconstructionMaxLLevelComboBox->currentIndex()) { case 0: { TemplatedMultiQBallReconstruction<2>(lambda, node); break; } case 1: { TemplatedMultiQBallReconstruction<4>(lambda, node); break; } case 2: { TemplatedMultiQBallReconstruction<6>(lambda, node); break; } case 3: { TemplatedMultiQBallReconstruction<8>(lambda, node); break; } case 4: { TemplatedMultiQBallReconstruction<10>(lambda, node); break; } case 5: { TemplatedMultiQBallReconstruction<12>(lambda, node); break; } } } catch (itk::ExceptionObject &ex) { MITK_INFO << ex ; QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription()); return ; } } template void QmitkQBallReconstructionView::TemplatedMultiQBallReconstruction(double lambda, mitk::DataNode* dataNodePointer) { typedef itk::DiffusionMultiShellQballReconstructionImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); std::string nodename; dataNodePointer->GetStringProperty("name",nodename); mitk::Image* dwi = dynamic_cast(dataNodePointer->GetData()); BValueMapType currSelectionMap = m_ShellSelectorMap[dataNodePointer]->GetBValueSelctionMap(); if(currSelectionMap.size() != 4)// || currSelectionMap.find(0) != currSelectionMap.end()) { QMessageBox::information(nullptr, "Reconstruction not possible:" ,QString("Only three equidistant shells are supported. (ImageName: " + QString(nodename.c_str()) + ")")); return; } BValueMapType::reverse_iterator it1 = currSelectionMap.rbegin(); BValueMapType::reverse_iterator it2 = currSelectionMap.rbegin(); ++it2; // Get average distance int avdistance = 0; for(; it2 != currSelectionMap.rend(); ++it1,++it2) avdistance += static_cast(it1->first - it2->first); avdistance /= currSelectionMap.size()-1; // Check if all shells are using the same averae distance it1 = currSelectionMap.rbegin(); it2 = currSelectionMap.rbegin(); ++it2; for(; it2 != currSelectionMap.rend(); ++it1,++it2) { if(avdistance != static_cast(it1->first - it2->first)) { QMessageBox::information(nullptr, "Reconstruction not possible:" ,QString("Selected Shells are not in a equidistant configuration. (ImageName: " + QString(nodename.c_str()) + ")")); return; } } ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); filter->SetBValueMap(m_ShellSelectorMap[dataNodePointer]->GetBValueSelctionMap()); filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer, mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetThreshold( static_cast(m_Controls->m_QBallReconstructionThreasholdEdit->value()) ); filter->SetLambda(lambda); filter->Update(); - // ODFs TO DATATREE - mitk::OdfImage::Pointer image = mitk::OdfImage::New(); - image->InitializeByItk( filter->GetOutput() ); - image->SetVolume( filter->GetOutput()->GetBufferPointer() ); - mitk::DataNode::Pointer node=mitk::DataNode::New(); - node->SetData( image ); - node->SetName(nodename+"_SH_MultiShell_Qball"); + mitk::Image::Pointer coeffsImage = dynamic_cast(mitk::ShImage::New().GetPointer()); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); - GetDataStorage()->Add(node, dataNodePointer); + mitk::DataNode::Pointer coeffsNode=mitk::DataNode::New(); + coeffsNode->SetData( coeffsImage ); + coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName() + "_SH_MultiShell_Qball_SH") ); + GetDataStorage()->Add(coeffsNode, dataNodePointer); - if(m_Controls->m_OutputCoeffsImage->isChecked()) + if(m_Controls->m_OutputOdfImage->isChecked()) { - mitk::Image::Pointer coeffsImage = dynamic_cast(mitk::ShImage::New().GetPointer()); - coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); - coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); + // ODFs TO DATATREE + mitk::OdfImage::Pointer image = mitk::OdfImage::New(); + image->InitializeByItk( filter->GetOutput() ); + image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + mitk::DataNode::Pointer node=mitk::DataNode::New(); + node->SetData( image ); + node->SetName(dataNodePointer->GetName() + "_SH_MultiShell_Qball_Sampled"); - mitk::DataNode::Pointer coeffsNode=mitk::DataNode::New(); - coeffsNode->SetData( coeffsImage ); - coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName()+"_SH-Coeffs") ); - GetDataStorage()->Add(coeffsNode, node); + GetDataStorage()->Add(node, coeffsNode); } } void QmitkQBallReconstructionView::GenerateShellSelectionUI(mitk::DataNode::Pointer node) { std::map tempMap; if(m_ShellSelectorMap.find( node.GetPointer() ) != m_ShellSelectorMap.end()) { tempMap[node.GetPointer()] = m_ShellSelectorMap[node.GetPointer()]; m_ShellSelectorMap.erase(node.GetPointer()); } else { tempMap[node.GetPointer()] = new QbrShellSelection(this, node ); tempMap[node.GetPointer()]->SetVisible(true); } for(std::map::iterator it = m_ShellSelectorMap.begin(); it != m_ShellSelectorMap.end();it ++) { delete it->second; } m_ShellSelectorMap.clear(); m_ShellSelectorMap = tempMap; } void QmitkQBallReconstructionView::PreviewThreshold(short threshold) { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) { mitk::Image* vols = static_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData()); // Extract b0 image ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New(); mitk::CastToItkImage(vols, itkVectorImagePointer); typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filterB0 = FilterType::New(); filterB0->SetInput( itkVectorImagePointer ); filterB0->SetDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(vols)); filterB0->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); typedef itk::Image ImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; // apply threshold ThresholdFilterType::Pointer filterThreshold = ThresholdFilterType::New(); filterThreshold->SetInput(filterB0->GetOutput()); filterThreshold->SetLowerThreshold(threshold); filterThreshold->SetInsideValue(0); filterThreshold->SetOutsideValue(1); // mark cut off values red filterThreshold->Update(); mitkImage->InitializeByItk( filterThreshold->GetOutput() ); mitkImage->SetVolume( filterThreshold->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node; if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_ImageBox->GetSelectedNode())) { node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_ImageBox->GetSelectedNode()); } else { // create a new node, to show thresholded values node = mitk::DataNode::New(); GetDataStorage()->Add( node, m_Controls->m_ImageBox->GetSelectedNode() ); node->SetProperty( "name", mitk::StringProperty::New("ThresholdOverlay")); node->SetBoolProperty("helper object", true); } node->SetData( mitkImage ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui index 9ef1097384..d73a88cf59 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionViewControls.ui @@ -1,424 +1,424 @@ QmitkQBallReconstructionViewControls 0 0 372 844 0 0 true QmitkQBallReconstructionViewControls QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; } 25 Parameters 6 6 6 6 2 Numerical Standard Solid Angle ADC-Profile only Raw Signal only Multi-Shell TextLabel QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 true Regularization Parameter Lambda: false Regularization factor 3 1.000000000000000 0.001000000000000 0.006000000000000 true SH-Order: false true -1 true B0 Threshold false 10000 - + - Output SH-Coefficient Image + Output Sampled ODF Image false false Start Reconstruction Input Data 6 6 6 6 Input for Q-Ball reconstruction. Raw DWI: true Qt::LeftToRight false Multi-Shell Reconstruction 6 6 6 6 Qt::Vertical 20 0 Convert SH to sampled ODF image 6 6 6 6 false Convert QFrame::NoFrame QFrame::Raised 0 0 0 0 Input for Q-Ball reconstruction. SH Image: QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h