Statismo  0.10.1
 All Classes Namespaces Functions Typedefs
StatisticalModel.hxx
1 /*
2  * This file is part of the statismo library.
3  *
4  * Author: Marcel Luethi (marcel.luethi@unibas.ch)
5  *
6  * Copyright (c) 2011 University of Basel
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  *
16  * Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  *
20  * Neither the name of the project's author nor the names of its
21  * contributors may be used to endorse or promote products derived from
22  * this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef __StatisticalModel_hxx
39 #define __StatisticalModel_hxx
40 
41 #include <cmath>
42 
43 #include <fstream>
44 #include <iostream>
45 #include <string>
46 
47 #include "Exceptions.h"
48 #include "HDF5Utils.h"
49 #include "ModelBuilder.h"
50 #include "StatisticalModel.h"
51 
52 namespace statismo {
53 
54 template <typename T>
55 StatisticalModel<T>::StatisticalModel(const RepresenterType* representer, const VectorType& m, const MatrixType& orthonormalPCABasis, const VectorType& pcaVariance, double noiseVariance)
56  : m_representer(representer->Clone()),
57  m_mean(m),
58  m_pcaVariance(pcaVariance),
59  m_noiseVariance(noiseVariance),
60  m_cachedValuesValid(false),
61  m_modelLoaded(false) {
62  VectorType D = pcaVariance.array().sqrt();
63  m_pcaBasisMatrix = orthonormalPCABasis * DiagMatrixType(D);
64 }
65 
66 template <typename T>
67 StatisticalModel<T>::StatisticalModel(const RepresenterType* representer)
68  : m_representer(representer->Clone()), m_noiseVariance(0), m_cachedValuesValid(0) {
69 }
70 
71 
72 template <typename T>
74 
75  if (m_representer != 0) {
76 // not all representers can implement a const correct version of delete.
77 // We therefore simply const cast it. This is save here.
78  const_cast<RepresenterType*>(m_representer)->Delete();
79  m_representer = 0;
80  }
81 
82 }
83 
84 
85 
86 template <typename T>
87 typename StatisticalModel<T>::DatasetPointerType
88 StatisticalModel<T>::DatasetToSample(DatasetConstPointerType ds) const {
89  DatasetPointerType sample;
90  sample = m_representer->CloneDataset(ds);
91  return sample;
92 }
93 
94 
95 template <typename T>
96 typename StatisticalModel<T>::ValueType
97 StatisticalModel<T>::EvaluateSampleAtPoint(const DatasetConstPointerType sample, const PointType& point) const {
98  unsigned ptid = this->m_representer->GetPointIdForPoint(point);
99  return EvaluateSampleAtPoint(sample, ptid);
100 }
101 
102 
103 template <typename T>
104 typename StatisticalModel<T>::ValueType
105 StatisticalModel<T>::EvaluateSampleAtPoint(const DatasetConstPointerType sample, unsigned ptid) const {
106  return this->m_representer->PointSampleFromSample(sample, ptid);
107 }
108 
109 
110 template <typename T>
111 typename StatisticalModel<T>::DatasetPointerType
113  VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
114  return DrawSample(coeffs, false);
115 }
116 
117 
118 template <typename T>
119 typename StatisticalModel<T>::ValueType
120 StatisticalModel<T>::DrawMeanAtPoint(const PointType& point) const {
121  VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
122  return DrawSampleAtPoint(coeffs, point);
123 
124 }
125 
126 template <typename T>
127 typename StatisticalModel<T>::ValueType
128 StatisticalModel<T>::DrawMeanAtPoint(unsigned pointId) const {
129  VectorType coeffs = VectorType::Zero(this->GetNumberOfPrincipalComponents());
130  return DrawSampleAtPoint(coeffs, pointId, false);
131 
132 }
133 
134 
135 
136 
137 template <typename T>
138 typename StatisticalModel<T>::DatasetPointerType
139 StatisticalModel<T>::DrawSample(bool addNoise) const {
140 
141  // we create random coefficients and draw a random sample from the model
142  VectorType coeffs = Utils::generateNormalVector(GetNumberOfPrincipalComponents());
143 
144  return DrawSample(coeffs, addNoise);
145 }
146 
147 
148 template <typename T>
149 typename StatisticalModel<T>::DatasetPointerType
150 StatisticalModel<T>::DrawSample(const VectorType& coefficients, bool addNoise) const {
151  return m_representer->SampleVectorToSample(DrawSampleVector(coefficients, addNoise));
152 }
153 
154 
155 template <typename T>
156 typename StatisticalModel<T>::DatasetPointerType
157 StatisticalModel<T>::DrawPCABasisSample(const unsigned pcaComponent) const {
158  if (pcaComponent >= this->GetNumberOfPrincipalComponents()) {
159  throw StatisticalModelException("Wrong pcaComponent index provided to DrawPCABasisSample!");
160  }
161 
162 
163  return m_representer->SampleVectorToSample( m_pcaBasisMatrix.col(pcaComponent));
164 }
165 
166 
167 
168 template <typename T>
169 VectorType
170 StatisticalModel<T>::DrawSampleVector(const VectorType& coefficients, bool addNoise) const {
171 
172  if (coefficients.size() != this->GetNumberOfPrincipalComponents()) {
173  throw StatisticalModelException("Incorrect number of coefficients provided !");
174  }
175 
176  unsigned vectorSize = this->m_mean.size();
177  assert (vectorSize != 0);
178 
179  VectorType epsilon = VectorType::Zero(vectorSize);
180  if (addNoise) {
181  epsilon = Utils::generateNormalVector(vectorSize) * sqrt(m_noiseVariance);
182  }
183 
184 
185  return m_mean+ m_pcaBasisMatrix * coefficients + epsilon;
186 }
187 
188 
189 template <typename T>
190 typename StatisticalModel<T>::ValueType
191 StatisticalModel<T>::DrawSampleAtPoint(const VectorType& coefficients, const PointType& point, bool addNoise) const {
192 
193  unsigned ptId = this->m_representer->GetPointIdForPoint(point);
194 
195  return DrawSampleAtPoint(coefficients, ptId, addNoise);
196 
197 }
198 
199 template <typename T>
200 typename StatisticalModel<T>::ValueType
201 StatisticalModel<T>::DrawSampleAtPoint(const VectorType& coefficients, const unsigned ptId, bool addNoise) const {
202 
203  unsigned dim = m_representer->GetDimensions();
204 
205  VectorType v(dim);
206  VectorType epsilon = VectorType::Zero(dim);
207  if (addNoise) {
208  epsilon = Utils::generateNormalVector(dim) * sqrt(m_noiseVariance);
209  }
210  for (unsigned d = 0; d < dim; d++) {
211  unsigned idx =m_representer->MapPointIdToInternalIdx(ptId, d);
212 
213  if (idx >= m_mean.rows()) {
214  std::ostringstream os;
215  os << "Invalid idx computed in DrawSampleAtPoint. ";
216  os << " The most likely cause of this error is that you provided an invalid point id (" << ptId <<")";
217  throw StatisticalModelException(os.str().c_str());
218  }
219 
220  v[d] = m_mean[idx] + m_pcaBasisMatrix.row(idx).dot(coefficients) + epsilon[d];
221  }
222 
223  return this->m_representer->PointSampleVectorToPointSample(v);
224 }
225 
226 
227 
228 template <typename T>
229 MatrixType
230 StatisticalModel<T>::GetCovarianceAtPoint(const PointType& pt1, const PointType& pt2) const {
231  unsigned ptId1 = this->m_representer->GetPointIdForPoint(pt1);
232  unsigned ptId2 = this->m_representer->GetPointIdForPoint(pt2);
233 
234  return GetCovarianceAtPoint(ptId1, ptId2);
235 }
236 
237 template <typename T>
238 MatrixType
239 StatisticalModel<T>::GetCovarianceAtPoint(unsigned ptId1, unsigned ptId2) const {
240  unsigned dim = m_representer->GetDimensions();
241  MatrixType cov(dim, dim);
242 
243  for (unsigned i = 0; i < dim; i++) {
244  unsigned idxi = m_representer->MapPointIdToInternalIdx(ptId1, i);
245  VectorType vi = m_pcaBasisMatrix.row(idxi);
246  for (unsigned j = 0; j < dim; j++) {
247  unsigned idxj = m_representer->MapPointIdToInternalIdx(ptId2, j);
248  VectorType vj = m_pcaBasisMatrix.row(idxj);
249  cov(i,j) = vi.dot(vj);
250  if (i == j) cov(i,j) += m_noiseVariance;
251  }
252  }
253  return cov;
254 }
255 
256 template <typename T>
257 MatrixType
259  MatrixType M = m_pcaBasisMatrix * m_pcaBasisMatrix.transpose();
260  M.diagonal() += m_noiseVariance * VectorType::Ones(m_pcaBasisMatrix.rows());
261  return M;
262 }
263 
264 
265 template <typename T>
266 VectorType
267 StatisticalModel<T>::ComputeCoefficientsForDataset(DatasetConstPointerType dataset) const {
268  DatasetPointerType sample;
269  sample = m_representer->CloneDataset(dataset);
270  VectorType v = ComputeCoefficientsForSample(sample);
271  m_representer->DeleteDataset(sample);
272  return v;
273 }
274 
275 template <typename T>
276 VectorType
277 StatisticalModel<T>::ComputeCoefficientsForSample(DatasetConstPointerType sample) const {
278  return ComputeCoefficientsForSampleVector(m_representer->SampleToSampleVector(sample));
279 }
280 
281 template <typename T>
282 VectorType
284 
285  CheckAndUpdateCachedParameters();
286 
287  const MatrixType& WT = m_pcaBasisMatrix.transpose();
288 
289  VectorType coeffs = m_MInverseMatrix * (WT * (sample - m_mean));
290  return coeffs;
291 }
292 
293 
294 
295 template <typename T>
296 VectorType
297 StatisticalModel<T>::ComputeCoefficientsForPointValues(const PointValueListType& pointValueList, double pointValueNoiseVariance) const {
298  PointIdValueListType ptIdValueList;
299 
300  for (typename PointValueListType::const_iterator it = pointValueList.begin();
301  it != pointValueList.end();
302  ++it) {
303  ptIdValueList.push_back(PointIdValuePairType(m_representer->GetPointIdForPoint(it->first), it->second));
304  }
305  return ComputeCoefficientsForPointIDValues(ptIdValueList, pointValueNoiseVariance);
306 }
307 
308 template <typename T>
309 VectorType
310 StatisticalModel<T>::ComputeCoefficientsForPointIDValues(const PointIdValueListType& pointIdValueList, double pointValueNoiseVariance) const {
311 
312  unsigned dim = m_representer->GetDimensions();
313 
314  double noiseVariance = std::max(pointValueNoiseVariance, (double) m_noiseVariance);
315 
316  // build the part matrices with , considering only the points that are fixed
317  MatrixType PCABasisPart(pointIdValueList.size()* dim, this->GetNumberOfPrincipalComponents());
318  VectorType muPart(pointIdValueList.size() * dim);
319  VectorType sample(pointIdValueList.size() * dim);
320 
321  unsigned i = 0;
322  for (typename PointIdValueListType::const_iterator it = pointIdValueList.begin(); it != pointIdValueList.end(); ++it) {
323  VectorType val = this->m_representer->PointSampleToPointSampleVector(it->second);
324  unsigned pt_id = it->first;
325  for (unsigned d = 0; d < dim; d++) {
326  PCABasisPart.row(i * dim + d) = this->GetPCABasisMatrix().row(m_representer->MapPointIdToInternalIdx(pt_id, d));
327  muPart[i * dim + d] = this->GetMeanVector()[m_representer->MapPointIdToInternalIdx(pt_id, d)];
328  sample[i * dim + d] = val[d];
329  }
330  i++;
331  }
332 
333  MatrixType M = PCABasisPart.transpose() * PCABasisPart;
334  M.diagonal() += noiseVariance * VectorType::Ones(PCABasisPart.cols());
335  VectorType coeffs = M.inverse() * PCABasisPart.transpose() * (sample - muPart);
336 
337  return coeffs;
338 }
339 
340 
341 template <typename T>
342 double
343 StatisticalModel<T>::ComputeLogProbabilityOfDataset(DatasetConstPointerType ds) const {
344  VectorType alpha = ComputeCoefficientsForDataset(ds);
345  return ComputeLogProbabilityOfCoefficients(alpha);
346 }
347 
348 template <typename T>
349 double
350 StatisticalModel<T>::ComputeProbabilityOfDataset(DatasetConstPointerType ds) const {
351  VectorType alpha = ComputeCoefficientsForDataset(ds);
352  return ComputeProbabilityOfCoefficients(alpha);
353 }
354 
355 
356 template <typename T>
357 double
358 StatisticalModel<T>::ComputeLogProbabilityOfCoefficients(const VectorType& coefficents) const {
359  return log(pow(2 * PI, -0.5 * this->GetNumberOfPrincipalComponents())) - 0.5 * coefficents.squaredNorm();
360 }
361 
362 template <typename T>
363 double
364 StatisticalModel<T>::ComputeProbabilityOfCoefficients(const VectorType& coefficients) const {
365  return pow(2 * PI, - 0.5 * this->GetNumberOfPrincipalComponents()) * exp(- 0.5 * coefficients.squaredNorm());
366 }
367 
368 
369 template <typename T>
370 double
372  VectorType alpha = ComputeCoefficientsForDataset(ds);
373  return std::sqrt(alpha.squaredNorm());
374 }
375 
376 
377 template <typename T>
378 VectorType
379 StatisticalModel<T>::RobustlyComputeCoefficientsForDataset(DatasetConstPointerType ds, unsigned nIterations, unsigned nu, double sigma2) const {
380  throw NotImplementedException("StatisticalModel", "RobustlyComputeCoefficientsForDataset");
381  /*
382  unsigned dim = Representer::GetDimensions();
383 
384  // we use double to improve the stability
385  MatrixType U = Utils::toDouble(this->m_pcaBasisMatrix);
386  VectorType yfloat;
387  m_representer->DatasetToSample(ds,&yfloat);
388 
389  MatrixTypeDoublePrecision y = Eigen::Map::toDouble(yfloat);
390  VectorTypeDoublePrecision mu = Utils::toDouble(this->m_mean);
391 
392 
393  const MatrixTypeDoublePrecision& UT = U.transpose();
394 
395  unsigned nPCA = GetNumberOfPrincipalComponents();
396 
397  typedef typename Representer::DatasetTraitsType DatasetTraitsType;
398 
399 
400  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> Vinv(VectorTypeDoublePrecision::Zero(y.size());
401  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> VinvSqrt(VectorTypeDoublePrecision::Zero(y.size()));
402 
403  y -= mu;
404  VectorTypeDoublePrecision f = VectorTypeDoublePrecistion::Zero(y.size());
405 
406  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> D(Utils::toDouble(m_pcaVariance.topLeftCorner(nPCA)));
407  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> Dinv = D.inverse();
408  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> D2 = D * D;
409  Eigen::DiagonalWrapper<VectorTypeDoublePrecision> D2inv = D2.inverse();
410 
411  for (unsigned i = 0; i < nIterations; i++) {
412 
413  // E step
414  for (unsigned j = 0; j < Vinv.size(); j++) {
415  // student-t case
416  Vinv(j) = (nu + 1.0) / (nu * sigma2 + pow(y(j) - f(j), 2));
417 
418  // for later use
419  VinvSqrt(j) = sqrt(Vinv(j));
420  }
421 
422  // M step
423  const MatrixTypeDoublePrecision W = VinvSqrt * U * D;
424  const MatrixTypeDoublePrecision WT = W.transpose();
425 
426  const VectorTypeDoublePrecision outer_term = (Vinv * y);
427  const MatrixTypeDoublePrecision IWTWInv = vnl_matrix_inverse<double>(vnl_diag_matrix<double>(nPCA, 1) + WT * W);
428  const VectorTypeDoublePrecision fst_term = (U * (D2 * (UT * outer_term)));
429  const VectorTypeDoublePrecision snd_term = (U * (D2 * (UT * (Vinv * (U * (D2 * (UT * outer_term)))))));
430  const VectorTypeDoublePrecision trd_term = (U * (D2 * (UT * (VinvSqrt * (W * (IWTWInv * (WT * (VinvSqrt * (U * (D2 * (UT * outer_term)))))))))));
431  f = fst_term - snd_term + trd_term;
432  }
433 
434  // the latent variable f is now a robust approximation for the data set. We return its coefficients.
435  DatasetConstPointerType newds = m_representer->sampleToDataset(f);
436  VectorType coeffs = GetCoefficientsForData(newds);
437  Representer::DeleteDataset(newds);
438  return coeffs;
439  */
440 }
441 
442 
443 
444 
445 template <typename T>
446 float
448  return m_noiseVariance;
449 }
450 
451 
452 template <typename T>
453 const VectorType&
455  return m_mean;
456 }
457 
458 template <typename T>
459 const VectorType&
461  return m_pcaVariance;
462 }
463 
464 
465 template <typename T>
466 const MatrixType&
468  return m_pcaBasisMatrix;
469 }
470 
471 template <typename T>
472 MatrixType
474  // we can recover the orthonormal matrix by undoing the scaling with the pcaVariance
475  // (c.f. the method SetParameters)
476 
477  assert(m_pcaVariance.maxCoeff() > 1e-8);
478  VectorType D = m_pcaVariance.array().sqrt();
479  return m_pcaBasisMatrix * DiagMatrixType(D).inverse();
480 }
481 
482 
483 
484 template <typename T>
485 void
487  m_modelInfo = modelInfo;
488 }
489 
490 
491 template <typename T>
492 const ModelInfo&
494  return m_modelInfo;
495 }
496 
497 
498 
499 template <typename T>
500 unsigned int
502  return m_pcaBasisMatrix.cols();
503 }
504 
505 template <typename T>
506 MatrixType
507 StatisticalModel<T>::GetJacobian(const PointType& pt) const {
508 
509  unsigned Dimensions = m_representer->GetDimensions();
510  MatrixType J = MatrixType::Zero(Dimensions, GetNumberOfPrincipalComponents());
511 
512  unsigned ptId = m_representer->GetPointIdForPoint(pt);
513 
514  for(unsigned i = 0; i < Dimensions; i++) {
515  unsigned idx = m_representer->MapPointIdToInternalIdx(ptId, i);
516  for(unsigned j = 0; j < GetNumberOfPrincipalComponents(); j++) {
517  J(i,j) += m_pcaBasisMatrix(idx,j) ;
518  }
519  }
520  return J;
521 }
522 
523 
524 template <typename T>
526 StatisticalModel<T>::Load(Representer<T>* representer, const std::string& filename, unsigned maxNumberOfPCAComponents) {
527 
528  StatisticalModel* newModel = 0;
529 
530  H5::H5File file;
531  try {
532  file = H5::H5File(filename.c_str(), H5F_ACC_RDONLY);
533  } catch (H5::Exception& e) {
534  std::string msg(std::string("could not open HDF5 file \n") + e.getCDetailMsg());
535  throw StatisticalModelException(msg.c_str());
536  }
537 
538  H5::Group modelRoot = file.openGroup("/");
539 
540  newModel = Load(representer, modelRoot, maxNumberOfPCAComponents);
541 
542  modelRoot.close();
543  file.close();
544  return newModel;
545 
546 }
547 
548 
549 template <typename T>
551 StatisticalModel<T>::Load(Representer<T>* representer, const H5::Group& modelRoot, unsigned maxNumberOfPCAComponents) {
552 
553  StatisticalModel* newModel = 0;
554 
555  try {
556  H5::Group representerGroup = modelRoot.openGroup("./representer");
557 
558  representer->Load(representerGroup);
559  representerGroup.close();
560 
561  newModel = new StatisticalModel(representer);
562 
563  int minorVersion = 0;
564  int majorVersion = 0;
565 
566  if (HDF5Utils::existsObjectWithName(modelRoot, "version") == false) {
567  // this is an old statismo format, that had not been versioned. We set the version to 0.8 as this is the last version
568  // that stores the old format
569  std::cout << "Warning: version attribute does not exist in hdf5 file. Assuming version 0.8" <<std::endl;
570  minorVersion = 8;
571  majorVersion = 0;
572  } else {
573  H5::Group versionGroup = modelRoot.openGroup("./version");
574  minorVersion = HDF5Utils::readInt(versionGroup, "./minorVersion");
575  majorVersion = HDF5Utils::readInt(versionGroup, "./majorVersion");
576  }
577 
578  H5::Group modelGroup = modelRoot.openGroup("./model");
579  HDF5Utils::readVector(modelGroup, "./mean", newModel->m_mean);
580  statismo::VectorType pcaVariance;
581  HDF5Utils::readVector(modelGroup, "./pcaVariance", maxNumberOfPCAComponents, pcaVariance);
582  newModel->m_pcaVariance = pcaVariance;
583 
584  // Depending on the statismo version, the pcaBasis matrix was stored as U*D or U (where U are the orthonormal PCA Basis functions and D the standard deviations).
585  // Here we make sure that we fill the pcaBasisMatrix (which statismo stores as U*D) with the right values.
586  if (majorVersion == 0 && minorVersion == 8) {
587  HDF5Utils::readMatrix(modelGroup, "./pcaBasis", maxNumberOfPCAComponents, newModel->m_pcaBasisMatrix);
588  } else if (majorVersion ==0 && minorVersion == 9) {
589  MatrixType orthonormalPCABasis;
590  HDF5Utils::readMatrix(modelGroup, "./pcaBasis", maxNumberOfPCAComponents, orthonormalPCABasis);
591 
592  VectorType D = pcaVariance.array().sqrt();
593  newModel->m_pcaBasisMatrix = orthonormalPCABasis * DiagMatrixType(D);
594  } else {
595  std::ostringstream os;
596  os << "an invalid statismo version was provided (" << majorVersion << "." << minorVersion << ")";
597  throw StatisticalModelException(os.str().c_str());
598  }
599  newModel->m_noiseVariance = HDF5Utils::readFloat(modelGroup, "./noiseVariance");
600 
601  modelGroup.close();
602  newModel->m_modelInfo.Load(modelRoot);
603 
604  } catch (H5::Exception& e) {
605  std::string msg(std::string("an exeption occured while reading HDF5 file") +
606  "The most likely cause is that the hdf5 file does not contain the required objects. \n" + e.getCDetailMsg());
607  throw StatisticalModelException(msg.c_str());
608  }
609 
610  assert(newModel != 0);
611  newModel->m_cachedValuesValid = false;
612 
613  newModel->m_modelLoaded = true;
614 
615  return newModel;
616 }
617 
618 template <typename T>
619 void
620 StatisticalModel<T>::Save(const std::string& filename) const {
621  using namespace H5;
622 
623  if (m_modelLoaded == true) {
624  throw StatisticalModelException("Cannot save the model: Note, to prevent inconsistencies in the model's history, only models that have been newly created can be saved, and not those loaded from an hdf5 file.");
625  }
626 
627 
628 
629  H5File file;
630  std::ifstream ifile(filename.c_str());
631 
632  try {
633  file = H5::H5File( filename.c_str(), H5F_ACC_TRUNC);
634  } catch (H5::FileIException& e) {
635  std::string msg(std::string("Could not open HDF5 file for writing \n") + e.getCDetailMsg());
636  throw StatisticalModelException(msg.c_str());
637  }
638 
639 
640  H5::Group modelRoot = file.openGroup("/");
641 
642  H5::Group versionGroup = modelRoot.createGroup("version");
643  HDF5Utils::writeInt(versionGroup, "majorVersion", 0);
644  HDF5Utils::writeInt(versionGroup, "minorVersion", 9);
645  versionGroup.close();
646 
647  Save(modelRoot);
648  modelRoot.close();
649  file.close();
650 }
651 
652 template <typename T>
653 void
654 StatisticalModel<T>::Save(const H5::Group& modelRoot) const {
655 
656  try {
657  // create the group structure
658 
659  std::string dataTypeStr = RepresenterType::TypeToString(m_representer->GetType());
660 
661  H5::Group representerGroup = modelRoot.createGroup("./representer");
662  HDF5Utils::writeStringAttribute(representerGroup, "name", m_representer->GetName());
663  HDF5Utils::writeStringAttribute(representerGroup, "version", m_representer->GetVersion());
664  HDF5Utils::writeStringAttribute(representerGroup, "datasetType", dataTypeStr);
665 
666  this->m_representer->Save(representerGroup);
667  representerGroup.close();
668 
669  H5::Group modelGroup = modelRoot.createGroup( "./model" );
670  HDF5Utils::writeMatrix(modelGroup, "./pcaBasis", GetOrthonormalPCABasisMatrix());
671  HDF5Utils::writeVector(modelGroup, "./pcaVariance", m_pcaVariance);
672  HDF5Utils::writeVector(modelGroup, "./mean", m_mean);
673  HDF5Utils::writeFloat(modelGroup, "./noiseVariance", m_noiseVariance);
674  modelGroup.close();
675 
676  m_modelInfo.Save(modelRoot);
677 
678 
679  } catch (H5::Exception& e) {
680  std::string msg(std::string("an exception occurred while writing HDF5 file \n") + e.getCDetailMsg());
681  throw StatisticalModelException(msg.c_str());
682  }
683 }
684 
685 template <typename T>
686 void
688 
689  if (m_cachedValuesValid == false) {
690  VectorType I = VectorType::Ones(m_pcaBasisMatrix.cols());
691  MatrixType Mmatrix = m_pcaBasisMatrix.transpose() * m_pcaBasisMatrix;
692  Mmatrix.diagonal() += m_noiseVariance * I;
693 
694  m_MInverseMatrix = Mmatrix.inverse();
695 
696  }
697  m_cachedValuesValid = true;
698 }
699 
700 } // namespace statismo
701 
702 #endif
static bool existsObjectWithName(const H5::CommonFG &fg, const std::string &name)
Definition: HDF5Utils.hxx:542
static void readMatrix(const H5::CommonFG &fg, const char *name, MatrixType &matrix)
Definition: HDF5Utils.hxx:154
static StatisticalModel * Load(Representer< T > *representer, const std::string &filename, unsigned maxNumberOfPCAComponents=std::numeric_limits< unsigned >::max())
Definition: StatisticalModel.hxx:526
ValueType DrawSampleAtPoint(const VectorType &coefficients, const PointType &point, bool addNoise=false) const
Definition: StatisticalModel.hxx:191
VectorType ComputeCoefficientsForPointIDValues(const PointIdValueListType &pointValues, double pointValueNoiseVariance=0.0) const
Definition: StatisticalModel.hxx:310
double ComputeMahalanobisDistanceForDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:371
static H5::DataSet writeMatrix(const H5::CommonFG &fg, const char *name, const MatrixType &matrix)
Definition: HDF5Utils.hxx:248
const ModelInfo & GetModelInfo() const
Definition: StatisticalModel.hxx:493
A trivial representer, that does no representation at all, but works directly with vectorial data...
Definition: TrivialVectorialRepresenter.h:83
VectorType DrawSampleVector(const VectorType &coefficients, bool addNoise=false) const
Definition: StatisticalModel.hxx:170
Used to indicate that a method has not yet been implemented.
Definition: Exceptions.h:50
MatrixType GetOrthonormalPCABasisMatrix() const
Definition: StatisticalModel.hxx:473
VectorType ComputeCoefficientsForSample(DatasetConstPointerType sample) const
Definition: StatisticalModel.hxx:277
float GetNoiseVariance() const
Definition: StatisticalModel.hxx:447
VectorType ComputeCoefficientsForSampleVector(const VectorType &sample) const
Definition: StatisticalModel.hxx:283
VectorType RobustlyComputeCoefficientsForDataset(DatasetConstPointerType dataset, unsigned nIterations=100, unsigned nu=6, double sigma2=1) const
Definition: StatisticalModel.hxx:379
DatasetPointerType DrawPCABasisSample(unsigned componentNumber) const
Definition: StatisticalModel.hxx:157
static void writeStringAttribute(const H5::H5Object &group, const char *name, const std::string &s)
Definition: HDF5Utils.hxx:387
static float readFloat(const H5::CommonFG &fg, const char *name)
Definition: HDF5Utils.hxx:452
virtual ~StatisticalModel()
Definition: StatisticalModel.hxx:73
static H5::DataSet writeInt(const H5::CommonFG &fg, const char *name, int value)
Definition: HDF5Utils.hxx:426
MatrixType GetCovarianceMatrix() const
Definition: StatisticalModel.hxx:258
Generic Exception class for the statismo Library.
Definition: Exceptions.h:68
const VectorType & GetPCAVarianceVector() const
Definition: StatisticalModel.hxx:460
const MatrixType & GetPCABasisMatrix() const
Definition: StatisticalModel.hxx:467
void SetModelInfo(const ModelInfo &modelInfo)
Definition: StatisticalModel.hxx:486
ValueType DrawMeanAtPoint(const PointType &point) const
Definition: StatisticalModel.hxx:120
stores meta information about the model, such as e.g. the name (uri) of the datasets used to build th...
Definition: ModelInfo.h:61
DatasetPointerType DatasetToSample(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:88
DatasetPointerType DrawMean() const
Definition: StatisticalModel.hxx:112
double ComputeProbabilityOfCoefficients(const VectorType &coefficients) const
Definition: StatisticalModel.hxx:364
static void readVector(const H5::CommonFG &fg, const char *name, unsigned nElements, VectorType &vector)
Definition: HDF5Utils.hxx:296
static H5::DataSet writeVector(const H5::CommonFG &fg, const char *name, const VectorType &vector)
Definition: HDF5Utils.hxx:363
MatrixType GetJacobian(const PointType &pt) const
Definition: StatisticalModel.hxx:507
double ComputeProbabilityOfDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:350
unsigned int GetNumberOfPrincipalComponents() const
Definition: StatisticalModel.hxx:501
VectorType ComputeCoefficientsForDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:267
ValueType EvaluateSampleAtPoint(DatasetConstPointerType sample, unsigned ptId) const
Definition: StatisticalModel.hxx:105
double ComputeLogProbabilityOfDataset(DatasetConstPointerType dataset) const
Definition: StatisticalModel.hxx:343
MatrixType GetCovarianceAtPoint(const PointType &pt1, const PointType &pt2) const
Definition: StatisticalModel.hxx:230
const VectorType & GetMeanVector() const
Definition: StatisticalModel.hxx:454
static H5::DataSet writeFloat(const H5::CommonFG &fg, const char *name, float value)
Definition: HDF5Utils.hxx:444
DatasetPointerType DrawSample(const VectorType &coefficients, bool addNoise=false) const
Definition: StatisticalModel.hxx:150
A Point/Value pair that is used to specify a value at a given point.
Definition: StatisticalModel.h:100
virtual void Load(const H5::CommonFG &publicFg)
Definition: ModelInfo.cxx:118
void Save(const std::string &filename) const
Definition: StatisticalModel.hxx:620
double ComputeLogProbabilityOfCoefficients(const VectorType &coefficients) const
Definition: StatisticalModel.hxx:358
static int readInt(const H5::CommonFG &fg, const char *name)
Definition: HDF5Utils.hxx:434
VectorType ComputeCoefficientsForPointValues(const PointValueListType &pointValues, double pointValueNoiseVariance=0.0) const
Definition: StatisticalModel.hxx:297