3 #include <itkSymmetricEigenAnalysis.h> 17 quadForm += m_DiffusionTensor(i,i) * gradient[i] * gradient[i];
19 quadForm += 2 * m_DiffusionTensor(i,j) * gradient[i] * gradient[j];
24 return std::exp(- bValue * quadForm);
37 double DgTe1DTheta = m_CosTheta * (gradient[0] * m_CosPhi + gradient[1] * m_SinPhi) - gradient[2] * m_SinTheta;
38 double DgTe1DPhi = m_SinTheta * (gradient[1] * m_CosPhi - gradient[0] * m_SinPhi);
40 double DgTe2DTheta = m_SinAlpha * innerProd1;
41 double DgTe2DPhi = gradient[0] * (m_CosTheta * m_SinPhi * m_SinAlpha - m_CosPhi * m_CosAlpha) - gradient[1] * (m_SinPhi * m_CosAlpha + m_CosTheta * m_CosPhi * m_SinAlpha);
42 double DgTe2DAlpha = gradient[0] * (m_SinPhi * m_SinAlpha - m_CosTheta * m_CosPhi * m_CosAlpha) - gradient[1] * (m_CosPhi * m_SinAlpha + m_CosTheta * m_SinPhi * m_CosAlpha) + gradient[2] * m_SinTheta * m_CosAlpha;
49 m_JacobianVector[0] = -2.0 * bValue * (diffAxialRadial2 * innerProd1 * DgTe1DTheta + diffRadialDiffusivities * innerProd2 * DgTe2DTheta) * signalAttenuation;
52 m_JacobianVector[1] = -2.0 * bValue * (diffAxialRadial2 * innerProd1 * DgTe1DPhi + diffRadialDiffusivities * innerProd2 * DgTe2DPhi) * signalAttenuation;
55 m_JacobianVector[2] = -2.0 * bValue * diffRadialDiffusivities * innerProd2 * DgTe2DAlpha * signalAttenuation;
57 if (m_EstimateDiffusivities)
60 m_JacobianVector[3] = - bValue * innerProd1 * innerProd1 * signalAttenuation;
63 m_JacobianVector[4] = - bValue * (innerProd1 * innerProd1 + innerProd2 * innerProd2) * signalAttenuation;
66 m_JacobianVector[5] = - bValue * signalAttenuation;
76 double resVal = - 1.5 * std::log(2.0 * M_PI) - 0.5 * std::log(m_TensorDeterminant);
82 quadForm += m_InverseDiffusionTensor(i,i) * sample[i] * sample[i];
84 quadForm += 2 * m_InverseDiffusionTensor(i,j) * sample[i] * sample[j];
87 resVal -= quadForm / 2.0;
96 m_ModifiedTensor =
true;
97 m_ModifiedAngles =
true;
112 m_ModifiedTensor =
true;
113 m_ModifiedAngles =
true;
128 m_ModifiedTensor =
true;
129 m_ModifiedAngles =
true;
144 m_ModifiedTensor =
true;
159 m_ModifiedTensor =
true;
174 m_ModifiedTensor =
true;
194 if (m_EstimateDiffusivities)
210 if (m_EstimateDiffusivities)
225 if (m_EstimateDiffusivities)
242 if (m_EstimateDiffusivities)
254 if (m_EstimateDiffusivities == arg)
257 m_EstimateDiffusivities = arg;
258 m_ChangedConstraints =
true;
264 itkExceptionMacro(
"The input vector size does not match the size of the compartment");
267 m_DiffusionTensor = m_WorkVnlMatrix1;
269 m_TensorDeterminant = vnl_determinant <double> (m_WorkVnlMatrix1);
271 if (m_TensorDeterminant <= 0)
272 m_TensorDeterminant = 0;
274 m_ModifiedTensor =
false;
275 m_ModifiedAngles =
false;
276 m_UpdateInverseTensor =
true;
277 m_UpdatedCompartment =
true;
282 if (!m_UpdatedCompartment)
288 itk::SymmetricEigenAnalysis < Matrix3DType,vnl_diag_matrix <double>,vnl_matrix <double> > eigSys(
m_SpaceDimension);
290 eigSys.ComputeEigenValuesAndVectors(m_DiffusionTensor,eVals,eVecs);
299 double theta = sphDir[0];
300 double phi = sphDir[1];
303 if ((theta != 0)&&(theta != M_PI))
304 alpha = std::atan2(eVecs(1,2),- eVecs(0,2));
309 alpha = std::atan2(1 - eVecs(1,0), eVecs(1,1));
310 phi = alpha - M_PI / 2.0;
319 m_UpdatedCompartment =
false;
341 if (!m_ChangedConstraints)
342 return m_NumberOfParameters;
346 if (!m_EstimateDiffusivities)
347 m_NumberOfParameters -= 3;
349 m_ChangedConstraints =
false;
350 return m_NumberOfParameters;
368 m_WorkVnlMatrix1 = m_DiffusionTensor.GetVnlMatrix().as_matrix();
370 if (!affineTransform)
375 vnl_matrix <double> ppdOrientationMatrix(3,3);
376 typedef itk::Matrix <double, 3, 3> EigVecMatrixType;
377 typedef vnl_vector_fixed <double,3> EigValVectorType;
378 itk::SymmetricEigenAnalysis < EigVecMatrixType, EigValVectorType, EigVecMatrixType> eigenComputer(3);
379 EigVecMatrixType eigVecs;
380 EigValVectorType eigVals;
382 eigenComputer.ComputeEigenValuesAndVectors(m_WorkVnlMatrix1,eigVals,eigVecs);
396 return m_DiffusionTensor;
401 if (!m_ModifiedTensor)
409 m_DiffusionTensor.Fill(0.0);
412 m_DiffusionTensor(i,i) = radialDiff2;
417 m_DiffusionTensor(i,j) += m_EigenVector1[i] * m_EigenVector1[j] * (axialDiff - radialDiff2);
418 m_DiffusionTensor(i,j) += m_EigenVector2[i] * m_EigenVector2[j] * (radialDiff1 - radialDiff2);
421 m_DiffusionTensor(j,i) = m_DiffusionTensor(i,j);
424 m_TensorDeterminant = axialDiff * radialDiff1 * radialDiff2;
426 m_UpdateInverseTensor =
true;
427 m_ModifiedTensor =
false;
434 if (!m_UpdateInverseTensor)
437 if (m_TensorDeterminant == 0.0)
439 m_InverseDiffusionTensor.Fill(0.0);
440 m_UpdateInverseTensor =
false;
445 m_WorkVnlMatrix1 = m_DiffusionTensor.GetVnlMatrix().as_matrix();
446 m_leCalculator->GetTensorPower(m_WorkVnlMatrix1, m_WorkVnlMatrix2, -1.0);
447 m_InverseDiffusionTensor = m_WorkVnlMatrix2;
449 m_UpdateInverseTensor =
false;
454 if (!m_ModifiedAngles)
464 m_EigenVector1[0] = m_SinTheta * m_CosPhi;
465 m_EigenVector1[1] = m_SinTheta * m_SinPhi;
466 m_EigenVector1[2] = m_CosTheta;
468 m_EigenVector2[0] = -1.0 * (m_CosTheta * m_CosPhi * m_SinAlpha + m_SinPhi * m_CosAlpha);
469 m_EigenVector2[1] = m_CosPhi * m_CosAlpha - m_CosTheta * m_SinPhi * m_SinAlpha;
470 m_EigenVector2[2] = m_SinTheta * m_SinAlpha;
472 m_ModifiedAngles =
false;
481 double numFA = std::sqrt ((l1 - l2) * (l1 - l2) + (l2 - l3) * (l2 - l3) + (l3 - l1) * (l3 - l1));
482 double denomFA = std::sqrt (l1 * l1 + l2 * l2 + l3 * l3);
486 fa = std::sqrt(0.5) * (numFA / denomFA);
497 return (l1 + l2 + l3) / 3.0;
void SetAxialDiffusivity(double num) ITK_OVERRIDE
void UpdateParametersFromTensor()
const double MCMZeroLowerBound
Default zero lower bound (in case we want something else than zero one day)
std::vector< double > ListType
virtual void SetAxialDiffusivity(double num)
double GetPerpendicularAngle() ITK_OVERRIDE
ListType m_ParametersLowerBoundsVector
Vector holding current parameters lower bounds.
virtual double GetFourierTransformedDiffusionProfile(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) ITK_OVERRIDE
Superclass::ModelOutputVectorType ModelOutputVectorType
Superclass::Vector3DType Vector3DType
const double MCMAzimuthAngleUpperBound
Azimuth angle upper bound.
virtual ListType & GetSignalAttenuationJacobian(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) ITK_OVERRIDE
virtual void SetRadialDiffusivity2(double num)
void SetOrientationTheta(double num) ITK_OVERRIDE
virtual void SetParametersFromVector(const ListType ¶ms) ITK_OVERRIDE
Various methods for optimization parameters setting and getting.
virtual double GetOrientationPhi()
virtual ListType & GetParameterUpperBounds() ITK_OVERRIDE
void UpdateDiffusionTensor()
Update diffusion tensor value from parameters.
virtual double GetLogDiffusionProfile(const Vector3DType &sample) ITK_OVERRIDE
virtual void SetRadialDiffusivity1(double num)
void SetRadialDiffusivity1(double num) ITK_OVERRIDE
double GetApparentParallelDiffusivity() ITK_OVERRIDE
Get approximation to parallel diffusivity of the compartment (may be different from axial diffusivity...
void Reorient(vnl_matrix< double > &orientationMatrix, bool affineTransform) ITK_OVERRIDE
Reorient the fascicle compartment using a matrix, the flag specifies if the transform is affine or ri...
void SetOrientationPhi(double num) ITK_OVERRIDE
virtual void SetPerpendicularAngle(double num)
virtual double GetAxialDiffusivity()
const double MCMRadialDiffusivityUpperBound
Radial diffusivity upper bound.
ListType m_ParametersVector
Vector holding current parameters vector.
virtual double GetPerpendicularAngle()
double GetBValueFromAcquisitionParameters(double smallDelta, double bigDelta, double gradientStrength)
Given gyromagnetic ratio in rad/s/T, gradient strength in T/mm and deltas in s, computes b-value in s...
void SetEstimateDiffusivities(bool arg)
virtual double GetOrientationTheta()
const double MCMPolarAngleUpperBound
Polar angle upper bound (used in tensor for now)
void GetVectorRepresentation(const vnl_matrix< T1 > &tensor, itk::VariableLengthVector< T2 > &vector, unsigned int vecDim=0, bool scale=false)
void SetPerpendicularAngle(double num) ITK_OVERRIDE
unsigned int GetCompartmentSize() ITK_OVERRIDE
Number of parameters to describe the model, these parameters will be self-contained, i.e. include fixed parameters for example.
void RotateSymmetricMatrix(T1 &tensor, T2 &rotationMatrix, T3 &rotated_tensor, unsigned int tensorDim)
Rotates a symmetric matrix by performing R^T D R where R is a rotation matrix and D the symmetric mat...
const Matrix3DType & GetDiffusionTensor() ITK_OVERRIDE
Get compartment as a 3D tensor (default behavior: throw exception if not supported by the compartment...
virtual void SetOrientationTheta(double num)
double GetOrientationTheta() ITK_OVERRIDE
void GetTensorFromVectorRepresentation(const itk::VariableLengthVector< T1 > &vector, vnl_matrix< T2 > &tensor, unsigned int tensDim=0, bool scale=false)
unsigned int GetNumberOfParameters() ITK_OVERRIDE
Number of optimized parameters: smaller than total number of parameters.
ListType m_ParametersUpperBoundsVector
Vector holding current parameters upper bounds.
ModelOutputVectorType & GetCompartmentVector() ITK_OVERRIDE
Get compartment overall description vector, mainly for writing, should be self-contained.
void UpdateInverseDiffusionTensor()
Update inverse diffusion tensor value from parameters.
double GetOrientationPhi() ITK_OVERRIDE
Superclass::Matrix3DType Matrix3DType
double GetApparentPerpendicularDiffusivity() ITK_OVERRIDE
Get approximation to perpendicular diffusivity of the compartment (may be different from radial diffu...
virtual double GetRadialDiffusivity2()
double GetApparentFractionalAnisotropy() ITK_OVERRIDE
ListType m_JacobianVector
Vector holding current jacobian value.
double GetRadialDiffusivity1() ITK_OVERRIDE
void SetRadialDiffusivity2(double num) ITK_OVERRIDE
const double MCMDiffusivityUpperBound
Diffusivity upper bound.
virtual double GetRadialDiffusivity1()
double GetAxialDiffusivity() ITK_OVERRIDE
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
virtual ListType & GetParametersAsVector() ITK_OVERRIDE
virtual void SetOrientationPhi(double num)
const double MCMDiffusivityLowerBound
Diffusivity lower bound for estimation.
void SetCompartmentVector(ModelOutputVectorType &compartmentVector) ITK_OVERRIDE
Set compartment overall description vector, for setting automatically the individual parameters when ...
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)
void UpdateAngleConfiguration()
Update angles' sine and cosine values from parameters.
ModelOutputVectorType m_CompartmentVector
Vector to hold working value of compartment vector.
static const unsigned int m_SpaceDimension
void ExtractPPDRotationFromJacobianMatrix(vnl_matrix< RealType > &jacobianMatrix, vnl_matrix< RealType > &rotationMatrix, MatrixType &eigenVectors)
double GetApparentMeanDiffusivity() ITK_OVERRIDE
const double MCMAxialDiffusivityAddonLowerBound
Axial diffusivity add on to lower bound (used to ensure a minimal anisotropy to the anisotropic compa...
double GetRadialDiffusivity2() ITK_OVERRIDE
virtual ListType & GetParameterLowerBounds() ITK_OVERRIDE