Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.