Shapeworks Studio  2.1
Shape analysis software suite
itkPSMMixedEffectsShapeMatrixAttribute.h
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 
19 #ifndef __itkPSMMixedEffectsShapeMatrixAttribute_h
20 #define __itkPSMMixedEffectsShapeMatrixAttribute_h
21 
22 #include "itkPSMShapeMatrixAttribute.h"
23 #include "vnl/vnl_vector.h"
24 #include "itkPSMParticleSystem.h"
25 #include "vnl/vnl_trace.h"
26 
27 namespace itk
28 {
34  template <class T, unsigned int VDimension>
36  : public PSMShapeMatrixAttribute<T,VDimension>
37  {
38  public:
40  typedef T DataType;
42  typedef PSMShapeMatrixAttribute<T,VDimension> Superclass;
43  typedef SmartPointer<Self> Pointer;
44  typedef SmartPointer<const Self> ConstPointer;
45  typedef WeakPointer<const Self> ConstWeakPointer;
46 
48  itkNewMacro(Self);
49 
52 
53  inline vnl_vector<double> ComputeMean(double k) const
54  {
55  return m_Intercept + m_Slope * k;
56  }
57 
58  void ResizeParameters(unsigned int n)
59  {
60  vnl_vector<double> tmpA = m_Intercept; // copy existing matrix
61  vnl_vector<double> tmpB = m_Slope; // copy existing matrix
62 
63  // Create new
64  m_Intercept.set_size(n);
65  m_Slope.set_size(n);
66 
67  // Copy old data into new vector.
68  for (unsigned int r = 0; r < tmpA.size(); r++)
69  {
70  m_Intercept(r) = tmpA(r);
71  m_Slope(r) = tmpB(r);
72  }
73  }
74 
75  virtual void ResizeMeanMatrix(int rs, int cs)
76  {
77  vnl_matrix<T> tmp = m_MeanMatrix; // copy existing matrix
78 
79  // Create new column (shape)
80  m_MeanMatrix.set_size(rs, cs);
81  m_MeanMatrix.fill(0.0);
82 
83  // Copy old data into new matrix.
84  for (unsigned int c = 0; c < tmp.cols(); c++)
85  {
86  for (unsigned int r = 0; r < tmp.rows(); r++)
87  {
88  m_MeanMatrix(r,c) = tmp(r,c);
89  }
90  }
91  }
92 
93  void ResizeExplanatory(unsigned int n)
94  {
95  if (n > m_Expl.size())
96  {
97  vnl_vector<double> tmp = m_Expl; // copy existing matrix
98 
99  // Create new
100  m_Expl.set_size(n);
101  m_Expl.fill(0.0);
102 
103  // Copy old data into new vector.
104  for (unsigned int r = 0; r < tmp.size(); r++)
105  {
106  m_Expl(r) = tmp(r);
107  }
108  }
109  }
110 
115  virtual void DomainAddEventCallback(Object *, const EventObject &e)
116  {
117  const itk::ParticleDomainAddEvent &event
118  = dynamic_cast<const itk::ParticleDomainAddEvent &>(e);
119  unsigned int d = event.GetDomainIndex();
120 
121  if ( d % this->m_DomainsPerShape == 0 )
122  {
123  this->ResizeMatrix(this->rows(), this->cols()+1);
124  this->ResizeMeanMatrix(this->rows(), this->cols()+1);
125  this->ResizeExplanatory(this->cols());
126  }
127  }
128 
129  virtual void PositionAddEventCallback(Object *o, const EventObject &e)
130  {
131  const itk::ParticlePositionAddEvent &event
132  = dynamic_cast<const itk::ParticlePositionAddEvent &>(e);
134  = dynamic_cast<const itk::PSMParticleSystem<VDimension> *>(o);
135  const int d = event.GetDomainIndex();
136  const unsigned int idx = event.GetPositionIndex();
138  = ps->GetTransformedPosition(idx, d);
139 
140  const unsigned int PointsPerDomain = ps ->GetNumberOfParticles(d);
141 
142  // Make sure we have enough rows.
143  if ( (ps->GetNumberOfParticles(d) * VDimension * this->m_DomainsPerShape) > this->rows() )
144  {
145  this->ResizeParameters(PointsPerDomain * VDimension * this->m_DomainsPerShape);
146  this->ResizeMatrix(PointsPerDomain * VDimension * this->m_DomainsPerShape,
147  this->cols());
148  this->ResizeMeanMatrix(PointsPerDomain * VDimension * this->m_DomainsPerShape,
149  this->cols());
150  }
151 
152  // CANNOT ADD POSITION INFO UNTIL ALL POINTS PER DOMAIN IS KNOWN
153  // Add position info to the matrix
154  unsigned int k = ((d % this->m_DomainsPerShape) * PointsPerDomain * VDimension)
155  + (idx * VDimension);
156  for (unsigned int i = 0; i < VDimension; i++)
157  {
158  this->operator()(i+k, d / this->m_DomainsPerShape) = pos[i];
159  }
160  }
161 
162  virtual void PositionSetEventCallback(Object *o, const EventObject &e)
163  {
164  const itk::ParticlePositionSetEvent &event
165  = dynamic_cast <const itk::ParticlePositionSetEvent &>(e);
166 
168  = dynamic_cast<const itk::PSMParticleSystem<VDimension> *>(o);
169  const int d = event.GetDomainIndex();
170  const unsigned int idx = event.GetPositionIndex();
171  const typename itk::PSMParticleSystem<VDimension>::PointType pos = ps->GetTransformedPosition(idx, d);
172  const unsigned int PointsPerDomain = ps ->GetNumberOfParticles(d);
173 
174  // Modify matrix info
175  unsigned int k = ((d % this->m_DomainsPerShape) * PointsPerDomain * VDimension)
176  + (idx * VDimension);
177 
178  for (unsigned int i = 0; i < VDimension; i++)
179  {
180  this->operator()(i+k, d / this->m_DomainsPerShape) =
181  pos[i] - m_MeanMatrix(i+k, d/ this->m_DomainsPerShape);
182  }
183  }
184 
185  virtual void PositionRemoveEventCallback(Object *, const EventObject &)
186  {
187  // NEED TO IMPLEMENT THIS
188  }
189 
192  void SetDomainsPerShape(int i)
193  {
194  this->m_DomainsPerShape = i;
195  }
196 
197  int GetDomainsPerShape() const
198  {
199  return this->m_DomainsPerShape;
200  }
201 
202  void SetTimePointsPerIndividual(const vnl_vector<int> & v)
203  {
204  (this->m_TimeptsPerIndividual).set_size(v.size());
205 
206  for (int i = 0; i < v.size(); i++)
207  {
208  (this->m_TimeptsPerIndividual)(i) = v(i);
209  }
210  }
211 
212  vnl_vector<int> &GetTimePointsPerIndividual() const
213  {
214  return this->m_TimeptsPerIndividual;
215  }
216 
217  vnl_vector<int> &GetTimePointsPerIndividual()
218  {
219  return this->m_TimeptsPerIndividual;
220  }
221 
222  void SetNumIndividuals(int i)
223  {
224  this->m_NumIndividuals = i;
225  }
226 
227  int GetNumIndividuals()
228  {
229  return this->m_NumIndividuals;
230  }
231 
232  void SetExplanatory(std::vector<double> v)
233  {
234  ResizeExplanatory(v.size());
235  for (unsigned int i = 0; i < v.size(); i++)
236  {
237  m_Expl[i] = v[i];
238  }
239  }
240 
241  void SetExplanatory(unsigned int i, double q)
242  {
243  m_Expl[i] = q;
244  }
245 
246  const double &GetExplanatory(unsigned int i) const
247  {
248  return m_Expl[i];
249  }
250 
251  double &GetExplanatory(unsigned int i)
252  {
253  return m_Expl[i];
254  }
255 
256  const vnl_vector<double> &GetSlope() const
257  {
258  return m_Slope;
259  }
260 
261  const vnl_vector<double> &GetIntercept() const
262  {
263  return m_Intercept;
264  }
265 
266  const vnl_matrix<double> &GetSlopeRandom() const
267  {
268  return m_SlopeRand;
269  }
270 
271  const vnl_matrix<double> &GetInterceptRandom() const
272  {
273  return m_InterceptRand;
274  }
275 
276  void SetSlope(const std::vector<double> &v)
277  {
278  ResizeParameters(v.size());
279  for (unsigned int i = 0; i < v.size(); i++)
280  {
281  m_Slope[i] = v[i];
282  }
283  }
284 
285  void SetIntercept(const std::vector<double> &v)
286  {
287  ResizeParameters(v.size());
288  for (unsigned int i = 0; i < v.size(); i++)
289  {
290  m_Intercept[i] = v[i];
291  }
292  }
293 
294  // Initialize variables
295  void Initialize()
296  {
297  m_Intercept.fill(0.0);
298  m_Slope.fill(0.0);
299  m_MeanMatrix.fill(0.0);
300 
301  m_SlopeRand.fill(0.0);
302  m_InterceptRand.fill(0.0);
303  }
304 
305  virtual void BeforeIteration()
306  {
307  m_UpdateCounter ++;
308  if (m_UpdateCounter >= m_RegressionInterval)
309  {
310  m_UpdateCounter = 0;
311  this->EstimateParameters();
312  this->UpdateMeanMatrix();
313  }
314  }
315 
316  void SetRegressionInterval( int i)
317  {
318  m_RegressionInterval = i;
319  }
320 
321  int GetRegressionInterval() const
322  {
323  return m_RegressionInterval;
324  }
325 
326  virtual void UpdateMeanMatrix();
327 
328  virtual void EstimateParameters();
329 
330  protected:
332  {
333  this->m_DefinedCallbacks.DomainAddEvent = true;
334  this->m_DefinedCallbacks.PositionAddEvent = true;
335  this->m_DefinedCallbacks.PositionSetEvent = true;
336  this->m_DefinedCallbacks.PositionRemoveEvent = true;
337  m_UpdateCounter = 0;
338  m_RegressionInterval = 1;
339  m_NumIndividuals = 1;
340  m_TimeptsPerIndividual.set_size(m_NumIndividuals);
341  for(int i = 0; i < m_NumIndividuals; i++)
342  m_TimeptsPerIndividual(i) = 2;
343  }
344 
346 
347  void PrintSelf(std::ostream& os, Indent indent) const
348  {
349  Superclass::PrintSelf(os,indent);
350  }
351 
352  private:
353  PSMMixedEffectsShapeMatrixAttribute(const Self&); //purposely not implemented
354  void operator=(const Self&); //purposely not implemented
355 
356  int m_UpdateCounter;
357  int m_RegressionInterval;
358 
359  // Parameters for the linear model
360  vnl_vector<double> m_Intercept;
361  vnl_vector<double> m_Slope;
362 
363  // The explanatory variable value for each sample (matrix column)
364  vnl_vector<double> m_Expl;
365 
366  // A matrix to store the mean estimated for each explanatory variable (each sample)
367  vnl_matrix<double> m_MeanMatrix;
368 
369  vnl_matrix<double> m_InterceptRand; //added: AK , random intercepts for each group
370  vnl_matrix<double> m_SlopeRand; //added: AK , random slopes for each group
371 
372  int m_NumIndividuals;
373  // timepoints per individual
374  vnl_vector<int> m_TimeptsPerIndividual;
375  };
376 
377 } // end namespace
378 
379 #ifndef ITK_MANUAL_INSTANTIATION
380 #include "itkPSMMixedEffectsShapeMatrixAttribute.hxx"
381 #endif
382 
383 #endif
Each column describes a shape. A shape may be composed of m_DomainsPerShape domains (default 1)...
virtual void PositionRemoveEventCallback(Object *, const EventObject &)
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)
Base class for PSMParticleSystem attribute classes.
Definition: Shape.h:14