4 #include <vnl/vnl_matrix_fixed.h> 7 #include <itkImageRegionConstIteratorWithIndex.h> 17 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
21 m_FixedImagePoints.clear();
22 m_FixedImageValues.clear();
30 m_ZeroDiffusionVector = m_ZeroDiffusionModel->GetModelVector();
34 m_GradientStrengths.clear();
35 m_GradientDirections.clear();
37 m_ForceApproximation =
false;
39 m_LowerBoundGaussianSigma = 0;
40 m_UpperBoundGaussianSigma = 25;
43 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
48 if (m_ForceApproximation)
53 for (
unsigned int i = 0;i < val->GetNumberOfCompartments();++i)
55 if (!val->GetCompartment(i)->GetTensorCompatible())
60 val = movingImage->GetDescriptionModel();
61 for (
unsigned int i = 0;i < val->GetNumberOfCompartments();++i)
63 if (!val->GetCompartment(i)->GetTensorCompatible())
70 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
78 itkExceptionMacro(
"Fixed image has not been assigned");
80 if (this->m_NumberOfPixelsCounted == 0)
83 this->SetTransformParameters( parameters );
91 bool tensorCompatibilityCondition = this->CheckTensorCompatibility();
93 std::vector <MCModelPointer> movingValues(this->m_NumberOfPixelsCounted);
95 for (
unsigned int i = 0;i < this->m_NumberOfPixelsCounted;++i)
97 transformedPoint = this->m_Transform->TransformPoint( m_FixedImagePoints[i] );
98 this->m_Interpolator->GetInputImage()->TransformPhysicalPointToContinuousIndex(transformedPoint,transformedIndex);
100 if( this->m_Interpolator->IsInsideBuffer( transformedIndex ) )
102 movingValue = this->m_Interpolator->EvaluateAtContinuousIndex( transformedIndex );
104 if (!isZero(movingValue))
106 MCModelPointer currentMovingValue = movingImage->GetDescriptionModel()->Clone();
107 currentMovingValue->SetModelVector(movingValue);
109 if (this->GetModelRotation() != Superclass::NONE)
110 currentMovingValue->Reorient(this->m_OrientationMatrix, (this->GetModelRotation() ==
Superclass::PPD));
112 movingValues[i] = currentMovingValue;
115 movingValues[i] = m_ZeroDiffusionModel;
118 movingValues[i] = m_ZeroDiffusionModel;
121 if (tensorCompatibilityCondition)
122 return this->ComputeTensorBasedMetric(movingValues);
124 return this->ComputeNonTensorBasedMetric(movingValues);
127 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
133 typename CostFunctionType::Pointer smootherCostFunction = CostFunctionType::New();
135 smootherCostFunction->SetReferenceModels(m_FixedImageValues);
136 smootherCostFunction->SetMovingModels(movingValues);
137 smootherCostFunction->SetTensorsScale(1000.0);
140 OptimizerType::ParametersType p(smootherCostFunction->GetNumberOfParameters());
141 OptimizerType::ParametersType lowerBounds(smootherCostFunction->GetNumberOfParameters());
142 OptimizerType::ParametersType upperBounds(smootherCostFunction->GetNumberOfParameters());
144 lowerBounds[0] = m_LowerBoundGaussianSigma;
145 upperBounds[0] = m_UpperBoundGaussianSigma;
147 p[0] = m_LowerBoundGaussianSigma + (m_UpperBoundGaussianSigma - m_LowerBoundGaussianSigma) / 10.0;
149 typename OptimizerType::Pointer smoothingOptimizer = OptimizerType::New();
150 smoothingOptimizer->SetAlgorithm(NLOPT_LN_BOBYQA);
151 smoothingOptimizer->SetMaximize(
false);
152 smoothingOptimizer->SetXTolRel(1.0e-8);
153 smoothingOptimizer->SetMaxEval(2000);
154 smoothingOptimizer->SetCostFunction(smootherCostFunction);
156 smoothingOptimizer->SetLowerBoundParameters(lowerBounds);
157 smoothingOptimizer->SetUpperBoundParameters(upperBounds);
159 smoothingOptimizer->SetInitialPosition(p);
160 smoothingOptimizer->StartOptimization();
162 p = smoothingOptimizer->GetCurrentPosition();
163 return smootherCostFunction->GetValue(p);
166 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
172 typename CostFunctionType::Pointer smootherCostFunction = CostFunctionType::New();
174 smootherCostFunction->SetReferenceModels(m_FixedImageValues,m_GradientDirections,
175 m_SmallDelta,m_BigDelta,m_GradientStrengths);
176 smootherCostFunction->SetMovingModels(movingValues,m_GradientDirections,
177 m_SmallDelta,m_BigDelta,m_GradientStrengths);
178 smootherCostFunction->SetGradientDirections(m_GradientDirections);
179 smootherCostFunction->SetSmallDelta(m_SmallDelta);
180 smootherCostFunction->SetBigDelta(m_SmallDelta);
181 smootherCostFunction->SetGradientStrengths(m_GradientStrengths);
182 smootherCostFunction->SetBValueWeightIndexes(m_BValWeightsIndexes);
183 smootherCostFunction->SetSphereWeights(m_SphereWeights);
184 smootherCostFunction->SetParameterScale(1.0e-3);
187 OptimizerType::ParametersType p(smootherCostFunction->GetNumberOfParameters());
188 OptimizerType::ParametersType lowerBounds(smootherCostFunction->GetNumberOfParameters());
189 OptimizerType::ParametersType upperBounds(smootherCostFunction->GetNumberOfParameters());
191 lowerBounds[0] = m_LowerBoundGaussianSigma;
192 upperBounds[0] = m_UpperBoundGaussianSigma;
194 p[0] = m_LowerBoundGaussianSigma + (m_UpperBoundGaussianSigma - m_LowerBoundGaussianSigma) / 10.0;
196 typename OptimizerType::Pointer smoothingOptimizer = OptimizerType::New();
197 smoothingOptimizer->SetAlgorithm(NLOPT_LN_BOBYQA);
198 smoothingOptimizer->SetMaximize(
false);
199 smoothingOptimizer->SetXTolRel(1.0e-8);
200 smoothingOptimizer->SetMaxEval(2000);
201 smoothingOptimizer->SetCostFunction(smootherCostFunction);
203 smoothingOptimizer->SetLowerBoundParameters(lowerBounds);
204 smoothingOptimizer->SetUpperBoundParameters(upperBounds);
206 smoothingOptimizer->SetInitialPosition(p);
207 smoothingOptimizer->StartOptimization();
209 p = smoothingOptimizer->GetCurrentPosition();
210 return smootherCostFunction->GetValue(p);
213 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
218 double oldVal = m_SmallDelta;
222 this->UpdateSphereWeights();
225 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
230 double oldVal = m_BigDelta;
234 this->UpdateSphereWeights();
237 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
242 m_GradientStrengths = val;
244 if ((m_GradientDirections.size() == m_GradientStrengths.size())&&(m_GradientStrengths.size() != 0)&&(m_GradientDirections.size() != 0))
245 this->UpdateSphereWeights();
248 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
253 m_GradientDirections = val;
255 if ((m_GradientDirections.size() == m_GradientStrengths.size())&&(m_GradientStrengths.size() != 0)&&(m_GradientDirections.size() != 0))
256 this->UpdateSphereWeights();
259 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
264 std::vector <double> individualGradientStrengths;
265 for (
unsigned int i = 0;i < m_GradientStrengths.size();++i)
267 bool alreadyIn =
false;
268 for (
unsigned int j = 0;j < individualGradientStrengths.size();++j)
270 if (individualGradientStrengths[j] == m_GradientStrengths[i])
278 individualGradientStrengths.push_back(m_GradientStrengths[i]);
281 std::sort(individualGradientStrengths.begin(),individualGradientStrengths.end());
283 if (individualGradientStrengths[0] != 0)
285 m_GradientStrengths.push_back(0);
288 m_GradientDirections.push_back(tmpVec);
289 individualGradientStrengths.insert(individualGradientStrengths.begin(),0);
292 m_SphereWeights.resize(individualGradientStrengths.size());
293 m_BValWeightsIndexes.resize(m_GradientStrengths.size());
296 for (
unsigned int i = 0;i < individualGradientStrengths.size();++i)
298 unsigned int numValues = 0;
299 for (
unsigned int j = 0;j < m_GradientStrengths.size();++j)
301 if (m_GradientStrengths[j] == individualGradientStrengths[i])
304 m_BValWeightsIndexes[j] = i;
308 double lowerRadius = 0;
309 double baseValue = 0;
315 lowerRadius = (bValueCenter + bValueBefore) / 2.0;
316 baseValue = bValueBefore;
319 double upperRadius = lastBValue + lowerRadius - baseValue;
320 if (i < individualGradientStrengths.size() - 1)
323 upperRadius = (bValueCenter + bValueAfter) / 2.0;
326 lowerRadius = std::sqrt(2.0 * lowerRadius);
327 upperRadius = std::sqrt(2.0 * upperRadius);
329 m_SphereWeights[i] = 4 * M_PI * (std::pow(upperRadius,3.0) - std::pow(lowerRadius,3.0)) / (3.0 * numValues);
333 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
338 unsigned int ndim = vector.GetSize();
340 for (
unsigned int i = 0;i < ndim;++i)
349 template <
class TFixedImagePixelType,
class TMovingImagePixelType,
unsigned int ImageDimension >
354 if(!this->m_FixedImage)
355 itkExceptionMacro( <<
"Fixed image has not been assigned" );
358 this->m_NumberOfPixelsCounted = this->GetFixedImageRegion().GetNumberOfPixels();
359 typedef itk::ImageRegionConstIteratorWithIndex<FixedImageType> FixedIteratorType;
360 FixedIteratorType ti(fixedImage, this->GetFixedImageRegion());
361 typename FixedImageType::IndexType index;
363 m_FixedImagePoints.resize(this->m_NumberOfPixelsCounted);
364 m_FixedImageValues.resize(this->m_NumberOfPixelsCounted);
368 unsigned int pos = 0;
372 index = ti.GetIndex();
373 fixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
375 m_FixedImagePoints[pos] = inputPoint;
376 fixedValue = ti.Get();
378 if (!isZero(fixedValue))
380 m_FixedImageValues[pos] = fixedImage->GetDescriptionModel()->Clone();
381 m_FixedImageValues[pos]->SetModelVector(fixedValue);
385 m_FixedImageValues[pos] = m_ZeroDiffusionModel->Clone();
386 m_FixedImageValues[pos]->SetModelVector(m_ZeroDiffusionVector);
MCMPointer GetNewMultiCompartmentModel()
void SetBigDelta(double val)
void SetNumberOfCompartments(unsigned int num)
TFixedImage::PixelType PixelType
Implements an ITK wrapper for the NLOPT library.
Superclass::MovingImageType MovingImageType
double ComputeNonTensorBasedMetric(const std::vector< MCModelPointer > &movingValues) const
Superclass::TransformParametersType TransformParametersType
void UpdateSphereWeights()
Compute base integration weights for non tensor integration.
void SetGradientDirections(std::vector< GradientType > &val)
const double DiffusionBigDelta
Default big delta value (classical values)
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...
const double DiffusionSmallDelta
Default small delta value (classical values)
bool CheckTensorCompatibility() const
void SetModelWithStationaryWaterComponent(bool arg)
void SetGradientStrengths(std::vector< double > &val)
Superclass::FixedImageConstPointer FixedImageConstPointer
Superclass::OutputPointType OutputPointType
bool isZero(PixelType &vector) const
Superclass::InputPointType InputPointType
itk::ContinuousIndex< double, ImageDimension > ContinuousIndexType
MCMCorrelationImageToImageMetric()
Superclass::MeasureType MeasureType
Superclass::FixedImageType FixedImageType
double ComputeTensorBasedMetric(const std::vector< MCModelPointer > &movingValues) const
void SetSmallDelta(double val)
MeasureType GetValue(const TransformParametersType ¶meters) const ITK_OVERRIDE
MCModelType::Vector3DType GradientType
void PreComputeFixedValues()
Really this class is some simplified factory that creates the MCM that it knows.
void SetModelWithFreeWaterComponent(bool arg)
MCModelType::Pointer MCModelPointer