ANIMA  4.0
animaODFSphericalHarmonicBasis.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 namespace anima
5 {
6 
7 template <class T>
8 double
10 getValueAtPosition(const T &coefficients, double theta, double phi)
11 {
12  double resVal = 0;
13  std::complex <double> tmpVal;
14 
15  for (int k = 0;k <= (int)m_LOrder;k += 2)
16  for (int m = -k;m <= k;++m)
17  {
18  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].Value(theta,phi);
19 
20  if (m > 0)
21  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
22  else if (m < 0)
23  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
24  else
25  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
26  }
27 
28  return resVal;
29 }
30 
31 template <class T>
32 itk::VariableLengthVector <T>
34 GetSampleValues(itk::VariableLengthVector <T> &data,
35  std::vector < std::vector <double> > &m_SampleDirections)
36 {
37  itk::VariableLengthVector <T> resVal(m_SampleDirections.size());
38 
39  for (unsigned int i = 0;i < m_SampleDirections.size();++i)
40  resVal[i] = this->getValueAtPosition(data,m_SampleDirections[i][0],m_SampleDirections[i][1]);
41 
42  return resVal;
43 }
44 
45 template <class T>
46 double
48 getThetaFirstDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
49 {
50  double resVal = 0;
51  std::complex <double> tmpVal;
52 
53  for (int k = 0;k <= (int)m_LOrder;k += 2)
54  for (int m = -k;m <= k;++m)
55  {
56  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].getThetaFirstDerivative(theta,phi);
57 
58  if (m > 0)
59  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
60  else if (m < 0)
61  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
62  else
63  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
64  }
65 
66  return resVal;
67 }
68 
69 template <class T>
70 double
72 getPhiFirstDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
73 {
74  double resVal = 0;
75  std::complex <double> tmpVal;
76 
77  for (int k = 0;k <= (int)m_LOrder;k += 2)
78  for (int m = -k;m <= k;++m)
79  {
80  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].getPhiFirstDerivative(theta,phi);
81 
82  if (m > 0)
83  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
84  else if (m < 0)
85  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
86  else
87  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
88  }
89 
90  return resVal;
91 }
92 
93 template <class T>
94 double
96 getThetaSecondDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
97 {
98  double resVal = 0;
99  std::complex <double> tmpVal;
100 
101  for (int k = 0;k <= (int)m_LOrder;k += 2)
102  for (int m = -k;m <= k;++m)
103  {
104  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].getThetaSecondDerivative(theta,phi);
105 
106  if (m > 0)
107  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
108  else if (m < 0)
109  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
110  else
111  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
112  }
113 
114  return resVal;
115 }
116 
117 template <class T>
118 double
120 getThetaPhiDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
121 {
122  double resVal = 0;
123  std::complex <double> tmpVal;
124 
125  for (int k = 0;k <= (int)m_LOrder;k += 2)
126  for (int m = -k;m <= k;++m)
127  {
128  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].getThetaPhiDerivative(theta,phi);
129 
130  if (m > 0)
131  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
132  else if (m < 0)
133  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
134  else
135  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
136  }
137 
138  return resVal;
139 }
140 
141 template <class T>
142 double
144 getPhiSecondDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
145 {
146  double resVal = 0;
147  std::complex <double> tmpVal;
148 
149  for (int k = 0;k <= (int)m_LOrder;k += 2)
150  for (int m = -k;m <= k;++m)
151  {
152  tmpVal = m_SphericalHarmonics[k*(k+1)/2 + m].getPhiSecondDerivative(theta,phi);
153 
154  if (m > 0)
155  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*imag(tmpVal);
156  else if (m < 0)
157  resVal += coefficients[k*(k+1)/2 + m]*sqrt(2.0)*real(tmpVal);
158  else
159  resVal += coefficients[k*(k+1)/2 + m]*real(tmpVal);
160  }
161 
162  return resVal;
163 }
164 
165 template <class T>
166 double
168 getCurvatureAtPosition(const T &coefficients, double theta, double phi)
169 {
170  // Taken from Bloy and Verma, simplified to the maximum (this supposes we are actually at an extremum of the odf)
171  double odfValue = this->getValueAtPosition(coefficients,theta,phi);
172  double sqSinTheta = sin(theta) * sin(theta);
173  if (sqSinTheta <= 1.0e-16)
174  sqSinTheta = 1.0e-16;
175 
176  double denom = 2.0 * odfValue * odfValue * sqSinTheta;
177 
178  double num = 2.0 * odfValue * sqSinTheta;
179  num -= sqSinTheta * this->getThetaSecondDerivativeValueAtPosition(coefficients,theta,phi) +
180  this->getPhiSecondDerivativeValueAtPosition(coefficients,theta,phi);
181 
182  return num / denom;
183 }
184 
185 } // end of namespace anima
double getCurvatureAtPosition(const T &coefficients, double theta, double phi)
double getThetaSecondDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
double getThetaFirstDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
double getPhiSecondDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
double getThetaPhiDerivativeValueAtPosition(const T &coefficients, double theta, double phi)
itk::VariableLengthVector< T > GetSampleValues(itk::VariableLengthVector< T > &data, std::vector< std::vector< double > > &m_SampleDirections)
double getValueAtPosition(const T &coefficients, double theta, double phi)
double getPhiFirstDerivativeValueAtPosition(const T &coefficients, double theta, double phi)