DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
itkSphericalPolarFourierGenerator.hxx
Go to the documentation of this file.
1 
18 #ifndef __itkSphericalPolarFourierGenerator_hxx
19 #define __itkSphericalPolarFourierGenerator_hxx
20 
21 
23 
24 #include <gsl/gsl_sf_expint.h>
25 #include "utl.h"
28 
29 
30 namespace itk
31 {
32 
33 template < class PreciseType >
36 {
37  m_N = 0; m_L=0;
38  m_SPFType = SPF;
39  m_Scale = -1;
40 } // ----- end of constructor of template class SphericalPolarFourierRadialGenerator -----
41 
42 
43 template < class PreciseType >
44 PreciseType
46 ::GetNormalizeFacotr ( const bool isFourier) const
47 {
48  utlShowPosition(this->GetDebug());
49  utlException(m_Scale<=0, "need to set a scale");
50 
51  if (m_SPFType==SPF)
52  {
53  if (!isFourier)
54  {
55  PreciseType first_temp = 2.0 / utl::PowHalfInteger((double)this->m_Scale,(double)1.5) * PreciseType(utl::Factorial(m_N)) / utl::GammaHalfInteger(m_N+1.5);
56  first_temp = std::sqrt(first_temp);
57  return first_temp;
58  }
59  else
60  {
61  utlException(true, "no normalizeFacotr in dSPF basis");
62  }
63  }
64  else if (m_SPFType==DSPF)
65  {
66  if (!isFourier)
67  utlException(true, "no normalizeFacotr in dSPF basis");
68  else
69  {
71  radial_dual->SetNLSPF(m_N,m_L,SPF);
72  radial_dual->SetScale(m_Scale);
73  return radial_dual->GetNormalizeFacotr(false);
74  }
75  }
76  else if (m_SPFType==SHORE)
77  {
78  if (!isFourier)
79  {
80  PreciseType first_temp = 2.0 / utl::PowHalfInteger((double)this->m_Scale,1.5) * utl::Factorial(m_N-m_L/2) / utl::GammaHalfInteger(m_N+m_L/2+1.5);
81  first_temp = std::sqrt(first_temp);
82  return first_temp;
83  }
84  else
85  {
87  radial_dual->SetNLSPF(m_N,m_L,SHORE);
88  radial_dual->SetScale( 1.0/(4*M_PI*M_PI*this->GetScale()) );
89  PreciseType sign = (m_N)%2==0 ? 1 : -1;
90  return sign*radial_dual->GetNormalizeFacotr(false);
91  }
92  }
93  else
94  utlException(true, "wrong type");
95 } // ----- end of method SphericalPolarFourierGenerator<PreciseType>::Evaluate -----
96 
97 template < class PreciseType >
98 PreciseType
100 ::Evaluate ( const PreciseType qrValue, const bool isFourier) const
101 {
102  utlShowPosition(this->GetDebug());
103  utlException(m_Scale<=0, "need to set a scale");
104 
105  if (m_SPFType==SPF)
106  {
107  if (!isFourier)
108  {
109  PreciseType first_temp = 2.0 / utl::PowHalfInteger((double)this->m_Scale,(double)1.5) * PreciseType(utl::Factorial(m_N)) / utl::GammaHalfInteger(m_N+1.5);
110  first_temp = std::sqrt(first_temp);
111  if (this->GetDebug())
112  {
113  std::cout << "radial order = " << m_N << std::endl;
114  std::cout << "utl::Factorial("<<m_N<<") = " << utl::Factorial(m_N) << std::endl;
115  std::cout << "std::pow(m_Scale,1.5) = " << std::pow((double)this->m_Scale,(double)1.5) << std::endl;
116  std::cout << "utl::Gamma(m_N+1.5) = " << utl::GammaHalfInteger(m_N+1.5) << std::endl;
117  std::cout << "first_temp = " << first_temp << std::endl;
118  }
119  PreciseType result = first_temp * std::exp( -1.0*qrValue*qrValue / (2*this->m_Scale) )
120  * utl::Lagurre(m_N, 0.5, qrValue*qrValue/this->m_Scale);
121  return result;
122  }
123  else
124  {
126  radial_dual->SetNLSPF(m_N,m_L,DSPF);
127  radial_dual->SetScale(m_Scale);
128  return radial_dual->Evaluate(qrValue, false);
129  }
130  }
131  else if (m_SPFType==DSPF)
132  {
133  if (!isFourier)
134  {
135  PreciseType first_temp = 2.0 / utl::PowHalfInteger((double)this->m_Scale,1.5) * utl::Factorial(m_N) / utl::GammaHalfInteger(m_N+1.5);
136  first_temp = std::sqrt(first_temp) * utl::PowHalfInteger((double)this->m_Scale, 1.5);
137  std::vector<PreciseType> coef_laguerre = utl::GetCoefLaguerre(m_N);
138  if (this->GetDebug())
139  {
140  std::cout << "radial order = " << m_N << std::endl;
141  std::cout << "utl::Factorial("<<m_N<<") = " << utl::Factorial(m_N) << std::endl;
142  std::cout << "std::pow(m_Scale,1.5) = " << std::pow((double)this->m_Scale,1.5) << std::endl;
143  std::cout << "utl::Gamma(m_N+1.5) = " << utl::GammaHalfInteger(m_N+1.5) << std::endl;
144  std::cout << "first_temp = " << first_temp << std::endl;
145  }
146  PreciseType rr = qrValue*std::sqrt(this->m_Scale);
147  if (this->GetDebug())
148  std::cout << "qrValue = " << qrValue << ", relative qrvalue = " << rr << std::endl;
149  PreciseType sign = 4.0;
150  if ( (m_L/2) % 2 == 1)
151  sign = -4.0;
152  sign *= utl::PowHalfInteger(M_PI, m_L+1.5)*utl::PowHalfInteger(rr,m_L) / utl::GammaHalfInteger(m_L+1.5);
153  PreciseType integral = 0;
154  for ( int i = 0; i <= m_N; i += 1 )
155  {
156  PreciseType first_C = utl::PowHalfInteger(2,0.5*m_L+i-0.5) * utl::GammaHalfInteger(i+0.5*m_L+1.5);
157  // std::cout << "first_C = " << first_C << std::endl;
158  double a = double(i+0.5*m_L+1.5);
159  double b = double(m_L+1.5);
160  double c = double(-2*M_PI*M_PI*rr*rr);
161  // utlPrintVar3(true, a,b,c);
162  // integral += coef_laguerre[i]* first_C;
163  // NOTE: when c is small, 1F1=1
164  if (-1.0*c>1e-7)
165  integral += coef_laguerre[i]* first_C *utl::Hyperg1F1(a, b, c);
166  else
167  integral += coef_laguerre[i]* first_C;
168  // utlPrintVar4(true, a,b,c, utl::Hyperg1F1(a, b, c));
169  // std::cout << "integral = " << integral << std::endl;
170  }
171  PreciseType result = sign * first_temp * integral;
172  return result;
173  }
174  else
175  {
177  radial_dual->SetNLSPF(m_N,m_L,SPF);
178  radial_dual->SetScale(m_Scale);
179  return radial_dual->Evaluate(qrValue, false);
180  }
181  }
182  else if (m_SPFType==SHORE)
183  {
184  if (!isFourier)
185  {
186  PreciseType first_temp = 2.0 / utl::PowHalfInteger((double)this->m_Scale,1.5) * utl::Factorial(m_N-m_L/2) / utl::GammaHalfInteger(m_N+m_L/2+1.5);
187  first_temp = std::sqrt(first_temp);
188  PreciseType x2_temp = qrValue*qrValue / this->m_Scale;
189  PreciseType result = first_temp * std::exp(-0.5*x2_temp)* utl::PowHalfInteger((double)x2_temp, m_L/2) * utl::Lagurre(m_N-m_L/2, m_L+0.5, x2_temp);
190  if (this->GetDebug())
191  {
192  utlPrintVar3(true, m_N, m_L, x2_temp);
193  PreciseType exp_temp = std::exp( -1.0*x2_temp / 2 );
194  PreciseType lagurre_temp = utl::Lagurre(m_N-m_L/2, m_L+0.5, x2_temp);
195  PreciseType pow_temp = utl::PowHalfInteger((double)x2_temp, m_L/2);
196  utlPrintVar4(this->GetDebug(),m_N,m_L, std::sqrt(x2_temp), qrValue);
197  utlPrintVar5(this->GetDebug(), first_temp, exp_temp, lagurre_temp, pow_temp, result);
198  }
199  return result;
200  }
201  else
202  {
204  radial_dual->SetNLSPF(m_N,m_L,SHORE);
205  radial_dual->SetScale( 1.0/(4*M_PI*M_PI*m_Scale) );
206  PreciseType sign = (m_N)%2==0 ? 1 : -1;
207  return sign*radial_dual->Evaluate(qrValue, false);
208  }
209  }
210  else
211  utlException(true, "wrong type");
212  return 0;
213 } // ----- end of method SphericalPolarFourierGenerator<PreciseType>::Evaluate -----
214 
215 template < class PreciseType >
216 PreciseType
218 ::Evaluate (const PreciseType qrValue, const PreciseType theta, const PreciseType phi, const bool isFourier) const
219 {
220  utlShowPosition(this->GetDebug());
221 
222  PreciseType radial_value = m_Radial->Evaluate(qrValue, isFourier);
223  PreciseType spherical_value = SphericalHarmonicsGenerator<PreciseType>::RealSH(m_Radial->GetL(),m_M,theta,phi);
224  utlPrintVar2(this->GetDebug(), radial_value, spherical_value);
225  return radial_value*spherical_value;
226 } // ----- end of method SphericalPolarFourierGenerator<PreciseType>::Evaluate -----
227 
228 template < class PreciseType >
229 PreciseType
231 ::EvaluateRadial (const PreciseType qrValue, const bool isFourier) const
232 {
233  return m_Radial->Evaluate(qrValue, isFourier);
234 }
235 
236 template <class PreciseType>
237 void
239 ::PrintSelf(std::ostream& os, Indent indent) const
240 {
241  Superclass::PrintSelf(os, indent);
242  // PrintVar4(true, GetN(), GetL(), GetM(), GetScale(), os<<indent);
243  typename RadialType::SPFType spfType = this->GetSPFType();
244  if (spfType==SPF)
245  os << indent << "SPFType: SPF basis" << std::endl;
246  else if (spfType==DSPF)
247  os << indent << "SPFType: Dual SPF basis" << std::endl;
248  else if (spfType==SHORE)
249  os << indent << "SPFType: SHORE basis" << std::endl;
250  else
251  utlException(true, "wrong SPF type");
252 }
253 
254 
255 }
256 
257 
258 
259 #endif
static PreciseType RealSH(const int l, const int m, const PreciseType theta, const PreciseType phi)
PreciseType Evaluate(const PreciseType qrValue, const PreciseType theta, const PreciseType phi, const bool isFourier=false) const
void PrintSelf(std::ostream &os, Indent indent) const
PreciseType EvaluateRadial(const PreciseType qrValue, const bool isFourier=false) const
helper functions specifically used in dmritool
#define utlPrintVar3(cond, var1, var2, var3)
Definition: utlCoreMacro.h:558
virtual void SetScale(double _arg)
void SetNLSPF(const int n, const int l, const SPFType spf)
#define utlException(cond, expout)
Definition: utlCoreMacro.h:548
#define utlPrintVar4(cond, var1, var2, var3, var4)
Definition: utlCoreMacro.h:559
unsigned long Factorial(const int n)
Definition: utlMath.h:190
double Hyperg1F1(double a, double b, double x)
#define M_PI
Definition: utlCoreMacro.h:57
#define utlPrintVar2(cond, var1, var2)
Definition: utlCoreMacro.h:557
T Lagurre(const int n, const double a, const T x)
PreciseType Evaluate(const PreciseType qrValue, const bool isFourier=false) const
std::vector< double > GetCoefLaguerre(const int n, const double a=0.5)
Definition: utlMath.h:752
#define utlPrintVar5(cond, var1, var2, var3, var4, var5)
Definition: utlCoreMacro.h:560
double GammaHalfInteger(const double x)
Definition: utlMath.h:887
#define utlShowPosition(cond)
Definition: utlCoreMacro.h:554
PreciseType GetNormalizeFacotr(const bool isFourier=false) const
int sign(const T &x)
Return the sign of x.
Definition: utlCore.h:285
double PowHalfInteger(const double a, const double b)
Definition: utlMath.h:170