5 #include <boost/math/distributions/beta.hpp> 21 std::uniform_real_distribution<T> uniDbl(a,b);
22 return uniDbl(generator);
25 template <
class VectorType>
28 std::uniform_real_distribution<double> uniDbl(-1.0,1.0);
32 resVec[0] = uniDbl(generator);
33 resVec[1] = uniDbl(generator);
35 sqSum = resVec[0] * resVec[0] + resVec[1] * resVec[1];
38 double factor = 2.0 * std::sqrt(1.0 - sqSum);
41 resVec[2] = 2.0 * sqSum - 1.0;
47 std::bernoulli_distribution bernoulli(p);
48 return bernoulli(generator);
54 std::normal_distribution<T> normalDist(mean,std);
55 return normalDist(generator);
58 template <
class VectorType,
class ScalarType>
60 std::mt19937 &generator,
bool isMatCovariance)
62 unsigned int vectorSize = mat.rows();
64 vnl_matrix <ScalarType> stdMatrix = mat;
68 vnl_matrix <ScalarType> eVecs(vectorSize,vectorSize);
69 vnl_diag_matrix <ScalarType> eVals(vectorSize);
71 itk::SymmetricEigenAnalysis < vnl_matrix <ScalarType>, vnl_diag_matrix<ScalarType>, vnl_matrix <ScalarType> > eigenComputer(vectorSize);
72 eigenComputer.ComputeEigenValuesAndVectors(mat, eVals, eVecs);
74 for (
unsigned int i = 0;i < vectorSize;++i)
75 eVals[i] = std::sqrt(eVals[i]);
80 VectorType tmpVec (resVec);
81 for (
unsigned int i = 0;i < vectorSize;++i)
84 for (
unsigned int i = 0;i < vectorSize;++i)
87 for (
unsigned int j = 0;j < vectorSize;++j)
88 resVec[i] += stdMatrix(i,j) * tmpVec[j];
92 template <
class VectorType,
class ScalarType>
93 void SampleFromVMFDistribution(
const ScalarType &kappa,
const VectorType &meanDirection, VectorType &resVec, std::mt19937 &generator)
97 for (
unsigned int i = 0;i < 3;++i)
109 if (std::abs(tmpVec[2] - 1.0) > 1.0e-6)
110 throw itk::ExceptionObject(__FILE__, __LINE__,
"Von Mises & Fisher sampling requires mean direction of norm 1.",ITK_LOCATION);
112 double tmpVal = std::sqrt(kappa * kappa + 1.0);
113 double b = (-2.0 * kappa + 2.0 * tmpVal) / 2.0;
114 double a = (1.0 + kappa + tmpVal) / 2.0;
117 boost::math::beta_distribution<double> betaDist(1.0, 1.0);
120 double U = std::exp(d);
127 tmpVal = 1.0 - (1.0 - b) * Z;
128 T = 2.0 * a * b / tmpVal;
129 W = (1.0 - (1.0 + b) * Z) / tmpVal;
133 tmpVec[0] = std::sqrt(1.0 - W*W) * std::cos(theta);
134 tmpVec[1] = std::sqrt(1.0 - W*W) * std::sin(theta);
137 for (
unsigned int i = 0;i < 3;++i)
138 for (
unsigned int j = 0;j < 3;++j)
139 resVec[i] += rotationMatrix(i,j) * tmpVec[j];
142 template <
class VectorType,
class ScalarType>
147 for (
unsigned int i = 0;i < 3;++i)
159 if (std::abs(tmpVec[2] - 1.0) > 1.0e-6)
160 throw itk::ExceptionObject(__FILE__, __LINE__,
"Von Mises & Fisher sampling requires mean direction of norm 1.",ITK_LOCATION);
166 tmpVec[0] = std::sqrt(1.0 - W*W) * std::cos(theta);
167 tmpVec[1] = std::sqrt(1.0 - W*W) * std::sin(theta);
170 for (
unsigned int i = 0;i < 3;++i)
171 for (
unsigned int j = 0;j < 3;++j)
172 resVec[i] += rotationMatrix(i,j) * tmpVec[j];
175 template <
class ScalarType,
class VectorType>
177 SampleFromWatsonDistribution(
const ScalarType &kappa,
const VectorType &meanDirection, VectorType &resVec,
unsigned int DataDimension, std::mt19937 &generator)
203 for (
unsigned int i = 0;i < DataDimension;++i)
212 VectorType rotationNormal;
219 double rotationAngle = tmpVec[0];
221 if (std::abs(tmpVec[2] - 1.0) > 1.0e-6)
222 throw itk::ExceptionObject(__FILE__, __LINE__,
"The Watson distribution is on the 2-sphere.",ITK_LOCATION);
228 S = 1.0 + std::log(U + (1.0 - U) * std::exp(-kappa)) / kappa;
234 while (std::log(V) > kappa * S * (S - 1.0))
237 S = 1.0 + std::log(U + (1.0 - U) * std::exp(-kappa)) / kappa;
246 else if (kappa < -1.0e-6)
248 double C1 = std::sqrt(std::abs(kappa));
249 double C2 = std::atan(C1);
252 S = (1.0 / C1) * std::tan(C2 * U);
254 double T = kappa * S * S;
255 while (V > (1.0 - T) * std::exp(T))
259 S = (1.0 / C1) * std::tan(C2 * U);
271 tmpVec[0] = std::sqrt(1.0 - S*S) * std::cos(phi);
272 tmpVec[1] = std::sqrt(1.0 - S*S) * std::sin(phi);
279 if (std::abs(resNorm - 1.0) > 1.0e-4)
281 std::cout <<
"Sampled direction norm: " << resNorm << std::endl;
282 std::cout <<
"Mean direction: " << meanDirection << std::endl;
283 std::cout <<
"Concentration parameter: " << kappa << std::endl;
284 throw itk::ExceptionObject(__FILE__, __LINE__,
"The Watson sampler should generate points on the 2-sphere.",ITK_LOCATION);
290 template <
class ScalarType,
unsigned int DataDimension>
292 SampleFromWatsonDistribution(
const ScalarType &kappa,
const vnl_vector_fixed < ScalarType, DataDimension > &meanDirection, vnl_vector_fixed < ScalarType, DataDimension > &resVec, std::mt19937 &generator)
318 template <
class ScalarType,
unsigned int DataDimension>
320 SampleFromWatsonDistribution(
const ScalarType &kappa,
const itk::Point < ScalarType, DataDimension > &meanDirection, itk::Point < ScalarType, DataDimension > &resVec, std::mt19937 &generator)
346 template <
class ScalarType,
unsigned int DataDimension>
348 SampleFromWatsonDistribution(
const ScalarType &kappa,
const itk::Vector < ScalarType, DataDimension > &meanDirection, itk::Vector < ScalarType, DataDimension > &resVec, std::mt19937 &generator)
void SampleFromUniformDistributionOn2Sphere(std::mt19937 &generator, VectorType &resVec)
double ComputeNorm(const VectorType &v)
void RotateAroundAxis(const std::vector< T1 > &v, const T2 &phi, const std::vector< T3 > &normalVec, std::vector< T4 > &resVec)
itk::Matrix< double, 3, 3 > GetRotationMatrixFromVectors(const VectorType &first_direction, const VectorType &second_direction, const unsigned int dimension)
void SampleFromVMFDistribution(const ScalarType &kappa, const VectorType &meanDirection, VectorType &resVec, std::mt19937 &generator)
void SampleFromVMFDistributionNumericallyStable(const ScalarType &kappa, const VectorType &meanDirection, VectorType &resVec, std::mt19937 &generator)
unsigned int SampleFromBernoulliDistribution(const T &p, std::mt19937 &generator)
void RecomposeTensor(vnl_diag_matrix< T1 > &eigs, vnl_matrix< T1 > &eigVecs, vnl_matrix< T2 > &resMatrix)
Recompose tensor from values extracted using SymmetricEigenAnalysis (vnl_symmetric_eigensystem transp...
double SampleFromGaussianDistribution(const T &mean, const T &std, std::mt19937 &generator)
void Normalize(const VectorType &v, const unsigned int NDimension, VectorType &resVec)
double safe_log(const ScalarType x)
void SampleFromMultivariateGaussianDistribution(const VectorType &mean, const vnl_matrix< ScalarType > &mat, VectorType &resVec, std::mt19937 &generator, bool isMatCovariance=true)
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)
void ComputeCrossProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension, VectorType &resVec)
void SampleFromWatsonDistribution(const ScalarType &kappa, const VectorType &meanDirection, VectorType &resVec, unsigned int DataDimension, std::mt19937 &generator)
double SampleFromUniformDistribution(const T &a, const T &b, std::mt19937 &generator)