Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkNavigationDataReaderXML.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 // MITK
19 #include <mitkIGTMimeTypes.h>
20 #include <mitkLocaleSwitch.h>
21 
22 // Third Party
23 #include <itksys/SystemTools.hxx>
24 #include <fstream>
25 #include <tinyxml.h>
26 
27 
29  mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(),
30  "MITK NavigationData Reader (XML)"), m_parentElement(nullptr), m_currentNode(nullptr)
31 {
33 }
34 
36 {
37 }
38 
39 mitk::NavigationDataReaderXML::NavigationDataReaderXML(const mitk::NavigationDataReaderXML& other) : AbstractFileReader(other), m_parentElement(nullptr), m_currentNode(nullptr)
40 {
41 }
42 
44 {
45  return new NavigationDataReaderXML(*this);
46 }
47 
48 
49 std::vector<itk::SmartPointer<mitk::BaseData>> mitk::NavigationDataReaderXML::Read()
50 {
52  std::istream* in = GetInputStream();
53  if (in == nullptr)
54  {
55  dataset = Read(GetInputLocation());
56  } else {
57  dataset = Read(in);
58  }
59  std::vector<mitk::BaseData::Pointer> result;
60  mitk::BaseData::Pointer base = dataset.GetPointer();
61  result.push_back(base);
62  return result;
63 }
64 
65 
66 
68 {
69  //define own locale
70  mitk::LocaleSwitch localeSwitch("C");
71 
72  m_FileName = fileName;
73 
74  TiXmlDocument document;
75  if (!document.LoadFile(fileName))
76  {
77  mitkThrowException(mitk::IGTIOException) << "File '" << fileName << "' could not be loaded.";
78  }
79 
80  TiXmlElement* m_DataElem = document.FirstChildElement("Version");
81  if (!m_DataElem)
82  {
83  // for backwards compatibility of version tag
84  m_DataElem = document.FirstChildElement("Data");
85  if (!m_DataElem)
86  {
87  mitkThrowException(mitk::IGTIOException) << "Data element not found.";
88  }
89 
90  }
91 
92  if (m_DataElem->QueryIntAttribute("Ver", &m_FileVersion) != TIXML_SUCCESS)
93  {
94  if (m_DataElem->QueryIntAttribute("version", &m_FileVersion) != TIXML_SUCCESS)
95  {
96  mitkThrowException(mitk::IGTIOException) << "Version not specified in XML file.";
97  }
98  }
99 
100  if (m_FileVersion != 1)
101  {
102  mitkThrowException(mitk::IGTIOException) << "File format version " << m_FileVersion << " is not supported.";
103  }
104 
105  m_parentElement = document.FirstChildElement("Data");
106  if (!m_parentElement)
107  {
108  mitkThrowException(mitk::IGTIOException) << "Data element not found.";
109  }
110 
111  m_parentElement->QueryIntAttribute("ToolCount", &m_NumberOfOutputs);
112 
113  mitk::NavigationDataSet::Pointer navigationDataSet = this->ReadNavigationDataSet();
114 
115  return navigationDataSet;
116 }
117 
119 {
120  //define own locale
121  mitk::LocaleSwitch localeSwitch("C");
122 
123  // first get the file version
124  m_FileVersion = this->GetFileVersion(stream);
125 
126  // check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing
127  if (m_FileVersion < 1)
128  {
129  StreamInvalid("Playing not possible. Invalid file version!");
130  return nullptr;
131  }
132 
133  m_NumberOfOutputs = this->GetNumberOfNavigationDatas(stream);
134  if (m_NumberOfOutputs == 0) { return nullptr; }
135 
136  mitk::NavigationDataSet::Pointer dataSet = this->ReadNavigationDataSet();
137 
138  return dataSet;
139 }
140 
142 {
143  mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(m_NumberOfOutputs);
144  mitk::NavigationData::Pointer curNavigationData;
145 
146  do
147  {
148  std::vector<mitk::NavigationData::Pointer> navDatas(m_NumberOfOutputs);
149  for (int n = 0; n < m_NumberOfOutputs; ++n)
150  {
151  curNavigationData = this->ReadVersion1();
152 
153  if (curNavigationData.IsNull())
154  {
155  if (n != 0)
156  {
157  MITK_WARN("mitkNavigationDataReaderXML")
158  << "Different number of NavigationData objects for different tools. Ignoring last ones.";
159  }
160  break;
161  }
162  navDatas.at(n) = curNavigationData;
163  }
164 
165  if (curNavigationData.IsNotNull())
166  {
167  navigationDataSet->AddNavigationDatas(navDatas);
168  }
169  }
170  while (curNavigationData.IsNotNull());
171 
172  return navigationDataSet;
173 }
174 
176 {
177  if ( !m_parentElement )
178  {
179  mitkThrowException(mitk::IGTIOException) << "Reading XML is not possible. Parent element is not set.";
180  }
181 
182  TiXmlElement* elem;
183  m_currentNode = m_parentElement->IterateChildren(m_currentNode);
184 
185  bool delElem;
186 
187  if(m_currentNode)
188  {
189  elem = m_currentNode->ToElement();
190  if(elem==nullptr)
191  {
192  mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?";
193  }
194  delElem = false;
195  }
196 
197  else
198  {
199  elem = new TiXmlElement("");
200  delElem = true;
201  }
202 
203 
204  mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem);
205 
206  if(delElem) { delete elem; }
207 
208  return nd;
209 }
210 
212 {
213  if (elem == nullptr) {mitkThrow() << "Error: Element is NULL!";}
214 
216 
218  mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0);
221 
222  bool hasPosition = true;
223  bool hasOrientation = true;
224  bool dataValid = false;
225 
226  position.Fill(0.0);
227  matrix.SetIdentity();
228 
229  elem->QueryDoubleAttribute("Time",&timestamp);
230  if (timestamp == -1)
231  {
232  return nullptr; //the calling method should check the return value if it is valid/not NULL
233  }
234 
235  elem->QueryDoubleAttribute("X", &position[0]);
236  elem->QueryDoubleAttribute("Y", &position[1]);
237  elem->QueryDoubleAttribute("Z", &position[2]);
238 
239  elem->QueryDoubleAttribute("QX", &orientation[0]);
240  elem->QueryDoubleAttribute("QY", &orientation[1]);
241  elem->QueryDoubleAttribute("QZ", &orientation[2]);
242  elem->QueryDoubleAttribute("QR", &orientation[3]);
243 
244  elem->QueryDoubleAttribute("C00", &matrix[0][0]);
245  elem->QueryDoubleAttribute("C01", &matrix[0][1]);
246  elem->QueryDoubleAttribute("C02", &matrix[0][2]);
247  elem->QueryDoubleAttribute("C03", &matrix[0][3]);
248  elem->QueryDoubleAttribute("C04", &matrix[0][4]);
249  elem->QueryDoubleAttribute("C05", &matrix[0][5]);
250  elem->QueryDoubleAttribute("C10", &matrix[1][0]);
251  elem->QueryDoubleAttribute("C11", &matrix[1][1]);
252  elem->QueryDoubleAttribute("C12", &matrix[1][2]);
253  elem->QueryDoubleAttribute("C13", &matrix[1][3]);
254  elem->QueryDoubleAttribute("C14", &matrix[1][4]);
255  elem->QueryDoubleAttribute("C15", &matrix[1][5]);
256 
257  int tmpval = 0;
258  elem->QueryIntAttribute("Valid", &tmpval);
259  if (tmpval == 0)
260  dataValid = false;
261  else
262  dataValid = true;
263 
264  tmpval = 0;
265  elem->QueryIntAttribute("hO", &tmpval);
266  if (tmpval == 0)
267  hasOrientation = false;
268  else
269  hasOrientation = true;
270 
271  tmpval = 0;
272  elem->QueryIntAttribute("hP", &tmpval);
273  if (tmpval == 0)
274  hasPosition = false;
275  else
276  hasPosition = true;
277 
278  nd->SetIGTTimeStamp(timestamp);
279  nd->SetPosition(position);
280  nd->SetOrientation(orientation);
281  nd->SetCovErrorMatrix(matrix);
282  nd->SetDataValid(dataValid);
283  nd->SetHasOrientation(hasOrientation);
284  nd->SetHasPosition(hasPosition);
285 
286 
287  return nd;
288 }
289 
290 // -- deprecated | begin
291 unsigned int mitk::NavigationDataReaderXML::GetFileVersion(std::istream* stream)
292 {
293  if (stream==nullptr)
294  {
295  MITK_ERROR << "No input stream set!";
296  mitkThrowException(mitk::IGTIOException)<<"No input stream set!";
297  }
298  if (!stream->good())
299  {
300  MITK_ERROR << "Stream is not good!";
301  mitkThrowException(mitk::IGTIOException)<<"Stream is not good!";
302  }
303  int version = 1;
304 
305  auto dec = new TiXmlDeclaration();
306  *stream >> *dec;
307  if(strcmp(dec->Version(),"") == 0)
308  {
309  MITK_ERROR << "The input stream seems to have XML incompatible format";
310  mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format";
311  }
312 
313  m_parentElement = new TiXmlElement("");
314  *stream >> *m_parentElement; //2nd line this is the file version
315 
316  std::string tempValue = m_parentElement->Value();
317  if(tempValue != "Version")
318  {
319  if(tempValue == "Data"){
320  m_parentElement->QueryIntAttribute("version",&version);
321  }
322  }
323  else
324  {
325  m_parentElement->QueryIntAttribute("Ver",&version);
326  }
327 
328  if (version > 0) { return version; }
329  else { return 0; }
330 }
331 
333 {
334  if (stream == nullptr)
335  {
336  MITK_ERROR << "No input stream set!";
337  mitkThrowException(mitk::IGTException)<<"No input stream set!";
338  }
339  if (!stream->good())
340  {
341  MITK_ERROR << "Stream not good!";
342  mitkThrowException(mitk::IGTException)<<"Stream not good!";
343  }
344 
345  //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters
346  //catch this here with a select case block (see GenerateData() method)
347 
348  int numberOfTools = 0;
349 
350  std::string tempValue = m_parentElement->Value();
351  if(tempValue == "Version"){
352  *stream >> *m_parentElement;
353  }
354  m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools);
355 
356  if (numberOfTools > 0) { return numberOfTools; }
357 
358  return 0;
359 }
360 
362 {
363  m_StreamEnd = true;
364  m_ErrorMessage = message;
365  m_StreamValid = false;
366  mitkThrowException(mitk::IGTIOException) << "Invalid stream!";
367 }
368 // -- deprecated | end
virtual std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
static Pointer New()
itk::SmartPointer< Self > Pointer
unsigned int GetNumberOfNavigationDatas(std::istream *stream)
Returns the number of tracked tools out of the XML document.
itk::Matrix< mitk::ScalarType, 6, 6 > CovarianceMatrixType
type that holds the error characterization of the position and orientation measurements ...
#define MITK_ERROR
Definition: mitkLogMacros.h:24
An object of this class represents an exception of the MITK-IGT module.
mitk::NavigationData::Pointer ReadVersion1()
This method reads one line of the XML document and returns the data as a NavigationData object If the...
DataCollection - Class to facilitate loading/accessing structured data.
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
An object of this class represents an exception of the MITK-IGT module which are releated to the inpu...
double TimeStampType
type that holds the time at which the data was recorded
void StreamInvalid(std::string message)
This is a helping method which gives an error message and throws an exception with the given message...
us::ServiceRegistration< IFileReader > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define MITK_WARN
Definition: mitkLogMacros.h:23
Convenience class to temporarily change the current locale.
#define mitkThrow()
NavigationDataSet::Pointer ReadNavigationDataSet()
mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement *elem)
virtual mitk::NavigationDataReaderXML * Clone() const override
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: jsoncpp.cpp:244
#define mitkThrowException(classname)
Base class for creating mitk::BaseData objects from files or streams.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.
unsigned int GetFileVersion(std::istream *stream)
Creates a stream out of the filename given by the variable m_FileName. The stream is then set to m_St...