Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkSceneIOTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkTestingConfig.h"
14 #include "mitkTestingMacros.h"
15 
16 #include "mitkSceneIO.h"
17 
18 #include "Poco/File.h"
19 #include "Poco/TemporaryFile.h"
20 #include "mitkBaseData.h"
21 #include "mitkCoreObjectFactory.h"
22 #include "mitkGeometryData.h"
23 #include "mitkIOUtil.h"
24 #include "mitkImage.h"
25 #include "mitkPointSet.h"
28 #include "mitkSurface.h"
29 
30 #ifndef WIN32
31 #include <cerrno>
32 #include <ulimit.h>
33 #endif
34 
35 class SceneIOTestClass
36 {
37 public:
38  static mitk::Image::Pointer LoadImage(const std::string &filename)
39  {
40  mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(filename);
41  if (image.IsNull())
42  {
43  MITK_TEST_FAILED_MSG(<< "Test image '" << filename << "' was not loaded as an mitk::Image");
44  }
45  return image;
46  }
47 
48  static mitk::Surface::Pointer LoadSurface(const std::string &filename)
49  {
50  mitk::Surface::Pointer surface = mitk::IOUtil::Load<mitk::Surface>(filename);
51  if (surface.IsNull())
52  {
53  MITK_TEST_FAILED_MSG(<< "Test surface '" << filename << "' was not loaded as an mitk::Surface");
54  }
55  return surface;
56  }
57 
58  static mitk::PointSet::Pointer CreatePointSet()
59  {
62  mitk::FillVector3D(p, 1.0, -2.0, 33.0);
63  ps->SetPoint(0, p);
64  mitk::FillVector3D(p, 100.0, -200.0, 3300.0);
65  ps->SetPoint(1, p);
66  mitk::FillVector3D(p, 2.0, -3.0, 22.0);
67  ps->SetPoint(2, p, mitk::PTCORNER); // add point spec
68  // mitk::FillVector3D(p, -2.0, -2.0, -2.22);
69  // ps->SetPoint(0, p, 1); // ID 0 in timestep 1
70  // mitk::FillVector3D(p, -1.0, -1.0, -11.22);
71  // ps->SetPoint(1, p, 1); // ID 1 in timestep 1
72  // mitk::FillVector3D(p, 1000.0, 1000.0, 1122.22);
73  // ps->SetPoint(11, p, mitk::PTCORNER, 2); // ID 11, point spec, timestep 2
74  return ps;
75  }
76 
77  static mitk::GeometryData::Pointer CreateGeometryDataObject()
78  {
80 
81  // define Geometry3D parameters
82  mitk::AffineTransform3D::MatrixType matrix;
83  matrix[0][0] = 1.1;
84  matrix[1][1] = 2.2;
85  matrix[2][2] = 3.3;
86  mitk::AffineTransform3D::OffsetType offset;
87  mitk::FillVector3D(offset, 0.1, 0.2, 0.3);
88  bool isImageGeometry(false);
89  unsigned int frameOfReferenceID(47);
91  mitk::Point3D origin;
92  mitk::FillVector3D(origin, 5.1, 5.2, 5.3);
93  mitk::Vector3D spacing;
94  mitk::FillVector3D(spacing, 2.1, 2.2, 2.3);
95 
96  // build GeometryData from matrix/offset/etc.
97  mitk::AffineTransform3D::Pointer newTransform = mitk::AffineTransform3D::New();
98  newTransform->SetMatrix(matrix);
99  newTransform->SetOffset(offset);
100 
102  newGeometry->SetFrameOfReferenceID(frameOfReferenceID);
103  newGeometry->SetImageGeometry(isImageGeometry);
104 
105  newGeometry->SetIndexToWorldTransform(newTransform);
106 
107  newGeometry->SetBounds(bounds);
108  newGeometry->SetOrigin(origin);
109  newGeometry->SetSpacing(spacing);
110 
112  gdata->SetGeometry(newGeometry);
113 
114  return gdata;
115  }
116 
117  static void FillStorage(mitk::DataStorage *storage, std::string imageName, std::string surfaceName)
118  {
119  mitk::Image::Pointer image = LoadImage(imageName);
120  MITK_TEST_CONDITION_REQUIRED(image.IsNotNull(), "Loading test image" + imageName);
121 
122  image->SetProperty("image type", mitk::StringProperty::New("test image"));
123  image->SetProperty("greetings", mitk::StringProperty::New("to mom"));
124  image->SetProperty("test_float_property", mitk::FloatProperty::New(-2.57f));
125 
127  imagenode->SetData(image);
128  imagenode->SetName("Pic3D");
129  storage->Add(imagenode);
130 
131  mitk::DataNode::Pointer imagechildnode = mitk::DataNode::New();
132  imagechildnode->SetData(image);
133  imagechildnode->SetName("Pic3D again");
134  storage->Add(imagechildnode, imagenode);
135 
136  mitk::Surface::Pointer surface = LoadSurface(surfaceName);
137  MITK_TEST_CONDITION_REQUIRED(surface.IsNotNull(), "Loading test surface binary.stl");
138 
139  surface->SetProperty("surface type", mitk::StringProperty::New("test surface"));
140  surface->SetProperty("greetings", mitk::StringProperty::New("to dad"));
141 
143  surfacenode->SetData(surface);
144  surfacenode->SetName("binary");
145  storage->Add(surfacenode);
146 
147  mitk::PointSet::Pointer ps = CreatePointSet();
149  psenode->SetData(ps);
150  psenode->SetName("points");
151  storage->Add(psenode);
152 
153  mitk::GeometryData::Pointer gdo = CreateGeometryDataObject();
155  geomNode->SetData(gdo);
156  geomNode->SetName("geometry3d");
157  storage->Add(geomNode);
158  }
159 
160  static void VerifyStorage(mitk::DataStorage *storage)
161  {
162  mitk::DataNode::Pointer imagenode = storage->GetNamedNode("Pic3D");
163  MITK_TEST_CONDITION_REQUIRED(imagenode.IsNotNull(), "Get previously stored image node");
164 
165  mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(imagenode->GetData());
166  MITK_TEST_CONDITION_REQUIRED(image.IsNotNull(), "Loading test image from Datastorage");
167 
168  // Image
169  std::string testString("");
170  float testFloatValue = 0.0f;
171  mitk::PropertyList::Pointer imagePropList = image->GetPropertyList();
172 
173  imagePropList->GetStringProperty("image type", testString);
174  MITK_TEST_CONDITION(testString == "test image", "Get StringProperty from previously stored image");
175 
176  imagePropList->GetStringProperty("greetings", testString);
177  MITK_TEST_CONDITION(testString == "to mom", "Get another StringProperty from previously stored image");
178 
179  imagePropList->GetFloatProperty("test_float_property", testFloatValue);
180  MITK_TEST_CONDITION(testFloatValue == -2.57f, "Get FloatProperty from previously stored image.")
181 
182  // Get Image child node
183  mitk::DataNode::Pointer imagechildnode = storage->GetNamedNode("Pic3D again");
184  mitk::DataStorage::SetOfObjects::ConstPointer objects = storage->GetSources(imagechildnode);
185 
186  MITK_TEST_CONDITION_REQUIRED(objects->Size() == 1, "Check size of image child nodes source list");
187  MITK_TEST_CONDITION_REQUIRED(objects->ElementAt(0) == imagenode, "Check for right parent node");
188 
189  mitk::Image::Pointer imagechild = dynamic_cast<mitk::Image *>(imagechildnode->GetData());
190  MITK_TEST_CONDITION_REQUIRED(imagechild.IsNotNull(), "Loading child test image from Datastorage");
191 
192  // Surface
193  mitk::DataNode::Pointer surfacenode = storage->GetNamedNode("binary");
194  MITK_TEST_CONDITION_REQUIRED(surfacenode.IsNotNull(), "Get previously stored surface node");
195 
196  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(surfacenode->GetData());
197  MITK_TEST_CONDITION_REQUIRED(surface.IsNotNull(), "Loading test surface from Datastorage");
198 
199  // Get the property list and test the properties
200  mitk::PropertyList::Pointer surfacePropList = surface->GetPropertyList();
201  surfacePropList->GetStringProperty("surface type", testString);
202  MITK_TEST_CONDITION((testString.compare("test surface") == 0),
203  "Get StringProperty from previously stored surface node");
204 
205  surfacePropList->GetStringProperty("greetings", testString);
206  MITK_TEST_CONDITION((testString.compare("to dad") == 0),
207  "Get another StringProperty from previously stored surface node");
208 
209  // PointSet
210  mitk::DataNode::Pointer pointsnode = storage->GetNamedNode("points");
211  MITK_TEST_CONDITION_REQUIRED(pointsnode.IsNotNull(), "Get previously stored PointSet node");
212 
213  mitk::PointSet::Pointer pointset = dynamic_cast<mitk::PointSet *>(pointsnode->GetData());
214  MITK_TEST_CONDITION_REQUIRED(pointset.IsNotNull(), "Loading test PointSet from Datastorage");
215 
216  mitk::PointSet::PointType p = pointset->GetPoint(0);
217  MITK_TEST_CONDITION_REQUIRED(p[0] == 1.0 && p[1] == -2.0 && p[2] == 33.0, "Test Pointset entry 0 after loading");
218 
219  p = pointset->GetPoint(1);
220  MITK_TEST_CONDITION_REQUIRED(p[0] == 100.0 && p[1] == -200.0 && p[2] == 3300.0,
221  "Test Pointset entry 1 after loading");
222 
223  p = pointset->GetPoint(2);
224  MITK_TEST_CONDITION_REQUIRED(p[0] == 2.0 && p[1] == -3.0 && p[2] == 22.0, "Test Pointset entry 2 after loading");
225 
226  // GeometryData
227  mitk::DataNode::Pointer geomnode = storage->GetNamedNode("geometry3d");
228  MITK_TEST_CONDITION_REQUIRED(geomnode.IsNotNull(), "Get previously stored GeometryData node");
229 
230  mitk::GeometryData::Pointer gdata = dynamic_cast<mitk::GeometryData *>(geomnode->GetData());
231  MITK_TEST_CONDITION_REQUIRED(gdata.IsNotNull(), "Loading test GeometryData from Datastorage");
232 
233  mitk::Geometry3D::Pointer geom3D = dynamic_cast<mitk::Geometry3D *>(gdata->GetGeometry());
234  MITK_TEST_CONDITION_REQUIRED(geom3D.IsNotNull(), "Reconstructed a Geometry3D from serialization");
235  MITK_TEST_CONDITION(geom3D->GetImageGeometry() == false, "Reconstructed Geometry3D 'is image geometry'");
236  MITK_TEST_CONDITION(geom3D->GetFrameOfReferenceID() == 47, "Reconstructa Geometry3D has frame of reference '47'");
237 
238  // TODO test other properties, BUT don't test too much, that shall be done in a reader/writer test!
239  }
240 }; // end test helper class
241 
242 int mitkSceneIOTest(int, char *argv[])
243 {
244  MITK_TEST_BEGIN("SceneIO")
245  std::string sceneFileName;
246 
247  for (unsigned int i = 0; i < 1; ++i) // TODO change to " < 2" to check cases where file system would be full
248  {
249  if (i == 1)
250  {
251 // call ulimit and restrict maximum file size to something small
252 #ifndef WIN32
253  errno = 0;
254  long int value = ulimit(UL_SETFSIZE, 1);
255  MITK_TEST_CONDITION_REQUIRED(value != -1, "ulimit() returned with errno = " << errno);
256 #else
257  continue;
258 #endif
259  }
260 
261  // create a data storage and fill it with some test data
262  mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New();
263  MITK_TEST_CONDITION_REQUIRED(sceneIO.IsNotNull(), "SceneIO instantiation")
264 
266  MITK_TEST_CONDITION_REQUIRED(storage.IsNotNull(), "StandaloneDataStorage instantiation");
267 
268  std::cout << "ImageName: " << argv[1] << std::endl;
269  std::cout << "SurfaceName: " << argv[2] << std::endl;
270 
271  SceneIOTestClass::FillStorage(storage, argv[1], argv[2]);
272 
273  // attempt to save it
274  Poco::Path newname(Poco::TemporaryFile::tempName());
275  sceneFileName = std::string(MITK_TEST_OUTPUT_DIR) + Poco::Path::separator() + newname.getFileName() + ".zip";
276  MITK_TEST_CONDITION_REQUIRED(sceneIO->SaveScene(storage->GetAll(), storage, sceneFileName),
277  "Saving scene file '" << sceneFileName << "'");
278 
279  // test if no errors were reported
280  mitk::SceneIO::FailedBaseDataListType::ConstPointer failedNodes = sceneIO->GetFailedNodes();
281  if (failedNodes.IsNotNull() && !failedNodes->empty())
282  {
283  MITK_TEST_OUTPUT(<< "The following nodes could not be serialized:");
284  for (auto iter = failedNodes->begin();
285  iter != failedNodes->end();
286  ++iter)
287  {
288  MITK_TEST_OUTPUT_NO_ENDL(<< " - ");
289  if (mitk::BaseData *data = (*iter)->GetData())
290  {
291  MITK_TEST_OUTPUT_NO_ENDL(<< data->GetNameOfClass());
292  }
293  else
294  {
295  MITK_TEST_OUTPUT_NO_ENDL(<< "(nullptr)");
296  }
297 
298  MITK_TEST_OUTPUT(<< " contained in node '" << (*iter)->GetName() << "'");
299  // \TODO: should we fail the test case if failed properties exist?
300  }
301  }
302 
303  mitk::PropertyList::ConstPointer failedProperties = sceneIO->GetFailedProperties();
304  if (failedProperties.IsNotNull() && !failedProperties->IsEmpty())
305  {
306  MITK_TEST_OUTPUT(<< "The following properties could not be serialized:");
307  const mitk::PropertyList::PropertyMap *propmap = failedProperties->GetMap();
308  for (auto iter = propmap->begin(); iter != propmap->end(); ++iter)
309  {
310  MITK_TEST_OUTPUT(<< " - " << iter->second->GetNameOfClass() << " associated to key '" << iter->first << "'");
311  // \TODO: should we fail the test case if failed properties exist?
312  }
313  }
314  MITK_TEST_CONDITION_REQUIRED(failedProperties.IsNotNull() && failedProperties->IsEmpty(),
315  "Checking if all properties have been saved.")
316  MITK_TEST_CONDITION_REQUIRED(failedNodes.IsNotNull() && failedNodes->empty(),
317  "Checking if all nodes have been saved.")
318 
319  // Now do the loading part
320  sceneIO = mitk::SceneIO::New();
321 
322  // Load scene into the datastorage and clean the DS first
323  MITK_TEST_OUTPUT(<< "Loading scene again");
324  storage = sceneIO->LoadScene(sceneFileName, storage, true);
325 
326  // test if no errors were reported
327  failedNodes = sceneIO->GetFailedNodes();
328  if (failedNodes.IsNotNull() && !failedNodes->empty())
329  {
330  MITK_TEST_OUTPUT(<< "The following nodes could not be serialized:");
331  for (auto iter = failedNodes->begin();
332  iter != failedNodes->end();
333  ++iter)
334  {
335  MITK_TEST_OUTPUT_NO_ENDL(<< " - ");
336  if (mitk::BaseData *data = (*iter)->GetData())
337  {
338  MITK_TEST_OUTPUT_NO_ENDL(<< data->GetNameOfClass());
339  }
340  else
341  {
342  MITK_TEST_OUTPUT_NO_ENDL(<< "(nullptr)");
343  }
344 
345  MITK_TEST_OUTPUT(<< " contained in node '" << (*iter)->GetName() << "'");
346  // \TODO: should we fail the test case if failed properties exist?
347  }
348  }
349 
350  failedProperties = sceneIO->GetFailedProperties();
351  if (failedProperties.IsNotNull() && !failedProperties->IsEmpty())
352  {
353  MITK_TEST_OUTPUT(<< "The following properties could not be serialized:");
354  const mitk::PropertyList::PropertyMap *propmap = failedProperties->GetMap();
355  for (auto iter = propmap->begin(); iter != propmap->end(); ++iter)
356  {
357  MITK_TEST_OUTPUT(<< " - " << iter->second->GetNameOfClass() << " associated to key '" << iter->first << "'");
358  // \TODO: should we fail the test case if failed properties exist?
359  }
360  }
361 
362  // check if data storage content has been restored correctly
363  SceneIOTestClass::VerifyStorage(storage);
364  }
365  // if no sub-test failed remove the scene file, otherwise it is kept for debugging purposes
366  if (mitk::TestManager::GetInstance()->NumberOfFailedTests() == 0)
367  {
368  Poco::File pocoSceneFile(sceneFileName);
369  MITK_TEST_CONDITION_REQUIRED(pocoSceneFile.exists(), "Checking if scene file still exists before cleaning up.")
370  pocoSceneFile.remove();
371  }
372  MITK_TEST_END();
373 }
Data management class that handles &#39;was created by&#39; relations.
BoundingBoxType::BoundsArrayType BoundsArrayType
Base of all data objects.
Definition: mitkBaseData.h:37
Follow Up Storage - Class to facilitate loading/accessing structured follow-up data.
Definition: testcase.h:28
static Pointer New()
#define MITK_TEST_CONDITION_REQUIRED(COND, MSG)
DataCollection - Class to facilitate loading/accessing structured data.
section GeneralTestsDeprecatedOldTestingStyle Deprecated macros All tests with MITK_TEST_BEGIN()
static Pointer New()
virtual void Add(DataNode *node, const DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
static Pointer New()
#define MITK_TEST_OUTPUT(x)
Output some text.
int mitkSceneIOTest(int, char *argv[])
static Vector3D offset
static TestManager * GetInstance()
#define MITK_TEST_OUTPUT_NO_ENDL(x)
Output some text without generating a terminating newline. Include.
virtual SetOfObjects::ConstPointer GetAll() const =0
returns a set of all data objects that are stored in the data storage
class ITK_EXPORT Image
#define MITK_TEST_OUTPUT_DIR
std::map< std::string, BaseProperty::Pointer > PropertyMap
static Pointer New()
#define MITK_TEST_CONDITION(COND, MSG)
bool compare(std::pair< double, int > i, std::pair< double, int > j)
#define MITK_TEST_FAILED_MSG(MSG)
Fail and finish test with message MSG.
Image class for storing images.
Definition: mitkImage.h:72
static Pointer New()
mitk::Image::Pointer image
static Pointer New()
and MITK_TEST_END()
static Pointer New()
DataNode * GetNamedNode(const char *name) const
Convenience method to get the first node with a given name.