Statismo  0.10.1
 All Classes Namespaces Functions Typedefs
genericRepresenterTest.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 addINTERRUPTION) 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 #include <iostream>
39 
40 #include "CommonTypes.h"
41 #include "HDF5Utils.h"
42 #include "StatismoUtils.h"
43 
47 template <typename Representer>
49 
50 
51  // we define typedefs for all required typenames, to force a compilation error if one of them
52  // is not defined
53  typedef typename Representer::DatasetConstPointerType DatasetConstPointerType;
54  typedef typename Representer::DatasetPointerType DatasetPointerType;
55  typedef typename Representer::PointType PointType;
56  typedef typename Representer::ValueType ValueType;
57 
58  typedef typename Representer::DomainType DomainType;
59 
60  public:
61 
65  GenericRepresenterTest(const Representer* representer, DatasetConstPointerType testDataset, std::pair<PointType, ValueType> pointValuePair)
66  : m_representer(representer),
67  m_testDataset(testDataset),
68  m_testPoint(pointValuePair.first),
69  m_testValue(pointValuePair.second) {
70  }
71 
72 
73  bool testSamplePointEvaluation() const {
74  DatasetConstPointerType sample = m_testDataset;
75  unsigned id = m_representer->GetPointIdForPoint(m_testPoint);
76  ValueType val = m_representer->PointSampleFromSample(sample, id);
77  statismo::VectorType valVec = m_representer->PointSampleToPointSampleVector(val);
78 
79  // the obtained value should correspond to the value that is obtained by obtaining the sample vector, and evaluating it at the given position
80  statismo::VectorType sampleVector = m_representer->SampleToSampleVector(sample);
81  for (unsigned i = 0; i < m_representer->GetDimensions(); ++i) {
82  unsigned idx = m_representer->MapPointIdToInternalIdx(id, i);
83  if (sampleVector(i) != valVec(i)) {
84  return false;
85  }
86  }
87  return true;
88  }
89 
90  bool testDomainValid() const {
91  std::cout << "testDomainValid" << std::endl;
92 
93  const DomainType domain = m_representer->GetDomain();
94  typename DomainType::DomainPointsListType domPoints = domain.GetDomainPoints();
95 
96  if (domPoints.size() == 0) {
97  std::cout << "representer defined empty domain" << std::endl;
98  return false;
99  }
100  if (domPoints.size() != domain.GetNumberOfPoints()) {
101  std::cout << "domPoints.size() != domain.GetNumberOfPoints() (" << domPoints.size() << " != " << domain.GetNumberOfPoints() << std::endl;
102  return false;
103  }
104  // if we convert a dataset to a samplevector, the resulting vector needs to have
105  // as many entries as there are points * dimensions
106  DatasetConstPointerType sample = m_testDataset;
107  statismo::VectorType sampleVector = m_representer->SampleToSampleVector(sample);
108  if (sampleVector.rows() != m_representer->GetDimensions() * domain.GetNumberOfPoints()) {
109  std::cout << "the dimension of the sampleVector does not agree with the number of points in the domain (#points * dimensionality)" << std::endl;
110  return false;
111  }
112 
113 
114  unsigned ptNo = 0;
115  for (typename DomainType::DomainPointsListType::const_iterator it = domPoints.begin();
116  it != domPoints.end();
117  ++it) {
118  // since this can take long, we only do it for every 10th point
119  if (ptNo % 10 != 0)
120  break;
121 
122  if (m_representer->GetPointIdForPoint(*it) >= domain.GetNumberOfPoints()) {
123  std::cout << "a point in the domain did not evaluate to a valid point it" << std::endl;
124  return false;
125  }
126  ptNo++;
127  }
128 
129 
130  return true;
131 
132  }
133 
134 
135 
138  std::cout << "testSampleToVectorToSample" << std::endl;
139 
140  statismo::VectorType sampleVec = getSampleVectorFromTestDataset();
141 
142  DatasetConstPointerType reconstructedSample = m_representer->SampleVectorToSample(sampleVec);
143 
144  // as we don't know anything about how to compare samples, we compare their vectorial representation
145  statismo::VectorType reconstructedSampleAsVec = m_representer->SampleToSampleVector(reconstructedSample);
146  bool isOkay = assertSampleVectorsEqual(sampleVec, reconstructedSampleAsVec);
147  if (isOkay == false) {
148  std::cout << "Error: the sample has changed by converting between the representations " << std::endl;
149  }
150  return true;
151  }
152 
155  std::cout << "testPointSampleDimension" << std::endl;
156 
157  statismo::VectorType valVec = m_representer->PointSampleToPointSampleVector(m_testValue);
158 
159  if (valVec.rows() != m_representer->GetDimensions()) {
160  std::cout << "Error: The dimensionality of the pointSampleVector is not the same as the Dimensionality of the representer" << std::endl;
161  return false;
162  }
163  return true;
164  }
165 
166 
170  std::cout << "testPointSampleToPointSampleVectorAndBack" << std::endl;
171 
172  statismo::VectorType valVec = m_representer->PointSampleToPointSampleVector(m_testValue);
173  ValueType recVal = m_representer->PointSampleVectorToPointSample(valVec);
174 
175  // we compare the vectors and not the points, as we don't know how to compare poitns.
176  statismo::VectorType recValVec = m_representer->PointSampleToPointSampleVector(recVal);
177  bool ok = assertSampleVectorsEqual(valVec, recValVec);
178  if (!ok) {
179  std::cout << "Error: the point sample has changed by converting between the representations" << std::endl;
180  }
181  return ok;
182  }
183 
187  std::cout << "testSampleVectorHasCorrectValueAtPoint" << std::endl;
188 
189  unsigned ptId = m_representer->GetPointIdForPoint(m_testPoint);
190  if (ptId < 0 || ptId >= m_representer->GetNumberOfPoints()) {
191  std::cout << "Error: invalid point id for test point " << ptId << std::endl;
192  return false;
193  }
194 
195  // the value of the point in the sample vector needs to correspond the the value that was provided
196  statismo::VectorType sampleVec = getSampleVectorFromTestDataset();
197  statismo::VectorType pointSampleVec = m_representer->PointSampleToPointSampleVector(m_testValue);
198 
199  for (unsigned d = 0; d < m_representer->GetDimensions(); ++d) {
200  unsigned idx = m_representer->MapPointIdToInternalIdx(ptId, d);
201  if (sampleVec[idx] != pointSampleVec[d]) {
202  std::cout << "Error: the sample vector does not contain the correct value of the pointSample " << std::endl;
203  return false;
204  }
205  }
206  return true;
207 
208  }
209 
210 
212  bool testSaveLoad() const {
213  std::cout << "testSaveLoad" << std::endl;
214 
215  using namespace H5;
216 
217  std::string filename = statismo::Utils::CreateTmpName(".rep");
218  H5File file;
219  try {
220  file = H5File( filename, H5F_ACC_TRUNC );
221  } catch (Exception& e) {
222  std::string msg(std::string("Error: Could not open HDF5 file for writing \n") + e.getCDetailMsg());
223  std::cout << msg << std::endl;
224  return false;
225  }
226  H5::Group representerGroup = file.createGroup("/representer");
227 
228  m_representer->Save(representerGroup);
229 
230  // We add the required attributes, which are usually written by the StatisticalModel class.
231  // This is needed, as some representers check on these values.
232 
233  statismo::HDF5Utils::writeStringAttribute(representerGroup, "name", m_representer->GetName());
234  std::string dataTypeStr = Representer::TypeToString(m_representer->GetType());
235  statismo::HDF5Utils::writeStringAttribute(representerGroup, "datasetType", dataTypeStr);
236 
237  file.close();
238  try {
239  file = H5File(filename.c_str(), H5F_ACC_RDONLY);
240  } catch (Exception& e) {
241  std::string msg(std::string("Error: could not open HDF5 file \n") + e.getCDetailMsg());
242  std::cout << msg << std::endl;
243  return false;
244  }
245 
246  representerGroup.close();
247  representerGroup = file.openGroup("/representer");
248 
249  Representer* newRep = Representer::Create();
250  newRep->Load(representerGroup);
251 
252  bool isOkay = assertRepresenterEqual(newRep, m_representer);
253  newRep->Delete();
254 
255  return isOkay;
256 
257  }
258 
260  bool testClone() const {
261  std::cout << "testClone" << std::endl;
262  bool isOkay = true;
263 
264  Representer* rep = m_representer->Clone();
265  if (assertRepresenterEqual(rep, m_representer) == false) {
266  std::cout << "Error: the clone of the representer is not the same as the representer " << std::endl;
267  isOkay = false;
268  }
269  rep->Delete();
270  return isOkay;
271  }
272 
275  std::cout << "testSampleVectorDimensions()" << std::endl;
276  statismo::VectorType testSampleVec = getSampleVectorFromTestDataset();
277 
278  bool isOk = m_representer->GetDimensions() * m_representer->GetNumberOfPoints() == testSampleVec.rows();
279  if (!isOk) {
280  std::cout << "Error: Dimensionality of the sample vector does not agree with the representer parameters "
281  << "dimension and numberOfPoints" << std::endl;
282  std::cout << testSampleVec.rows() << " != " << m_representer->GetDimensions() << " * " << m_representer->GetNumberOfPoints() << std::endl;
283  }
284  return isOk;
285  }
286 
288  bool testGetName() const {
289  std::cout << "testGetName" << std::endl;
290 
291  if (m_representer->GetName() == "") {
292  std::cout << "Error: representer name has to be non empty" << std::endl;
293  return false;
294  }
295  return true;
296  }
297 
299  bool testDimensions() const {
300  std::cout << "testDimensions " << std::endl;
301 
302  if (m_representer->GetDimensions() <= 0) {
303  std::cout << "Error: Dimensionality of representer has to be > 0" << std::endl;
304  return false;
305  }
306  return true;
307  }
308 
310  bool runAllTests() {
311  bool ok = true;
312  ok = testPointSampleDimension() && ok;
313  ok = testSamplePointEvaluation() && ok;
314  ok = testDomainValid() && ok;
317  ok = testSampleToVectorAndBack() && ok;
318  ok = testSaveLoad() && ok;
319  ok = testClone() && ok;
320  ok = testSampleVectorDimensions() && ok;
321  ok = testGetName() && ok;
322  ok = testDimensions() && ok;
323  return ok;
324  }
325 
326 
327  private:
328 
329 
330  bool assertRepresenterEqual(const Representer* representer1, const Representer* representer2) const {
331  if (representer1->GetNumberOfPoints() != representer2->GetNumberOfPoints()) {
332  std::cout << "the representers do not have the same nubmer of points " <<std::endl;
333  return false;
334  }
335  statismo::VectorType sampleRep1 = getSampleVectorFromTestDataset(representer1);
336  statismo::VectorType sampleRep2 = getSampleVectorFromTestDataset(representer2);
337  if (assertSampleVectorsEqual(sampleRep1, sampleRep2) == false) {
338  std::cout << "the representers produce different sample vectors for the same sample" << std::endl;
339  return false;
340  }
341 
342  return true;
343  }
344 
345 
346  bool assertSampleVectorsEqual(const statismo::VectorType& v1, const statismo::VectorType& v2) const {
347  if (v1.rows() != v2.rows()) {
348  std::cout << "dimensionality of SampleVectors do not agree" << std::endl;
349  return false;
350  }
351 
352  for (unsigned i = 0; i < v1.rows(); ++i) {
353  if (v1[i] != v2[i]) {
354  std::cout << "the sample vectors are not the same" << std::endl;
355  return false;
356  }
357  }
358 
359  return true;
360  }
361 
362 
363  statismo::VectorType getSampleVectorFromTestDataset() const {
364  return getSampleVectorFromTestDataset(m_representer);
365  }
366 
367  statismo::VectorType getSampleVectorFromTestDataset(const Representer* representer) const {
368  DatasetConstPointerType sample = m_testDataset;
369  statismo::VectorType sampleVec = representer->SampleToSampleVector(sample);
370  return sampleVec;
371  }
372 
373 
374  const Representer* m_representer;
375  DatasetConstPointerType m_testDataset;
376  PointType m_testPoint;
377  ValueType m_testValue;
378 
379 };
380 
381 
bool runAllTests()
run all the tests
Definition: genericRepresenterTest.hxx:310
const unsigned GetNumberOfPoints() const
Definition: Domain.h:72
bool testSampleVectorDimensions() const
test if the sample vector dimensions are correct
Definition: genericRepresenterTest.hxx:274
bool testGetName() const
test whether the name is defined
Definition: genericRepresenterTest.hxx:288
GenericRepresenterTest(const Representer *representer, DatasetConstPointerType testDataset, std::pair< PointType, ValueType > pointValuePair)
Definition: genericRepresenterTest.hxx:65
bool testSaveLoad() const
test whether the representer is correctly restored
Definition: genericRepresenterTest.hxx:212
Definition: genericRepresenterTest.hxx:48
bool testDimensions() const
test if the dimensionality is nonnegative
Definition: genericRepresenterTest.hxx:299
bool testPointSampleDimension() const
test if the pointSamples have the correct dimensionality
Definition: genericRepresenterTest.hxx:154
static void writeStringAttribute(const H5::H5Object &group, const char *name, const std::string &s)
Definition: HDF5Utils.hxx:387
bool testClone() const
test whether cloning a representer results in a representer with the same behaviour ...
Definition: genericRepresenterTest.hxx:260
bool testPointSampleToPointSampleVectorAndBack() const
Definition: genericRepresenterTest.hxx:169
const DomainPointsListType & GetDomainPoints() const
Definition: Domain.h:67
bool testSampleVectorHasCorrectValueAtPoint() const
Definition: genericRepresenterTest.hxx:186
bool testSampleToVectorAndBack() const
test whether converting a sample to a vector and back to a sample yields the original sample ...
Definition: genericRepresenterTest.hxx:137
Definition: Domain.h:51