MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkIGTTrackingDataEvaluationView.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#include <algorithm>
13
14// Blueberry
15#include <berryISelectionService.h>
16#include <berryIWorkbenchWindow.h>
17
18// Qmitk
20
21// Qt
22#include <QMessageBox>
23#include <qfiledialog.h>
24#include <qstringlist.h>
25
26// MITK
30#include <mitkTransform.h>
32#include <mitkNodePredicateDataType.h>
33
34
35//ITK
36#include <itksys/SystemTools.hxx>
37
38//VNL
39#include <vnl/vnl_vector.h>
40
41//vtk headers
42#include <vtkPoints.h>
43#include <vtkSmartPointer.h>
44#include <vtkLandmarkTransform.h>
45
46const std::string QmitkIGTTrackingDataEvaluationView::VIEW_ID = "org.mitk.views.igttrackingdataevaluation";
47
49 : m_Controls(nullptr)
50 , m_scalingfactor(1)
51{
52 m_CSVtoXMLInputFilenameVector = std::vector<std::string>();
53 m_CSVtoXMLOutputFilenameVector = std::vector<std::string>();
54}
55
59
61{
62 // build up qt view, unless already done
63 if (!m_Controls)
64 {
65 // create GUI widgets from the Qt Designer's .ui file
66 m_Controls = new Ui::QmitkIGTTrackingDataEvaluationViewControls;
67 m_Controls->setupUi(parent);
68
69 connect(m_Controls->m_LoadInputFileList, SIGNAL(clicked()), this, SLOT(OnLoadFileList()));
70 connect(m_Controls->m_StartEvaluation, SIGNAL(clicked()), this, SLOT(OnEvaluateData()));
71 connect(m_Controls->m_AddToCurrentList, SIGNAL(clicked()), this, SLOT(OnAddToCurrentList()));
72 connect(m_Controls->m_GeneratePointSetOfMeanPositions, SIGNAL(clicked()), this, SLOT(OnGeneratePointSet()));
73 connect(m_Controls->m_GenerateRotationLines, SIGNAL(clicked()), this, SLOT(OnGenerateRotationLines()));
74 connect(m_Controls->m_GeneratePointSet, SIGNAL(clicked()), this, SLOT(OnGenerateGroundTruthPointSet()));
75 connect(m_Controls->m_Convert, SIGNAL(clicked()), this, SLOT(OnConvertCSVtoXMLFile()));
76 connect(m_Controls->m_loadCSVtoXMLInputList, SIGNAL(clicked()), this, SLOT(OnCSVtoXMLLoadInputList()));
77 connect(m_Controls->m_loadCSVtoXMLOutputList, SIGNAL(clicked()), this, SLOT(OnCSVtoXMLLoadOutputList()));
78 connect(m_Controls->m_OrientationCalculationGenerateReference, SIGNAL(clicked()), this, SLOT(OnOrientationCalculation_CalcRef()));
79 connect(m_Controls->m_OrientationCalculationWriteOrientationsToFile, SIGNAL(clicked()), this, SLOT(OnOrientationCalculation_CalcOrientandWriteToFile()));
80 connect(m_Controls->m_GeneratePointSetsOfSinglePositions, SIGNAL(clicked()), this, SLOT(OnGeneratePointSetsOfSinglePositions()));
81 connect(m_Controls->m_StartEvaluationAll, SIGNAL(clicked()), this, SLOT(OnEvaluateDataAll()));
82 connect(m_Controls->m_GridMatching, SIGNAL(clicked()), this, SLOT(OnPerfomGridMatching()));
83 connect(m_Controls->m_ComputeRotation, SIGNAL(clicked()), this, SLOT(OnComputeRotation()));
84
85 //initialize data storage combo boxes
86 m_Controls->m_ReferencePointSetComboBox->SetDataStorage(this->GetDataStorage());
87 m_Controls->m_ReferencePointSetComboBox->SetAutoSelectNewItems(true);
88 m_Controls->m_ReferencePointSetComboBox->SetPredicate(mitk::NodePredicateDataType::New("PointSet"));
89 m_Controls->m_MeasurementPointSetComboBox->SetDataStorage(this->GetDataStorage());
90 m_Controls->m_MeasurementPointSetComboBox->SetAutoSelectNewItems(true);
91 m_Controls->m_MeasurementPointSetComboBox->SetPredicate(mitk::NodePredicateDataType::New("PointSet"));
92 }
93}
94
96{
97 //Get all data from UI
98 auto EvaluationDataCollection = GetAllDataFromUIList();
99 //Compute mean Quaternions
100 auto OrientationVector = GetMeanOrientationsOfAllData(EvaluationDataCollection);
101
102 //Compute Rotations
103
104 itk::Vector<double> rotationVec;
105 //adapt for Aurora 5D tools: [0,0,1000]
106 rotationVec[0] = m_Controls->m_rotVecX->value(); //X
107 rotationVec[1] = m_Controls->m_rotVecY->value(); //Y
108 rotationVec[2] = m_Controls->m_rotVecZ->value(); //Z
109
110 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> allOrientationErrors;
111 for (std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError>::size_type i = 0; i < OrientationVector.size() - 1; ++i)
112 {
113 double AngleBetweenTwoQuaternions = mitk::StaticIGTHelperFunctions::GetAngleBetweenTwoQuaterions(OrientationVector.at(i), OrientationVector.at(i+1), rotationVec);
114 double AngularError = fabs(AngleBetweenTwoQuaternions - 11.25);
115 std::stringstream description;
116 description << "Rotation Error ROT" << (i + 1) << " / ROT" << (i + 2);
117 allOrientationErrors.push_back({ AngularError, description.str() });
118 MITK_INFO << description.str() << ": " << AngularError;
119 }
120
121 //compute statistics
122 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> orientationErrorStatistics;
123 orientationErrorStatistics = mitk::HummelProtocolEvaluation::ComputeStatistics(allOrientationErrors);
124 MITK_INFO << "## Rotation error statistics: ##";
125 for (auto stat : orientationErrorStatistics) { MITK_INFO << stat.description << ": " << stat.distanceError; }
126
127 //write results to file
128 allOrientationErrors.insert(allOrientationErrors.end(), orientationErrorStatistics.begin(), orientationErrorStatistics.end());
129 allOrientationErrors.push_back({rotationVec[0],"Rot Vector [x]"});
130 allOrientationErrors.push_back({rotationVec[1], "Rot Vector [y]"});
131 allOrientationErrors.push_back({rotationVec[2], "Rot Vector [z]"});
132 std::stringstream filenameOrientationStat;
133 filenameOrientationStat << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".orientationStatistics.csv";
134 MITK_INFO << "Writing output to file " << filenameOrientationStat.str();
135 writeToFile(filenameOrientationStat.str(), allOrientationErrors);
136}
137
139{
140 mitk::PointSet::Pointer reference = dynamic_cast<mitk::PointSet*>(m_Controls->m_ReferencePointSetComboBox->GetSelectedNode()->GetData());
141 mitk::PointSet::Pointer measurement = dynamic_cast<mitk::PointSet*>(m_Controls->m_MeasurementPointSetComboBox->GetSelectedNode()->GetData());
142 //convert point sets to vtk poly data
145 for (int i = 0; i<reference->GetSize(); i++)
146 {
147 double point[3] = { reference->GetPoint(i)[0], reference->GetPoint(i)[1], reference->GetPoint(i)[2] };
148 sourcePoints->InsertNextPoint(point);
149 double point_targets[3] = { measurement->GetPoint(i)[0], measurement->GetPoint(i)[1], measurement->GetPoint(i)[2] };
150 targetPoints->InsertNextPoint(point_targets);
151 }
152 //compute transform
154 transform->SetSourceLandmarks(sourcePoints);
155 transform->SetTargetLandmarks(targetPoints);
156 transform->SetModeToRigidBody();
157 transform->Modified();
158 transform->Update();
159 //compute FRE of transform
160 double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(reference, measurement, transform);
161 MITK_INFO << "FRE after grid matching: " + QString::number(FRE) + " mm";
162 //convert from vtk to itk data types
163 itk::Matrix<float, 3, 3> rotationFloat = itk::Matrix<float, 3, 3>();
164 itk::Vector<float, 3> translationFloat = itk::Vector<float, 3>();
165 itk::Matrix<double, 3, 3> rotationDouble = itk::Matrix<double, 3, 3>();
166 itk::Vector<double, 3> translationDouble = itk::Vector<double, 3>();
167
168 vtkSmartPointer<vtkMatrix4x4> m = transform->GetMatrix();
169 for (int k = 0; k<3; k++) for (int l = 0; l<3; l++)
170 {
171 rotationFloat[k][l] = m->GetElement(k, l);
172 rotationDouble[k][l] = m->GetElement(k, l);
173
174 }
175 for (int k = 0; k<3; k++)
176 {
177 translationFloat[k] = m->GetElement(k, 3);
178 translationDouble[k] = m->GetElement(k, 3);
179 }
180 //create affine transform 3D
181 mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New();
182 mitkTransform->SetMatrix(rotationDouble);
183 mitkTransform->SetOffset(translationDouble);
184 mitk::NavigationData::Pointer transformNavigationData = mitk::NavigationData::New(mitkTransform);
185 m_Controls->m_ReferencePointSetComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(mitkTransform);
186 m_Controls->m_ReferencePointSetComboBox->GetSelectedNode()->GetData()->GetGeometry()->Modified();
187
188 //write to file
189
190 std::stringstream filename;
191 filename << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".GridMatchingResult.csv";
192 MITK_INFO << "Writing output to file " << filename.str();
193 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> FRE_Error;
194 FRE_Error.push_back({ FRE, "FRE after grid matching [mm]" });
195 writeToFile(filename.str(), FRE_Error);
196}
197
199{
200 if (m_FilenameVector.size() != 3)
201 {
202 MessageBox("Need exactly three points as reference, aborting!");
203 return;
204 }
205
206 //start loop and iterate through all files of list
207 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
208 {
209 //create navigation data player
210 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
212 myPlayer->SetFileName(m_FilenameVector[i]);
213
214 //check if the stream is valid and skip file if not
215
216 //create evaluation filter
217 mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
218
219 //connect pipeline
220 for (unsigned int j = 0; j < myPlayer->GetNumberOfOutputs(); ++j)
221 myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j));
222
223 //update pipline until number of samples is reached
224 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); ++j)
225 myEvaluationFilter->Update();
226
227 //store mean position as reference
228 switch (i)
229 {
230 case 0:
231 m_RefPoint1 = myEvaluationFilter->GetPositionMean(0);
232 break;
233 case 1:
234 m_RefPoint2 = myEvaluationFilter->GetPositionMean(0);
235 break;
236 case 2:
237 m_RefPoint3 = myEvaluationFilter->GetPositionMean(0);
238 break;
239 }
240 }
241 MessageBox("Created Reference!");
242}
243
245{
246 //start loop and iterate through all files of list
247 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
248 {
249 //create navigation data player
250 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
252 myPlayer->SetFileName(m_FilenameVector.at(i));
253
254 //open file header
255 QString outputname = QString(m_FilenameVector.at(i).c_str()) + "_orientationFile.csv";
256 m_CurrentWriteFile.open(outputname.toStdString().c_str(), std::ios::out);
257 if (m_CurrentWriteFile.bad())
258 {
259 MessageBox("Error: Can't open output file!");
260 return;
261 }
262
263 //write header to file
264 m_CurrentWriteFile << "Nr;Calypso_Time;Valid_Reference;MeasureTool_Measurement-Tool[x];MeasureTool_Measurement-Tool[y];MeasureTool_Measurement-Tool[z];MeasureTool_Measurement-Tool[qx];MeasureTool_Measurement-Tool[qy];MeasureTool_Measurement-Tool[qz];MeasureTool_Measurement-Tool[qr]\n";
265
266 //update pipeline until number of samples is reached
267 int step = 0;
268 mitk::Point3D point1, point2, point3;
269 mitk::Quaternion current_orientation;
270
271 for (int j = 0; !myPlayer->IsAtEnd(); j++)
272 {
273 myPlayer->Update();
274 mitk::NavigationData::Pointer currentNavData = myPlayer->GetOutput(0);
275 switch (step)
276 {
277 case 0:
278 step++;
279 point1 = currentNavData->GetPosition();
280 break;
281 case 1:
282 step++;
283 point2 = currentNavData->GetPosition();
284 break;
285 case 2:
286 step = 0;
287 point3 = currentNavData->GetPosition();
288
289 //compute transform from reference to current points
290 if (point1[0] == 0 &&
291 point1[1] == 0 &&
292 point1[2] == 0 &&
293 point2[0] == 0 &&
294 point2[1] == 0 &&
295 point2[2] == 0 &&
296 point3[0] == 0 &&
297 point3[1] == 0 &&
298 point3[2] == 0
299 ) current_orientation.fill(0);
300 else
301 {
304 double sourcepoint1[3] = { point1[0], point1[1], point1[2] };
305 double sourcepoint2[3] = { point2[0], point2[1], point2[2] };
306 double sourcepoint3[3] = { point3[0], point3[1], point3[2] };
307 sourcePoints->InsertNextPoint(sourcepoint1);
308 sourcePoints->InsertNextPoint(sourcepoint2);
309 sourcePoints->InsertNextPoint(sourcepoint3);
311 double targetpoint1[3] = { m_RefPoint1[0], m_RefPoint1[1], m_RefPoint1[2] };
312 double targetpoint2[3] = { m_RefPoint2[0], m_RefPoint2[1], m_RefPoint2[2] };
313 double targetpoint3[3] = { m_RefPoint3[0], m_RefPoint3[1], m_RefPoint3[2] };
314 targetPoints->InsertNextPoint(targetpoint1);
315 targetPoints->InsertNextPoint(targetpoint2);
316 targetPoints->InsertNextPoint(targetpoint3);
317
318 transform->SetSourceLandmarks(sourcePoints);
319 transform->SetTargetLandmarks(targetPoints);
320 transform->Modified();
321 transform->Update();
322
323 mitk::Transform::Pointer newTransform = mitk::Transform::New();
324 newTransform->SetMatrix(transform->GetMatrix());
325 current_orientation = newTransform->GetOrientation();
326
327 //add pointset with the three positions
328 if ((j > 15) && (j < 18))
329 {
330 mitk::DataNode::Pointer newNode = mitk::DataNode::New();
331 mitk::PointSet::Pointer newPointSet = mitk::PointSet::New();
332 newPointSet->InsertPoint(0, point1);
333 newPointSet->InsertPoint(1, point2);
334 newPointSet->InsertPoint(2, point3);
335 QString name = QString(m_FilenameVector.at(i).c_str());
336 newNode->SetName(name.toStdString().c_str());
337 newNode->SetData(newPointSet);
338 newNode->SetFloatProperty("pointsize", 0.1);
339 this->GetDataStorage()->Add(newNode);
340 }
341 }
342
343 break;
344 }
345 m_CurrentWriteFile << i << ";";
346 m_CurrentWriteFile << currentNavData->GetTimeStamp() << ";"; //IMPORTANT: change to GetIGTTimeStamp in new version!
347 m_CurrentWriteFile << "true;";
348 m_CurrentWriteFile << currentNavData->GetPosition()[0] << ";";
349 m_CurrentWriteFile << currentNavData->GetPosition()[1] << ";";
350 m_CurrentWriteFile << currentNavData->GetPosition()[2] << ";";
351 m_CurrentWriteFile << current_orientation.x() << ";";
352 m_CurrentWriteFile << current_orientation.y() << ";";
353 m_CurrentWriteFile << current_orientation.z() << ";";
354 m_CurrentWriteFile << current_orientation.r() << ";";
355 m_CurrentWriteFile << "\n";
356 }
357 //close output file
358 m_CurrentWriteFile.close();
359 }
360 MessageBox("Finished!");
361}
362
364{
365 //read in files
366 QStringList files = QFileDialog::getOpenFileNames(nullptr, "Select one or more files to open", "/", "CSV (*.csv)");
367 if (files.isEmpty()) return;
368
369 for (int i = 0; i < files.size(); i++)
370 {
371 std::string tmp = files.at(i).toStdString().c_str();
372 m_FilenameVector.push_back(tmp);
373 }
374
375 //fill list at GUI
376 m_Controls->m_FileList->clear();
377 for (unsigned int i = 0; i < m_FilenameVector.size(); i++) { new QListWidgetItem(tr(m_FilenameVector.at(i).c_str()), m_Controls->m_FileList); }
378}
379
381{
382 m_FilenameVector = std::vector<std::string>();
383 m_FilenameVector.clear();
385}
386
388{
389 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> results5cm, results15cm, results30cm, resultsAccum;
391 if (m_Controls->m_standardVolume->isChecked())
392 {
398 }
399 else if (m_Controls->m_smallVolume->isChecked())
400 {
403 }
404 else if (m_Controls->m_mediumVolume->isChecked())
405 {
408 }
409
410
411 //write results to file
412 std::stringstream filename5cm;
413 filename5cm << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".results5cm.csv";
414 MITK_INFO << "Writing output to file " << filename5cm.str();
415 writeToFile(filename5cm.str(), results5cm);
416
417 std::stringstream filename15cm;
418 filename15cm << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".results15cm.csv";
419 MITK_INFO << "Writing output to file " << filename15cm.str();
420 writeToFile(filename15cm.str(), results15cm);
421
422 std::stringstream filename30cm;
423 filename30cm << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".results30cm.csv";
424 MITK_INFO << "Writing output to file " << filename30cm.str();
425 writeToFile(filename30cm.str(), results30cm);
426
427 std::stringstream filenameAccum;
428 filenameAccum << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".resultsAccumDist.csv";
429 MITK_INFO << "Writing output to file " << filenameAccum.str();
430 writeToFile(filenameAccum.str(), resultsAccum);
431}
432
434{
435 //open output file
436 m_CurrentWriteFile.open(std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str(), std::ios::out);
437 if (m_CurrentWriteFile.bad())
438 {
439 MessageBox("Error: Can't open output file!");
440 return;
441 }
442
443 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> jitterValues;
444
445 //write output file header
446 WriteHeader();
447
448 //start loop and iterate through all files of list
449 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
450 {
451 //create navigation data player
452 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
454 myPlayer->SetFileName(m_FilenameVector.at(i));
455
456 //create evaluation filter
457 mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
458
459 //connect pipeline
460 for (unsigned int j = 0; j < myPlayer->GetNumberOfOutputs(); ++i) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); }
461
462 if (myPlayer->GetNumberOfSnapshots() < m_Controls->m_NumberOfSamples->value())
463 {
464 MITK_WARN << "Number of snapshots (" << myPlayer->GetNumberOfSnapshots() << ") smaller than number of samples to evaluate (" << m_Controls->m_NumberOfSamples->value() << ") ! Cannot proceed!";
465 return;
466 }
467
468 //update pipline until number of samples is reached
469 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++)
470 myEvaluationFilter->Update();
471
472 //store all jitter values in separate vector for statistics
473 jitterValues.push_back({ myEvaluationFilter->GetPositionErrorRMS(0), "RMS" });
474
475 //write result to output file
476 WriteDataSet(myEvaluationFilter, m_FilenameVector.at(i));
477 }
478
479 //close output file for single data
480 m_CurrentWriteFile.close();
481
482 //compute statistics
483 std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> jitterStatistics = mitk::HummelProtocolEvaluation::ComputeStatistics(jitterValues);
484 MITK_INFO << "## Jitter (RMS) statistics: ##";
485 for (auto jitterStat : jitterStatistics) {MITK_INFO << jitterStat.description << ": " << jitterStat.distanceError;}
486
487 //write statistic results to separate file
488 std::stringstream filenameJitterStat;
489 filenameJitterStat << std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str() << ".resultsJitterStatistics.csv";
490 MITK_INFO << "Writing output to file " << filenameJitterStat.str();
491 writeToFile(filenameJitterStat.str(), jitterStatistics);
492
493 //calculate angles if option is on
494 if (m_Controls->m_settingDifferenceAngles->isChecked() || m_Controls->m_DifferencesSLERP->isChecked()) CalculateDifferenceAngles();
495
496 MessageBox("Finished!");
497}
498
500{
501 m_scalingfactor = m_Controls->m_ScalingFactor->value();
502
503 //start loop and iterate through all files of list
504 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
505 {
506 //create point set for this file
507 mitk::PointSet::Pointer thisPointSet = mitk::PointSet::New();
508
509 //create navigation data player
510 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
512 myPlayer->SetFileName(m_FilenameVector.at(i));
513
514 //update pipline until number of samlples is reached and store every single point
515 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++)
516 {
517 myPlayer->Update();
518 mitk::Point3D thisPoint = myPlayer->GetOutput()->GetPosition();
519 thisPoint[0] *= m_scalingfactor;
520 thisPoint[1] *= m_scalingfactor;
521 thisPoint[2] *= m_scalingfactor;
522 thisPointSet->InsertPoint(j, thisPoint);
523 }
524
525 //add point set to data storage
526 mitk::DataNode::Pointer newNode = mitk::DataNode::New();
527 QString name = this->m_Controls->m_prefix->text() + QString("PointSet_of_All_Positions_") + QString::number(i);
528 newNode->SetName(name.toStdString());
529 newNode->SetData(thisPointSet);
530 this->GetDataStorage()->Add(newNode);
531 }
532}
533
535{
536 m_scalingfactor = m_Controls->m_ScalingFactor->value();
537
538 mitk::PointSet::Pointer generatedPointSet = mitk::PointSet::New();
539
540 //start loop and iterate through all files of list
541 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
542 {
543 //create navigation data player
544 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
546 myPlayer->SetFileName(m_FilenameVector.at(i));
547
548 //create evaluation filter
549 mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
550
551 //connect pipeline
552 for (unsigned int j = 0; j < myPlayer->GetNumberOfOutputs(); ++j) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); }
553
554 //update pipline until number of samlples is reached
555 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); ++j) { myEvaluationFilter->Update(); }
556
557 //add mean position to point set
558 mitk::Point3D meanPos = myEvaluationFilter->GetPositionMean(0);
559 if (m_scalingfactor != 1)
560 {
561 meanPos[0] *= m_scalingfactor;
562 meanPos[1] *= m_scalingfactor;
563 meanPos[2] *= m_scalingfactor;
564 }
565 generatedPointSet->InsertPoint(i, meanPos);
566 }
567
568 //add point set to data storage
569 mitk::DataNode::Pointer newNode = mitk::DataNode::New();
570 QString name = this->m_Controls->m_prefix->text() + "PointSet_of_Mean_Positions";
571 newNode->SetName(name.toStdString());
572 newNode->SetData(generatedPointSet);
573 newNode->SetFloatProperty("pointsize", 5);
574 this->GetDataStorage()->Add(newNode);
575 m_PointSetMeanPositions = generatedPointSet;
576}
577
579{
580 m_scalingfactor = m_Controls->m_ScalingFactor->value();
581
582 //start loop and iterate through all files of list
583 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
584 {
585 //create navigation data player
586 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
588 myPlayer->SetFileName(m_FilenameVector.at(i));
589
590 //create evaluation filter
591 mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
592
593 //connect pipeline
594 for (unsigned int j = 0; j < myPlayer->GetNumberOfOutputs(); ++j) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); }
595
596 //update pipline until number of samlples is reached
597 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); ++j)
598 myEvaluationFilter->Update();
599
600 //create line from mean pos to a second point which lies along the sensor (1,0,0 in tool coordinates for aurora)
601 mitk::Point3D meanPos = myEvaluationFilter->GetPositionMean(0);
602 if (m_scalingfactor != 1)
603 {
604 meanPos[0] *= m_scalingfactor;
605 meanPos[1] *= m_scalingfactor;
606 meanPos[2] *= m_scalingfactor;
607 }
608 mitk::Point3D secondPoint;
609 mitk::Point3D thirdPoint;
610 mitk::Point3D fourthPoint;
611
612 mitk::FillVector3D(secondPoint, 2, 0, 0); //X
613 vnl_vector<mitk::ScalarType> secondPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * secondPoint.GetVnlVector() + meanPos.GetVnlVector();
614 mitk::Point3D secondPointTransformedMITK;
615 mitk::FillVector3D(secondPointTransformedMITK, secondPointTransformed[0], secondPointTransformed[1], secondPointTransformed[2]);
616
617 mitk::FillVector3D(thirdPoint, 0, 4, 0); //Y
618 vnl_vector<mitk::ScalarType> thirdPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * thirdPoint.GetVnlVector() + meanPos.GetVnlVector();
619 mitk::Point3D thirdPointTransformedMITK;
620 mitk::FillVector3D(thirdPointTransformedMITK, thirdPointTransformed[0], thirdPointTransformed[1], thirdPointTransformed[2]);
621
622 mitk::FillVector3D(fourthPoint, 0, 0, 6); //Z
623 vnl_vector<mitk::ScalarType> fourthPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * fourthPoint.GetVnlVector() + meanPos.GetVnlVector();
624 mitk::Point3D fourthPointTransformedMITK;
625 mitk::FillVector3D(fourthPointTransformedMITK, fourthPointTransformed[0], fourthPointTransformed[1], fourthPointTransformed[2]);
626
627 mitk::PointSet::Pointer rotationLine = mitk::PointSet::New();
628 rotationLine->InsertPoint(0, secondPointTransformedMITK);
629 rotationLine->InsertPoint(1, meanPos);
630 rotationLine->InsertPoint(2, thirdPointTransformedMITK);
631 rotationLine->InsertPoint(3, meanPos);
632 rotationLine->InsertPoint(4, fourthPointTransformedMITK);
633
634 mitk::DataNode::Pointer newNode = mitk::DataNode::New();
635 QString nodeName = this->m_Controls->m_prefix->text() + "RotationLineNumber" + QString::number(i);
636 newNode->SetName(nodeName.toStdString());
637 newNode->SetData(rotationLine);
638 newNode->SetBoolProperty("show contour", true);
639 newNode->SetFloatProperty("pointsize", 0.5);
640 this->GetDataStorage()->Add(newNode);
641 }
642}
643
645{
646 mitk::PointSet::Pointer generatedPointSet = mitk::PointSet::New();
647 int currentPointID = 0;
648 mitk::Point3D currentPoint;
649 mitk::FillVector3D(currentPoint, 0, 0, 0);
650 for (int i = 0; i < m_Controls->m_PointNumber2->value(); i++)
651 {
652 for (int j = 0; j < m_Controls->m_PointNumber1->value(); j++)
653 {
654 generatedPointSet->InsertPoint(currentPointID, currentPoint);
655 currentPointID++;
656 currentPoint[1] += m_Controls->m_PointDistance->value();
657 }
658 currentPoint[1] = 0;
659 currentPoint[2] += m_Controls->m_PointDistance->value();
660 }
661 mitk::DataNode::Pointer newNode = mitk::DataNode::New();
662 QString nodeName = "GroundTruthPointSet_" + QString::number(m_Controls->m_PointNumber1->value()) + "x" + QString::number(m_Controls->m_PointNumber2->value()) + "_(" + QString::number(m_Controls->m_PointDistance->value()) + "mm)";
663 newNode->SetName(nodeName.toStdString());
664 newNode->SetData(generatedPointSet);
665 newNode->SetFloatProperty("pointsize", 5);
666 this->GetDataStorage()->Add(newNode);
667}
668
670{
671 if (m_Controls->m_ConvertSingleFile->isChecked())
672 { //convert one file
673 int lines = ConvertOneFile(this->m_Controls->m_InputCSV->text().toStdString(), this->m_Controls->m_OutputXML->text().toStdString());
674
675 QString result = "Converted one file with" + QString::number(lines) + " data sets";
676 MessageBox(result.toStdString());
677 }
678 else //converte file list
679 {
681 {
682 MessageBox("Error: one list is not loaded!");
683 return;
684 }
686 {
687 MessageBox("Error: lists do not have the same number of files!");
688 return;
689 }
690 for (std::size_t i = 0; i < m_CSVtoXMLInputFilenameVector.size(); ++i)
691 {
693 }
694 QString result = "Converted " + QString::number(m_CSVtoXMLInputFilenameVector.size()) + " files from file list!";
695 MessageBox(result.toStdString());
696 }
697}
698
699int QmitkIGTTrackingDataEvaluationView::ConvertOneFile(std::string inputFilename, std::string outputFilename)
700{
701 std::vector<mitk::NavigationData::Pointer> myNavigationDatas = GetNavigationDatasFromFile(inputFilename);
702 mitk::NavigationDataRecorderDeprecated::Pointer myRecorder = mitk::NavigationDataRecorderDeprecated::New();
703 myRecorder->SetFileName(outputFilename.c_str());
704 mitk::NavigationData::Pointer input = mitk::NavigationData::New();
705 if (m_Controls->m_ConvertCSV->isChecked()) myRecorder->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv);
706 myRecorder->AddNavigationData(input);
707 myRecorder->StartRecording();
708 for (std::size_t i = 0; i < myNavigationDatas.size(); ++i)
709 {
710 input->Graft(myNavigationDatas.at(i));
711 myRecorder->Update();
712 }
713 myRecorder->StopRecording();
714 return myNavigationDatas.size();
715}
716
718{
719 //read in filename
720 QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)"));
721 if (filename.isNull()) return;
722
723 m_CSVtoXMLInputFilenameVector = this->GetFileContentLineByLine(filename.toStdString());
724
725 m_Controls->m_labelCSVtoXMLInputList->setText("READY");
726}
727
729{
730 //read in filename
731 QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)"));
732 if (filename.isNull()) return;
733
734 m_CSVtoXMLOutputFilenameVector = this->GetFileContentLineByLine(filename.toStdString());
735
736 m_Controls->m_labelCSVtoXMLOutputList->setText("READY");
737}
738
740{
741 QMessageBox msgBox;
742 msgBox.setText(s.c_str());
743 msgBox.exec();
744}
745
747{
748 m_CurrentWriteFile << "Filename;";
749 m_CurrentWriteFile << "N;";
750 m_CurrentWriteFile << "N_invalid;";
751 m_CurrentWriteFile << "Percentage_invalid;";
752
753 if (m_Controls->m_settingPosMean->isChecked())
754 {
755 m_CurrentWriteFile << "Position_Mean[x];";
756 m_CurrentWriteFile << "Position_Mean[y];";
757 m_CurrentWriteFile << "Position_Mean[z];";
758 }
759
760 if (m_Controls->m_settingPosStabw->isChecked())
761 {
762 m_CurrentWriteFile << "Position_StandDev[x];";
763 m_CurrentWriteFile << "Position_StandDev[y];";
764 m_CurrentWriteFile << "Position_StandDev[z];";
765 }
766
767 if (m_Controls->m_settingPosSampleStabw->isChecked())
768 {
769 m_CurrentWriteFile << "Position_SampleStandDev[x];";
770 m_CurrentWriteFile << "Position_SampleStandDev[y];";
771 m_CurrentWriteFile << "Position_SampleStandDev[z];";
772 }
773
774 if (m_Controls->m_settingQuaternionMean->isChecked())
775 {
776 m_CurrentWriteFile << "Quaternion_Mean[qx];";
777 m_CurrentWriteFile << "Quaternion_Mean[qy];";
778 m_CurrentWriteFile << "Quaternion_Mean[qz];";
779 m_CurrentWriteFile << "Quaternion_Mean[qr];";
780 }
781
782 if (m_Controls->m_settionQuaternionStabw->isChecked())
783 {
784 m_CurrentWriteFile << "Quaternion_StandDev[qx];";
785 m_CurrentWriteFile << "Quaternion_StandDev[qy];";
786 m_CurrentWriteFile << "Quaternion_StandDev[qz];";
787 m_CurrentWriteFile << "Quaternion_StandDev[qr];";
788 }
789
790 if (m_Controls->m_settingPosErrorMean->isChecked()) m_CurrentWriteFile << "PositionError_Mean;";
791
792 if (m_Controls->m_settingPosErrorStabw->isChecked()) m_CurrentWriteFile << "PositionError_StandDev;";
793
794 if (m_Controls->m_settingPosErrorSampleStabw->isChecked()) m_CurrentWriteFile << "PositionError_SampleStandDev;";
795
796 if (m_Controls->m_settingPosErrorRMS->isChecked()) m_CurrentWriteFile << "PositionError_RMS;";
797
798 if (m_Controls->m_settingPosErrorMedian->isChecked()) m_CurrentWriteFile << "PositionError_Median;";
799
800 if (m_Controls->m_settingPosErrorMinMax->isChecked())
801 {
802 m_CurrentWriteFile << "PositionError_Max;";
803 m_CurrentWriteFile << "PositionError_Min;";
804 }
805
806 if (m_Controls->m_settingEulerMean->isChecked())
807 {
808 m_CurrentWriteFile << "Euler_tx;";
809 m_CurrentWriteFile << "Euler_ty;";
810 m_CurrentWriteFile << "Euler_tz;";
811 }
812
813 if (m_Controls->m_settingEulerRMS->isChecked())
814 {
815 m_CurrentWriteFile << "EulerErrorRMS (rad);";
816 m_CurrentWriteFile << "EulerErrorRMS (grad);";
817 }
818
819 m_CurrentWriteFile << "\n";
820}
821
822void QmitkIGTTrackingDataEvaluationView::WriteDataSet(mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter, std::string dataSetName)
823{
824 if (myEvaluationFilter->GetNumberOfOutputs() == 0) m_CurrentWriteFile << "Error: no input \n";
825 else
826 {
827 m_CurrentWriteFile << dataSetName << ";";
828 m_CurrentWriteFile << myEvaluationFilter->GetNumberOfAnalysedNavigationData(0) << ";";
829 m_CurrentWriteFile << myEvaluationFilter->GetNumberOfInvalidSamples(0) << ";";
830 m_CurrentWriteFile << myEvaluationFilter->GetPercentageOfInvalidSamples(0) << ";";
831
832 if (m_Controls->m_settingPosMean->isChecked())
833 {
834 m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[0] << ";";
835 m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[1] << ";";
836 m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[2] << ";";
837 }
838
839 if (m_Controls->m_settingPosStabw->isChecked())
840 {
841 m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[0] << ";";
842 m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[1] << ";";
843 m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[2] << ";";
844 }
845
846 if (m_Controls->m_settingPosSampleStabw->isChecked())
847 {
848 m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[0] << ";";
849 m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[1] << ";";
850 m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[2] << ";";
851 }
852
853 if (m_Controls->m_settingQuaternionMean->isChecked())
854 {
855 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).x() << ";";
856 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).y() << ";";
857 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).z() << ";";
858 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).r() << ";";
859 }
860
861 if (m_Controls->m_settionQuaternionStabw->isChecked())
862 {
863 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).x() << ";";
864 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).y() << ";";
865 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).z() << ";";
866 m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).r() << ";";
867 }
868
869 if (m_Controls->m_settingPosErrorMean->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMean(0) << ";";
870 if (m_Controls->m_settingPosErrorStabw->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorStandardDeviation(0) << ";";
871 if (m_Controls->m_settingPosErrorSampleStabw->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorSampleStandardDeviation(0) << ";";
872 if (m_Controls->m_settingPosErrorRMS->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorRMS(0) << ";";
873 if (m_Controls->m_settingPosErrorMedian->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMedian(0) << ";";
874 if (m_Controls->m_settingPosErrorMinMax->isChecked())
875 {
876 m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMax(0) << ";";
877 m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMin(0) << ";";
878 }
879
880 if (m_Controls->m_settingEulerMean->isChecked())
881 {
882 m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[0] << ";";
883 m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[1] << ";";
884 m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[2] << ";";
885 }
886
887 if (m_Controls->m_settingEulerRMS->isChecked())
888 {
889 m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesRMS(0) << ";";
890 m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesRMSDegree(0) << ";";
891 }
892
893 m_CurrentWriteFile << "\n";
894 }
895}
896
897
898std::vector<mitk::Quaternion> QmitkIGTTrackingDataEvaluationView::GetMeanOrientationsOfAllData(std::vector<mitk::NavigationDataEvaluationFilter::Pointer> allData, bool useSLERP)
899{
900 std::vector<mitk::Quaternion> returnValue;
901
902 for (auto dataSet : allData)
903 {
904 if (useSLERP) returnValue.push_back(GetSLERPAverage(dataSet));
905 else returnValue.push_back(dataSet->GetQuaternionMean(0));
906 }
907
908 return returnValue;
909}
910
911
912std::vector<mitk::NavigationDataEvaluationFilter::Pointer> QmitkIGTTrackingDataEvaluationView::GetAllDataFromUIList()
913{
914 std::vector<mitk::NavigationDataEvaluationFilter::Pointer> EvaluationDataCollection;
915
916 //start loop and iterate through all files of list: store the evaluation data
917 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
918 {
919 //create navigation data player
920 mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = ConstructNewNavigationDataPlayer();
922 myPlayer->SetFileName(m_FilenameVector.at(i));
923
924 //create evaluation filter
925 mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New();
926
927 //connect pipeline
928 for (unsigned int j = 0; j < myPlayer->GetNumberOfOutputs(); ++j)
929 myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j));
930
931 //update pipline until number of samlples is reached
932 for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); ++j)
933 myEvaluationFilter->Update();
934
935 myEvaluationFilter->SetInput(nullptr);
936 myPlayer = nullptr;
937 EvaluationDataCollection.push_back(myEvaluationFilter);
938 }
939
940 return EvaluationDataCollection;
941}
942
944{
945 //Get all data from UI
946 std::vector<mitk::NavigationDataEvaluationFilter::Pointer> EvaluationDataCollection = GetAllDataFromUIList();
947
948 //calculation and writing of output data
949 //open output file
950 m_CurrentAngleDifferencesWriteFile.open(std::string((m_Controls->m_OutputFilename->text() + ".angledifferences.csv").toUtf8()).c_str(), std::ios::out);
952 {
953 MessageBox("Error: Can't open output file for angle differences calculation!");
954 return;
955 }
956 //write header
958 //compute angle differences
959 QString pos1 = "invalid";
960 QString pos2 = "invalid";
961 //now iterate through all evaluation data and calculate the angles
962 for (std::size_t i = 0; i < m_FilenameVector.size(); ++i)
963 {
964 pos1 = QString::fromStdString(itksys::SystemTools::GetFilenameWithoutLastExtension(m_FilenameVector.at(i)));
965 for (std::size_t j = 0; j < m_FilenameVector.size(); ++j)
966 {
967 pos2 = QString::fromStdString(itksys::SystemTools::GetFilenameWithoutLastExtension(m_FilenameVector.at(j)));
968
969 mitk::Quaternion q1;
970 mitk::Quaternion q2;
971
972 if (m_Controls->m_DifferencesSLERP->isChecked())
973 {
974 //compute slerp average
975 q1 = GetSLERPAverage(EvaluationDataCollection.at(i));
976 q2 = GetSLERPAverage(EvaluationDataCollection.at(j));
977 }
978 else
979 {
980 //compute arithmetic average
981 q1 = EvaluationDataCollection.at(i)->GetQuaternionMean(0);
982 q2 = EvaluationDataCollection.at(j)->GetQuaternionMean(0);
983 }
984
985 itk::Vector<double> rotationVec;
986 //adapt for Aurora 5D tools: [0,0,1000]
987 rotationVec[0] = 10000; //X
988 rotationVec[1] = 0; //Y
989 rotationVec[2] = 0; //Z
990 double AngleBetweenTwoQuaternions = mitk::StaticIGTHelperFunctions::GetAngleBetweenTwoQuaterions(q1, q2, rotationVec);
991
992 //write data set
993 WriteDifferenceAnglesDataSet(pos1.toStdString(), pos2.toStdString(), i, j, AngleBetweenTwoQuaternions);
994 }
995 }
996
997 //close output file
999}
1000
1005
1006void QmitkIGTTrackingDataEvaluationView::WriteDifferenceAnglesDataSet(std::string pos1, std::string pos2, int idx1, int idx2, double angle)
1007{
1008 m_CurrentAngleDifferencesWriteFile << "Angle between " << pos1 << " and " << pos2 << ";" << idx1 << ";" << idx2 << ";" << angle << "\n";
1009 MITK_INFO << "Angle: " << angle;
1010}
1011
1012std::vector<mitk::NavigationData::Pointer> QmitkIGTTrackingDataEvaluationView::GetNavigationDatasFromFile(std::string filename)
1013{
1014 std::vector<mitk::NavigationData::Pointer> returnValue = std::vector<mitk::NavigationData::Pointer>();
1015 std::vector<std::string> fileContentLineByLine = GetFileContentLineByLine(filename);
1016 for (std::size_t i = 1; i < fileContentLineByLine.size(); ++i) //skip header so start at 1
1017 {
1018 returnValue.push_back(GetNavigationDataOutOfOneLine(fileContentLineByLine.at(i)));
1019 }
1020
1021 return returnValue;
1022}
1023
1024std::vector<std::string> QmitkIGTTrackingDataEvaluationView::GetFileContentLineByLine(std::string filename)
1025{
1026 std::vector<std::string> readData = std::vector<std::string>();
1027
1028 //save old locale
1029 char * oldLocale;
1030 oldLocale = setlocale(LC_ALL, nullptr);
1031
1032 //define own locale
1033 std::locale C("C");
1034 setlocale(LC_ALL, "C");
1035
1036 //read file
1037 std::ifstream file;
1038 file.open(filename.c_str(), std::ios::in);
1039 if (file.good())
1040 {
1041 //read out file
1042 file.seekg(0L, std::ios::beg); // move to begin of file
1043 while (!file.eof())
1044 {
1045 std::string buffer;
1046 std::getline(file, buffer); // read out file line by line
1047 if (buffer.size() > 0) readData.push_back(buffer);
1048 }
1049 }
1050
1051 file.close();
1052
1053 //switch back to old locale
1054 setlocale(LC_ALL, oldLocale);
1055
1056 return readData;
1057}
1058
1059mitk::NavigationData::Pointer QmitkIGTTrackingDataEvaluationView::GetNavigationDataOutOfOneLine(std::string line)
1060{
1061 mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New();
1062
1063 QString myLine = QString(line.c_str());
1064
1065 QStringList myLineList = myLine.split(';');
1066
1067 mitk::Point3D position;
1068 mitk::Quaternion orientation;
1069
1070 bool valid = false;
1071 if (myLineList.at(2).toStdString() == "1") valid = true;
1072
1073 position[0] = myLineList.at(3).toDouble();
1074 position[1] = myLineList.at(4).toDouble();
1075 position[2] = myLineList.at(5).toDouble();
1076
1077 orientation[0] = myLineList.at(6).toDouble();
1078 orientation[1] = myLineList.at(7).toDouble();
1079 orientation[2] = myLineList.at(8).toDouble();
1080 orientation[3] = myLineList.at(9).toDouble();
1081
1082 returnValue->SetDataValid(valid);
1083 returnValue->SetPosition(position);
1084 returnValue->SetOrientation(orientation);
1085
1086 return returnValue;
1087}
1088
1089mitk::Quaternion QmitkIGTTrackingDataEvaluationView::GetSLERPAverage(mitk::NavigationDataEvaluationFilter::Pointer evaluationFilter)
1090{
1091 mitk::Quaternion average;
1092
1093 //build a vector of quaternions from the evaluation filter (caution always takes the first (0) input of the filter
1094 std::vector<mitk::Quaternion> quaternions = std::vector<mitk::Quaternion>();
1095 for (int i = 0; i < evaluationFilter->GetNumberOfAnalysedNavigationData(0); i++)
1096 {
1097 mitk::Quaternion currentq = evaluationFilter->GetLoggedOrientation(i, 0);
1098
1099 quaternions.push_back(currentq);
1100 }
1101
1102 //compute the slerp average using the quaternion averaging class
1103 mitk::QuaternionAveraging::Pointer myAverager = mitk::QuaternionAveraging::New();
1104 average = myAverager->CalcAverage(quaternions);
1105
1106 return average;
1107}
1108
1109void QmitkIGTTrackingDataEvaluationView::writeToFile(std::string filename, std::vector<mitk::HummelProtocolEvaluation::HummelProtocolDistanceError> values)
1110{
1111 std::fstream currentFile;
1112 currentFile.open(filename.c_str(), std::ios::out);
1113 if (currentFile.bad()) { MITK_WARN << "Cannot open file, aborting!"; return; }
1114 currentFile << "Description" << ";" << "Error[mm]" << "\n";
1115 for (auto currentError : values)
1116 {
1117 currentFile << currentError.description << ";" << currentError.distanceError << "\n";
1118 }
1119 currentFile.close();
1120}
1121
1122mitk::NavigationDataCSVSequentialPlayer::Pointer QmitkIGTTrackingDataEvaluationView::ConstructNewNavigationDataPlayer()
1123{
1124 bool rightHanded = m_Controls->m_RigthHanded->isChecked();
1125 QString separator = m_Controls->m_SeparatorSign->text();
1126 QChar sepaSign = separator.at(0);
1127 //char separatorSign;
1128 char separatorSign = sepaSign.toLatin1();
1129 //std::string separatorSign = m_Controls->m_SeparatorSign->text().toStdString();
1130 int sampleCount = m_Controls->m_SampleCount->value();
1131 bool headerRow = m_Controls->m_HeaderRow->isChecked();
1132 int xPos = m_Controls->m_XPos->value();
1133 int yPos = m_Controls->m_YPos->value();
1134 int zPos = m_Controls->m_ZPos->value();
1135 bool useQuats = m_Controls->m_UseQuats->isChecked();
1136 int qx = m_Controls->m_Qx->value();
1137 int qy = m_Controls->m_Qy->value();
1138 int qz = m_Controls->m_Qz->value();
1139 int qr = m_Controls->m_Qr->value();
1140 int azimuth = m_Controls->m_Azimuth->value();
1141 int elevation = m_Controls->m_Elevation->value();
1142 int roll = m_Controls->m_Roll->value();
1143 bool eulersInRad = m_Controls->m_Radiants->isChecked();
1144 //need to find the biggest column number to determine the minimal number of columns the .csv file has to have
1145 int allInts[] = {xPos, yPos, zPos, qx, qy, qr, azimuth, elevation, roll};
1146 int minNumberOfColumns = (*std::max_element(allInts, allInts+9)+1); //size needs to be +1 because columns start at 0 but size at 1
1147
1148 mitk::NavigationDataCSVSequentialPlayer::Pointer navDataPlayer = mitk::NavigationDataCSVSequentialPlayer::New();
1149 navDataPlayer->SetOptions(rightHanded, separatorSign, sampleCount, headerRow, xPos, yPos, zPos, useQuats,
1150 qx, qy, qz, qr, azimuth, elevation, roll, eulersInRad, minNumberOfColumns);
1151 return navDataPlayer;
1152}
Definition diagrams_c.h:5
int ConvertOneFile(std::string inputFilename, std::string outputFilename)
void WriteDataSet(mitk::NavigationDataEvaluationFilter::Pointer evaluationFilter, std::string dataSetName)
Ui::QmitkIGTTrackingDataEvaluationViewControls * m_Controls
mitk::NavigationData::Pointer GetNavigationDataOutOfOneLine(std::string line)
void WriteDifferenceAnglesDataSet(std::string pos1, std::string pos2, int idx1, int idx2, double angle)
mitk::PointSet::Pointer m_PointSetMeanPositions
Stores the mean positions of all evaluated data.
std::vector< mitk::NavigationDataEvaluationFilter::Pointer > GetAllDataFromUIList()
mitk::Quaternion GetSLERPAverage(mitk::NavigationDataEvaluationFilter::Pointer)
calculates the slerp average of a set of quaternions which is stored in the navigation data evaluatio...
mitk::NavigationDataCSVSequentialPlayer::Pointer ConstructNewNavigationDataPlayer()
void writeToFile(std::string filename, std::vector< mitk::HummelProtocolEvaluation::HummelProtocolDistanceError > values)
std::vector< mitk::Quaternion > GetMeanOrientationsOfAllData(std::vector< mitk::NavigationDataEvaluationFilter::Pointer > allData, bool useSLERP=false)
std::vector< std::string > GetFileContentLineByLine(std::string filename)
std::vector< mitk::NavigationData::Pointer > GetNavigationDatasFromFile(std::string filename)
static bool Evaluate15cmDistances(mitk::PointSet::Pointer p, HummelProtocolMeasurementVolume m, std::vector< HummelProtocolDistanceError > &Results)
static bool Evaluate30cmDistances(mitk::PointSet::Pointer p, HummelProtocolMeasurementVolume m, std::vector< HummelProtocolDistanceError > &Results)
static bool Evaluate5cmDistances(mitk::PointSet::Pointer p, HummelProtocolMeasurementVolume m, std::vector< HummelProtocolDistanceError > &Results)
static std::vector< HummelProtocolDistanceError > ComputeStatistics(std::vector< HummelProtocolDistanceError > values)
static bool EvaluateAccumulatedDistances(mitk::PointSet::Pointer p, HummelProtocolMeasurementVolume m, std::vector< HummelProtocolDistanceError > &Results)
MITKIGTBASE_EXPORT double GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b, itk::Vector< double, 3 > rotationVector)
MITKIGTBASE_EXPORT double ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer< vtkLandmarkTransform > transform=nullptr)
Computes the fiducial registration error out of two sets of fiducials. The two sets must have the sam...