ANIMA  4.0
animaStickCompartment.cxx
Go to the documentation of this file.
2 
4 #include <itkSymmetricEigenAnalysis.h>
5 #include <animaMCMConstants.h>
6 
7 namespace anima
8 {
9 
10 double StickCompartment::GetFourierTransformedDiffusionProfile(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient)
11 {
12  m_GradientEigenvector1 = gradient[0] * std::sin(this->GetOrientationTheta()) * std::cos(this->GetOrientationPhi())
13  + gradient[1] * std::sin(this->GetOrientationTheta()) * std::sin(this->GetOrientationPhi())
14  + gradient[2] * std::cos(this->GetOrientationTheta());
15 
16  double bValue = anima::GetBValueFromAcquisitionParameters(smallDelta, bigDelta, gradientStrength);
17  return std::exp(-bValue * (this->GetRadialDiffusivity1() + (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
18  * m_GradientEigenvector1 * m_GradientEigenvector1));
19 }
20 
21 StickCompartment::ListType &StickCompartment::GetSignalAttenuationJacobian(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient)
22 {
24  double bValue = anima::GetBValueFromAcquisitionParameters(smallDelta, bigDelta, gradientStrength);
25 
26  double signalAttenuation = this->GetFourierTransformedDiffusionProfile(smallDelta, bigDelta, gradientStrength, gradient);
27 
28  // Derivative w.r.t. theta
29  m_JacobianVector[0] = -2.0 * bValue * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
30  * (gradient[0] * std::cos(this->GetOrientationTheta()) * std::cos(this->GetOrientationPhi())
31  + gradient[1] * std::cos(this->GetOrientationTheta()) * std::sin(this->GetOrientationPhi())
32  - gradient[2] * std::sin(this->GetOrientationTheta())) * m_GradientEigenvector1 * signalAttenuation;
33 
34  // Derivative w.r.t. phi
35  m_JacobianVector[1] = -2.0 * bValue * std::sin(this->GetOrientationTheta()) * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
36  * (gradient[1] * std::cos(this->GetOrientationPhi()) - gradient[0] * std::sin(this->GetOrientationPhi()))
37  * m_GradientEigenvector1 * signalAttenuation;
38 
39  if (m_EstimateAxialDiffusivity)
40  {
41  // Derivative w.r.t. to d1
42  m_JacobianVector[2] = -bValue * m_GradientEigenvector1 * m_GradientEigenvector1 * signalAttenuation;
43  }
44 
45  return m_JacobianVector;
46 }
47 
49 {
50  Vector3DType compartmentOrientation(0.0);
52 
53  double scalarProduct = anima::ComputeScalarProduct(compartmentOrientation,sample);
54 
55  double resVal = - 1.5 * std::log(2.0 * M_PI) - 0.5 * std::log(this->GetAxialDiffusivity()) - std::log(this->GetRadialDiffusivity1());
56 
57  resVal -= (sample.squared_magnitude() - (1.0 - this->GetRadialDiffusivity1() / this->GetAxialDiffusivity()) * scalarProduct * scalarProduct) / (2.0 * this->GetRadialDiffusivity1());
58 
59  return resVal;
60 }
61 
63 {
64  if (params.size() != this->GetNumberOfParameters())
65  return;
66 
67  this->SetOrientationTheta(params[0]);
68  this->SetOrientationPhi(params[1]);
69 
70  if (m_EstimateAxialDiffusivity)
71  this->SetAxialDiffusivity(params[2] + this->GetRadialDiffusivity1());
72 }
73 
75 {
77 
80 
81  if (m_EstimateAxialDiffusivity)
83 
84  return m_ParametersVector;
85 }
86 
88 {
91 
92  if (m_EstimateAxialDiffusivity)
94 
96 }
97 
99 {
101 
104 
105  if (m_EstimateAxialDiffusivity)
107 
109 }
110 
112 {
113  if (m_EstimateAxialDiffusivity == arg)
114  return;
115 
116  m_EstimateAxialDiffusivity = arg;
117  m_ChangedConstraints = true;
118 }
119 
121 {
122  if (compartmentVector.GetSize() != this->GetCompartmentSize())
123  itkExceptionMacro("The input vector size does not match the size of the compartment");
124 
125  Matrix3DType tensor, eVecs;
126  vnl_diag_matrix <double> eVals(m_SpaceDimension);
127  itk::SymmetricEigenAnalysis <Matrix3DType,vnl_diag_matrix <double>,Matrix3DType> eigSys(m_SpaceDimension);
128 
129  unsigned int pos = 0;
130  for (unsigned int i = 0;i < m_SpaceDimension;++i)
131  {
132  for (unsigned int j = 0;j <= i;++j)
133  {
134  tensor(i,j) = compartmentVector[pos];
135 
136  if (i != j)
137  tensor(j,i) = compartmentVector[pos];
138 
139  ++pos;
140  }
141  }
142 
143  eigSys.ComputeEigenValuesAndVectors(tensor,eVals,eVecs);
144 
145  Vector3DType compartmentOrientation, sphDir;
146 
147  for (unsigned int i = 0;i < m_SpaceDimension;++i)
148  compartmentOrientation[i] = eVecs(2,i);
149 
150  anima::TransformCartesianToSphericalCoordinates(compartmentOrientation,sphDir);
151 
152  this->SetOrientationTheta(sphDir[0]);
153  this->SetOrientationPhi(sphDir[1]);
154  this->SetAxialDiffusivity(eVals(2));
155  this->SetRadialDiffusivity1((eVals(1) + eVals(0)) / 2.0);
156 }
157 
159 {
160  return 6;
161 }
162 
164 {
165  if (!m_ChangedConstraints)
166  return m_NumberOfParameters;
167 
168  // The number of parameters is three: two orientations plus one axial diffusivity
169  m_NumberOfParameters = 3;
170 
171  if (!m_EstimateAxialDiffusivity)
172  --m_NumberOfParameters;
173 
174  m_ChangedConstraints = false;
175  return m_NumberOfParameters;
176 }
177 
179 {
180  if (m_CompartmentVector.GetSize() != this->GetCompartmentSize())
181  m_CompartmentVector.SetSize(this->GetCompartmentSize());
182 
183  Vector3DType compartmentOrientation(0.0);
185 
186  unsigned int pos = 0;
187  for (unsigned int i = 0;i < m_SpaceDimension;++i)
188  {
189  for (unsigned int j = 0;j <= i;++j)
190  {
191  m_CompartmentVector[pos] = (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1()) * compartmentOrientation[i] * compartmentOrientation[j];
192 
193  if (i == j)
195 
196  ++pos;
197  }
198  }
199 
200  return m_CompartmentVector;
201 }
202 
204 {
205  m_DiffusionTensor.Fill(0);
206 
207  for (unsigned int i = 0;i < m_SpaceDimension;++i)
209 
210  Vector3DType compartmentOrientation(0.0);
212 
213  for (unsigned int i = 0;i < m_SpaceDimension;++i)
214  for (unsigned int j = i;j < m_SpaceDimension;++j)
215  {
216  m_DiffusionTensor(i,j) += compartmentOrientation[i] * compartmentOrientation[j] * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1());
217  if (i != j)
219  }
220 
221  return m_DiffusionTensor;
222 }
223 
225 {
226  double l1 = this->GetAxialDiffusivity();
227  double l2 = this->GetRadialDiffusivity1();
228  double numFA = std::sqrt (2.0 * (l1 - l2) * (l1 - l2));
229  double denomFA = std::sqrt (l1 * l1 + 2.0 * l2 * l2);
230 
231  double fa = 0;
232  if (denomFA != 0.0)
233  fa = std::sqrt(0.5) * (numFA / denomFA);
234 
235  return fa;
236 }
237 
239 {
240  double l1 = this->GetAxialDiffusivity();
241  double l2 = this->GetRadialDiffusivity1();
242 
243  return (l1 + 2.0 * l2) / 3.0;
244 }
245 
247 {
248  return this->GetAxialDiffusivity();
249 }
250 
252 {
253  return this->GetRadialDiffusivity1();
254 }
255 
256 } //end namespace anima
257 
double GetApparentPerpendicularDiffusivity() ITK_OVERRIDE
Get approximation to perpendicular diffusivity of the compartment (may be different from radial diffu...
const double MCMZeroLowerBound
Default zero lower bound (in case we want something else than zero one day)
virtual ListType & GetParametersAsVector() ITK_OVERRIDE
std::vector< double > ListType
void TransformSphericalToCartesianCoordinates(const VectorType &v, VectorType &resVec)
virtual void SetAxialDiffusivity(double num)
ListType m_ParametersLowerBoundsVector
Vector holding current parameters lower bounds.
unsigned int GetNumberOfParameters() ITK_OVERRIDE
Number of optimized parameters: smaller than total number of parameters.
const double MCMAzimuthAngleUpperBound
Azimuth angle upper bound.
void SetCompartmentVector(ModelOutputVectorType &compartmentVector) ITK_OVERRIDE
Set compartment overall description vector, for setting automatically the individual parameters when ...
virtual ListType & GetParameterUpperBounds() ITK_OVERRIDE
virtual double GetLogDiffusionProfile(const Vector3DType &sample) ITK_OVERRIDE
ModelOutputVectorType & GetCompartmentVector() ITK_OVERRIDE
Get compartment overall description vector, mainly for writing, should be self-contained.
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.
virtual double GetOrientationPhi()
virtual void SetRadialDiffusivity1(double num)
virtual ListType & GetParameterLowerBounds() ITK_OVERRIDE
const Matrix3DType & GetDiffusionTensor() ITK_OVERRIDE
Get compartment as a 3D tensor (default behavior: throw exception if not supported by the compartment...
virtual double GetAxialDiffusivity()
ListType m_ParametersVector
Vector holding current parameters vector.
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...
virtual double GetOrientationTheta()
const double MCMPolarAngleUpperBound
Polar angle upper bound (used in tensor for now)
Superclass::Matrix3DType Matrix3DType
virtual void SetOrientationTheta(double num)
ListType m_ParametersUpperBoundsVector
Vector holding current parameters upper bounds.
virtual double GetFourierTransformedDiffusionProfile(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) ITK_OVERRIDE
ListType m_JacobianVector
Vector holding current jacobian value.
const double MCMDiffusivityUpperBound
Diffusivity upper bound.
virtual double GetRadialDiffusivity1()
void SetEstimateAxialDiffusivity(bool arg)
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
virtual void SetOrientationPhi(double num)
double GetApparentMeanDiffusivity() ITK_OVERRIDE
Superclass::ModelOutputVectorType ModelOutputVectorType
Matrix3DType m_DiffusionTensor
Matrix to hold working value of diffusion tensor approximation to the model.
Superclass::Vector3DType Vector3DType
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)
ModelOutputVectorType m_CompartmentVector
Vector to hold working value of compartment vector.
double GetApparentFractionalAnisotropy() ITK_OVERRIDE
static const unsigned int m_SpaceDimension
virtual void SetParametersFromVector(const ListType &params) ITK_OVERRIDE
Various methods for optimization parameters setting and getting.
const double MCMAxialDiffusivityAddonLowerBound
Axial diffusivity add on to lower bound (used to ensure a minimal anisotropy to the anisotropic compa...
double GetApparentParallelDiffusivity() ITK_OVERRIDE
Get approximation to parallel diffusivity of the compartment (may be different from axial diffusivity...
virtual ListType & GetSignalAttenuationJacobian(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) ITK_OVERRIDE