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
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...