16 #include <vnl/vnl_cross.h>
17 #include <vnl/vnl_quaternion.h>
19 #include <boost/math/special_functions.hpp>
22 #include <itkDiffusionTensor3DReconstructionImageFilter.h>
32 template<
class ScalarType >
36 , m_MaxNumKernels(1000)
46 template<
class ScalarType >
52 template<
class ScalarType >
55 m_ShCoefficients.clear();
56 m_PrototypeMaxDirection.clear();
60 template<
class ScalarType >
63 m_ModelIndex = this->m_RandGen->GetIntegerVariate(m_B0Signal.size()-1);
66 template<
class ScalarType >
69 return m_B0Signal.size();
72 template<
class ScalarType >
78 typedef itk::VectorImage<short, 3> ITKDiffusionImageType;
82 const int shOrder = 2;
84 if (tensorImage.IsNull())
86 typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType;
92 tensorImage = filter->GetOutput();
95 const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder;
96 if (itkFeatureImage.IsNull())
101 qballfilter->SetLambda(0.006);
102 qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL);
103 qballfilter->Update();
104 itkFeatureImage = qballfilter->GetCoefficientImage();
107 if (adcImage.IsNull())
110 adcFilter->SetInput(itkVectorImagePointer);
114 adcImage = adcFilter->GetOutput();
127 itk::ImageRegionIterator< itk::VectorImage< short, 3 > > it(itkVectorImagePointer, itkVectorImagePointer->GetLargestPossibleRegion());
130 if (maskImage.IsNotNull() && maskImage->GetPixel(it.GetIndex())<=0)
135 if (it.Get()[b0Index]>
max)
136 max = it.Get()[b0Index];
142 unsigned int count = 0;
143 itk::ImageRegionIterator< itk::Image< itk::DiffusionTensor3D< double >, 3 > > it(tensorImage, tensorImage->GetLargestPossibleRegion());
146 bool skipPixel =
false;
147 if (maskImage.IsNotNull() && maskImage->GetPixel(it.GetIndex())<=0)
154 if (itkVectorImagePointer->GetPixel(it.GetIndex())[i]!=itkVectorImagePointer->GetPixel(it.GetIndex())[i] || itkVectorImagePointer->GetPixel(it.GetIndex())[i]<=0 || itkVectorImagePointer->GetPixel(it.GetIndex())[i]>itkVectorImagePointer->GetPixel(it.GetIndex())[b0Index])
166 typedef itk::DiffusionTensor3D<double> TensorType;
167 TensorType::EigenValuesArrayType eigenvalues;
168 TensorType::EigenVectorsMatrixType eigenvectors;
169 TensorType tensor = it.Get();
170 double FA = tensor.GetFractionalAnisotropy();
171 double ADC = adcImage->GetPixel(it.GetIndex());
173 vnl_vector_fixed< double, NumCoeffs > coeffs;
174 for (
unsigned int c=0; c<itkv.Size(); c++)
175 coeffs[c] = itkv[c]/max;
177 if ( this->GetMaxNumKernels()>this->GetNumberOfKernels() && FA>m_FaRange.first && FA<m_FaRange.second && ADC>m_AdcRange.first && ADC<m_AdcRange.second)
179 if (this->SetShCoefficients( coeffs, (
double)itkVectorImagePointer->GetPixel(it.GetIndex())[b0Index]/max ))
181 tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
182 itk::Vector<double,3> dir;
183 dir[0] = eigenvectors(2, 0);
184 dir[1] = eigenvectors(2, 1);
185 dir[2] = eigenvectors(2, 2);
186 m_PrototypeMaxDirection.push_back(dir);
188 MITK_INFO <<
"KERNEL: " << it.GetIndex() <<
" (" << count <<
")";
194 if (m_ShCoefficients.size()>0)
200 template<
class ScalarType >
203 m_SphCoords.set_size(gradients.size(), 2);
204 m_SphCoords.fill(0.0);
206 for (
unsigned int i=0; i<gradients.size(); i++)
209 if( g.GetNorm() > 0.0001 )
211 gradients[i].Normalize();
212 m_SphCoords(i,0) = acos(gradients[i][2]);
213 m_SphCoords(i,1) = atan2(gradients[i][1], gradients[i][0]);
218 template<
class ScalarType >
221 this->m_FiberDirection = fiberDirection;
222 this->m_FiberDirection.Normalize();
225 GradientType axis = itk::CrossProduct(this->m_FiberDirection, m_PrototypeMaxDirection.at(m_ModelIndex));
228 vnl_quaternion<double>
rotation(axis.GetVnlVector(), acos(dot_product(this->m_FiberDirection.GetVnlVector(), m_PrototypeMaxDirection.at(m_ModelIndex).GetVnlVector())));
232 for (
unsigned int i=0; i<this->m_GradientList.size(); i++)
235 if( dir.GetNorm() > 0.0001 )
238 vnl_vector_fixed< double, 3 > vnlDir =
rotation.rotate(dir.GetVnlVector());
239 dir[0] = vnlDir[0]; dir[1] = vnlDir[1]; dir[2] = vnlDir[2];
242 gradients.push_back(dir);
245 Cart2Sph( gradients );
248 template<
class ScalarType >
252 while ( (m_ShOrder*m_ShOrder + m_ShOrder + 2)/2 + m_ShOrder <= shCoefficients.size() )
256 m_ModelIndex = m_B0Signal.size();
257 m_B0Signal.push_back(b0);
258 m_ShCoefficients.push_back(shCoefficients);
292 Cart2Sph( this->m_GradientList );
298 template<
class ScalarType >
303 if (m_ModelIndex==-1)
306 if (dir>=this->m_GradientList.size())
309 int j, m;
double mag, plm;
311 if (this->m_GradientList[dir].GetNorm()>0.001)
314 for (
int l=0; l<=m_ShOrder; l=l+2)
315 for (m=-l; m<=l; m++)
317 plm = legendre_p<double>(l,abs(m),cos(m_SphCoords(dir,0)));
318 mag = sqrt((
double)(2*l+1)/(4.0*
M_PI)*factorial<double>(l-abs(m))/factorial<double>(l+abs(m)))*plm;
322 basis = sqrt(2.0)*mag*cos(fabs((
double)m)*m_SphCoords(dir,1));
326 basis = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*m_SphCoords(dir,1));
328 signal += m_ShCoefficients.at(m_ModelIndex)[j]*basis;
333 signal = m_B0Signal.at(m_ModelIndex);
340 template<
class ScalarType >
343 if (m_ModelIndex==-1)
347 signal.SetSize(this->m_GradientList.size());
349 int M = this->m_GradientList.size();
350 int j, m;
double mag, plm;
352 vnl_matrix< double > shBasis;
353 shBasis.set_size(M, m_ShCoefficients.at(m_ModelIndex).size());
356 for (
int p=0; p<M; p++)
358 if (this->m_GradientList[p].GetNorm()>0.001)
361 for (
int l=0; l<=m_ShOrder; l=l+2)
362 for (m=-l; m<=l; m++)
364 plm = legendre_p<double>(l,abs(m),cos(m_SphCoords(p,0)));
365 mag = sqrt((
double)(2*l+1)/(4.0*
M_PI)*factorial<double>(l-abs(m))/factorial<double>(l+abs(m)))*plm;
368 shBasis(p,j) = sqrt(2.0)*mag*cos(fabs((
double)m)*m_SphCoords(p,1));
372 shBasis(p,j) = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*m_SphCoords(p,1));
379 for (
unsigned int cidx=0; cidx<m_ShCoefficients.at(m_ModelIndex).size(); cidx++)
380 val += m_ShCoefficients.at(m_ModelIndex)[cidx]*shBasis(p,cidx);
384 signal[p] = m_B0Signal.at(m_ModelIndex);
bool SetShCoefficients(vnl_vector< double > shCoefficients, double b0)
static const std::string REFERENCEBVALUEPROPERTYNAME
void Cart2Sph(GradientListType gradients)
itk::SmartPointer< Self > Pointer
PixelType SimulateMeasurement()
bool SampleKernels(Image::Pointer diffImg, ItkUcharImageType::Pointer maskImage, TensorImageType::Pointer tensorImage=NULL, QballFilterType::CoefficientImageType::Pointer coeffImage=NULL, ItkDoubleImageType::Pointer adcImage=NULL)
void SetFiberDirection(GradientType fiberDirection)
DataCollection - Class to facilitate loading/accessing structured data.
ItkRandGenType::Pointer m_RandGen
Random number generator.
unsigned int GetNumberOfKernels()
std::vector< GradientType > GradientListType
itk::Vector< double, 3 > GradientType
std::pair< double, double > m_AdcRange
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
std::pair< double, double > m_FaRange
static const std::string GRADIENTCONTAINERPROPERTYNAME
static const std::string ORIGINALGRADIENTCONTAINERPROPERTYNAME
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.