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