ANIMA  4.0
animaMCMWeightedAverager.cxx
Go to the documentation of this file.
2 
3 namespace anima
4 {
5 
7 {
8  m_UpToDate = false;
9  m_NumberOfOutputDirectionalCompartments = 3;
10  m_InternalEigenAnalyzer.SetDimension(3);
11  m_InternalEigenAnalyzer.SetOrder(3);
12 
16 
18 }
19 
21 {
22  m_OutputModel = model->Clone();
24 }
25 
27 {
28  m_NumberOfOutputDirectionalCompartments = val;
29  m_UpToDate = false;
30 }
31 
33 {
34  m_NumberOfOutputDirectionalCompartments = m_OutputModel->GetNumberOfCompartments() - m_OutputModel->GetNumberOfIsotropicCompartments();
35  m_UpToDate = false;
36 }
37 
39 {
40  if (!m_UpToDate)
41  this->Update();
42 
43  return m_OutputModel;
44 }
45 
47 {
48  return m_OutputModel;
49 }
50 
52 {
53  if (!m_OutputModel)
54  itkExceptionMacro("Output model not initialized")
55 
56  return m_OutputModel->GetSize();
57 }
58 
60 {
61  if (m_UpToDate)
62  return;
63 
64  if (m_InputModels.size() != m_InputWeights.size())
65  itkExceptionMacro("Not the same number of weights and input models");
66 
67  unsigned int numInputs = m_InputModels.size();
68  // First make sure weights sum up to 1
69  double sumWeights = 0;
70  for (unsigned int i = 0;i < numInputs;++i)
71  sumWeights += m_InputWeights[i];
72 
73  for (unsigned int i = 0;i < numInputs;++i)
74  m_InputWeights[i] /= sumWeights;
75 
76  // Perform isotropic models average
77  unsigned int numIsoCompartments = m_InputModels[0]->GetNumberOfIsotropicCompartments();
78  m_InternalOutputWeights.resize(m_OutputModel->GetNumberOfCompartments());
79  std::fill(m_InternalOutputWeights.begin(),m_InternalOutputWeights.end(),0.0);
80 
81  for (unsigned int i = 0;i < numIsoCompartments;++i)
82  {
83  double outputLogDiffusivity = 0;
84  double outputRadius = 0.0;
85  double sumWeights = 0;
86  for (unsigned int j = 0;j < numInputs;++j)
87  {
88  if (m_InputWeights[j] <= 0)
89  continue;
90 
91  double tmpWeight = m_InputModels[j]->GetCompartmentWeight(i);
92  if (tmpWeight <= 0)
93  continue;
94 
95  m_InternalOutputWeights[i] += m_InputWeights[j] * tmpWeight;
96  outputLogDiffusivity += m_InputWeights[j] * std::log(m_InputModels[j]->GetCompartment(i)->GetAxialDiffusivity());
97  outputRadius += m_InputWeights[j] * m_InputModels[j]->GetCompartment(i)->GetTissueRadius();
98  sumWeights += m_InputWeights[j];
99  }
100 
101  if (sumWeights > 0)
102  {
103  m_OutputModel->GetCompartment(i)->SetAxialDiffusivity(std::exp(outputLogDiffusivity / sumWeights));
104  m_OutputModel->GetCompartment(i)->SetTissueRadius(outputRadius / sumWeights);
105  }
106  }
107 
108  unsigned int maxNumOutputCompartments = m_OutputModel->GetNumberOfCompartments() - m_OutputModel->GetNumberOfIsotropicCompartments();
109  unsigned int numOutputCompartments = m_NumberOfOutputDirectionalCompartments;
110  if (numOutputCompartments > maxNumOutputCompartments)
111  numOutputCompartments = maxNumOutputCompartments;
112 
113  m_WorkCompartmentsVector.clear();
114  m_WorkCompartmentWeights.clear();
115 
116  for (unsigned int i = 0;i < numInputs;++i)
117  {
118  if (m_InputWeights[i] <= 0)
119  continue;
120 
121  for (unsigned int j = numIsoCompartments;j < m_InputModels[i]->GetNumberOfCompartments();++j)
122  {
123  double tmpWeight = m_InputModels[i]->GetCompartmentWeight(j);
124  if (tmpWeight <= 0)
125  continue;
126 
127  m_WorkCompartmentsVector.push_back(m_InputModels[i]->GetCompartment(j));
128  m_WorkCompartmentWeights.push_back(m_InputWeights[i] * tmpWeight);
129  }
130  }
131 
132  unsigned int numInputCompartments = m_WorkCompartmentsVector.size();
133 
134  if (numInputCompartments <= numOutputCompartments)
135  {
136  for (unsigned int i = 0;i < numInputCompartments;++i)
137  {
138  m_OutputModel->GetCompartment(i + numIsoCompartments)->SetCompartmentVector(m_WorkCompartmentsVector[i]->GetCompartmentVector());
139  m_InternalOutputWeights[i + numIsoCompartments] = m_WorkCompartmentWeights[i];
140  }
141 
142  m_OutputModel->SetCompartmentWeights(m_InternalOutputWeights);
143 
144  m_UpToDate = true;
145  return;
146  }
147 
148  bool tensorCompatibility = m_WorkCompartmentsVector[0]->GetTensorCompatible();
149  if (tensorCompatibility)
151  else
153 
154  m_InternalSpectralCluster.SetNbClass(numOutputCompartments);
158 
160 
161  m_InternalSpectralMemberships.resize(numInputCompartments);
162  for (unsigned int i = 0;i < numInputCompartments;++i)
164 
165  if (tensorCompatibility)
167  else
169 
170  m_OutputModel->SetCompartmentWeights(m_InternalOutputWeights);
171 
172  m_UpToDate = true;
173 }
174 
176 {
177  unsigned int numCompartments = m_WorkCompartmentsVector.size();
178  m_InternalLogTensors.resize(numCompartments);
179 
180  for (unsigned int i = 0;i < numCompartments;++i)
181  {
182  m_InternalWorkMatrix = m_WorkCompartmentsVector[i]->GetDiffusionTensor().GetVnlMatrix().as_matrix();
185  }
186 
187  m_InternalDistanceMatrix.set_size(numCompartments,numCompartments);
188  m_InternalDistanceMatrix.fill(0);
189 
190  for (unsigned int i = 0;i < numCompartments;++i)
191  for (unsigned int j = i+1;j < numCompartments;++j)
192  {
193  double distValue = 0;
194  for (unsigned int k = 0;k < 6;++k)
195  distValue += (m_InternalLogTensors[i][k] - m_InternalLogTensors[j][k]) * (m_InternalLogTensors[i][k] - m_InternalLogTensors[j][k]);
196 
197  m_InternalDistanceMatrix(i,j) = distValue;
199  }
200 }
201 
203 {
204  itkExceptionMacro("No non-tensor distance matrix implemented in public version")
205 }
206 
208 {
209  unsigned int numCompartments = m_WorkCompartmentsVector.size();
210  unsigned int numIsoCompartments = m_OutputModel->GetNumberOfIsotropicCompartments();
211  unsigned int numberOfOutputCompartments = m_InternalSpectralMemberships[0].size();
212 
213  m_InternalWorkMatrix.set_size(3,3);
214  m_InternalWorkEigenVectors.set_size(3,3);
215  m_InternalWorkEigenValues.set_size(3);
216 
217  m_InternalOutputVector.SetSize(6);
219 
220  anima::DiffusionModelCompartmentType anisoCompartmentType = m_OutputModel->GetCompartment(numIsoCompartments)->GetCompartmentType();
221 
222  for (unsigned int i = 0;i < numberOfOutputCompartments;++i)
223  {
224  m_InternalOutputVector.Fill(0);
225  double totalWeights = 0;
226  for (unsigned int j = 0;j < numCompartments;++j)
227  {
228  double weight = m_WorkCompartmentWeights[j] * m_InternalSpectralMemberships[j][i];
229  if (weight == 0)
230  continue;
231 
232  // Stick is with a fixed radial diffusivity, get it for later setting it back
233  if ((anisoCompartmentType == anima::Stick) && (totalWeights == 0.0))
234  {
237  }
238 
239  totalWeights += weight;
241  }
242 
243  if (totalWeights > 0.0)
244  {
245  m_InternalOutputVector /= totalWeights;
246 
247  m_InternalOutputWeights[i+numIsoCompartments] = totalWeights;
249 
250  if (anisoCompartmentType != anima::Tensor)
252 
253  if (anisoCompartmentType == anima::Stick)
254  {
255  // Replace smaller eigen values by stick default value
258 
260  }
261  else if (anisoCompartmentType == anima::Zeppelin)
262  {
263  // Force radial diffusivity as the sum of the two smallest ones
264  double logEigenValue = (m_InternalWorkEigenValues[0] + m_InternalWorkEigenValues[1]) / 2.0;
265  m_InternalWorkEigenValues[0] = logEigenValue;
266  m_InternalWorkEigenValues[1] = logEigenValue;
267 
269  }
270 
273  }
274 
275  anima::BaseCompartment *workCompartment = m_OutputModel->GetCompartment(i+numIsoCompartments);
277  }
278 }
279 
281 {
282  itkExceptionMacro("No non-tensor model computation implemented in public version")
283 }
284 
285 } // end namespace anima
itk::VariableLengthVector< double > m_InternalOutputVector
virtual void SetCompartmentVector(ModelOutputVectorType &compartmentVector)=0
Set compartment overall description vector, for setting automatically the individual parameters when ...
void SetCMeansAverageType(CMeansAverageType val)
std::vector< double > m_WorkCompartmentWeights
void SetInputData(MatrixType &data)
Input data: matrix of squared distances.
VectorType & GetClassesMembership(unsigned int i)
void GetVectorRepresentation(const vnl_matrix< T1 > &tensor, itk::VariableLengthVector< T2 > &vector, unsigned int vecDim=0, bool scale=false)
DiffusionModelCompartmentType
std::vector< std::vector< double > > m_InternalSpectralMemberships
void GetTensorFromVectorRepresentation(const itk::VariableLengthVector< T1 > &vector, vnl_matrix< T2 > &tensor, unsigned int tensDim=0, bool scale=false)
vnl_diag_matrix< double > m_InternalWorkEigenValuesInputSticks
vnl_diag_matrix< double > m_InternalWorkEigenValues
void RecomposeTensor(vnl_diag_matrix< T1 > &eigs, vnl_matrix< T1 > &eigVecs, vnl_matrix< T2 > &resMatrix)
Recompose tensor from values extracted using SymmetricEigenAnalysis (vnl_symmetric_eigensystem transp...
MultiCompartmentModel: holds several diffusion compartments, ordered by type It also handles weights ...
void SetNumberOfOutputDirectionalCompartments(unsigned int val)
vnl_matrix< double > m_InternalDistanceMatrix
vnl_matrix< double > m_InternalWorkEigenVectors
std::vector< itk::VariableLengthVector< double > > m_InternalLogTensors
vnl_matrix< double > m_InternalWorkMatrix
std::vector< MCMCompartmentPointer > m_WorkCompartmentsVector
std::vector< double > m_InternalOutputWeights
SpectralClusterType m_InternalSpectralCluster