ANIMA  4.0
animaZeppelinCompartment.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 ZeppelinCompartment::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()
18  + (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
19  * m_GradientEigenvector1 * m_GradientEigenvector1));
20 }
21 
22 ZeppelinCompartment::ListType &ZeppelinCompartment::GetSignalAttenuationJacobian(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient)
23 {
25 
26  double signalAttenuation = this->GetFourierTransformedDiffusionProfile(smallDelta, bigDelta, gradientStrength, gradient);
27  double bValue = anima::GetBValueFromAcquisitionParameters(smallDelta, bigDelta, gradientStrength);
28 
29  // Derivative w.r.t. theta
30  m_JacobianVector[0] = -2.0 * bValue * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
31  * (gradient[0] * std::cos(this->GetOrientationTheta()) * std::cos(this->GetOrientationPhi())
32  + gradient[1] * std::cos(this->GetOrientationTheta()) * std::sin(this->GetOrientationPhi())
33  - gradient[2] * std::sin(this->GetOrientationTheta())) * m_GradientEigenvector1 * signalAttenuation;
34 
35  // Derivative w.r.t. phi
36  m_JacobianVector[1] = -2.0 * bValue * std::sin(this->GetOrientationTheta())
37  * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1())
38  * (gradient[1] * std::cos(this->GetOrientationPhi()) - gradient[0] * std::sin(this->GetOrientationPhi()))
39  * m_GradientEigenvector1 * signalAttenuation;
40 
41  if (m_EstimateDiffusivities)
42  {
43  // Derivative w.r.t. to d1
44  m_JacobianVector[2] = - bValue * m_GradientEigenvector1 * m_GradientEigenvector1 * signalAttenuation;
45 
46  // Derivative w.r.t. to d3
47  m_JacobianVector[3] = - bValue * signalAttenuation;
48  }
49 
50  return m_JacobianVector;
51 }
52 
54 {
55  Vector3DType compartmentOrientation(0.0);
57 
58  double scalarProduct = anima::ComputeScalarProduct(compartmentOrientation,sample);
59 
60  double resVal = - 1.5 * std::log(2.0 * M_PI) - 0.5 * std::log(this->GetAxialDiffusivity()) - std::log(this->GetRadialDiffusivity1());
61 
62  resVal -= (sample.squared_magnitude() - (1.0 - this->GetRadialDiffusivity1() / this->GetAxialDiffusivity()) * scalarProduct * scalarProduct) / (2.0 * this->GetRadialDiffusivity1());
63 
64  return resVal;
65 }
66 
68 {
70  this->SetRadialDiffusivity2(num);
71 }
72 
74 {
75  if (params.size() != this->GetNumberOfParameters())
76  return;
77 
78  this->SetOrientationTheta(params[0]);
79  this->SetOrientationPhi(params[1]);
80 
81  if (m_EstimateDiffusivities)
82  {
83  this->SetAxialDiffusivity(params[2] + params[3]);
84  this->SetRadialDiffusivity1(params[3]);
85  }
86 }
87 
89 {
91 
94 
95  if (m_EstimateDiffusivities)
96  {
99  }
100 
101  return m_ParametersVector;
102 }
103 
105 {
108 
109  if (m_EstimateDiffusivities)
110  {
113  }
114 
116 }
117 
119 {
121 
124 
125  if (m_EstimateDiffusivities)
126  {
129  }
130 
132 }
133 
135 {
136  if (m_EstimateDiffusivities == arg)
137  return;
138 
139  m_EstimateDiffusivities = arg;
140  m_ChangedConstraints = true;
141 }
142 
144 {
145  if (compartmentVector.GetSize() != this->GetCompartmentSize())
146  itkExceptionMacro("The input vector size does not match the size of the compartment");
147 
148  Matrix3DType tensor, eVecs;
149  vnl_diag_matrix <double> eVals(m_SpaceDimension);
150  itk::SymmetricEigenAnalysis <Matrix3DType,vnl_diag_matrix <double>,Matrix3DType> eigSys(m_SpaceDimension);
151 
152  unsigned int pos = 0;
153  for (unsigned int i = 0;i < m_SpaceDimension;++i)
154  {
155  for (unsigned int j = 0;j <= i;++j)
156  {
157  tensor(i,j) = compartmentVector[pos];
158 
159  if (i != j)
160  tensor(j,i) = compartmentVector[pos];
161 
162  ++pos;
163  }
164  }
165 
166  eigSys.ComputeEigenValuesAndVectors(tensor,eVals,eVecs);
167 
168  Vector3DType compartmentOrientation, sphDir;
169 
170  for (unsigned int i = 0;i < m_SpaceDimension;++i)
171  compartmentOrientation[i] = eVecs(2,i);
172 
173  anima::TransformCartesianToSphericalCoordinates(compartmentOrientation,sphDir);
174 
175  this->SetOrientationTheta(sphDir[0]);
176  this->SetOrientationPhi(sphDir[1]);
177  this->SetAxialDiffusivity(eVals(2));
178  this->SetRadialDiffusivity1((eVals(1) + eVals(0)) / 2.0);
179 }
180 
182 {
183  return 6;
184 }
185 
187 {
188  if (!m_ChangedConstraints)
189  return m_NumberOfParameters;
190 
191  // The number of parameters before constraints is the compartment size - 2 because a cylindrical tensor has 4 dof but is stored as a tensor (6 dof)
192  m_NumberOfParameters = this->GetCompartmentSize() - 2;
193 
194  if (!m_EstimateDiffusivities)
195  m_NumberOfParameters -= 2;
196 
197  m_ChangedConstraints = false;
198  return m_NumberOfParameters;
199 }
200 
202 {
203  if (m_CompartmentVector.GetSize() != this->GetCompartmentSize())
204  m_CompartmentVector.SetSize(this->GetCompartmentSize());
205 
206  Vector3DType compartmentOrientation(0.0);
208 
209  unsigned int pos = 0;
210  for (unsigned int i = 0;i < m_SpaceDimension;++i)
211  {
212  for (unsigned int j = 0;j <= i;++j)
213  {
214  m_CompartmentVector[pos] = (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1()) * compartmentOrientation[i] * compartmentOrientation[j];
215 
216  if (i == j)
218 
219  ++pos;
220  }
221  }
222 
223  return m_CompartmentVector;
224 }
225 
227 {
228  m_DiffusionTensor.Fill(0.0);
229 
230  for (unsigned int i = 0;i < m_SpaceDimension;++i)
232 
233  Vector3DType compartmentOrientation(0.0);
235 
236  for (unsigned int i = 0;i < m_SpaceDimension;++i)
237  for (unsigned int j = i;j < m_SpaceDimension;++j)
238  {
239  m_DiffusionTensor(i,j) += compartmentOrientation[i] * compartmentOrientation[j] * (this->GetAxialDiffusivity() - this->GetRadialDiffusivity1());
240  if (i != j)
242  }
243 
244  return m_DiffusionTensor;
245 }
246 
248 {
249  double l1 = this->GetAxialDiffusivity();
250  double l2 = this->GetRadialDiffusivity1();
251  double numFA = std::sqrt (2.0 * (l1 - l2) * (l1 - l2));
252  double denomFA = std::sqrt (l1 * l1 + 2.0 * l2 * l2);
253 
254  double fa = 0;
255  if (denomFA != 0)
256  fa = std::sqrt(0.5) * (numFA / denomFA);
257 
258  return fa;
259 }
260 
262 {
263  double l1 = this->GetAxialDiffusivity();
264  double l2 = this->GetRadialDiffusivity1();
265 
266  return (l1 + 2.0 * l2) / 3.0;
267 }
268 
270 {
271  return this->GetAxialDiffusivity();
272 }
273 
275 {
276  return this->GetRadialDiffusivity1();
277 }
278 
279 } //end namespace anima
280 
const double MCMZeroLowerBound
Default zero lower bound (in case we want something else than zero one day)
double GetApparentPerpendicularDiffusivity() ITK_OVERRIDE
Get approximation to perpendicular diffusivity of the compartment (may be different from radial diffu...
double GetApparentParallelDiffusivity() ITK_OVERRIDE
Get approximation to parallel diffusivity of the compartment (may be different from axial diffusivity...
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.
Superclass::ModelOutputVectorType ModelOutputVectorType
virtual ListType & GetSignalAttenuationJacobian(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) ITK_OVERRIDE
unsigned int GetNumberOfParameters() ITK_OVERRIDE
Number of optimized parameters: smaller than total number of parameters.
const double MCMAzimuthAngleUpperBound
Azimuth angle upper bound.
virtual void SetRadialDiffusivity2(double num)
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()
void SetRadialDiffusivity1(double num) ITK_OVERRIDE
virtual void SetRadialDiffusivity1(double num)
virtual void SetParametersFromVector(const ListType &params) ITK_OVERRIDE
Various methods for optimization parameters setting and getting.
virtual double GetLogDiffusionProfile(const Vector3DType &sample) ITK_OVERRIDE
virtual double GetFourierTransformedDiffusionProfile(double smallDelta, double bigDelta, double gradientStrength, const Vector3DType &gradient) 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()
void SetCompartmentVector(ModelOutputVectorType &compartmentVector) ITK_OVERRIDE
Set compartment overall description vector, for setting automatically the individual parameters when ...
const double MCMRadialDiffusivityUpperBound
Radial diffusivity upper bound.
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)
virtual ListType & GetParameterLowerBounds() ITK_OVERRIDE
virtual void SetOrientationTheta(double num)
ListType m_ParametersUpperBoundsVector
Vector holding current parameters upper bounds.
virtual ListType & GetParameterUpperBounds() ITK_OVERRIDE
Superclass::Matrix3DType Matrix3DType
ListType m_JacobianVector
Vector holding current jacobian value.
const double MCMDiffusivityUpperBound
Diffusivity upper bound.
virtual double GetRadialDiffusivity1()
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
virtual void SetOrientationPhi(double num)
const double MCMDiffusivityLowerBound
Diffusivity lower bound for estimation.
double GetApparentFractionalAnisotropy() ITK_OVERRIDE
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.
static const unsigned int m_SpaceDimension
double GetApparentMeanDiffusivity() ITK_OVERRIDE
const double MCMAxialDiffusivityAddonLowerBound
Axial diffusivity add on to lower bound (used to ensure a minimal anisotropy to the anisotropic compa...
ModelOutputVectorType & GetCompartmentVector() ITK_OVERRIDE
Get compartment overall description vector, mainly for writing, should be self-contained.
virtual ListType & GetParametersAsVector() ITK_OVERRIDE