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