5 #include <itkImageRegionIterator.h> 6 #include <itkImageRegionConstIterator.h> 7 #include <itkSymmetricEigenAnalysis.h> 30 template <
class InputPixelType,
class OutputPixelType>
35 if (i == m_GradientDirections.size())
36 m_GradientDirections.push_back(grad);
37 else if (i > m_GradientDirections.size())
38 std::cerr <<
"Trying to add a direction not contiguous... Add directions contiguously (0,1,2,3,...)..." << std::endl;
40 m_GradientDirections[i] = grad;
43 template <
class InputPixelType,
class OutputPixelType>
51 template <
class InputPixelType,
class OutputPixelType>
59 this->Superclass::GenerateOutputInformation();
74 output->SetVectorLength(tmpMCM->GetSize());
80 template <
class InputPixelType,
class OutputPixelType>
85 MCMPointer tmpMCM = m_MCMCreators[0]->GetNewMultiCompartmentModel();
88 MCMFileWriterType writer;
91 writer.SetFileName(fileName);
96 template <
class InputPixelType,
class OutputPixelType>
101 if (this->GetComputationMask())
104 typedef itk::ImageRegionConstIterator <InputImageType> B0IteratorType;
105 typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
107 unsigned int firstB0Index = 0;
109 while (bValueFirstB0Index > 10)
115 B0IteratorType b0Itr(this->GetInput(firstB0Index),this->GetOutput()->GetLargestPossibleRegion());
117 if (!this->GetComputationMask())
118 this->Superclass::CheckComputationMask();
120 MaskIteratorType maskItr(this->GetComputationMask(),this->GetOutput()->GetLargestPossibleRegion());
122 while (!b0Itr.IsAtEnd())
124 if ((maskItr.Get() != 0)&&(b0Itr.Get() <= m_B0Threshold))
132 template <
class InputPixelType,
class OutputPixelType>
137 if ((m_Optimizer ==
"levenberg")&&((m_MLEstimationStrategy == Marginal)||(m_NoiseType != Gaussian)))
138 itkExceptionMacro(
"Levenberg Marquardt optimizer only working with Gaussian noise and variable projection");
140 if ((m_Optimizer !=
"bobyqa")&&(m_UseCommonDiffusivities||m_UseCommonExtraAxonalFractions||m_UseCommonConcentrations))
141 itkExceptionMacro(
"Derivative based optimizers not supported yet for common parameters, use Bobyqa instead");
143 if ((m_NoiseType == NCC)&&(m_MLEstimationStrategy != Profile))
144 itkExceptionMacro(
"NCC noise is only compatible with profile estimation strategy");
146 m_NumberOfImages = this->GetNumberOfIndexedInputs();
148 if (m_GradientStrengths.size() != m_NumberOfImages)
149 itkExceptionMacro(
"There should be the same number of input images and input b-values...");
151 itk::ImageRegionIterator <OutputImageType> fillOut(this->GetOutput(),this->GetOutput()->GetLargestPossibleRegion());
152 unsigned int outSize = this->GetOutput()->GetNumberOfComponentsPerPixel();
153 typename OutputImageType::PixelType emptyModelVec(outSize);
154 emptyModelVec.Fill(0);
156 while (!fillOut.IsAtEnd())
158 fillOut.Set(emptyModelVec);
163 m_AICcVolume = OutputScalarImageType::New();
164 m_AICcVolume->Initialize();
165 m_AICcVolume->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
166 m_AICcVolume->SetSpacing (this->GetInput(0)->GetSpacing());
167 m_AICcVolume->SetOrigin (this->GetInput(0)->GetOrigin());
168 m_AICcVolume->SetDirection (this->GetInput(0)->GetDirection());
169 m_AICcVolume->Allocate();
170 m_AICcVolume->FillBuffer(0);
173 m_B0Volume = OutputScalarImageType::New();
174 m_B0Volume->Initialize();
175 m_B0Volume->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
176 m_B0Volume->SetSpacing (this->GetInput(0)->GetSpacing());
177 m_B0Volume->SetOrigin (this->GetInput(0)->GetOrigin());
178 m_B0Volume->SetDirection (this->GetInput(0)->GetDirection());
179 m_B0Volume->Allocate();
180 m_B0Volume->FillBuffer(0);
183 m_SigmaSquareVolume = OutputScalarImageType::New();
184 m_SigmaSquareVolume->Initialize();
185 m_SigmaSquareVolume->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
186 m_SigmaSquareVolume->SetSpacing (this->GetInput(0)->GetSpacing());
187 m_SigmaSquareVolume->SetOrigin (this->GetInput(0)->GetOrigin());
188 m_SigmaSquareVolume->SetDirection (this->GetInput(0)->GetDirection());
189 m_SigmaSquareVolume->Allocate();
190 m_SigmaSquareVolume->FillBuffer(0);
195 m_MoseVolume = MoseImageType::New();
196 m_MoseVolume->Initialize();
197 m_MoseVolume->SetRegions(this->GetInput(0)->GetLargestPossibleRegion());
198 m_MoseVolume->SetSpacing (this->GetInput(0)->GetSpacing());
199 m_MoseVolume->SetOrigin (this->GetInput(0)->GetOrigin());
200 m_MoseVolume->SetDirection (this->GetInput(0)->GetDirection());
201 m_MoseVolume->Allocate();
202 m_MoseVolume->FillBuffer(0);
205 if (m_ExternalMoseVolume)
206 m_FindOptimalNumberOfCompartments =
false;
208 Superclass::BeforeThreadedGenerateData();
210 m_MCMCreators.resize(this->GetNumberOfWorkUnits());
211 for (
unsigned int i = 0;i < this->GetNumberOfWorkUnits();++i)
212 m_MCMCreators[i] = this->GetNewMCMCreatorInstance();
214 std::cout <<
"Initial diffusivities:" << std::endl;
215 std::cout <<
" - Axial diffusivity: " << m_AxialDiffusivityValue <<
" mm2/s," << std::endl;
216 std::cout <<
" - Radial diffusivity 1: " << m_RadialDiffusivity1Value <<
" mm2/s," << std::endl;
217 std::cout <<
" - Radial diffusivity 2: " << m_RadialDiffusivity2Value <<
" mm2/s," << std::endl;
219 if (m_ModelWithRestrictedWaterComponent)
220 std::cout <<
" - IRW diffusivity: " << m_IRWDiffusivityValue <<
" mm2/s," << std::endl;
222 if (m_ModelWithStaniszComponent)
223 std::cout <<
" - Stanisz diffusivity: " << m_StaniszDiffusivityValue <<
" mm2/s," << std::endl;
226 for (
unsigned int i = 0;i < this->GetNumberOfWorkUnits();++i)
228 m_MCMCreators[i]->SetAxialDiffusivityValue(m_AxialDiffusivityValue);
229 m_MCMCreators[i]->SetFreeWaterDiffusivityValue(3.0e-3);
230 m_MCMCreators[i]->SetIRWDiffusivityValue(m_IRWDiffusivityValue);
231 m_MCMCreators[i]->SetStaniszDiffusivityValue(m_StaniszDiffusivityValue);
232 m_MCMCreators[i]->SetRadialDiffusivity1Value(m_RadialDiffusivity1Value);
233 m_MCMCreators[i]->SetRadialDiffusivity2Value(m_RadialDiffusivity2Value);
237 switch (m_CompartmentType)
241 this->ComputeExtraAxonalAndKappaCoarseGrids();
245 this->ComputeTensorRadialDiffsAndAzimuthCoarseGrids();
254 this->InitializeDictionary();
257 template <
class InputPixelType,
class OutputPixelType>
263 std::vector <double> fakeIsotropicDirection(3,0);
265 unsigned int countIsoComps = 0;
266 if (m_ModelWithFreeWaterComponent)
268 m_DictionaryDirections.insert(m_DictionaryDirections.begin(),fakeIsotropicDirection);
272 if (m_ModelWithStationaryWaterComponent)
274 m_DictionaryDirections.insert(m_DictionaryDirections.begin(),fakeIsotropicDirection);
278 if (m_ModelWithRestrictedWaterComponent)
280 m_DictionaryDirections.insert(m_DictionaryDirections.begin(),fakeIsotropicDirection);
284 if (m_ModelWithStaniszComponent)
286 m_DictionaryDirections.insert(m_DictionaryDirections.begin(),fakeIsotropicDirection);
290 m_SparseSticksDictionary.set_size(m_NumberOfImages,countIsoComps + m_NumberOfDictionaryEntries);
291 m_SparseSticksDictionary.fill(0.0);
302 if (m_ModelWithFreeWaterComponent)
308 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
309 m_SparseSticksDictionary(i,countIsoComps) = mcm->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
314 if (m_ModelWithStationaryWaterComponent)
320 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
321 m_SparseSticksDictionary(i,countIsoComps) = mcm->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
326 if (m_ModelWithRestrictedWaterComponent)
332 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
333 m_SparseSticksDictionary(i,countIsoComps) = mcm->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
338 if (m_ModelWithStaniszComponent)
344 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
345 m_SparseSticksDictionary(i,countIsoComps) = mcm->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
355 for (
unsigned int i = 0;i < m_NumberOfDictionaryEntries;++i)
358 m_DictionaryDirections[i + countIsoComps]);
360 mcm->GetCompartment(0)->SetOrientationTheta(m_DictionaryDirections[i + countIsoComps][0]);
361 mcm->GetCompartment(0)->SetOrientationPhi(m_DictionaryDirections[i + countIsoComps][1]);
364 m_DictionaryDirections[i + countIsoComps]);
366 for (
unsigned int j = 0;j < m_NumberOfImages;++j)
367 m_SparseSticksDictionary(j,countIsoComps + i) = mcm->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[j], m_GradientDirections[j]);
371 template <
class InputPixelType,
class OutputPixelType>
377 m_ValuesCoarseGrid.resize(2);
379 unsigned int coarseGridSize = 8;
380 m_ValuesCoarseGrid[0].resize(coarseGridSize);
381 m_ValuesCoarseGrid[1].resize(coarseGridSize);
389 double power = 1.385829;
390 double halfLife = 5.312364;
391 for (
unsigned int i = 0;i < coarseGridSize;++i)
393 double tmpVal = (i + 1.0) / (coarseGridSize + 1.0);
394 m_ValuesCoarseGrid[0][i] = tmpVal;
395 m_ValuesCoarseGrid[1][i] = std::pow(tmpVal * halfLife / (1.0 - tmpVal), 1.0 / power);
399 template <
class InputPixelType,
class OutputPixelType>
407 m_ValuesCoarseGrid.resize(3);
409 unsigned int coarseGridSize = 8;
410 for (
unsigned int i = 0;i < 3;++i)
411 m_ValuesCoarseGrid[i].resize(coarseGridSize);
413 for (
unsigned int i = 0;i < coarseGridSize;++i)
415 m_ValuesCoarseGrid[0][i] = 2.0 * (i + 1) * M_PI / (coarseGridSize + 1.0);
416 m_ValuesCoarseGrid[1][i] = i / (coarseGridSize - 1.0);
417 m_ValuesCoarseGrid[2][i] = i / (coarseGridSize - 1.0);
421 template <
class InputPixelType,
class OutputPixelType>
426 typedef itk::ImageRegionConstIterator <InputImageType> ConstImageIteratorType;
428 std::vector <ConstImageIteratorType> inIterators(m_NumberOfImages);
429 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
430 inIterators[i] = ConstImageIteratorType(this->GetInput(i),outputRegionForThread);
432 typedef itk::ImageRegionIterator <OutputImageType> OutImageIteratorType;
433 OutImageIteratorType outIterator(this->GetOutput(),outputRegionForThread);
435 typedef itk::ImageRegionIterator <MaskImageType> MaskIteratorType;
436 MaskIteratorType maskItr(this->GetComputationMask(),outputRegionForThread);
438 typedef itk::ImageRegionIterator <OutputScalarImageType> ImageIteratorType;
439 ImageIteratorType aiccIterator(m_AICcVolume, outputRegionForThread);
440 ImageIteratorType b0Iterator(m_B0Volume, outputRegionForThread);
441 ImageIteratorType sigmaIterator(m_SigmaSquareVolume, outputRegionForThread);
443 typedef itk::ImageRegionIterator <MoseImageType> MoseIteratorType;
444 MoseIteratorType moseIterator(m_MoseVolume, outputRegionForThread);
446 std::vector <double> observedSignals(m_NumberOfImages,0);
448 typename OutputImageType::PixelType resVec(this->GetOutput()->GetNumberOfComponentsPerPixel());
451 MCMPointer outputMCMData = this->GetOutput()->GetDescriptionModel()->Clone();
454 double aiccValue, b0Value, sigmaSqValue;
456 unsigned int threadId = this->GetSafeThreadId();
458 while (!outIterator.IsAtEnd())
462 if (maskItr.Get() == 0)
464 outIterator.Set(resVec);
466 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
480 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
481 observedSignals[i] = inIterators[i].Get();
484 bool estimateNonIsoCompartments =
false;
485 if (m_ExternalMoseVolume)
487 moseValue = moseIterator.Get();
489 estimateNonIsoCompartments =
true;
491 else if (m_NumberOfCompartments > 0)
492 estimateNonIsoCompartments =
true;
494 bool hasIsoCompartment = m_ModelWithFreeWaterComponent || m_ModelWithRestrictedWaterComponent || m_ModelWithStationaryWaterComponent || m_ModelWithStaniszComponent;
495 if (estimateNonIsoCompartments)
498 unsigned int minimalNumberOfCompartments = m_NumberOfCompartments;
499 unsigned int maximalNumberOfCompartments = m_NumberOfCompartments;
500 if (m_FindOptimalNumberOfCompartments)
502 minimalNumberOfCompartments = 1;
505 if (hasIsoCompartment)
506 this->EstimateFreeWaterModel(mcmData,observedSignals,threadId,aiccValue,b0Value,sigmaSqValue);
508 else if (moseValue != -1)
510 int numMoseCompartments = std::min(moseValue,(
int)m_NumberOfCompartments);
511 minimalNumberOfCompartments = numMoseCompartments;
512 maximalNumberOfCompartments = numMoseCompartments;
515 for (
unsigned int i = minimalNumberOfCompartments;i <= maximalNumberOfCompartments;++i)
517 double tmpB0Value = 0;
518 double tmpSigmaSqValue = 0;
519 double tmpAiccValue = 0;
522 this->OptimizeNonIsotropicCompartments(mcmValue,i,observedSignals,threadId,tmpAiccValue,tmpB0Value,tmpSigmaSqValue);
524 if ((tmpAiccValue < aiccValue)||(!m_FindOptimalNumberOfCompartments))
526 aiccValue = tmpAiccValue;
527 if (m_FindOptimalNumberOfCompartments)
529 b0Value = tmpB0Value;
530 sigmaSqValue = tmpSigmaSqValue;
535 else if (hasIsoCompartment)
536 this->EstimateFreeWaterModel(mcmData,observedSignals,threadId,aiccValue,b0Value,sigmaSqValue);
538 itkExceptionMacro(
"Nothing to estimate...");
540 if (outputMCMData->GetNumberOfCompartments() != mcmData->GetNumberOfCompartments())
543 std::fill(outputWeights.begin(),outputWeights.end(),0.0);
544 for (
unsigned int i = 0;i < mcmData->GetNumberOfCompartments();++i)
546 outputMCMData->GetCompartment(i)->CopyFromOther(mcmData->GetCompartment(i));
547 outputWeights[i] = mcmData->GetCompartmentWeight(i);
550 outputMCMData->SetCompartmentWeights(outputWeights);
551 resVec = outputMCMData->GetModelVector();
554 resVec = mcmData->GetModelVector();
556 outIterator.Set(resVec);
557 aiccIterator.Set(aiccValue);
558 b0Iterator.Set(b0Value);
559 sigmaIterator.Set(sigmaSqValue);
560 moseIterator.Set(mcmData->GetNumberOfCompartments() - mcmData->GetNumberOfIsotropicCompartments());
562 for (
unsigned int i = 0;i < m_NumberOfImages;++i)
565 this->IncrementNumberOfProcessedPoints();
574 this->SafeReleaseThreadId(threadId);
577 template <
class InputPixelType,
class OutputPixelType>
581 std::vector <double> &observedSignals, itk::ThreadIdType threadId,
582 double &aiccValue,
double &b0Value,
double &sigmaSqValue)
588 this->InitialOrientationsEstimation(mcmValue,
false,currentNumberOfCompartments,observedSignals,threadId,
589 aiccValue,b0Value,sigmaSqValue);
591 this->ModelEstimation(mcmValue,
false,observedSignals,threadId,aiccValue,b0Value,sigmaSqValue);
595 this->InitialOrientationsEstimation(mcmValue,
true,currentNumberOfCompartments,observedSignals,threadId,
596 aiccValue,b0Value,sigmaSqValue);
598 this->ModelEstimation(mcmValue,
true,observedSignals,threadId,aiccValue,b0Value,sigmaSqValue);
605 for (
unsigned int i = 0;i < outputWeights.size();++i)
606 outputWeights[i] /= b0Value;
608 mcmValue->SetCompartmentWeights(outputWeights);
612 template <
class InputPixelType,
class OutputPixelType>
616 double &aiccValue,
double &b0Value,
double &sigmaSqValue)
638 unsigned int dimension = mcmValue->GetNumberOfParameters();
642 workVec = mcmValue->GetParametersAsVector();
643 for (
unsigned int i = 0;i < dimension;++i)
646 double costValue = this->GetCostValue(cost,p);
647 itk::Array<double> lowerBounds(dimension), upperBounds(dimension);
651 workVec = mcmValue->GetParameterLowerBounds();
652 for (
unsigned int i = 0;i < dimension;++i)
653 lowerBounds[i] = workVec[i];
655 workVec = mcmValue->GetParameterUpperBounds();
656 for (
unsigned int i = 0;i < dimension;++i)
657 upperBounds[i] = workVec[i];
659 costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
662 for (
unsigned int i = 0;i < dimension;++i)
665 mcmValue->SetParametersFromVector(workVec);
668 this->GetProfiledInformation(cost,mcmValue,b0Value,sigmaSqValue);
669 aiccValue = this->ComputeAICcValue(mcmValue,costValue);
674 mcmValue->SetNegativeWeightBounds(
true);
675 costValue = this->GetCostValue(cost,p);
679 workVec = mcmValue->GetParameterLowerBounds();
680 for (
unsigned int i = 0;i < dimension;++i)
681 lowerBounds[i] = workVec[i];
683 workVec = mcmValue->GetParameterUpperBounds();
684 for (
unsigned int i = 0;i < dimension;++i)
685 upperBounds[i] = workVec[i];
687 workVec = mcmValue->GetParametersAsVector();
688 for (
unsigned int i = 0;i < dimension;++i)
691 costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
694 for (
unsigned int i = 0;i < dimension;++i)
697 mcmValue->SetParametersFromVector(workVec);
700 this->GetProfiledInformation(cost,mcmValue,b0Value,sigmaSqValue);
701 aiccValue = this->ComputeAICcValue(mcmValue,costValue);
708 for (
unsigned int i = 0;i < outputWeights.size();++i)
709 outputWeights[i] /= b0Value;
711 mcmValue->SetCompartmentWeights(outputWeights);
715 template <
class InputPixelType,
class OutputPixelType>
721 if (m_NoiseType != Gaussian)
722 itkExceptionMacro(
"Cost function type not supported");
725 if (m_MLEstimationStrategy != VariableProjection)
728 internalCost->SetMarginalEstimation(m_MLEstimationStrategy == Marginal);
729 baseCost = internalCost;
734 baseCost = internalCost;
737 baseCost->SetObservedSignals(observedSignals);
738 baseCost->SetGradients(m_GradientDirections);
739 baseCost->SetSmallDelta(m_SmallDelta);
740 baseCost->SetBigDelta(m_BigDelta);
741 baseCost->SetGradientStrengths(m_GradientStrengths);
742 baseCost->SetMCMStructure(mcmModel);
744 if (m_Optimizer ==
"levenberg")
749 tmpCost->SetInternalCost(baseCost);
751 returnCost = tmpCost;
758 tmpCost->SetInternalCost(baseCost);
760 returnCost = tmpCost;
766 template <
class InputPixelType,
class OutputPixelType>
770 std::vector <double> &observedSignals, itk::ThreadIdType threadId,
771 double &aiccValue,
double &b0Value,
double &sigmaSqValue)
797 mcmUpdateValue->SetNegativeWeightBounds(authorizedNegativeB0Value);
800 this->SparseInitializeSticks(mcmUpdateValue,authorizedNegativeB0Value,observedSignals,threadId);
802 unsigned int dimension = mcmUpdateValue->GetNumberOfParameters();
805 itk::Array<double> lowerBounds(dimension), upperBounds(dimension);
807 workVec = mcmUpdateValue->GetParameterLowerBounds();
808 for (
unsigned int j = 0;j < dimension;++j)
809 lowerBounds[j] = workVec[j];
811 workVec = mcmUpdateValue->GetParameterUpperBounds();
812 for (
unsigned int j = 0;j < dimension;++j)
813 upperBounds[j] = workVec[j];
818 workVec = mcmUpdateValue->GetParametersAsVector();
819 for (
unsigned int j = 0;j < dimension;++j)
822 double costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
825 for (
unsigned int j = 0;j < dimension;++j)
828 mcmUpdateValue->SetParametersFromVector(workVec);
830 this->GetProfiledInformation(cost,mcmUpdateValue,b0Value,sigmaSqValue);
832 aiccValue = this->ComputeAICcValue(mcmUpdateValue,costValue);
833 mcmValue = mcmUpdateValue;
836 template <
class InputPixelType,
class OutputPixelType>
840 double &aiccValue,
double &b0Value,
double &sigmaSqValue)
842 unsigned int optimalNumberOfCompartments = mcmValue->GetNumberOfCompartments() - mcmValue->GetNumberOfIsotropicCompartments();
845 if ((m_CompartmentType ==
Stick)&&(m_UseConstrainedDiffusivity))
855 mcmUpdateValue->SetNegativeWeightBounds(authorizedNegativeB0Value);
858 this->InitializeModelFromSimplifiedOne(mcmValue,mcmUpdateValue);
862 unsigned int dimension = mcmUpdateValue->GetNumberOfParameters();
865 itk::Array<double> lowerBounds(dimension), upperBounds(dimension);
867 workVec = mcmUpdateValue->GetParameterLowerBounds();
868 for (
unsigned int i = 0;i < dimension;++i)
869 lowerBounds[i] = workVec[i];
871 workVec = mcmUpdateValue->GetParameterUpperBounds();
872 for (
unsigned int i = 0;i < dimension;++i)
873 upperBounds[i] = workVec[i];
875 workVec = mcmUpdateValue->GetParametersAsVector();
876 for (
unsigned int i = 0;i < dimension;++i)
879 double costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
880 this->GetProfiledInformation(cost,mcmUpdateValue,b0Value,sigmaSqValue);
882 for (
unsigned int i = 0;i < dimension;++i)
885 mcmUpdateValue->SetParametersFromVector(workVec);
887 mcmValue = mcmUpdateValue;
888 aiccValue = this->ComputeAICcValue(mcmValue,costValue);
890 if ((m_CompartmentType ==
Stick)||(b0Value == 0.0))
897 mcmUpdateValue->SetNegativeWeightBounds(authorizedNegativeB0Value);
900 this->InitializeModelFromSimplifiedOne(mcmValue,mcmUpdateValue);
903 cost = this->CreateCostFunction(observedSignals,mcmUpdateValue);
904 dimension = mcmUpdateValue->GetNumberOfParameters();
905 p.SetSize(dimension);
906 lowerBounds.SetSize(dimension);
907 upperBounds.SetSize(dimension);
909 workVec = mcmUpdateValue->GetParameterLowerBounds();
910 for (
unsigned int i = 0;i < dimension;++i)
911 lowerBounds[i] = workVec[i];
913 workVec = mcmUpdateValue->GetParameterUpperBounds();
914 for (
unsigned int i = 0;i < dimension;++i)
915 upperBounds[i] = workVec[i];
917 workVec = mcmUpdateValue->GetParametersAsVector();
918 for (
unsigned int i = 0;i < dimension;++i)
921 costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
922 this->GetProfiledInformation(cost,mcmUpdateValue,b0Value,sigmaSqValue);
924 for (
unsigned int i = 0;i < dimension;++i)
927 mcmUpdateValue->SetParametersFromVector(workVec);
929 mcmValue = mcmUpdateValue;
930 aiccValue = this->ComputeAICcValue(mcmValue,costValue);
932 if ((m_CompartmentType ==
Zeppelin)||(b0Value == 0.0))
944 mcmUpdateValue->SetNegativeWeightBounds(authorizedNegativeB0Value);
947 this->InitializeModelFromSimplifiedOne(mcmValue,mcmUpdateValue);
950 cost = this->CreateCostFunction(observedSignals,mcmUpdateValue);
951 dimension = mcmUpdateValue->GetNumberOfParameters();
952 p.SetSize(dimension);
953 lowerBounds.SetSize(dimension);
954 upperBounds.SetSize(dimension);
956 workVec = mcmUpdateValue->GetParameterLowerBounds();
957 for (
unsigned int i = 0;i < dimension;++i)
958 lowerBounds[i] = workVec[i];
960 workVec = mcmUpdateValue->GetParameterUpperBounds();
961 for (
unsigned int i = 0;i < dimension;++i)
962 upperBounds[i] = workVec[i];
964 switch (m_CompartmentType)
968 this->ExtraAxonalAndKappaCoarseGridInitialization(mcmUpdateValue, cost, workVec, p);
972 this->TensorCoarseGridInitialization(mcmUpdateValue, cost, workVec, p);
976 itkExceptionMacro(
"No coarse grid initialization for simple models, shouldn't be here");
980 workVec = mcmUpdateValue->GetParametersAsVector();
981 for (
unsigned int i = 0;i < dimension;++i)
984 costValue = this->PerformSingleOptimization(p,cost,lowerBounds,upperBounds);
985 this->GetProfiledInformation(cost,mcmUpdateValue,b0Value,sigmaSqValue);
987 for (
unsigned int i = 0;i < dimension;++i)
990 mcmUpdateValue->SetParametersFromVector(workVec);
992 mcmValue = mcmUpdateValue;
993 aiccValue = this->ComputeAICcValue(mcmValue,costValue);
996 template <
class InputPixelType,
class OutputPixelType>
1002 unsigned int dimension = p.GetSize();
1004 double optKappa = 0;
1005 double optValue = -1.0;
1007 unsigned int numIsoCompartments = mcmUpdateValue->GetNumberOfIsotropicCompartments();
1008 unsigned int numCompartments = mcmUpdateValue->GetNumberOfCompartments();
1010 for (
unsigned int j = 0;j < m_ValuesCoarseGrid[1].size();++j)
1012 double tmpKappa = m_ValuesCoarseGrid[1][j];
1014 for (
unsigned int k = 0;k < m_ValuesCoarseGrid[0].size();++k)
1016 double tmpNu = m_ValuesCoarseGrid[0][k];
1018 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1020 mcmUpdateValue->GetCompartment(i)->SetOrientationConcentration(tmpKappa);
1021 mcmUpdateValue->GetCompartment(i)->SetExtraAxonalFraction(tmpNu);
1024 workVec = mcmUpdateValue->GetParametersAsVector();
1025 for (
unsigned int i = 0;i < dimension;++i)
1028 double tmpValue = this->GetCostValue(cost,p);
1030 if ((tmpValue < optValue) || (optValue < 0))
1032 optValue = tmpValue;
1033 optKappa = tmpKappa;
1039 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1041 mcmUpdateValue->GetCompartment(i)->SetOrientationConcentration(optKappa);
1042 mcmUpdateValue->GetCompartment(i)->SetExtraAxonalFraction(optNu);
1046 template <
class InputPixelType,
class OutputPixelType>
1052 unsigned int dimension = p.GetSize();
1053 unsigned int numIsoCompartments = mcmUpdateValue->GetNumberOfIsotropicCompartments();
1054 unsigned int numCompartments = mcmUpdateValue->GetNumberOfCompartments();
1056 double optRadialDiff1 = 0.0;
1057 double optRadialDiff2 = 0.0;
1058 double optAzimuth = 0.0;
1059 double optValue = - 1.0;
1061 double meanAxialDiff = 0.0;
1062 double meanRadialDiff = 0.0;
1063 unsigned int numUsefulCompartments = 0;
1065 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1067 if (mcmUpdateValue->GetCompartmentWeight(i) > 0)
1069 meanAxialDiff += mcmUpdateValue->GetCompartment(i)->GetAxialDiffusivity();
1070 meanRadialDiff += mcmUpdateValue->GetCompartment(i)->GetRadialDiffusivity1();
1072 ++numUsefulCompartments;
1076 if (numUsefulCompartments > 0)
1078 meanAxialDiff /= numUsefulCompartments;
1079 meanRadialDiff /= numUsefulCompartments;
1083 meanAxialDiff = m_AxialDiffusivityValue;
1084 meanRadialDiff = (m_RadialDiffusivity1Value + m_RadialDiffusivity2Value) / 2.0;
1090 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1091 mcmUpdateValue->GetCompartment(i)->SetAxialDiffusivity(meanAxialDiff);
1093 for (
unsigned int l = 0;l < m_ValuesCoarseGrid[2].size();++l)
1095 double tmpWeight2 = m_ValuesCoarseGrid[2][l];
1100 for (
unsigned int k = 0;k < m_ValuesCoarseGrid[1].size();++k)
1102 double tmpWeight1 = m_ValuesCoarseGrid[1][k];
1105 double tmpRadialDiffusivity1 = 0.5 * ((1.0 + tmpWeight1) * meanRadialDiff + (1.0 - tmpWeight1) * meanAxialDiff);
1106 if (meanAxialDiff - tmpRadialDiffusivity1 < anima::MCMAxialDiffusivityAddonLowerBound)
1109 for (
unsigned int j = 0;j < m_ValuesCoarseGrid[0].size();++j)
1111 double tmpAzimuth = m_ValuesCoarseGrid[0][j];
1113 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1115 mcmUpdateValue->GetCompartment(i)->SetPerpendicularAngle(tmpAzimuth);
1116 mcmUpdateValue->GetCompartment(i)->SetRadialDiffusivity1(tmpRadialDiffusivity1);
1117 mcmUpdateValue->GetCompartment(i)->SetRadialDiffusivity2(tmpRadialDiffusivity2);
1120 workVec = mcmUpdateValue->GetParametersAsVector();
1121 for (
unsigned int i = 0;i < dimension;++i)
1124 double tmpValue = this->GetCostValue(cost,p);
1126 if ((tmpValue < optValue) || (optValue < 0))
1128 optValue = tmpValue;
1129 optRadialDiff1 = tmpRadialDiffusivity1;
1130 optRadialDiff2 = tmpRadialDiffusivity2;
1131 optAzimuth = tmpAzimuth;
1137 for (
unsigned int i = numIsoCompartments;i < numCompartments;++i)
1139 mcmUpdateValue->GetCompartment(i)->SetPerpendicularAngle(optAzimuth);
1140 mcmUpdateValue->GetCompartment(i)->SetRadialDiffusivity1(optRadialDiff1);
1141 mcmUpdateValue->GetCompartment(i)->SetRadialDiffusivity2(optRadialDiff2);
1145 template <
class InputPixelType,
class OutputPixelType>
1151 double xTol = m_XTolerance;
1152 bool defaultTol =
false;
1153 if (m_XTolerance == 0)
1159 unsigned int maxEvals = m_MaxEval;
1161 maxEvals = 400 * lowerBounds.GetSize();
1163 if (m_Optimizer !=
"levenberg")
1167 if (m_Optimizer ==
"bobyqa")
1169 tmpOpt->SetAlgorithm(NLOPT_LN_BOBYQA);
1173 else if (m_Optimizer ==
"ccsaq")
1174 tmpOpt->SetAlgorithm(NLOPT_LD_CCSAQ);
1175 else if (m_Optimizer ==
"bfgs")
1176 tmpOpt->SetAlgorithm(NLOPT_LD_LBFGS);
1178 double fTol = m_FTolerance;
1179 if (m_FTolerance == 0)
1180 fTol = 1.0e-2 * xTol;
1184 tmpOpt->SetCostFunction(costCast);
1186 tmpOpt->SetMaximize(
false);
1187 tmpOpt->SetXTolRel(xTol);
1188 tmpOpt->SetFTolRel(fTol);
1189 tmpOpt->SetMaxEval(maxEvals);
1190 tmpOpt->SetVectorStorageSize(2000);
1192 tmpOpt->SetLowerBoundParameters(lowerBounds);
1193 tmpOpt->SetUpperBoundParameters(upperBounds);
1199 if (m_MLEstimationStrategy == Marginal)
1200 itkExceptionMacro(
"Levenberg Marquardt optimizer not supported with marginal optimization");
1203 LevenbergMarquardtOptimizerType::Pointer tmpOpt = LevenbergMarquardtOptimizerType::New();
1208 double fTol = m_FTolerance;
1209 if (m_FTolerance == 0)
1210 fTol = 1.0e-2 * xTol;
1212 tmpOpt->SetCostFunction(costCast);
1213 tmpOpt->SetCostTolerance(fTol);
1214 tmpOpt->SetNumberOfIterations(maxEvals);
1215 tmpOpt->SetValueTolerance(xTol);
1217 tmpOpt->SetLowerBounds(lowerBounds);
1218 tmpOpt->SetUpperBounds(upperBounds);
1226 template <
class InputPixelType,
class OutputPixelType>
1231 double costValue = this->GetCostValue(cost,p);
1233 OptimizerPointer optimizer = this->CreateOptimizer(cost,lowerBounds,upperBounds);
1235 optimizer->SetInitialPosition(p);
1236 optimizer->StartOptimization();
1238 p = optimizer->GetCurrentPosition();
1242 for (
unsigned int i = 0;i < p.GetSize();++i)
1244 if (p[i] < lowerBounds[i])
1245 p[i] = lowerBounds[i];
1247 if (p[i] > upperBounds[i])
1248 p[i] = upperBounds[i];
1251 costValue = this->GetCostValue(cost,p);
1256 template <
class InputPixelType,
class OutputPixelType>
1261 if (m_Optimizer ==
"levenberg")
1276 template <
class InputPixelType,
class OutputPixelType>
1281 unsigned int numCompartments = mcm->GetNumberOfCompartments();
1284 if (m_Optimizer ==
"levenberg")
1302 for (
unsigned int i = 0;i < numCompartments;++i)
1303 b0Value += tmpWeights[i];
1305 if (m_MLEstimationStrategy == VariableProjection)
1306 mcm->SetCompartmentWeights(tmpWeights);
1309 template <
class InputPixelType,
class OutputPixelType>
1316 double nbparams = mcmValue->GetNumberOfParameters() + 1.0;
1319 double AICc = costValue + 2.0 * nbparams + 2.0 * nbparams * (nbparams + 1.0) / (m_NumberOfImages - nbparams - 1.0)
1320 + m_NumberOfImages * std::log(m_NumberOfImages / (m_NumberOfImages - nbparams - 1.0));
1325 template <
class InputPixelType,
class OutputPixelType>
1329 itk::ThreadIdType threadId)
1331 unsigned int numIsotropicComponents = complexModel->GetNumberOfIsotropicCompartments();
1332 unsigned int numNonIsotropicComponents = complexModel->GetNumberOfCompartments() - numIsotropicComponents;
1333 unsigned int numCompartments = complexModel->GetNumberOfCompartments();
1337 sparseOptimizer->SetDataMatrix(m_SparseSticksDictionary);
1339 unsigned int dictionarySize = m_SparseSticksDictionary.cols();
1340 unsigned int numSignals = observedSignals.size();
1342 for (
unsigned int i = 0;i < numSignals;++i)
1343 rightHandValues[i] = observedSignals[i];
1345 if (authorizeNegativeB0Value)
1346 rightHandValues *= -1;
1348 sparseOptimizer->SetPoints(rightHandValues);
1349 sparseOptimizer->SetSquaredProblem(
false);
1350 sparseOptimizer->StartOptimization();
1353 ParametersType dictionaryWeights = sparseOptimizer->GetCurrentPosition();
1354 std::vector <unsigned int> nonNullAtomIndexes;
1356 double totalWeightsSum = 0.0;
1357 double sumWeights = 0.0;
1358 for (
unsigned int i = 0;i < numIsotropicComponents;++i)
1360 totalWeightsSum += dictionaryWeights[i];
1361 sumWeights += dictionaryWeights[i];
1362 dictionaryWeights[i] = 0;
1365 std::sort(dictionaryWeights.begin(),dictionaryWeights.end());
1367 unsigned int numRealAnisotropicCompartments = dictionarySize;
1368 for (
int i = dictionarySize - 1;i >= 0;--i)
1370 if (dictionaryWeights[i] == 0.0)
1372 numRealAnisotropicCompartments = dictionarySize - 1 - i;
1376 totalWeightsSum += dictionaryWeights[i];
1379 unsigned int thrIndex = dictionarySize - std::max(numNonIsotropicComponents,static_cast <unsigned int>(std::floor(numRealAnisotropicCompartments * 0.75)));
1383 double thrWeight = dictionaryWeights[thrIndex];
1384 double maxDictionaryWeight = dictionaryWeights[dictionarySize - 1];
1385 dictionaryWeights = sparseOptimizer->GetCurrentPosition();
1387 for (
unsigned int i = numIsotropicComponents;i < dictionarySize;++i)
1389 if ((dictionaryWeights[i] > thrWeight) && (dictionaryWeights[i] > maxDictionaryWeight / 10.0))
1391 nonNullAtomIndexes.push_back(i);
1392 sumWeights += dictionaryWeights[i];
1396 numRealAnisotropicCompartments = nonNullAtomIndexes.size();
1398 for (
unsigned int i = 0;i < numIsotropicComponents;++i)
1400 if (!authorizeNegativeB0Value)
1401 sparseWeights[i] = dictionaryWeights[i];
1403 sparseWeights[i] = - dictionaryWeights[i];
1406 std::vector <double> tmpDirection(3,0.0);
1407 if (numRealAnisotropicCompartments <= numNonIsotropicComponents)
1413 numCompartments = complexModel->GetNumberOfCompartments();
1414 sparseWeights.resize(numCompartments);
1416 for (
unsigned int i = numIsotropicComponents;i < numCompartments;++i)
1418 unsigned int iIndex = i - numIsotropicComponents;
1420 if (!authorizeNegativeB0Value)
1421 sparseWeights[i] = dictionaryWeights[nonNullAtomIndexes[iIndex]];
1423 sparseWeights[i] = - dictionaryWeights[nonNullAtomIndexes[iIndex]];
1432 complexModel->SetCompartmentWeights(sparseWeights);
1437 vnl_matrix <double> directionsDistanceMatrix(numRealAnisotropicCompartments, numRealAnisotropicCompartments);
1438 for (
unsigned int i = 0;i < numRealAnisotropicCompartments;++i)
1440 directionsDistanceMatrix(i,i) = 0;
1441 for (
unsigned int j = i + 1;j < numRealAnisotropicCompartments;++j)
1443 double dotProduct = std::abs(
anima::ComputeScalarProduct(m_DictionaryDirections[nonNullAtomIndexes[i]],m_DictionaryDirections[nonNullAtomIndexes[j]]));
1444 if (dotProduct > 1.0)
1447 double acosValue = std::acos(dotProduct);
1448 directionsDistanceMatrix(i,j) = acosValue * acosValue;
1449 directionsDistanceMatrix(j,i) = directionsDistanceMatrix(i,j);
1454 SpectralClusterFilterType spectralClustering;
1455 spectralClustering.
SetInputData(directionsDistanceMatrix);
1456 spectralClustering.SetNbClass(numNonIsotropicComponents);
1457 spectralClustering.SetMaxIterations(200);
1458 spectralClustering.SetVerbose(
false);
1459 spectralClustering.InitializeSigmaFromDistances();
1460 spectralClustering.SetCMeansAverageType(SpectralClusterFilterType::CMeansFilterType::Euclidean);
1462 spectralClustering.Update();
1465 std::vector <double> classMemberships;
1466 vnl_matrix <double> dcmMatrix(3,3);
1467 typedef vnl_matrix <double> EigenMatrixType;
1468 typedef vnl_vector_fixed <double,3> EigenVectorType;
1469 typedef itk::SymmetricEigenAnalysis <EigenMatrixType,EigenVectorType,EigenMatrixType> EigenAnalysisType;
1470 EigenAnalysisType eigSystem(3);
1471 EigenMatrixType eigVecs(3,3);
1472 EigenVectorType eigVals;
1473 eigSystem.SetOrderEigenValues(
true);
1476 for (
unsigned int i = 0;i < numNonIsotropicComponents;++i)
1478 dcmMatrix.fill(0.0);
1479 double weightComponent = 0.0;
1480 for (
unsigned int j = 0;j < numRealAnisotropicCompartments;++j)
1482 classMemberships = spectralClustering.GetClassesMembership(j);
1483 unsigned int atomIndex = nonNullAtomIndexes[j];
1484 double membershipWeight = classMemberships[i];
1485 weightComponent += membershipWeight * dictionaryWeights[atomIndex];
1486 for (
unsigned int k = 0;k < 3;++k)
1488 dcmMatrix(k,k) += membershipWeight * dictionaryWeights[atomIndex] * m_DictionaryDirections[atomIndex][k] * m_DictionaryDirections[atomIndex][k];
1490 for (
unsigned int l = k + 1;l < 3;++l)
1492 double tmpValue = membershipWeight * dictionaryWeights[atomIndex] * m_DictionaryDirections[atomIndex][k] * m_DictionaryDirections[atomIndex][l];
1493 dcmMatrix(k,l) += tmpValue;
1494 dcmMatrix(l,k) += tmpValue;
1499 eigSystem.ComputeEigenValuesAndVectors(dcmMatrix, eigVals, eigVecs);
1500 for (
unsigned int j = 0;j < 3;++j)
1501 tmpDirection[j] = eigVecs(2,j);
1509 if (!authorizeNegativeB0Value)
1510 sparseWeights[i + numIsotropicComponents] = weightComponent;
1512 sparseWeights[i + numIsotropicComponents] = - weightComponent;
1516 for (
unsigned int i = numIsotropicComponents;i < numCompartments;++i)
1518 if (!authorizeNegativeB0Value)
1519 sparseWeights[i] += (totalWeightsSum - sumWeights) / numNonIsotropicComponents;
1521 sparseWeights[i] += (sumWeights - totalWeightsSum) / numNonIsotropicComponents;
1524 complexModel->SetCompartmentWeights(sparseWeights);
1527 template <
class InputPixelType,
class OutputPixelType>
1533 unsigned int numCompartments = complexModel->GetNumberOfCompartments();
1534 if (numCompartments != simplifiedModel->GetNumberOfCompartments())
1535 itkExceptionMacro(
"Simplified and complex model should have the same number of components.");
1537 for (
unsigned int i = 0;i < numCompartments;++i)
1538 complexModel->GetCompartment(i)->CopyFromOther(simplifiedModel->GetCompartment(i));
1541 complexModel->SetCompartmentWeights(simplifiedModel->GetCompartmentWeights());
itk::SmartPointer< Self > Pointer
void TensorCoarseGridInitialization(MCMPointer &mcmUpdateValue, CostFunctionBasePointer &cost, MCMType::ListType &workVec, ParametersType &p)
Coarse grid initialization of tensor model.
OptimizerType::ParametersType ParametersType
MCMPointer GetNewMultiCompartmentModel()
InternalCostType::MCMPointer & GetMCMStructure()
void TransformSphericalToCartesianCoordinates(const VectorType &v, VectorType &resVec)
itk::SmartPointer< Self > Pointer
virtual void InitializeModelFromSimplifiedOne(MCMPointer &simplifiedModel, MCMPointer &complexModel)
Performs initialization from simplified model with the same number of compartments.
void SetNumberOfCompartments(unsigned int num)
void SetUseConstrainedFreeWaterDiffusivity(bool arg)
void SetUseConstrainedStaniszRadius(bool arg)
void SetUseConstrainedDiffusivity(bool arg)
void EstimateFreeWaterModel(MCMPointer &mcmValue, std::vector< double > &observedSignals, itk::ThreadIdType threadId, double &aiccValue, double &b0Value, double &sigmaSqValue)
Specific method for N=0 compartments estimation (only free water)
double PerformSingleOptimization(ParametersType &p, CostFunctionBasePointer &cost, itk::Array< double > &lowerBounds, itk::Array< double > &upperBounds)
Performs an optimization of the supplied cost function and parameters using the specified optimizer(s...
void SetUseCommonExtraAxonalFractions(bool arg)
Levenberg-Marquardt optimizer with lower and upper bounds on parameters Implementation of the origina...
virtual void SparseInitializeSticks(MCMPointer &complexModel, bool authorizeNegativeB0Value, std::vector< double > &observedSignals, itk::ThreadIdType threadId)
Performs initialization from single DTI.
void SetUseConstrainedIRWDiffusivity(bool arg)
InternalCostType::MCMPointer & GetMCMStructure()
BaseCompartment::ListType ListType
void ComputeExtraAxonalAndKappaCoarseGrids()
Computes extra axonal and kappa coarse grids (used for NODDI and DDI initialization) ...
void SetInputData(MatrixType &data)
Input data: matrix of squared distances.
void SetInputImage(InputImageType *input)
double GetBValueFromAcquisitionParameters(double smallDelta, double bigDelta, double gradientStrength)
Given gyromagnetic ratio in rad/s/T, gradient strength in T/mm and deltas in s, computes b-value in s...
void AddGradientDirection(unsigned int i, GradientType &grad)
virtual const InternalCostPointer & GetInternalCost() const
CostFunctionBaseType::Pointer CostFunctionBasePointer
void SetUseCommonDiffusivities(bool arg)
double ComputeAICcValue(MCMPointer &mcmValue, double costValue)
Compute AICc value from a cost function value and model.
void GetProfiledInformation(CostFunctionBasePointer &cost, MCMPointer &mcm, double &b0Value, double &sigmaSqValue)
Utility function to get profiled data from the cost function into an MCM model.
void SetModelWithStationaryWaterComponent(bool arg)
itk::SmartPointer< Self > Pointer
void SetUseConstrainedOrientationConcentration(bool arg)
void ModelEstimation(MCMPointer &mcmValue, bool authorizedNegativeB0Value, std::vector< double > &observedSignals, itk::ThreadIdType threadId, double &aiccValue, double &b0Value, double &sigmaSqValue)
Doing estimation, calling initialization procedure until ball and zeppelin, returns AICc value...
virtual void SetOrientationTheta(double num)
void OptimizeNonIsotropicCompartments(MCMPointer &mcmValue, unsigned int currentNumberOfCompartments, std::vector< double > &observedSignals, itk::ThreadIdType threadId, double &aiccValue, double &b0Value, double &sigmaSqValue)
Doing estimation of non isotropic compartments (for a given number of anisotropic compartments) ...
void ComputeTensorRadialDiffsAndAzimuthCoarseGrids()
Computes extra axonal and kappa coarse grids (used for tensor final initaialization) ...
void GenerateOutputInformation() ITK_OVERRIDE
void SetModelWithStaniszComponent(bool arg)
void WriteMCMOutput(std::string fileName)
void SetModelWithRestrictedWaterComponent(bool arg)
void SetCompartmentType(CompartmentType arg)
OptimizerType::Pointer OptimizerPointer
itk::SmartPointer< Self > Pointer
itk::SmartPointer< Self > Pointer
Superclass::OutputImageRegionType OutputImageRegionType
void SetVariableProjectionEstimationMode(bool arg)
void GetSphereEvenSampling(std::vector< std::vector< ScalarType > > &spherePoints, unsigned int numSamples)
void ExtraAxonalAndKappaCoarseGridInitialization(MCMPointer &mcmUpdateValue, CostFunctionBasePointer &cost, MCMType::ListType &workVec, ParametersType &p)
Coarse grid initialization of NODDI and DDI models.
virtual MeasureType GetValue(const ParametersType ¶meters) const ITK_OVERRIDE
vnl_vector_fixed< double, 3 > GradientType
void SetDescriptionModel(MCMPointer &mcm)
OptimizerPointer CreateOptimizer(CostFunctionBasePointer &cost, itk::Array< double > &lowerBounds, itk::Array< double > &upperBounds)
Create an optimizer following the optimizer type and estimation mode.
void SetUseCommonConcentrations(bool arg)
void InitialOrientationsEstimation(MCMPointer &mcmValue, bool authorizedNegativeB0Value, unsigned int currentNumberOfCompartments, std::vector< double > &observedSignals, itk::ThreadIdType threadId, double &aiccValue, double &b0Value, double &sigmaSqValue)
Doing estimation only of multiple orientations.
double ComputeScalarProduct(const VectorType &v1, const VectorType &v2, const unsigned int NDimension)
virtual void SetOrientationPhi(double num)
const double MCMDiffusivityLowerBound
Diffusivity lower bound for estimation.
itk::SmartPointer< Self > Pointer
virtual MCMCreatorType * GetNewMCMCreatorInstance()
double GetCostValue(CostFunctionBasePointer &cost, ParametersType &p)
Utility function to get a value from a cost function.
virtual void BeforeThreadedGenerateData() ITK_OVERRIDE
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) ITK_OVERRIDE
void SetUseConstrainedExtraAxonalFraction(bool arg)
void CheckComputationMask() ITK_OVERRIDE
void TransformCartesianToSphericalCoordinates(const VectorType &v, VectorType &resVec)
MCMCreatorType::MCMPointer MCMPointer
itk::SmartPointer< Self > Pointer
const double MCMAxialDiffusivityAddonLowerBound
Axial diffusivity add on to lower bound (used to ensure a minimal anisotropy to the anisotropic compa...
Really this class is some simplified factory that creates the MCM that it knows.
void SetModelWithFreeWaterComponent(bool arg)
virtual CostFunctionBasePointer CreateCostFunction(std::vector< double > &observedSignals, MCMPointer &mcmModel)
Create a cost function following the noise type and estimation mode.
void SetUseConstrainedStaniszDiffusivity(bool arg)