9 #include <itkObjectFactory.h> 11 #include <boost/math/special_functions/bessel.hpp> 16 template <
class VectorType,
class ScalarType>
17 double EvaluateWatsonPDF(
const VectorType &v,
const VectorType &meanAxis,
const ScalarType &kappa)
37 if (std::abs(kappa) < 1.0e-6)
38 return 1.0 / (4.0 * M_PI);
41 double kappaSqrt = std::sqrt(kappa);
43 double inExp = kappa * (c * c - 1.0);
48 double Ck = std::sqrt(-kappa / M_PI) / (2.0 * M_PI * std::erf(std::sqrt(-kappa)));
50 double inExp = kappa * c * c;
51 return Ck * std::exp(inExp);
55 template <
class ScalarType>
56 double EvaluateWatsonPDF(
const vnl_vector_fixed <ScalarType,3> &v,
const vnl_vector_fixed <ScalarType,3> &meanAxis,
const ScalarType &kappa)
58 if (std::abs(v.squared_magnitude() - 1.0) > 1.0e-6 || std::abs(meanAxis.squared_magnitude() - 1.0) > 1.0e-6)
59 throw itk::ExceptionObject(__FILE__, __LINE__,
"The Watson distribution is on the 2-sphere.",ITK_LOCATION);
61 return EvaluateWatsonPDF<vnl_vector_fixed <ScalarType,3>, ScalarType>(v,meanAxis,kappa);
64 template <
class ScalarType>
65 double EvaluateWatsonPDF(
const itk::Point <ScalarType,3> &v,
const itk::Point <ScalarType,3> &meanAxis,
const ScalarType &kappa)
67 if (std::abs(v.GetVnlVector().squared_magnitude() - 1.0) > 1.0e-6 || std::abs(meanAxis.GetVnlVector().squared_magnitude() - 1.0) > 1.0e-6)
68 throw itk::ExceptionObject(__FILE__, __LINE__,
"The Watson distribution is on the 2-sphere.",ITK_LOCATION);
70 return EvaluateWatsonPDF<itk::Point <ScalarType,3>, ScalarType>(v,meanAxis,kappa);
73 template <
class ScalarType>
74 double EvaluateWatsonPDF(
const itk::Vector <ScalarType,3> &v,
const itk::Vector <ScalarType,3> &meanAxis,
const ScalarType &kappa)
76 if (std::abs(v.GetSquaredNorm() - 1.0) > 1.0e-6 || std::abs(meanAxis.GetSquaredNorm() - 1.0) > 1.0e-6)
77 throw itk::ExceptionObject(__FILE__, __LINE__,
"The Watson distribution is on the 2-sphere.",ITK_LOCATION);
79 return EvaluateWatsonPDF<itk::Vector <ScalarType,3>, ScalarType>(v,meanAxis,kappa);
82 template <
class ScalarType>
86 const unsigned int nbCoefs = 7;
87 coefficients.resize(nbCoefs);
88 derivatives.resize(nbCoefs);
90 double sqrtPi = std::sqrt(M_PI);
99 coefficients[0] = 2.0 * sqrtPi;
100 derivatives[0] = 0.0;
104 coefficients[1] = k / 3.0;
105 coefficients[2] = k2 / 35.0;
106 coefficients[3] = k3 / 693.0;
107 coefficients[4] = k4 / 19305.0;
108 coefficients[5] = k5 / 692835.0;
109 coefficients[6] = k6 / 30421755.0;
110 derivatives[1] = 1.0 / 3.0;
111 derivatives[2] = 2.0 * k / 35.0;
112 derivatives[3] = k2 / 231.0;
113 derivatives[4] = 4.0 * k3 / 19305.0;
114 derivatives[5] = k4 / 138567.0;
115 derivatives[6] = 6.0 * k5 / 30421755.0;
117 for (
unsigned int i = 1;i < nbCoefs;++i)
119 double tmpVal = std::pow(2.0, i + 1.0) * sqrtPi / std::sqrt(4.0 * i + 1.0);
120 coefficients[i] *= tmpVal;
121 derivatives[i] *= tmpVal;
127 coefficients[1] = (3.0 - (3.0 + 2.0 * k) * dawsonValue) / (2.0 * k);
128 coefficients[2] = (5.0 * (-21.0 + 2.0 * k) + 3.0 * (35.0 + 4.0 * k * (5.0 + k)) * dawsonValue) / (16.0 * k2);
129 coefficients[3] = (21.0 * (165.0 + 4.0 * (-5.0 + k) * k) - 5.0 * (693.0 + 378.0 * k + 84.0 * k2 + 8.0 * k3) * dawsonValue) / (64.0 * k3);
130 coefficients[4] = (3.0 * (-225225.0 + 2.0 * k * (15015.0 + 2.0 * k * (-1925.0 + 62.0 * k))) + 35.0 * (19305.0 + 8.0 * k * (1287.0 + k * (297.0 + 2.0 * k * (18.0 + k)))) * dawsonValue) / (1024.0 * k4);
131 coefficients[5] = (11.0 * (3968055.0 + 8.0 * k * (-69615.0 + 2.0 * k * (9828.0 + k * (-468.0 + 29.0 * k)))) - 63.0 * (692835.0 + 2.0 * k * (182325.0 + 4.0 * k * (10725.0 + 2.0 * k * (715.0 + k * (55.0 + 2.0 * k))))) * dawsonValue) / (4096.0 * k5);
132 coefficients[6] = (13.0 * (-540571185.0 + 2.0 * k * (39171825.0 + 4.0 * k * (-2909907.0 + 2.0 * k * (82467.0 + k * (-7469.0 + 122.0 * k))))) + 231.0 * (30421755.0 + 4.0 * k * (3968055.0 + k * (944775.0 + 4.0 * k * (33150.0 + k * (2925.0 + 4.0 * k * (39.0 + k)))))) * dawsonValue) / (32768.0 * k6);
134 derivatives[1] = 3.0 * (-1.0 + (-1.0 + 2.0 * k) * dawsonValue + 2.0 * dawsonValue * dawsonValue) / (4.0 * k2);
135 derivatives[2] = 5.0 * ((21.0 - 2.0 * k) + (63.0 + 4.0 * (-11.0 + k) * k) * dawsonValue - 12.0 * (7.0 + 2.0 * k) * dawsonValue * dawsonValue) / (32.0 * k3);
136 derivatives[3] = 21.0 * ((-165.0 - 4.0 * (-5.0 + k) * k) + (-5.0 + 2.0 * k) * (165.0 + 4.0 * (-3.0 + k) * k) * dawsonValue + 10.0 * (99.0 + 4.0 * k * (9.0 + k)) * dawsonValue * dawsonValue) / (128.0 * k4);
137 derivatives[4] = 3.0 * ((225225.0 - 2.0 * k * (15015.0 + 2.0 * k * (-1925.0 + 62.0 * k))) + (1576575.0 + 8.0 * k * (-75075.0 + k * (10395.0 + 2.0 * k * (-978.0 + 31.0 * k)))) * dawsonValue - 840.0 * (2145.0 + 2.0 * k * (429.0 + 66.0 * k + 4.0 * k2)) * dawsonValue * dawsonValue) / (2048.0 * k5);
138 derivatives[5] = 11.0 * ((-3968055.0 - 8.0 * k * (-69615.0 + 2.0 * k * (9828.0 + k * (-468.0 + 29.0 * k)))) + (-35712495.0 + 2.0 * k * (5917275.0 + 8.0 * k * (-118755.0 + k * (21060.0 + k * (-965.0 + 58.0 * k))))) * dawsonValue + 630.0 * (62985.0 + 8.0 * k * (3315.0 + k * (585.0 + 2.0 * k * (26.0 + k)))) * dawsonValue * dawsonValue) / (8192.0 * k6);
139 derivatives[6] = 13.0 * ((540571185.0 - 2.0 * k * (39171825.0 + 4.0 * k * (-2909907.0 + 2.0 * k * (82467.0 + k * (-7469.0 + 122.0 * k))))) + (5946283035.0 + 4.0 * k * (-446558805.0 + k * (79910523.0 + 4.0 * k * (-3322242.0 + k * (187341.0 + 4.0 * k * (-3765.0 + 61.0 * k)))))) * dawsonValue - 2772.0 * (2340135.0 + 2.0 * k * (508725.0 + 4.0 * k * (24225.0 + 2.0 * k * (1275.0 + k * (75.0 + 2.0 * k))))) * dawsonValue * dawsonValue) / (65536.0 * k7);
141 for (
unsigned int i = 1;i < nbCoefs;++i)
143 double sqrtVal = std::sqrt(1.0 + 4.0 * i);
144 coefficients[i] *= (sqrtPi * sqrtVal / dawsonValue);
145 derivatives[i] *= (sqrtPi * sqrtVal / (dawsonValue * dawsonValue));
double EvaluateWatsonPDF(const VectorType &v, const VectorType &meanAxis, const ScalarType &kappa)
void GetStandardWatsonSHCoefficients(const ScalarType k, std::vector< ScalarType > &coefficients, std::vector< ScalarType > &derivatives)
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
double EvaluateDawsonIntegral(const double x, const bool scaled)
double EvaluateDawsonFunctionNR(double x)
Numerical recipes implementation of Dawson integral.