Shapeworks Studio  2.1
Shape analysis software suite
itkPSMRegressionShapeMatrixAttribute.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 __itkPSMRegressionShapeMatrixAttribute_hxx
19 #define __itkPSMRegressionShapeMatrixAttribute_hxx
20 #include "itkPSMRegressionShapeMatrixAttribute.h"
21 
22 namespace itk
23 {
24 
25 template <class T, unsigned int VDimension>
26 void PSMRegressionShapeMatrixAttribute<T,VDimension>
27 ::UpdateMeanMatrix()
28 {
29  // for each sample
30  for (unsigned int i = 0; i < m_MeanMatrix.cols(); i++)
31  {
32  // compute the mean
33  m_MeanMatrix.set_column(i, m_Intercept + m_Slope * m_Explanatory(i));
34  }
35 }
36 
37 template <class T, unsigned int VDimension>
38 void PSMRegressionShapeMatrixAttribute<T,VDimension>
39 ::ResizeParameters(unsigned int n)
40 {
41  vnl_vector<double> tmpA = m_Intercept; // copy existing matrix
42  vnl_vector<double> tmpB = m_Slope; // copy existing matrix
43 
44  // Create new
45  m_Intercept.set_size(n);
46  m_Slope.set_size(n);
47 
48  // Copy old data into new vector.
49  for (unsigned int r = 0; r < tmpA.size(); r++)
50  {
51  m_Intercept(r) = tmpA(r);
52  m_Slope(r) = tmpB(r);
53  }
54 }
55 
56 template <class T, unsigned int VDimension>
57 void PSMRegressionShapeMatrixAttribute<T,VDimension>
58 ::ResizeMeanMatrix(int rs, int cs)
59 {
60  vnl_matrix<T> tmp = m_MeanMatrix; // copy existing matrix
61 
62  // Create new column (shape)
63  m_MeanMatrix.set_size(rs, cs);
64 
65  m_MeanMatrix.fill(0.0);
66 
67  // Copy old data into new matrix.
68  for (unsigned int c = 0; c < tmp.cols(); c++)
69  {
70  for (unsigned int r = 0; r < tmp.rows(); r++)
71  {
72  m_MeanMatrix(r,c) = tmp(r,c);
73  }
74  }
75 }
76 
77 template <class T, unsigned int VDimension>
78 void PSMRegressionShapeMatrixAttribute<T,VDimension>
79 ::ResizeExplanatory(unsigned int n)
80 {
81  if (n > m_Explanatory.size())
82  {
83  vnl_vector<double> tmp = m_Explanatory; // copy existing matrix
84 
85  // Create new
86  m_Explanatory.set_size(n);
87  m_Explanatory.fill(0.0);
88 
89  // Copy old data into new vector.
90  for (unsigned int r = 0; r < tmp.size(); r++)
91  {
92  m_Explanatory(r) = tmp(r);
93  }
94  }
95 }
96 
97 template <class T, unsigned int VDimension>
99 ::DomainAddEventCallback(Object *, const EventObject &e)
100 {
101  const ParticleDomainAddEvent &event
102  = dynamic_cast<const ParticleDomainAddEvent &>(e);
103  unsigned int d = event.GetDomainIndex();
104 
105  if ( d % this->m_DomainsPerShape == 0 )
106  {
107  this->ResizeMatrix(this->rows(), this->cols()+1);
108  this->ResizeMeanMatrix(this->rows(), this->cols()+1);
109  this->ResizeExplanatory(this->cols());
110  }
111 }
112 
113 template <class T, unsigned int VDimension>
115 ::PositionAddEventCallback(Object *o, const EventObject &e)
116 {
117  const ParticlePositionAddEvent &event
118  = dynamic_cast<const ParticlePositionAddEvent &>(e);
120  = dynamic_cast<const PSMParticleSystem<VDimension> *>(o);
121  const int d = event.GetDomainIndex();
122  const unsigned int idx = event.GetPositionIndex();
124  = ps->GetTransformedPosition(idx, d);
125 
126  const unsigned int PointsPerDomain = ps ->GetNumberOfParticles(d);
127 
128  // Make sure we have enough rows.
129  if ((ps->GetNumberOfParticles(d) * VDimension * this->m_DomainsPerShape)
130  > this->rows())
131  {
132  this->ResizeParameters(PointsPerDomain * VDimension * this->m_DomainsPerShape);
133  this->ResizeMatrix(PointsPerDomain * VDimension * this->m_DomainsPerShape,
134  this->cols());
135  this->ResizeMeanMatrix(PointsPerDomain * VDimension * this->m_DomainsPerShape,
136  this->cols());
137  }
138 
139  // ! CANNOT ADD POSITION INFO UNTIL ALL POINTS PER DOMAIN IS KNOWN !
140  // Add position info to the matrix
141  unsigned int k = ((d % this->m_DomainsPerShape) * PointsPerDomain * VDimension)
142  + (idx * VDimension);
143  for (unsigned int i = 0; i < VDimension; i++)
144  {
145  this->operator()(i+k, d / this->m_DomainsPerShape) = pos[i];
146  }
147 }
148 
149 template <class T, unsigned int VDimension>
151 ::PositionSetEventCallback(Object *o, const EventObject &e)
152 {
153  const ParticlePositionSetEvent &event
154  = dynamic_cast <const ParticlePositionSetEvent &>(e);
155 
157  = dynamic_cast<const PSMParticleSystem<VDimension> *>(o);
158  const int d = event.GetDomainIndex();
159  const unsigned int idx = event.GetPositionIndex();
160  const typename PSMParticleSystem<VDimension>::PointType pos = ps->GetTransformedPosition(idx, d);
161  const unsigned int PointsPerDomain = ps ->GetNumberOfParticles(d);
162 
163  // Modify matrix info
164  // unsigned int k = VDimension * idx;
165  unsigned int k = ((d % this->m_DomainsPerShape) * PointsPerDomain * VDimension)
166  + (idx * VDimension);
167 
168  for (unsigned int i = 0; i < VDimension; i++)
169  {
170  this->operator()(i+k, d / this->m_DomainsPerShape) =
171  pos[i] - m_MeanMatrix(i+k, d/ this->m_DomainsPerShape);
172  }
173 }
174 
175 template <class T, unsigned int VDimension>
177 ::SetExplanatory(const std::vector<double> &v)
178 {
179  this->ResizeExplanatory(v.size());
180  for (unsigned int i = 0; i < v.size(); i++)
181  {
182  m_Explanatory[i] = v[i];
183  }
184 }
185 
186 template <class T, unsigned int VDimension>
188 ::SetSlope(const std::vector<double> &v)
189 {
190  ResizeParameters(v.size());
191  for (unsigned int i = 0; i < v.size(); i++)
192  {
193  m_Slope[i] = v[i];
194  }
195 }
196 
197 template <class T, unsigned int VDimension>
199 ::SetIntercept(const std::vector<double> &v)
200 {
201  ResizeParameters(v.size());
202  for (unsigned int i = 0; i < v.size(); i++)
203  {
204  m_Intercept[i] = v[i];
205  }
206 
207 }
208 
209 template <class T, unsigned int VDimension>
212 {
213  const double tol = 1.0e-12;
214  vnl_matrix<double> X = *this + m_MeanMatrix;
215 
216  // Number of samples
217  double n = (double)(X.cols());
218 
219  vnl_vector<double> sumtx = m_Explanatory[0] * X.get_column(0);
220  vnl_vector<double> sumx = X.get_column(0);
221  double sumt = m_Explanatory[0];
222  double sumt2 = m_Explanatory[0] * m_Explanatory[0];
223  for (unsigned int k = 1; k < X.cols(); k++) // k is the sample number
224  {
225  sumtx += m_Explanatory[k] * X.get_column(k);
226  sumx += X.get_column(k);
227  sumt += m_Explanatory[k];
228  sumt2 += m_Explanatory[k] * m_Explanatory[k];
229  }
230 
231  m_Slope = (n * sumtx - (sumx * sumt)) / ((n * sumt2 - (sumt*sumt)) + tol);
232 
233  vnl_vector<double> sumbt = m_Slope * m_Explanatory[0];
234  for (unsigned int k = 1; k < X.cols(); k++)
235  {
236  sumbt += m_Slope * m_Explanatory[k];
237  }
238 
239  m_Intercept = (sumx - sumbt) / n;
240 }
241 
242 template <class T, unsigned int VDimension>
245 {
246  // if (m_Explanatory.size() != this->columns())
247  // {
248  // itkExceptionMacro("The number of columns (shapes) does not match the number of explanatory variables -- or no explanatory variables have been set.");
249  // }
250  // Check that the paramters are not all equal. This is likely
251  // because the user did not set the parameters. In any case, it
252  // will result in undefined results (nan) for the slope and
253  // intercept.
254  bool ok = false;
255  for (unsigned int i = 1; i < m_Explanatory.size(); i++)
256  {
257  if (m_Explanatory[i] != m_Explanatory[0]) ok = true;
258  }
259  if (!ok)
260  {
261  itkExceptionMacro("All explanatory variables are the same value. Please set these values before running the filter.");
262  }
263  m_Intercept.fill(0.0);
264  m_Slope.fill(0.0);
265  m_MeanMatrix.fill(0.0);
266 }
267 
268 template <class T, unsigned int VDimension>
271 {
272  m_UpdateCounter ++;
273  if (m_UpdateCounter >= m_RegressionInterval)
274  {
275  m_UpdateCounter = 0;
276  this->EstimateParameters();
277  this->UpdateMeanMatrix();
278  }
279 }
280 
281 } // end namespace itk
282 
283 
284 #endif
virtual void DomainAddEventCallback(Object *, const EventObject &e)
unsigned long int GetNumberOfParticles(unsigned int d=0) const
A facade class that manages interactions with a particle system.
virtual void PositionSetEventCallback(Object *o, const EventObject &e)
virtual void PositionAddEventCallback(Object *o, const EventObject &e)
Definition: Shape.h:14