MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkNavigationDataRecorderDeprecated.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include <fstream>
15#include <mitkIGTTimeStamp.h>
16#include <tinyxml2.h>
17#include <itksys/SystemTools.hxx>
18
19//headers for exceptions
20#include "mitkIGTException.h"
21#include "mitkIGTIOException.h"
22
42
46
47
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
59 m_NumberOfInputs++;
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 {
141 if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml)
142 {
143 tinyxml2::XMLDocument doc;
144 auto *elem = doc.NewElement("NavigationData");
145
146 elem->SetAttribute("Time", timestamp);
147 elem->SetAttribute("SystemTime", sysTimeStr.c_str()); // tag for system time
148 elem->SetAttribute("Tool", index);
149 elem->SetAttribute("X", position[0]);
150 elem->SetAttribute("Y", position[1]);
151 elem->SetAttribute("Z", position[2]);
152
153 elem->SetAttribute("QX", orientation[0]);
154 elem->SetAttribute("QY", orientation[1]);
155 elem->SetAttribute("QZ", orientation[2]);
156 elem->SetAttribute("QR", orientation[3]);
157
158 elem->SetAttribute("C00", matrix[0][0]);
159 elem->SetAttribute("C01", matrix[0][1]);
160 elem->SetAttribute("C02", matrix[0][2]);
161 elem->SetAttribute("C03", matrix[0][3]);
162 elem->SetAttribute("C04", matrix[0][4]);
163 elem->SetAttribute("C05", matrix[0][5]);
164 elem->SetAttribute("C10", matrix[1][0]);
165 elem->SetAttribute("C11", matrix[1][1]);
166 elem->SetAttribute("C12", matrix[1][2]);
167 elem->SetAttribute("C13", matrix[1][3]);
168 elem->SetAttribute("C14", matrix[1][4]);
169 elem->SetAttribute("C15", matrix[1][5]);
170
171 if (dataValid)
172 elem->SetAttribute("Valid",1);
173 else
174 elem->SetAttribute("Valid",0);
175
176 if (hasOrientation)
177 elem->SetAttribute("hO",1);
178 else
179 elem->SetAttribute("hO",0);
180
181 if (hasPosition)
182 elem->SetAttribute("hP",1);
183 else
184 elem->SetAttribute("hP",0);
185
186 // set additional attribute?
187 auto
188 it = m_AdditionalAttributes.find( nd );
189 if( it != m_AdditionalAttributes.end() )
190 {
191 elem->SetAttribute(it->second.first.c_str(), it->second.second.c_str());
192 }
193
194 tinyxml2::XMLPrinter printer;
195 doc.Print(&printer);
196
197 *m_Stream << " " << printer.CStr() << std::endl;
198 }
199 else if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
200 {
201 *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3];
202 }
203 }
204 }
205 if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv)
206 {
207 *m_Stream << "\n";
208 }
209 }
210 m_RecordCounter++;
211 if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();}
212}
213
215 const std::string& attributeName
216 , const std::string& attributeValue )
217{
218 auto
219 it = m_AdditionalAttributes.find( nd );
220 if( it == m_AdditionalAttributes.end() )
221 m_AdditionalAttributes[nd] = std::pair<std::string, std::string>(attributeName, attributeValue);
222 else
223 {
224 it->second.first = attributeName;
225 it->second.second = attributeValue;
226 }
227
228}
229
231{
232 auto
233 it = m_AdditionalAttributes.find( nd );
234 if( it != m_AdditionalAttributes.end() )
235 m_AdditionalAttributes.erase(it);
236}
237
239{
240
241 if(!m_Recording)
242 {
243 if (m_Stream == nullptr)
244 {
245 std::stringstream ss;
246 std::ostream* stream;
247
248 //An existing extension will be cut and replaced with .xml
249 std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName);
250 m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName);
251 std::string extension = ".xml";
253 extension = ".csv";
254
255 ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension;
256
257 if( m_DoNotOverwriteFiles )
258 {
259 unsigned int index = m_NumberOfRecordedFiles+1;
260 while( itksys::SystemTools::FileExists( ss.str().c_str() ) )
261 {
262 ss.str("");
263 ss << tmpPath << "/" << m_FileName << "-" << index << extension;
264 index++;
265 }
266 }
267
268 switch(m_RecordingMode)
269 {
270 case Console:
271 stream = &std::cout;
272 break;
273
274 case NormalFile:
275 if (m_FileName == "") //Check if there is a file name and path
276 {
277 std::string message = "No file name or file path set.";
278 MITK_ERROR << message;
279 mitkThrowException(mitk::IGTException) << message;
280 }
281 else
282 {
283 stream = new std::ofstream(ss.str().c_str());
284 }
285 break;
286
287 case ZipFile:
288 stream = &std::cout;
289 MITK_WARN << "Sorry no ZipFile support yet";
290 break;
291
292 default:
293 stream = &std::cout;
294 break;
295 }
296 m_Stream = stream;
297 m_StreamMustBeDeleted = true;
298 m_firstLine = true;
299 m_RecordCounter = 0;
300 StartRecording(stream);
301 }
302 }
303else if (m_Recording)
304 {
305 MITK_WARN << "Already recording please stop before start new recording session";
306 return;
307 }
308}
309
311{
312 if (m_Recording)
313 {
314 MITK_WARN << "Already recording please stop before start new recording session";
315 return;
316 }
317
318 m_Stream = stream;
319 m_Stream->precision(10);
320
321 //TODO store date and GMT time
322 //cheking if the stream is good
323 if (m_Stream->good())
324 {
326 {
327 *m_Stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" << std::endl;
329 // should be a generic version, meaning a member variable, which has the actual version
330 *m_Stream << " " << "<Data ToolCount=\"" << (m_NumberOfInputs) << "\" version=\"1.0\">" << std::endl;
331 }
332 m_Recording = true;
333 }
334 else
335 {
336 m_Recording = false;
337 mitkThrowException(mitk::IGTException)<<"The stream is not good";
338 }
339}
340
341
343{
344 if (!m_Recording)
345 {
346 std::cout << "You have to start a recording first" << std::endl;
347 return;
348 }
349
350 if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml))
351 {
352 *m_Stream << "</Data>" << std::endl;
353 }
354
355 m_NumberOfRecordedFiles++;
356 m_Recording = false;
357 m_Stream->flush();
358 if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class
359 {
360 m_StreamMustBeDeleted = false;
361 delete m_Stream;
362 }
363 m_Stream = nullptr;
364}
An object of this class represents an exception of the MITK-IGT module.
static IGTTimeStamp * GetInstance()
returns a pointer to the current instance of mitkTimeStamp
void Start(itk::Object::Pointer device)
starts the time-acquisition
double GetElapsed()
returns the time elapsed since calling Start() for the first time in milliseconds
void StopRecording()
Stops the recording and closes the stream.
void GenerateData() override
filter execute method here it is not used
bool m_Recording
indicates whether the recording is started or not
int m_RecordCounter
counts the number of frames which are recorded since StartRecording
void SetRecordingMode(RecordingMode mode)
Sets the recording mode which causes different types of output streams see enum RecordingMode.
void Update() override
Every call of update causes one line for each added NavigationData in the output if the recording was...
bool m_DoNotOverwriteFiles
do not overwrite any files if true
void SetAdditionalAttribute(const NavigationData *nd, const std::string &attributeName, const std::string &attributeValue)
void StartRecording()
Starts the recording with the presetted OutputMode. This method calls StartRecording(std::ostream*)....
unsigned int m_NumberOfInputs
counts the numbers of added input NavigationDatas
mitk::RealTimeClock::Pointer m_SystemTimeClock
system time clock for system time tag in output xml file
virtual void AddNavigationData(const NavigationData *nd)
Adds the input NavigationDatas.
std::string m_FileName
stores the file name and path
unsigned int m_NumberOfRecordedFiles
necessary for the naming of the file if there is more than one start-stop cycle
RecordingMode m_RecordingMode
stores the mode see enum RecordingMode
int m_RecordCountLimit
limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit
RecordingMode
Determines where the output is directed to.
OutputFormatEnum m_OutputFormat
stores the output format; see enum OutputFormat
itk::Matrix< mitk::ScalarType, 6, 6 > CovarianceMatrixType
type that holds the error characterization of the position and orientation measurements
mitk::Quaternion OrientationType
Type that holds the orientation part of the tracking data.
double TimeStampType
type that holds the time at which the data was recorded in milliseconds
virtual bool IsDataValid() const
returns true if the object contains valid data
mitk::Point3D PositionType
Type that holds the position part of the tracking data.
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.