22 m_MinimalDiffusionProbability = 0;
24 m_CurvatureScale = 6.0;
42 m_ODFSHOrder = std::round(-1.5 + 0.5 * std::sqrt(8 * this->
GetInputModelImage()->GetNumberOfComponentsPerPixel() + 1));
55 double &log_proposal, std::mt19937 &random_generator,
56 unsigned int threadId)
59 bool is2d = (this->
GetInputModelImage()->GetLargestPossibleRegion().GetSize()[2] == 1);
62 unsigned int numDirs = this->
FindODFMaxima(modelValue,maximaODF,m_MinimalDiffusionProbability,is2d);
66 double chosenKappa = 0;
70 double sumWeights = 0;
72 for (
unsigned int i = 0;i < numDirs;++i)
78 mixtureWeights[i] = m_ODFSHBasis->
getValueAtPosition(modelValue,sphDirection[0],sphDirection[1]);
81 kappaValues[i] = 0.5 * m_CurvatureScale * m_ODFSHBasis->
getCurvatureAtPosition(modelValue,sphDirection[0],sphDirection[1]);
83 if ((std::isnan(kappaValues[i]))||(kappaValues[i] <= 0)||(kappaValues[i] >= 1000))
84 mixtureWeights[i] = 0;
86 sumWeights += mixtureWeights[i];
92 sampling_direction = oldDirection;
97 for (
unsigned int i = 0;i < numDirs;++i)
98 mixtureWeights[i] /= sumWeights;
100 std::discrete_distribution<> dist(mixtureWeights.begin(),mixtureWeights.end());
101 unsigned int chosenDirection = dist(random_generator);
103 sampling_direction = maximaODF[chosenDirection];
104 chosenKappa = kappaValues[chosenDirection];
116 resVec[InputModelImageType::ImageDimension - 1] = 0;
126 for (
unsigned int i = 0;i < numDirs;++i)
142 unsigned int threadId)
145 bool is2d = (this->
GetInputModelImage()->GetLargestPossibleRegion().GetSize()[2] == 1);
148 unsigned int numDirs = this->
FindODFMaxima(modelValue,maximaODF,m_MinimalDiffusionProbability,is2d);
157 for (
unsigned int i = 0;i < numDirs;++i)
159 for (
unsigned int j = 0;j < InputModelImageType::ImageDimension;++j)
160 tmpVec[j] = maximaODF[i][j];
183 resVec = maximaODF[0];
201 if (estimatedB0Value < 50.0)
204 bool isModelNull =
true;
207 if (modelValue[j] != 0)
218 if (fractionalAnisotropy < m_GFAThreshold)
225 double &log_prior,
double &log_proposal,
unsigned int threadId)
227 double logLikelihood = 0.0;
229 bool is2d = (this->
GetInputModelImage()->GetLargestPossibleRegion().GetSize()[2] == 1);
232 unsigned int numDirs = this->
FindODFMaxima(modelValue,maximaODF,m_MinimalDiffusionProbability,is2d);
234 double concentrationParameter = b0Value / std::sqrt(noiseValue);
236 for (
unsigned int i = 0;i < numDirs;++i)
239 if ((tmpVal > logLikelihood)||(i == 0))
240 logLikelihood = tmpVal;
243 double resVal = logLikelihood + log_prior - log_proposal;
250 ListType modelValueList(modelValue.GetSize());
251 for (
unsigned int i = 0;i < modelValue.GetSize();++i)
252 modelValueList[i] = modelValue[i];
254 std::vector < std::vector <double> > initDirs(15);
257 struct XYZ array[] = {
261 {0.1789,0.1113,-0.9776},
262 {0.0635,-0.3767,-0.9242},
263 {-0.7108,-0.0516,-0.7015},
264 {-0.6191,0.4385,-0.6515},
265 {-0.2424,-0.7843,-0.571},
266 {0.2589,0.618,-0.7423},
267 {0.8169,-0.1697,-0.5513},
268 {0.8438,-0.5261,-0.106},
269 {0.2626,-0.9548,-0.1389},
270 {-1e-04,-0.9689,0.2476},
271 {-0.7453,-0.6663,0.0242},
272 {-0.9726,-0.2317,0.0209}
275 for (
unsigned int i = 0;i < initDirs.size();++i)
277 initDirs[i].resize(3);
278 initDirs[i][0] = array[i].
x;
279 initDirs[i][1] = array[i].
y;
280 initDirs[i][2] = array[i].
z;
286 OptimizerType::Pointer opt = OptimizerType::New();
287 opt->SetAlgorithm(NLOPT_LN_BOBYQA);
288 opt->SetXTolRel(1.0e-4);
289 opt->SetFTolRel(1.0e-6);
290 opt->SetMaxEval(200);
291 opt->SetVectorStorageSize(2000);
293 typedef std::map < double, Vector3DType > MapType;
296 std::vector <double> angle;
297 OptimizerType::ParametersType tmpValue(2);
301 itk::Array<double> lowerBounds(2);
302 itk::Array<double> upperBounds(2);
304 lowerBounds.fill(0.0);
305 upperBounds[0] = M_PI;
306 upperBounds[1] = 2.0 * M_PI;
308 opt->SetLowerBoundParameters(lowerBounds);
309 opt->SetUpperBoundParameters(upperBounds);
311 for (
unsigned int i = 0; i < initDirs.size();++i)
314 tmpValue[0] = angle[0];
315 tmpValue[1] = angle[1];
317 CostFunctionType::Pointer cost = CostFunctionType::New();
318 cost->SetODFSHOrder(m_ODFSHOrder);
319 cost->SetBasisParameters(modelValueList);
321 opt->SetCostFunction(cost);
322 opt->SetMaximize(
true);
324 opt->SetInitialPosition(tmpValue);
325 opt->StartOptimization();
327 tmpValue = opt->GetCurrentPosition();
328 tmpValueVector[0] = tmpValue[0];
329 tmpValueVector[1] = tmpValue[1];
333 dmap[opt->GetValue()] = cartesianVector;
337 std::vector <bool> usefulMaxima(15,
true);
338 unsigned int pos = 0;
339 for (MapType::reverse_iterator it = dmap.rbegin();it != dmap.rend();++it)
341 unsigned int posIn = pos+1;
342 MapType::reverse_iterator itin = it;
344 for (;itin != dmap.rend();++itin)
347 usefulMaxima[posIn] =
false;
357 for (MapType::reverse_iterator it = dmap.rbegin();it != dmap.rend();++it)
359 if ((usefulMaxima[pos])&&((*it).first > minVal))
360 maxima.push_back((*it).second);
367 std::vector <bool> outOfPlaneDirs(maxima.size(),
false);
368 for (
unsigned int i = 0;i < maxima.size();++i)
373 for (
unsigned int j = 0;j < InputModelImageType::ImageDimension - 1;++j)
374 norm += maxima[i][j] * maxima[i][j];
377 outOfPlaneDirs[i] = (std::abs(norm) < 0.5);
379 if (!outOfPlaneDirs[i])
381 for (
unsigned int j = 0;j < InputModelImageType::ImageDimension - 1;++j)
382 maxima[i][j] /= norm;
388 for (
unsigned int i = 0;i < maxima.size();++i)
390 if (!outOfPlaneDirs[i])
391 outMaxima.push_back(maxima[i]);
397 return maxima.size();
404 modelValue.Fill(0.0);
406 if (modelInterpolator->IsInsideBuffer(index))
407 modelValue = modelInterpolator->EvaluateAtContinuousIndex(index);
412 double sumSquares = 0;
414 sumSquares += modelValue[i]*modelValue[i];
416 return std::sqrt(1.0 - modelValue[0]*modelValue[0]/sumSquares);
double getCurvatureAtPosition(const T &coefficients, double theta, double phi)
void TransformSphericalToCartesianCoordinates(const VectorType &v, VectorType &resVec)
virtual bool CheckModelProperties(double estimatedB0Value, double estimatedNoiseValue, VectorType &modelValue, unsigned int threadId) ITK_OVERRIDE
Implements an ITK wrapper for the NLOPT library.
unsigned int FindODFMaxima(const VectorType &modelValue, DirectionVectorType &maxima, double minVal, bool is2d)
Returns ODF maxima ordered by probability of diffusion, only those with probability superior to minVa...
InputModelImageType * GetInputModelImage()
void PrepareTractography() ITK_OVERRIDE
Generate seed points.
virtual double GetKappaOfPriorDistribution()
double EvaluateWatsonPDF(const VectorType &v, const VectorType &meanAxis, const ScalarType &kappa)
virtual InitialDirectionModeType GetInitialDirectionMode()
ODFProbabilisticTractographyImageFilter()
virtual unsigned int GetModelDimension()
itk::Vector< ScalarType, 3 > Vector3DType
virtual Vector3DType ProposeNewDirection(Vector3DType &oldDirection, VectorType &modelValue, Vector3DType &sampling_direction, double &log_prior, double &log_proposal, std::mt19937 &random_generator, unsigned int threadId) ITK_OVERRIDE
double ComputeOrientationAngle(const VectorType &v1, const VectorType &v2)
double GetGeneralizedFractionalAnisotropy(VectorType &modelValue)
virtual void ComputeModelValue(InterpolatorPointer &modelInterpolator, ContinuousIndexType &index, VectorType &modelValue) ITK_OVERRIDE
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
double safe_log(const ScalarType x)
virtual void SetModelDimension(unsigned int _arg)
std::vector< ScalarType > ListType
virtual void PrepareTractography()
Generate seed points (can be re-implemented but this one has to be called)
itk::VariableLengthVector< ScalarType > VectorType
InterpolatorType::ContinuousIndexType ContinuousIndexType
virtual Vector3DType InitializeFirstIterationFromModel(Vector3DType &colinearDir, VectorType &modelValue, unsigned int threadId) ITK_OVERRIDE
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)
InterpolatorType::Pointer InterpolatorPointer
void SampleFromWatsonDistribution(const ScalarType &kappa, const VectorType &meanDirection, VectorType &resVec, unsigned int DataDimension, std::mt19937 &generator)
virtual double ComputeLogWeightUpdate(double b0Value, double noiseValue, Vector3DType &newDirection, VectorType &modelValue, double &log_prior, double &log_proposal, unsigned int threadId) ITK_OVERRIDE
double getValueAtPosition(const T &coefficients, double theta, double phi)
virtual ~ODFProbabilisticTractographyImageFilter()
std::vector< Vector3DType > DirectionVectorType