17 m_TestedParameters[i] = parameters[i];
29 unsigned int numT2Signals = m_T2RelaxometrySignals.size();
30 unsigned int numDistributions = m_GammaMeans.size();
34 if (!m_ConstrainedParameters)
36 for (
unsigned int i = 1;i < numParameters;++i)
37 m_GammaMeans[i] = m_TestedParameters[i];
40 m_GammaMeans[1] = m_TestedParameters[1];
42 double b1Value = m_TestedParameters[0];
49 m_PredictedSignalAttenuations.set_size(numT2Signals,numDistributions);
58 for (
unsigned int i = 0;i < numDistributions;++i)
64 double minInterestZoneValue = std::max(0.0, m_GammaMeans[i] - 5.0 * std::sqrt(m_GammaVariances[i]));
65 double theoreticalMinValue = m_GammaMeans[i] - i * std::sqrt(m_GammaVariances[i]);
66 double maxInterestZoneValue = m_GammaMeans[i] + 5.0 * std::sqrt(m_GammaVariances[i]);
67 if (theoreticalMinValue < 0.0)
68 maxInterestZoneValue -= theoreticalMinValue;
72 for (
unsigned int j = 0;j < numT2Signals;++j)
79 m_CholeskyMatrix.set_size(numDistributions,numDistributions);
80 m_FSignals.SetSize(numDistributions);
82 for (
unsigned int i = 0;i < numDistributions;++i)
85 for (
unsigned int j = 0;j < numT2Signals;++j)
86 m_FSignals[i] += m_PredictedSignalAttenuations(j,i) * m_T2RelaxometrySignals[j];
88 for (
unsigned int j = i;j < numDistributions;++j)
90 m_CholeskyMatrix(i,j) = 0;
91 for (
unsigned int k = 0;k < numT2Signals;++k)
92 m_CholeskyMatrix(i,j) += m_PredictedSignalAttenuations(k,i) * m_PredictedSignalAttenuations(k,j);
95 m_CholeskyMatrix(j,i) = m_CholeskyMatrix(i,j);
103 bool nnlsNeeded =
false;
105 for (
unsigned int i = 0;i < numDistributions;++i)
107 if (m_OptimalT2Weights[i] <= 0.0)
116 m_NNLSBordersOptimizer->SetDataMatrix(m_CholeskyMatrix);
117 m_NNLSBordersOptimizer->SetPoints(m_FSignals);
118 m_NNLSBordersOptimizer->SetSquaredProblem(
true);
119 m_NNLSBordersOptimizer->StartOptimization();
121 m_OptimalT2Weights = m_NNLSBordersOptimizer->GetCurrentPosition();
124 m_CompartmentSwitches.resize(numDistributions);
125 for (
unsigned int i = 0;i < numDistributions;++i)
127 if (m_OptimalT2Weights[i] > 0.0)
128 m_CompartmentSwitches[i] =
true;
131 m_CompartmentSwitches[i] =
false;
132 m_OptimalT2Weights[i] = 0.0;
136 m_Residuals.set_size(numT2Signals);
142 unsigned int numT2Signals = m_T2RelaxometrySignals.size();
143 unsigned int numDistributions = m_GammaMeans.size();
147 for (
unsigned int i = 0;i < numT2Signals;++i)
149 m_Residuals[i] = m_T2RelaxometrySignals[i];
150 for (
unsigned int j = 0;j < numDistributions;++j)
151 m_Residuals[i] -= m_PredictedSignalAttenuations(i,j) * m_OptimalT2Weights[j];
153 m_SigmaSquare += m_Residuals[i] * m_Residuals[i];
156 m_SigmaSquare /= numT2Signals;
162 unsigned int nbValues = m_T2RelaxometrySignals.size();
163 unsigned int numDistributions = m_GammaMeans.size();
166 unsigned int numOnDistributions = m_GramMatrix.rows();
169 for (
unsigned int i = 0;i < m_TestedParameters.size();++i)
171 if (m_TestedParameters[i] != parameters[i])
173 std::cerr << parameters << std::endl;
174 itkExceptionMacro(
"Get derivative not called with the same parameters as GetValue, suggestive of NaN...");
179 derivative.set_size(numParameters);
181 MatrixType derivativeMatrix(nbValues, numParameters);
182 derivativeMatrix.fill(0.0);
184 std::vector <double> DFw(nbValues,0.0);
185 std::vector <double> tmpVec(numOnDistributions,0.0);
187 for (
unsigned int k = 0;k < numParameters;++k)
190 std::fill(DFw.begin(),DFw.end(),0.0);
191 for (
unsigned int i = 0;i < nbValues;++i)
194 for (
unsigned int j = 0;j < numDistributions;++j)
195 DFw[i] += m_SignalAttenuationsJacobian[k](i,j) * m_OptimalT2Weights[j];
199 unsigned int pos = 0;
200 for (
unsigned int j = 0;j < numDistributions;++j)
202 if (!m_CompartmentSwitches[j])
207 for (
unsigned int i = 0;i < nbValues;++i)
208 tmpVec[pos] += m_PredictedSignalAttenuations(i,j) * DFw[i] - m_SignalAttenuationsJacobian[k](i,j) * m_Residuals[i];
214 for (
unsigned int i = 0;i < nbValues;++i)
216 double derivativeVal = - DFw[i];
218 for (
unsigned int j = 0;j < numOnDistributions;++j)
219 derivativeVal += m_FMatrixInverseG(i,j) * tmpVec[j];
221 derivativeMatrix(i,k) = derivativeVal;
225 bool problem =
false;
226 for (
unsigned int i = 0;i < numParameters;++i)
228 if (!std::isfinite(derivativeMatrix(0,i)))
237 std::cerr <<
"Derivative matrix: " << derivativeMatrix << std::endl;
238 std::cerr <<
"Optimal weights: " << m_OptimalT2Weights << std::endl;
239 std::cerr <<
"Gram matrix: " << m_GramMatrix << std::endl;
240 std::cerr <<
"Residuals: " << m_Residuals << std::endl;
242 std::cerr <<
"Params: " << parameters << std::endl;
243 itkExceptionMacro(
"Non finite derivative");
246 derivative.set_size(numParameters);
248 for (
unsigned int i = 0;i < numParameters;++i)
251 for (
unsigned int j = 0;j < nbValues;++j)
252 derivative[i] += m_Residuals[j] * derivativeMatrix(j,i);
254 derivative[i] *= 2.0 / m_SigmaSquare;
261 unsigned int numT2Signals = m_T2RelaxometrySignals.size();
262 unsigned int numDistributions = m_GammaMeans.size();
264 unsigned int numOnDistributions = 0;
265 for (
unsigned int i = 0;i < numDistributions;++i)
266 numOnDistributions += m_CompartmentSwitches[i];
271 MatrixType zeroMatrix(numT2Signals, numDistributions, 0.0);
273 m_SignalAttenuationsJacobian.resize(numParameters);
274 std::fill(m_SignalAttenuationsJacobian.begin(),m_SignalAttenuationsJacobian.end(),zeroMatrix);
276 m_GramMatrix.set_size(numOnDistributions,numOnDistributions);
277 m_InverseGramMatrix.set_size(numOnDistributions,numOnDistributions);
279 unsigned int posX = 0;
280 unsigned int posY = 0;
281 for (
unsigned int i = 0;i < numDistributions;++i)
283 if (!m_CompartmentSwitches[i])
286 m_GramMatrix(posX,posX) = m_CholeskyMatrix(i,i);
288 for (
unsigned int j = i + 1;j < numDistributions;++j)
290 if (!m_CompartmentSwitches[j])
293 m_GramMatrix(posX,posY) = m_CholeskyMatrix(i,j);
294 m_GramMatrix(posY,posX) = m_GramMatrix(posX,posY);
301 if (numOnDistributions > 0)
302 m_leCalculator->GetTensorPower(m_GramMatrix,m_InverseGramMatrix,-1.0);
305 m_FMatrixInverseG.set_size(numT2Signals,numOnDistributions);
306 for (
unsigned int i = 0;i < numT2Signals;++i)
308 for (
unsigned int j = 0;j < numOnDistributions;++j)
310 m_FMatrixInverseG(i,j) = 0.0;
311 unsigned int posK = 0;
312 for (
unsigned int k = 0;k < numDistributions;++k)
314 if (!m_CompartmentSwitches[k])
317 m_FMatrixInverseG(i,j) += m_PredictedSignalAttenuations(i,k) * m_InverseGramMatrix(posK,j);
323 double b1Value = m_TestedParameters[0];
333 for (
unsigned int i = 0;i < numDistributions;++i)
338 epgDerivativeVectors.clear();
340 double minInterestZoneValue = std::max(0.0, m_GammaMeans[i] - 5.0 * std::sqrt(m_GammaVariances[i]));
341 double theoreticalMinValue = m_GammaMeans[i] - i * std::sqrt(m_GammaVariances[i]);
342 double maxInterestZoneValue = m_GammaMeans[i] + 5.0 * std::sqrt(m_GammaVariances[i]);
343 if (theoreticalMinValue < 0.0)
344 maxInterestZoneValue -= theoreticalMinValue;
348 for (
unsigned int j = 0;j < numT2Signals;++j)
353 m_SignalAttenuationsJacobian[0](j,i) = glQuad.
GetIntegralValue(t2DerivativeIntegrand);
356 if ((i == 1)||(!m_ConstrainedParameters))
359 unsigned int index = 1 + (!m_ConstrainedParameters) * i;
360 m_SignalAttenuationsJacobian[index](j,i) = glQuad.
GetIntegralValue(t2DerivativeIntegrand);
void SetT1Value(double val)
double GetIntegralValue(FunctionType integrand)
Superclass::ParametersType ParametersType
Computes the Gauss Laguerre quadrature of a function defined from R^+ into R. Recenters the function ...
void SetFlipAngle(double val)
vnl_matrix< double > MatrixType
void PrepareDataForLLS() const
virtual MeasureType GetValue(const ParametersType ¶meters) const ITK_OVERRIDE
void PerformDecomposition()
Performs LDL decomposition from input matrix.
void SetInputMatrix(const MatrixType &matrix)
Set input matrix to decompose.
Superclass::MeasureType MeasureType
void SetB1DerivativeFlag(bool val)
void SetGammaVariance(double val)
Integrand to compute the internal integral per distribution in B1GammaMixtureT2RelaxometryCostFunctio...
void SolveLinearLeastSquares() const
Computes maximum likelihood estimates of weights.
Superclass::DerivativeType DerivativeType
VectorType & SolveLinearSystem(const VectorType &b)
Solves linear system Ax=b and outputs result in new variable.
void SetEchoSpacing(double val)
void SetExcitationFlipAngle(double val)
void SetInterestZone(double minVal, double maxVal)
Specifies region on which the main part of the function is to be seen. If not specified, R^+ is the region.
unsigned int GetNumberOfParameters() const ITK_OVERRIDE
void PrepareDataForDerivative() const
virtual void GetDerivative(const ParametersType ¶meters, DerivativeType &derivative) const ITK_OVERRIDE
void SetNumberOfEchoes(unsigned int val)
void SetGammaMean(double val)
std::map< double, anima::EPGSignalSimulator::RealVectorType > EPGVectorsMapType
Integrand to compute the internal derivative integral per distribution in B1GammaMixtureT2Relaxometry...
void SetEchoNumber(unsigned int val)