11 m_LowPassGaussianSigma = 2000;
12 m_ForceApproximation =
false;
13 m_SquaredDistance =
true;
21 double oldVal = m_SmallDelta;
30 double oldVal = m_BigDelta;
39 m_GradientStrengths = val;
41 if ((m_GradientDirections.size() == m_GradientStrengths.size())&&(m_GradientStrengths.size() != 0)&&(m_GradientDirections.size() != 0))
47 m_GradientDirections = val;
49 if ((m_GradientDirections.size() == m_GradientStrengths.size())&&(m_GradientStrengths.size() != 0)&&(m_GradientDirections.size() != 0))
55 std::vector <double> individualGradientStrengths;
56 for (
unsigned int i = 0;i < m_GradientStrengths.size();++i)
58 bool alreadyIn =
false;
59 for (
unsigned int j = 0;j < individualGradientStrengths.size();++j)
61 if (individualGradientStrengths[j] == m_GradientStrengths[i])
69 individualGradientStrengths.push_back(m_GradientStrengths[i]);
72 std::sort(individualGradientStrengths.begin(),individualGradientStrengths.end());
74 if (individualGradientStrengths[0] != 0)
76 m_GradientStrengths.push_back(0);
79 m_GradientDirections.push_back(tmpVec);
80 individualGradientStrengths.insert(individualGradientStrengths.begin(),0);
83 m_SphereWeights.resize(individualGradientStrengths.size());
84 m_BValWeightsIndexes.resize(m_GradientStrengths.size());
87 for (
unsigned int i = 0;i < individualGradientStrengths.size();++i)
89 unsigned int numValues = 0;
90 for (
unsigned int j = 0;j < m_GradientStrengths.size();++j)
92 if (m_GradientStrengths[j] == individualGradientStrengths[i])
95 m_BValWeightsIndexes[j] = i;
99 double lowerRadius = 0;
100 double baseValue = 0;
106 lowerRadius = (bValueCenter + bValueBefore) / 2.0;
107 baseValue = bValueBefore;
110 double upperRadius = lastBValue + lowerRadius - baseValue;
111 if (i < individualGradientStrengths.size() - 1)
114 upperRadius = (bValueCenter + bValueAfter) / 2.0;
117 lowerRadius = std::sqrt(2.0 * lowerRadius);
118 upperRadius = std::sqrt(2.0 * upperRadius);
120 m_SphereWeights[i] = 4 * M_PI * (std::pow(upperRadius,3.0) - std::pow(lowerRadius,3.0)) / (3.0 * numValues);
128 if (tensorCompatibility)
136 if (m_ForceApproximation)
139 for (
unsigned int i = 0;i < firstModel->GetNumberOfCompartments();++i)
141 if (!firstModel->GetCompartment(i)->GetTensorCompatible())
145 for (
unsigned int i = 0;i < secondModel->GetNumberOfCompartments();++i)
147 if (!secondModel->GetCompartment(i)->GetTensorCompatible())
156 unsigned int fixedNumCompartments = firstModel->GetNumberOfCompartments();
157 unsigned int movingNumCompartments = secondModel->GetNumberOfCompartments();
159 std::vector < vnl_matrix_fixed <double, 3, 3> > firstModelMatrices(fixedNumCompartments);
160 std::vector < vnl_matrix_fixed <double, 3, 3> > secondModelMatrices(movingNumCompartments);
161 std::vector <double> firstModelWeights(fixedNumCompartments);
162 std::vector <double> secondModelWeights(movingNumCompartments);
164 unsigned int pos = 0;
165 for (
unsigned int i = 0;i < fixedNumCompartments;++i)
167 if (firstModel->GetCompartmentWeight(i) == 0)
170 firstModelMatrices[pos] = firstModel->GetCompartment(i)->GetDiffusionTensor().GetVnlMatrix();
171 firstModelWeights[pos] = firstModel->GetCompartmentWeight(i);
175 fixedNumCompartments = pos;
177 if (fixedNumCompartments == 0)
180 firstModelMatrices.resize(fixedNumCompartments);
181 firstModelWeights.resize(fixedNumCompartments);
184 for (
unsigned int i = 0;i < movingNumCompartments;++i)
186 if (secondModel->GetCompartmentWeight(i) == 0)
189 secondModelMatrices[pos] = secondModel->GetCompartment(i)->GetDiffusionTensor().GetVnlMatrix();
190 secondModelWeights[pos] = secondModel->GetCompartmentWeight(i);
194 movingNumCompartments = pos;
196 if (movingNumCompartments == 0)
199 secondModelMatrices.resize(movingNumCompartments);
200 secondModelWeights.resize(movingNumCompartments);
202 double metricValue = 0;
203 double pi23half = std::pow(2.0 * M_PI,1.5);
205 vnl_matrix <double> workMatrix(3,3);
206 for (
unsigned int i = 0;i < fixedNumCompartments;++i)
208 double currentFixedWeight = firstModelWeights[i];
209 for (
unsigned int j = 0;j < 3;++j)
211 workMatrix(j,j) = 2.0 * firstModelMatrices[i](j,j) + 1.0 / m_LowPassGaussianSigma;
212 for (
unsigned int k = j+1;k < 3;++k)
214 workMatrix(j,k) = 2.0 * firstModelMatrices[i](j,k);
215 workMatrix(k,j) = workMatrix(j,k);
219 metricValue += currentFixedWeight * currentFixedWeight * pi23half / std::sqrt(vnl_determinant <double> (workMatrix));
221 for (
unsigned int j = i+1;j < fixedNumCompartments;++j)
223 double secondFixedWeight = firstModelWeights[j];
224 for (
unsigned int k = 0;k < 3;++k)
226 workMatrix(k,k) = firstModelMatrices[i](k,k) + firstModelMatrices[j](k,k) + 1.0 / m_LowPassGaussianSigma;
227 for (
unsigned int l = k+1;l < 3;++l)
229 workMatrix(k,l) = firstModelMatrices[i](k,l) + firstModelMatrices[j](k,l);
230 workMatrix(l,k) = workMatrix(k,l);
234 metricValue += 2.0 * currentFixedWeight * secondFixedWeight * pi23half / std::sqrt(vnl_determinant <double> (workMatrix));
237 for (
unsigned int j = 0;j < movingNumCompartments;++j)
239 double currentMovingWeight = secondModelWeights[j];
240 for (
unsigned int k = 0;k < 3;++k)
242 workMatrix(k,k) = firstModelMatrices[i](k,k) + secondModelMatrices[j](k,k) + 1.0 / m_LowPassGaussianSigma;
243 for (
unsigned int l = k+1;l < 3;++l)
245 workMatrix(k,l) = firstModelMatrices[i](k,l) + secondModelMatrices[j](k,l);
246 workMatrix(l,k) = workMatrix(k,l);
250 metricValue -= 2.0 * currentFixedWeight * currentMovingWeight * pi23half / std::sqrt(vnl_determinant <double> (workMatrix));
254 for (
unsigned int i = 0;i < movingNumCompartments;++i)
256 double currentMovingWeight = secondModelWeights[i];
257 for (
unsigned int j = 0;j < 3;++j)
259 workMatrix(j,j) = 2.0 * secondModelMatrices[i](j,j) + 1.0 / m_LowPassGaussianSigma;
260 for (
unsigned int k = j+1;k < 3;++k)
262 workMatrix(j,k) = 2.0 * secondModelMatrices[i](j,k);
263 workMatrix(k,j) = workMatrix(j,k);
267 metricValue += currentMovingWeight * currentMovingWeight * pi23half / std::sqrt(vnl_determinant <double> (workMatrix));
269 for (
unsigned int j = i+1;j < movingNumCompartments;++j)
271 double secondMovingWeight = secondModelWeights[j];
272 for (
unsigned int k = 0;k < 3;++k)
274 workMatrix(k,k) = secondModelMatrices[i](k,k) + secondModelMatrices[j](k,k) + 1.0 / m_LowPassGaussianSigma;
275 for (
unsigned int l = k+1;l < 3;++l)
277 workMatrix(k,l) = secondModelMatrices[i](k,l) + secondModelMatrices[j](k,l);
278 workMatrix(l,k) = workMatrix(k,l);
282 metricValue += 2.0 * currentMovingWeight * secondMovingWeight * pi23half / std::sqrt(vnl_determinant <double> (workMatrix));
289 if (m_SquaredDistance)
292 return std::sqrt(metricValue);
297 if ((m_GradientStrengths.size() == 0)||(m_GradientDirections.size() == 0)||(m_GradientStrengths.size() != m_GradientDirections.size()))
298 itkExceptionMacro(
"Problem in metric: b-values and gradient directions not correctly set");
300 double metricValue = 0;
301 for (
unsigned int i = 0;i < m_GradientStrengths.size();++i)
303 double firstCFValue = firstModel->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
304 double secondCFValue = secondModel->GetPredictedSignal(m_SmallDelta, m_BigDelta, m_GradientStrengths[i], m_GradientDirections[i]);
307 metricValue += m_SphereWeights[m_BValWeightsIndexes[i]] * (firstCFValue - secondCFValue) * (firstCFValue - secondCFValue);
313 if (m_SquaredDistance)
316 return std::sqrt(metricValue);
void SetGradientDirections(const std::vector< GradientType > &val)
double ComputeTensorDistance(const MCMPointer &firstModel, const MCMPointer &secondModel) const
void SetBigDelta(double val)
MCMType::Vector3DType GradientType
bool CheckTensorCompatibility(const MCMPointer &firstModel, const MCMPointer &secondModel) const
double ComputeApproximateDistance(const MCMPointer &firstModel, const MCMPointer &secondModel) const
void UpdateSphereWeights()
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)
MCMType::Pointer MCMPointer
void SetSmallDelta(double val)
void SetGradientStrengths(const std::vector< double > &val)
double ComputeDistance(const MCMPointer &firstModel, const MCMPointer &secondModel) const