Shapeworks Studio  2.1
Shape analysis software suite
itkPSMMixedEffectsShapeMatrixAttribute.hxx
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef __itkPSMMixedEffectsShapeMatrixAttribute_hxx
19 #define __itkPSMMixedEffectsShapeMatrixAttribute_hxx
20 #include "itkPSMMixedEffectsShapeMatrixAttribute.h"
21 #include <iostream>
22 
23 namespace itk
24 {
25 
26 template <class T, unsigned int VDimension>
27 void PSMMixedEffectsShapeMatrixAttribute<T,VDimension>
28 ::UpdateMeanMatrix()
29 {
30  // For each sample
31  vnl_vector<double> tempvect;
32  int indexSum = 0, group_indx = -1;
33  tempvect.set_size(m_MeanMatrix.rows());
34  tempvect.fill(0.0);
35  for (unsigned int i = 0; i < m_MeanMatrix.cols(); i++)
36  {
37  if(i == indexSum)
38  {
39 
41  // int group_indx = i / m_TimePointsPerIndividual;
42  // tempvect = this->GetIntercept() + this->GetSlope() * expl(i);
43  // tempvect = tempvect + m_InterceptRand.get_row(group_indx);
44  // tempvect = tempvect + m_SlopeRand.get_row(group_indx) * expl(i);
46  //this->GetMeanMatrix().set_column(i, tempvect);
47 
48  group_indx = group_indx + 1;
49  indexSum += m_TimeptsPerIndividual(group_indx);
50  }
51 
52  tempvect = m_Intercept + m_Slope * m_Expl(i);
53  tempvect = tempvect + m_InterceptRand.get_row(group_indx);
54  tempvect = tempvect + m_SlopeRand.get_row(group_indx) * m_Expl(i);
55  // Compute the mean
56  m_MeanMatrix.set_column(i, tempvect);
57  }
58 }
59 
60 
61 template <class T, unsigned int VDimension>
62 void PSMMixedEffectsShapeMatrixAttribute<T,VDimension>::
63 EstimateParameters()
64 {
65  std::cout << "Estimating params" << std::endl;
66 
67  vnl_matrix<double> X = *this + m_MeanMatrix;
68 
69  // Number of samples
70  int num_shapes = static_cast<double>(X.cols());
71 
72  int nr = X.rows(); //number of points*3
73 
74  // set the sizes of random slope and intercept matrix
75  m_SlopeRand.set_size(m_NumIndividuals, nr); // num_individuals X num_points*3
76  m_InterceptRand.set_size(m_NumIndividuals, nr); // num_individuals X num_points*3
77 
78  vnl_matrix<double> fixed; // slopes + intercepts for all points
79  vnl_matrix<double> random; // slopes + intercepts for all groups, for all points
80  fixed.set_size(2, nr);
81  random.set_size(2, nr * m_NumIndividuals);
82 
83  vnl_matrix<double> Ds(2, 2); // covariance matrix of random parameters (2x2)
84  Ds.set_identity(); // initialize to identity
85  vnl_matrix<double> identity_2;
86  identity_2.set_size(2, 2);
87  identity_2.set_identity();
88 
89  double sigma2s = 1; // variance of error
90  vnl_matrix<double> * Ws = NULL, * Vs = NULL, * identity_n = NULL, * Xp = NULL;
91  Ws = new vnl_matrix<double>[m_NumIndividuals];
92  Vs = new vnl_matrix<double>[m_NumIndividuals];
93  identity_n = new vnl_matrix<double>[m_NumIndividuals];
94  Xp = new vnl_matrix<double>[m_NumIndividuals]; // Xp: Design matrix. Stores all time points.
95 
96  vnl_vector<double> residual, y;
97  y.set_size(m_TimeptsPerIndividual(0));
98  y.fill(0.0);
99  residual.set_size(m_TimeptsPerIndividual(0));
100  residual.fill(0.0);
101 
102  for (int i = 0; i < m_NumIndividuals; i++)
103  {
104  Vs[i].set_size(m_TimeptsPerIndividual(i), m_TimeptsPerIndividual(i));
105  Ws[i].set_size(m_TimeptsPerIndividual(i), m_TimeptsPerIndividual(i));
106 
107  identity_n[i].set_size(m_TimeptsPerIndividual(i), m_TimeptsPerIndividual(i));
108  identity_n[i].set_identity();
109 
110  Xp[i].set_size(m_TimeptsPerIndividual(i), 2);
111  }
112 
113  vnl_matrix<double> sum_mat1(2, 2, 0);
114  vnl_vector<double> sum_mat2(2); sum_mat2.fill(0.0);
115  double ecorr = 0.0;
116  double tracevar = 0.0;
117  vnl_matrix<double> bscorr(2, 2, 0.0);
118  vnl_matrix<double> bsvar(2, 2, 0.0);
119  vnl_vector<double> tempvect; tempvect.set_size(2);
120  unsigned int indexSum = 0;
121 
122  for (int i = 0; i < nr; i++) //for all points (x,y,z coordinates)
123  {
124  sigma2s = 0.01;
125  Ds.set_identity();
126  Ds *= sigma2s;
127  for (int j = 0; j < 100; j++) //EM iterations
128  {
129  sum_mat1.fill(0.0); sum_mat2.fill(0.0);
130  indexSum = 0;
131 
132  for (int k = 0; k < m_NumIndividuals; k++)
133  {
134  y.clear();
135  y.set_size(m_TimeptsPerIndividual(k));
136  y.fill(0.0);
137 
138  for (int l = 0; l < m_TimeptsPerIndividual(k); l++)
139  {
140  Xp[k](l, 0) = m_Expl(indexSum + l);
141  Xp[k](l, 1) = 1;
142  y(l) = X(i, indexSum + l);
143  }
144 
145  indexSum += m_TimeptsPerIndividual(k);
146 
147  Vs[k] = (identity_n[k] * sigma2s) + Xp[k] * Ds * vnl_transpose(Xp[k]);
148 
149  if(Vs[k].rows() > 4)
150  {
151  Ws[k] = vnl_matrix_inverse<double>(Vs[k]);
152  }
153  else
154  {
155  Ws[k] = vnl_inverse<double>(Vs[k]);
156  }
157  sum_mat1 = sum_mat1 + vnl_transpose(Xp[k]) * Ws[k] * Xp[k];
158  sum_mat2 = sum_mat2 + vnl_transpose(Xp[k]) * Ws[k] * y;
159  }
160  tempvect = vnl_inverse<double>(sum_mat1) * sum_mat2;
161  fixed.set_column(i, tempvect);
162 
163  indexSum = 0; // re-initializing
164  ecorr = 0.0;
165  tracevar = 0.0;
166  bscorr.fill(0.0);
167  bsvar.fill(0.0);
168 
169  for (int k = 0; k < m_NumIndividuals; k++)
170  {
171  residual.clear(); y.clear();
172  residual.set_size(m_TimeptsPerIndividual(k));
173  y.set_size(m_TimeptsPerIndividual(k));
174  residual.fill(0.0); y.fill(0.0);
175 
176  for (int l = 0; l < m_TimeptsPerIndividual[k]; l++)
177  {
178  Xp[k](l,0) = m_Expl(indexSum + l);
179  Xp[k](l,1) = 1;
180  y(l) = X(i, indexSum + l);
181  }
182 
183  indexSum += m_TimeptsPerIndividual(k);
184 
185  tempvect = Ds * vnl_transpose(Xp[k]) * Ws[k] * (y - (Xp[k] * fixed.get_column(i)));
186  random.set_column(i * m_NumIndividuals + k, tempvect);
187  residual = y - (Xp[k] * fixed.get_column(i)) - (Xp[k] * random.get_column(i * m_NumIndividuals + k));
188  ecorr = ecorr + dot_product(residual, residual);
189  tracevar = tracevar + (m_TimeptsPerIndividual(k) - sigma2s * vnl_trace(Ws[k]));
190  bscorr = bscorr + outer_product(random.get_column(i * m_NumIndividuals + k), random.get_column(i * m_NumIndividuals + k));
191  bsvar = bsvar + (identity_2 - (vnl_transpose(Xp[k]) * Ws[k] * Xp[k] * Ds));
192  }
193 
194  indexSum = 0; // re-initializing
195  sigma2s = (ecorr + sigma2s * tracevar) / (num_shapes);
196  Ds = (bscorr + Ds * bsvar) / m_NumIndividuals;
197  } //endfor EM iterations
198  } //endfor all points on shape (x,y & z)
199 
200  m_Slope = fixed.get_row(0);
201  m_Intercept = fixed.get_row(1);
202  for (int i = 0; i < m_NumIndividuals; i++)
203  {
204  for (int j = 0; j < nr; j++) //for all points * 3
205  {
206  m_SlopeRand(i, j) = random(0, j * m_NumIndividuals + i);
207  m_InterceptRand(i, j) = random(1, j * m_NumIndividuals + i);
208  }
209  }
210 
211  delete [] Vs;
212  delete [] Ws;
213  delete [] identity_n;
214  delete [] Xp;
215 }
216 
217 } // end namespace itk
218 
219 #endif