17#ifndef __dwi_tractography_algorithms_iFOD_calibrator_h__
18#define __dwi_tractography_algorithms_iFOD_calibrator_h__
25#define SQRT_3_OVER_2 0.866025403784439
26#define NUM_CALIBRATE 1000
30 namespace Tractography {
31 namespace Algorithms {
37 const float maxR =
Math::pow2 (max_angle / spacing);
39 ssize_t extent =
std::ceil (max_angle / spacing);
41 for (ssize_t i = -extent; i <= extent; ++i) {
42 for (ssize_t j = -extent; j <= extent; ++j) {
47 n = spacing * std::sqrt (n);
48 float z = std::cos (n);
49 if (n) n = spacing * std::sin (n) / n;
50 list.push_back ({ n*x, n*y, z });
60 Pair (
float elevation,
float amplitude) :
el (elevation),
amp (amplitude) { }
65 template <
class Method>
68 typename Method::Calibrate calibrate_func (method);
69 const float sqrt3 = std::sqrt (3.0);
70 const float max_angle = std::isfinite (method.S.max_angle_ho) ? method.S.max_angle_ho : method.S.max_angle_1o;
73 for (
float el = 0.0;
el < max_angle;
el += 0.001) {
74 amps.push_back (Pair (
el, calibrate_func (
el)));
75 if (!std::isfinite (amps.back().amp) || amps.back().amp <= 0.0)
break;
77 float zero = amps.back().el;
79 float N_min =
Inf, theta_min =
NaN, ratio =
NaN;
80 for (
size_t i = 1; i < amps.size(); ++i) {
82 float Ns = N * (1.0+amps[0].amp/amps[i].amp)/(2.0*
Math::pow2(zero));
86 if (N > 0.0 && N < N_min) {
88 theta_min = amps[i].el;
89 ratio = amps[0].amp / amps[i].amp;
93 method.calibrate_list =
direction_grid (max_angle+theta_min, sqrt3*theta_min);
94 method.calibrate_ratio = ratio;
96 INFO (
"rejection sampling will use " +
str (method.calibrate_list.size())
97 +
" directions with a ratio of " +
str (method.calibrate_ratio) +
" (predicted number of samples per step = " +
str (N_min) +
")");
constexpr T pow2(const T &v)
constexpr I ceil(const T x)
template function with cast to different type
void calibrate(Method &method)
FORCE_INLINE vector< Eigen::Vector3f > direction_grid(float max_angle, float spacing)
std::string str(const T &value, int precision=0)
constexpr default_type Inf
constexpr default_type NaN