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