Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkNavigationDataRecorderDeprecated.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 
18 #include <fstream>
19 #include <mitkIGTTimeStamp.h>
20 #include <tinyxml.h>
21 #include <itksys/SystemTools.hxx>
22 
23 //headers for exceptions
24 #include "mitkIGTException.h"
25 #include "mitkIGTIOException.h"
26 
28 {
29  //set default values
30  m_NumberOfInputs = 0;
32  m_Recording = false;
34  m_Stream = nullptr;
35  m_FileName = "";
38  m_RecordCounter = 0;
39  m_RecordCountLimit = -1;
40  m_DoNotOverwriteFiles = false;
41  m_StreamMustBeDeleted = false;
42 
43  //To get a start time
45 }
46 
48 {
49 }
50 
51 
53 {
54 
55 }
56 
58 {
59  // Process object is not const-correct so the const_cast is required here
60  this->SetNthInput(m_NumberOfInputs,
61  const_cast< mitk::NavigationData * >( nd ) );
62 
63  m_NumberOfInputs++;
64 
65  this->Modified();
66 }
67 
69 {
70  m_RecordingMode = mode;
71  this->Modified();
72 }
73 
75 {
76  if (m_Recording)
77  {
78  DataObjectPointerArray inputs = this->GetInputs(); //get all inputs
79  mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time
81 
82 
83  mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time
84  sysTimestamp = m_SystemTimeClock->GetCurrentStamp();
85 
86  // cast system time double value to stringstream to avoid low precision rounding
87  std::ostringstream strs;
88  strs.precision(15); // rounding precision for system time double value
89  strs << sysTimestamp;
90  std::string sysTimeStr = strs.str();
91 
92  //if csv-mode: write csv header and timestamp at beginning
93  if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
94  {
95  //write header only when it's the first line
96  if (m_firstLine)
97  {
98  m_firstLine = false;
99  *m_Stream << "TimeStamp";
100  for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index <<
101  ";X_Tool" << index <<
102  ";Y_Tool" << index <<
103  ";Z_Tool" << index <<
104  ";QX_Tool" << index <<
105  ";QY_Tool" << index <<
106  ";QZ_Tool" << index <<
107  ";QR_Tool" << index;}
108  *m_Stream << "\n";
109  }
110  //write timestamp (always)
111  *m_Stream << timestamp;
112  }
113 
114  //write tool data for every tool
115  for (unsigned int index = 0; index < inputs.size(); index++)
116  {
117  mitk::NavigationData* nd = dynamic_cast<mitk::NavigationData*>(inputs[index].GetPointer());
118  nd->Update(); // call update to propagate update to previous filters
119 
121  mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0);
123 
124  bool hasPosition = true;
125  bool hasOrientation = true;
126  bool dataValid = false;
127 
128  position.Fill(0.0);
129  matrix.SetIdentity();
130 
131  position = nd->GetPosition();
132  orientation = nd->GetOrientation();
133  matrix = nd->GetCovErrorMatrix();
134 
135  hasPosition = nd->GetHasPosition();
136  hasOrientation = nd->GetHasOrientation();
137  dataValid = nd->IsDataValid();
138 
139  //use this one if you want the timestamps of the source
140  //timestamp = nd->GetIGTTimeStamp();
141 
142  //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one
143  if (timestamp >= 0)
144  {
145  if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml)
146  {
147  auto elem = new TiXmlElement("NavigationData");
148 
149  elem->SetDoubleAttribute("Time", timestamp);
150  elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time
151  elem->SetDoubleAttribute("Tool", index);
152  elem->SetDoubleAttribute("X", position[0]);
153  elem->SetDoubleAttribute("Y", position[1]);
154  elem->SetDoubleAttribute("Z", position[2]);
155 
156  elem->SetDoubleAttribute("QX", orientation[0]);
157  elem->SetDoubleAttribute("QY", orientation[1]);
158  elem->SetDoubleAttribute("QZ", orientation[2]);
159  elem->SetDoubleAttribute("QR", orientation[3]);
160 
161  elem->SetDoubleAttribute("C00", matrix[0][0]);
162  elem->SetDoubleAttribute("C01", matrix[0][1]);
163  elem->SetDoubleAttribute("C02", matrix[0][2]);
164  elem->SetDoubleAttribute("C03", matrix[0][3]);
165  elem->SetDoubleAttribute("C04", matrix[0][4]);
166  elem->SetDoubleAttribute("C05", matrix[0][5]);
167  elem->SetDoubleAttribute("C10", matrix[1][0]);
168  elem->SetDoubleAttribute("C11", matrix[1][1]);
169  elem->SetDoubleAttribute("C12", matrix[1][2]);
170  elem->SetDoubleAttribute("C13", matrix[1][3]);
171  elem->SetDoubleAttribute("C14", matrix[1][4]);
172  elem->SetDoubleAttribute("C15", matrix[1][5]);
173 
174  if (dataValid)
175  elem->SetAttribute("Valid",1);
176  else
177  elem->SetAttribute("Valid",0);
178 
179  if (hasOrientation)
180  elem->SetAttribute("hO",1);
181  else
182  elem->SetAttribute("hO",0);
183 
184  if (hasPosition)
185  elem->SetAttribute("hP",1);
186  else
187  elem->SetAttribute("hP",0);
188 
189  // set additional attribute?
190  auto
191  it = m_AdditionalAttributes.find( nd );
192  if( it != m_AdditionalAttributes.end() )
193  {
194  elem->SetAttribute(it->second.first, it->second.second);
195  }
196 
197  *m_Stream << " " << *elem << std::endl;
198 
199  delete elem;
200  }
201  else if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
202  {
203  *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3];
204  }
205  }
206  }
207  if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
208  {
209  *m_Stream << "\n";
210  }
211  }
212  m_RecordCounter++;
213  if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();}
214 }
215 
217  const std::string& attributeName
218  , const std::string& attributeValue )
219 {
220  auto
221  it = m_AdditionalAttributes.find( nd );
222  if( it == m_AdditionalAttributes.end() )
223  m_AdditionalAttributes[nd] = std::pair<std::string, std::string>(attributeName, attributeValue);
224  else
225  {
226  it->second.first = attributeName;
227  it->second.second = attributeValue;
228  }
229 
230 }
231 
233 {
234  auto
235  it = m_AdditionalAttributes.find( nd );
236  if( it != m_AdditionalAttributes.end() )
237  m_AdditionalAttributes.erase(it);
238 }
239 
241 {
242 
243  if(!m_Recording)
244  {
245  if (m_Stream == nullptr)
246  {
247  std::stringstream ss;
248  std::ostream* stream;
249 
250  //An existing extension will be cut and replaced with .xml
251  std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName);
252  m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName);
253  std::string extension = ".xml";
254  if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
255  extension = ".csv";
256 
257  ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension;
258 
259  if( m_DoNotOverwriteFiles )
260  {
261  unsigned int index = m_NumberOfRecordedFiles+1;
262  while( itksys::SystemTools::FileExists( ss.str().c_str() ) )
263  {
264  ss.str("");
265  ss << tmpPath << "/" << m_FileName << "-" << index << extension;
266  index++;
267  }
268  }
269 
270  switch(m_RecordingMode)
271  {
272  case Console:
273  stream = &std::cout;
274  break;
275 
276  case NormalFile:
277  if (m_FileName == "") //Check if there is a file name and path
278  {
279  std::string message = "No file name or file path set.";
280  MITK_ERROR << message;
282  }
283  else
284  {
285  stream = new std::ofstream(ss.str().c_str());
286  }
287  break;
288 
289  case ZipFile:
290  stream = &std::cout;
291  MITK_WARN << "Sorry no ZipFile support yet";
292  break;
293 
294  default:
295  stream = &std::cout;
296  break;
297  }
298  m_Stream = stream;
299  m_StreamMustBeDeleted = true;
300  m_firstLine = true;
301  m_RecordCounter = 0;
302  StartRecording(stream);
303  }
304  }
305 else if (m_Recording)
306  {
307  MITK_WARN << "Already recording please stop before start new recording session";
308  return;
309  }
310 }
311 
313 {
314  if (m_Recording)
315  {
316  MITK_WARN << "Already recording please stop before start new recording session";
317  return;
318  }
319 
320  m_Stream = stream;
321  m_Stream->precision(10);
322 
323  //TODO store date and GMT time
324  //cheking if the stream is good
325  if (m_Stream->good())
326  {
327  if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml)
328  {
329  *m_Stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" << std::endl;
331  // should be a generic version, meaning a member variable, which has the actual version
332  *m_Stream << " " << "<Data ToolCount=\"" << (m_NumberOfInputs) << "\" version=\"1.0\">" << std::endl;
333  }
334  m_Recording = true;
335  }
336  else
337  {
338  m_Recording = false;
339  mitkThrowException(mitk::IGTException)<<"The stream is not good";
340  }
341 }
342 
343 
345 {
346  if (!m_Recording)
347  {
348  std::cout << "You have to start a recording first" << std::endl;
349  return;
350  }
351 
352  if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml))
353  {
354  *m_Stream << "</Data>" << std::endl;
355  }
356 
357  m_NumberOfRecordedFiles++;
358  m_Recording = false;
359  m_Stream->flush();
360  if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class
361  {
362  m_StreamMustBeDeleted = false;
363  delete m_Stream;
364  }
365  m_Stream = nullptr;
366 }
void SetAdditionalAttribute(const NavigationData *nd, const std::string &attributeName, const std::string &attributeValue)
void SetRecordingMode(RecordingMode mode)
Sets the recording mode which causes different types of output streams see enum RecordingMode.
unsigned int m_NumberOfInputs
counts the numbers of added input NavigationDatas
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
void StopRecording()
Stops the recording and closes the stream.
Navigation Data.
double GetElapsed()
returns the time elapsed since calling Start() for the first time in milliseconds ...
An object of this class represents an exception of the MITK-IGT module.
virtual OrientationType GetOrientation() const
returns the orientation of the NavigationData object
int m_RecordCounter
counts the number of frames which are recorded since StartRecording
virtual void GenerateData() override
filter execute method here it is not used
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
virtual void AddNavigationData(const NavigationData *nd)
Adds the input NavigationDatas.
std::string m_FileName
stores the file name and path
double TimeStampType
type that holds the time at which the data was recorded
void StartRecording()
Starts the recording with the presetted OutputMode. This method calls StartRecording(std::ostream*). Does nothing if the recorder is already recording and the method StartRecording is called again.
#define MITK_WARN
Definition: mitkLogMacros.h:23
virtual CovarianceMatrixType GetCovErrorMatrix() const
gets the 6x6 Error Covariance Matrix of the NavigationData object
mitk::RealTimeClock::Pointer m_SystemTimeClock
system time clock for system time tag in output xml file
RecordingMode
Determines where the output is directed to.
bool m_Recording
indicates whether the recording is started or not
static IGTTimeStamp * GetInstance()
returns a pointer to the current instance of mitkTimeStamp
RecordingMode m_RecordingMode
stores the mode see enum RecordingMode
void Start(itk::Object::Pointer device)
starts the time-acquisition
unsigned int m_NumberOfRecordedFiles
necessary for the naming of the file if there is more than one start-stop cycle
virtual bool GetHasOrientation() const
gets the HasOrientation flag of the NavigationData object
virtual bool IsDataValid() const
returns true if the object contains valid data
virtual PositionType GetPosition() const
returns position of the NavigationData object
#define mitkThrowException(classname)
bool m_DoNotOverwriteFiles
do not overwrite any files if true
OutputFormatEnum m_OutputFormat
stores the output format; see enum OutputFormat
virtual bool GetHasPosition() const
gets the HasPosition flag of the NavigationData object
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.
int m_RecordCountLimit
limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit...
virtual void Update()
Every call of update causes one line for each added NavigationData in the output if the recording was...