PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkTRUSCalibrationTest.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5 =========================================================Plus=header=end*/
6 
13 #include "PlusConfigure.h"
14 
16 #include "PlusMath.h"
19 #include "vtkMath.h"
20 #include "vtkMatrix4x4.h"
22 #include "vtkIGSIOSequenceIO.h"
24 #include "vtkIGSIOTrackedFrameList.h"
25 #include "vtkIGSIOTransformRepository.h"
26 #include "vtkXMLDataElement.h"
27 #include "vtkXMLUtilities.h"
28 #include "vtksys/CommandLineArguments.hxx"
29 #include "vtksys/SystemTools.hxx"
30 
32 const double ERROR_THRESHOLD = 0.05; // error threshold is 5%
33 
34 int CompareCalibrationResultsWithBaseline(const char* baselineFileName, const char* currentResultFileName, double translationErrorThreshold, double rotationErrorThreshold);
35 
36 int main (int argc, char* argv[])
37 {
38  int numberOfFailures(0);
39  std::string inputCalibrationSeqMetafile;
40  std::string inputValidationSeqMetafile;
41  std::string inputProbeRotationSeqMetafile;
42 
43  std::string inputConfigFileName;
44  std::string inputBaselineFileName;
45  std::string inputProbeToReferenceTransformName("ProbeToReference");
46  double inputTranslationErrorThreshold(1e-10);
47  double inputRotationErrorThreshold(1e-10);
48 
49  int verboseLevel=vtkPlusLogger::LOG_LEVEL_UNDEFINED;
50 
51  vtksys::CommandLineArguments cmdargs;
52  cmdargs.Initialize(argc, argv);
53 
54  cmdargs.AddArgument("--calibration-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputCalibrationSeqMetafile, "Sequence metafile name of input random stepper motion calibration dataset.");
55  cmdargs.AddArgument("--validation-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputValidationSeqMetafile, "Sequence metafile name of input random stepper motion validation dataset.");
56  cmdargs.AddArgument("--probe-rotation-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputProbeRotationSeqMetafile, "Sequence metafile name of input probe rotation dataset.");
57 
58  cmdargs.AddArgument("--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName, "Configuration file name");
59 
60  cmdargs.AddArgument("--baseline-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputBaselineFileName, "Name of file storing baseline calibration results");
61  cmdargs.AddArgument("--translation-error-threshold", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTranslationErrorThreshold, "Translation error threshold in mm.");
62  cmdargs.AddArgument("--rotation-error-threshold", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputRotationErrorThreshold, "Rotation error threshold in degrees.");
63  cmdargs.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
64 
65  if ( !cmdargs.Parse() )
66  {
67  std::cerr << "Problem parsing arguments" << std::endl;
68  std::cout << "Help: " << cmdargs.GetHelp() << std::endl;
69  exit(EXIT_FAILURE);
70  }
71 
72  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
73 
74  // Read configuration
75  vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
76  if (PlusXmlUtils::ReadDeviceSetConfigurationFromFile(configRootElement, inputConfigFileName.c_str())==PLUS_FAIL)
77  {
78  LOG_ERROR("Unable to read configuration from file " << inputConfigFileName.c_str());
79  return EXIT_FAILURE;
80  }
82 
83  PlusFidPatternRecognition patternRecognition;
85  patternRecognition.ReadConfiguration(configRootElement);
86 
87  LOG_INFO("Reading probe rotation data from sequence metafile...");
88  vtkSmartPointer<vtkIGSIOTrackedFrameList> probeRotationTrackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
89  if( vtkIGSIOSequenceIO::Read(inputProbeRotationSeqMetafile, probeRotationTrackedFrameList) != PLUS_SUCCESS )
90  {
91  LOG_ERROR("Failed to read sequence metafile: " << inputProbeRotationSeqMetafile);
92  return EXIT_FAILURE;
93  }
94 
95  LOG_INFO("Segmenting probe rotation data...");
96  if (patternRecognition.RecognizePattern(probeRotationTrackedFrameList, error) != PLUS_SUCCESS)
97  {
98  LOG_ERROR("Error occured during segmentation of calibration images!");
99  return EXIT_FAILURE;
100  }
101 
102  LOG_INFO("Starting spacing calibration...");
103  vtkSmartPointer<vtkPlusSpacingCalibAlgo> spacingCalibAlgo = vtkSmartPointer<vtkPlusSpacingCalibAlgo>::New();
104  spacingCalibAlgo->SetInputs(probeRotationTrackedFrameList, patternRecognition.GetFidLineFinder()->GetNWires());
105 
106  double spacing[2]={0};
107  if ( spacingCalibAlgo->GetSpacing(spacing) != PLUS_SUCCESS )
108  {
109  LOG_ERROR("Spacing calibration failed!");
110  numberOfFailures++;
111  }
112  else
113  {
114  LOG_INFO("Spacing: " << std::fixed << spacing[0] << " " << spacing[1] << " mm/px");
115  }
116 
117  LOG_INFO("Create rotation data indices vector...");
118  std::vector<int> trackedFrameIndices(probeRotationTrackedFrameList->GetNumberOfTrackedFrames(), 0);
119  for ( unsigned int i = 0; i < probeRotationTrackedFrameList->GetNumberOfTrackedFrames(); ++i )
120  {
121  trackedFrameIndices[i]=i;
122  }
123 
124  LOG_INFO("Starting center of rotation calibration...");
125  vtkSmartPointer<vtkPlusCenterOfRotationCalibAlgo> centerOfRotationCalibAlgo = vtkSmartPointer<vtkPlusCenterOfRotationCalibAlgo>::New();
126  centerOfRotationCalibAlgo->SetInputs(probeRotationTrackedFrameList, trackedFrameIndices, spacing);
127 
128  // Get center of rotation calibration output
129  double centerOfRotationPx[2] = {0};
130  if ( centerOfRotationCalibAlgo->GetCenterOfRotationPx(centerOfRotationPx) != PLUS_SUCCESS )
131  {
132  LOG_ERROR("Center of rotation calibration failed!");
133  numberOfFailures++;
134  }
135  else
136  {
137  LOG_INFO("Center of rotation (px): " << std::fixed << centerOfRotationPx[0] << " " << centerOfRotationPx[1]);
138  }
139 
140  // Read coordinate definitions
141  vtkSmartPointer<vtkIGSIOTransformRepository> transformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
142  if ( transformRepository->ReadConfiguration(configRootElement) != PLUS_SUCCESS )
143  {
144  LOG_ERROR("Failed to read CoordinateDefinitions!");
145  return EXIT_FAILURE;
146  }
147 
148  // Phantom registration
149  vtkSmartPointer<vtkPlusBrachyStepperPhantomRegistrationAlgo> phantomRegistrationAlgo = vtkSmartPointer<vtkPlusBrachyStepperPhantomRegistrationAlgo>::New();
150  if (phantomRegistrationAlgo->ReadConfiguration(configRootElement) != PLUS_SUCCESS)
151  {
152  LOG_ERROR("Unable to read phantom definition!");
153  return EXIT_FAILURE;
154  }
155  phantomRegistrationAlgo->SetInputs(probeRotationTrackedFrameList, spacing, centerOfRotationPx, transformRepository, patternRecognition.GetFidLineFinder()->GetNWires());
156 
157  vtkSmartPointer<vtkMatrix4x4> tPhantomToReferenceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
158  if ( phantomRegistrationAlgo->GetPhantomToReferenceTransformMatrix( tPhantomToReferenceMatrix ) != PLUS_SUCCESS )
159  {
160  LOG_ERROR("Failed to register phantom frame to reference frame!");
161  return EXIT_FAILURE;
162  }
163 
164  // Load and segment validation tracked frame list
165  vtkSmartPointer<vtkIGSIOTrackedFrameList> validationTrackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
166  if( vtkIGSIOSequenceIO::Read(inputValidationSeqMetafile, validationTrackedFrameList) != PLUS_SUCCESS )
167  {
168  LOG_ERROR("Failed to read tracked frames from sequence metafile from: " << inputValidationSeqMetafile );
169  return EXIT_FAILURE;
170  }
171 
172  int numberOfSuccessfullySegmentedValidationImages = 0;
173  if (patternRecognition.RecognizePattern(validationTrackedFrameList, error, &numberOfSuccessfullySegmentedValidationImages) != PLUS_SUCCESS)
174  {
175  LOG_ERROR("Error occured during segmentation of validation images!");
176  return EXIT_FAILURE;
177  }
178 
179  // Load and segment calibration tracked frame list
180  vtkSmartPointer<vtkIGSIOTrackedFrameList> calibrationTrackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
181  if( vtkIGSIOSequenceIO::Read(inputCalibrationSeqMetafile, calibrationTrackedFrameList) != PLUS_SUCCESS )
182  {
183  LOG_ERROR("Failed to read tracked frames from sequence metafile from: " << inputCalibrationSeqMetafile );
184  return EXIT_FAILURE;
185  }
186 
187  int numberOfSuccessfullySegmentedCalibrationImages = 0;
188  if (patternRecognition.RecognizePattern(calibrationTrackedFrameList, error, &numberOfSuccessfullySegmentedCalibrationImages) != PLUS_SUCCESS)
189  {
190  LOG_ERROR("Error occured during segmentation of calibration images!");
191  return EXIT_FAILURE;
192  }
193 
194  LOG_INFO("Segmentation success rate of validation images: " << numberOfSuccessfullySegmentedValidationImages << " out of " << validationTrackedFrameList->GetNumberOfTrackedFrames());
195 
196  // Initialize the probe calibration algo
197  vtkSmartPointer<vtkPlusProbeCalibrationAlgo> probeCal = vtkSmartPointer<vtkPlusProbeCalibrationAlgo>::New();
198  probeCal->ReadConfiguration(configRootElement);
199 
200  // Calibrate
201  if (probeCal->Calibrate( validationTrackedFrameList, calibrationTrackedFrameList, transformRepository, patternRecognition.GetFidLineFinder()->GetNWires()) != PLUS_SUCCESS)
202  {
203  LOG_ERROR("Calibration failed!");
204  return EXIT_FAILURE;
205  }
206 
207  // Compare results
208  std::string currentConfigFileName = vtkPlusConfig::GetInstance()->GetOutputPath(
209  vtkPlusConfig::GetInstance()->GetApplicationStartTimestamp() + ".Calibration.results.xml" );
210  if ( CompareCalibrationResultsWithBaseline( inputBaselineFileName.c_str(), currentConfigFileName.c_str(), inputTranslationErrorThreshold, inputRotationErrorThreshold ) !=0 )
211  {
212  numberOfFailures++;
213  LOG_ERROR("Comparison of calibration data to baseline failed");
214  }
215 
216  if ( numberOfFailures > 0 )
217  {
218  std::cout << "Test exited with failures!!!" << std::endl;
219  return EXIT_FAILURE;
220  }
221 
222  std::cout << "Exit success!!!" << std::endl;
223  return EXIT_SUCCESS;
224 }
225 
226 //----------------------------------------------------------------------------
227 
228 // return the number of differences
229 int CompareCalibrationResultsWithBaseline(const char* baselineFileName, const char* currentResultFileName, double translationErrorThreshold, double rotationErrorThreshold)
230 {
231  int numberOfFailures=0;
232 
233  vtkSmartPointer<vtkXMLDataElement> baselineRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(
234  vtkXMLUtilities::ReadElementFromFile(baselineFileName));
235  vtkSmartPointer<vtkXMLDataElement> currentRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(
236  vtkXMLUtilities::ReadElementFromFile(currentResultFileName));
237 
238  // check to make sure we have the right element
239  if (baselineRootElem == NULL )
240  {
241  LOG_ERROR("Reading baseline data file failed: " << baselineFileName);
242  return ++numberOfFailures;
243  }
244  if (currentRootElem == NULL )
245  {
246  LOG_ERROR("Reading newly generated data file failed: " << currentResultFileName);
247  return ++numberOfFailures;
248  }
249 
250  { //<CalibrationResults>
251  vtkXMLDataElement* calibrationResultsBaseline = baselineRootElem->FindNestedElementWithName("CalibrationResults");
252  vtkXMLDataElement* calibrationResults = currentRootElem->FindNestedElementWithName("CalibrationResults");
253 
254  if ( calibrationResultsBaseline == NULL)
255  {
256  LOG_ERROR("Reading baseline CalibrationResults tag failed: " << baselineFileName);
257  return ++numberOfFailures;
258  }
259 
260  if ( calibrationResults == NULL)
261  {
262  LOG_ERROR("Reading current CalibrationResults tag failed: " << currentResultFileName);
263  return ++numberOfFailures;
264  }
265 
266  { // <Transform>
267  vtkXMLDataElement* transformBaseline = calibrationResultsBaseline->FindNestedElementWithName("Transform");
268  vtkXMLDataElement* transform = calibrationResults->FindNestedElementWithName("Transform");
269 
270  if ( transformBaseline == NULL)
271  {
272  LOG_ERROR("Reading baseline Transform tag failed: " << baselineFileName);
273  return ++numberOfFailures;
274  }
275 
276  if ( transform == NULL)
277  {
278  LOG_ERROR("Reading current Transform tag failed: " << currentResultFileName);
279  return ++numberOfFailures;
280  }
281 
282  // ImageToProbe
283  double blTransformImageToProbe[16];
284  double cTransformImageToProbe[16];
285  const char* blFrom = transformBaseline->GetAttribute("From");
286  const char* cFrom = transform->GetAttribute("From");
287  const char* blTo = transformBaseline->GetAttribute("To");
288  const char* cTo = transform->GetAttribute("To");
289 
290  if (STRCASECMP(blFrom, "Image") != 0 || STRCASECMP(blTo, "Probe"))
291  {
292  LOG_ERROR("Baseline From and To tags are invalid!");
293  numberOfFailures++;
294  }
295  else if (STRCASECMP(cFrom, "Image") != 0 || STRCASECMP(cTo, "Probe"))
296  {
297  LOG_ERROR("Current From and To tags are invalid!");
298  numberOfFailures++;
299  }
300  else if (!transformBaseline->GetVectorAttribute("Matrix", 16, blTransformImageToProbe))
301  {
302  LOG_ERROR("Baseline Matrix tag is missing");
303  numberOfFailures++;
304  }
305  else if (!transform->GetVectorAttribute("Matrix", 16, cTransformImageToProbe))
306  {
307  LOG_ERROR("Current Matrix tag is missing");
308  numberOfFailures++;
309  }
310  else
311  {
312  vtkSmartPointer<vtkMatrix4x4> baseTransMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
313  vtkSmartPointer<vtkMatrix4x4> currentTransMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
314  for ( int i = 0; i < 4; i++)
315  {
316  for ( int j = 0; j < 4; j++)
317  {
318  baseTransMatrix->SetElement(i,j, blTransformImageToProbe[4*i + j]);
319  currentTransMatrix->SetElement(i,j, cTransformImageToProbe[4*i + j]);
320  }
321  }
322 
323  double translationError = igsioMath::GetPositionDifference(baseTransMatrix, currentTransMatrix);
324  if ( translationError > translationErrorThreshold )
325  {
326  LOG_ERROR("TransformImageToProbe translation error is higher than expected: " << translationError << " mm (threshold: " << translationErrorThreshold << " mm). " );
327  numberOfFailures++;
328  }
329 
330  double rotationError = igsioMath::GetOrientationDifference(baseTransMatrix, currentTransMatrix);
331  if ( rotationError > rotationErrorThreshold )
332  {
333  LOG_ERROR("TransformImageToProbe rotation error is higher than expected: " << rotationError << " degree (threshold: " << rotationErrorThreshold << " degree). " );
334  numberOfFailures++;
335  }
336  }
337  } // </Transforms>
338  } // </CalibrationResults>
339 
340 
341  { // <ErrorReport>
342  vtkXMLDataElement* errorReportBaseline = baselineRootElem->FindNestedElementWithName("ErrorReport");
343  vtkXMLDataElement* errorReport = currentRootElem->FindNestedElementWithName("ErrorReport");
344 
345  if ( errorReportBaseline == NULL)
346  {
347  LOG_ERROR("Reading baseline ErrorReports tag failed: " << baselineFileName);
348  return ++numberOfFailures;
349  }
350 
351  if ( errorReport == NULL)
352  {
353  LOG_ERROR("Reading current ErrorReports tag failed: " << currentResultFileName);
354  return ++numberOfFailures;
355  }
356 
357  { // <ReprojectionError3DStatistics>
358  vtkXMLDataElement* reprojectionError3DStatisticsBaseline = errorReportBaseline->FindNestedElementWithName("ReprojectionError3DStatistics");
359  vtkXMLDataElement* reprojectionError3DStatistics = errorReport->FindNestedElementWithName("ReprojectionError3DStatistics");
360 
361  if ( reprojectionError3DStatisticsBaseline == NULL || reprojectionError3DStatistics == NULL )
362  {
363  LOG_ERROR("Reading ReprojectionError3DStatistics tag failed");
364  return ++numberOfFailures;
365  }
366 
367  double blReprojectionError3DValidationMeanMm = 0.0;
368  double blReprojectionError3DValidationStdDevMm = 0.0;
369  if ( ! reprojectionError3DStatisticsBaseline->GetScalarAttribute("ValidationMeanMm", blReprojectionError3DValidationMeanMm)
370  || ! reprojectionError3DStatisticsBaseline->GetScalarAttribute("ValidationStdDevMm", blReprojectionError3DValidationStdDevMm) )
371  {
372  LOG_ERROR("Reading baseline validation ReprojectionError3DStatistics statistics failed: " << baselineFileName);
373  return ++numberOfFailures;
374  }
375 
376  double cReprojectionError3DValidationMeanMm = 0.0;
377  double cReprojectionError3DValidationStdDevMm = 0.0;
378  if ( ! reprojectionError3DStatistics->GetScalarAttribute("ValidationMeanMm", cReprojectionError3DValidationMeanMm)
379  || ! reprojectionError3DStatistics->GetScalarAttribute("ValidationStdDevMm", cReprojectionError3DValidationStdDevMm) )
380  {
381  LOG_ERROR("Reading current validation ReprojectionError3DStatistics statistics failed: " << currentResultFileName);
382  return ++numberOfFailures;
383  }
384 
385  double ratioValidationMean = 1.0 * blReprojectionError3DValidationMeanMm / cReprojectionError3DValidationMeanMm;
386  if ( ratioValidationMean > 1 + ERROR_THRESHOLD || ratioValidationMean < 1 - ERROR_THRESHOLD )
387  {
388  LOG_ERROR("ReprojectionError3DStatistics/ValidationMeanMm mismatch: current=" << cReprojectionError3DValidationMeanMm << ", baseline=" << blReprojectionError3DValidationMeanMm);
389  return ++numberOfFailures;
390  }
391  double ratioValidationStdDev = 1.0 * blReprojectionError3DValidationStdDevMm / cReprojectionError3DValidationStdDevMm;
392  if ( ratioValidationStdDev > 1 + ERROR_THRESHOLD || ratioValidationStdDev < 1 - ERROR_THRESHOLD )
393  {
394  LOG_ERROR("ReprojectionError3DStatistics/ValidationStdDevMm mismatch: current=" << cReprojectionError3DValidationStdDevMm << ", baseline=" << blReprojectionError3DValidationStdDevMm);
395  return ++numberOfFailures;
396  }
397 
398  double blReprojectionError3DCalibrationMeanMm = 0.0;
399  double blReprojectionError3DCalibrationStdDevMm = 0.0;
400  if ( ! reprojectionError3DStatisticsBaseline->GetScalarAttribute("CalibrationMeanMm", blReprojectionError3DCalibrationMeanMm)
401  || ! reprojectionError3DStatisticsBaseline->GetScalarAttribute("CalibrationStdDevMm", blReprojectionError3DCalibrationStdDevMm) )
402  {
403  LOG_ERROR("Reading baseline calibration ReprojectionError3DStatistics statistics failed: " << baselineFileName);
404  return ++numberOfFailures;
405  }
406 
407  double cReprojectionError3DCalibrationMeanMm = 0.0;
408  double cReprojectionError3DCalibrationStdDevMm = 0.0;
409  if ( ! reprojectionError3DStatistics->GetScalarAttribute("CalibrationMeanMm", cReprojectionError3DCalibrationMeanMm)
410  || ! reprojectionError3DStatistics->GetScalarAttribute("CalibrationStdDevMm", cReprojectionError3DCalibrationStdDevMm) )
411  {
412  LOG_ERROR("Reading current calibration ReprojectionError3DStatistics statistics failed: " << currentResultFileName);
413  return ++numberOfFailures;
414  }
415 
416  double ratioCalibrationMean = 1.0 * blReprojectionError3DCalibrationMeanMm / cReprojectionError3DCalibrationMeanMm;
417  if ( ratioCalibrationMean > 1 + ERROR_THRESHOLD || ratioCalibrationMean < 1 - ERROR_THRESHOLD )
418  {
419  LOG_ERROR("ReprojectionError3DStatistics/CalibrationMeanMm mismatch: current=" << cReprojectionError3DCalibrationMeanMm << ", baseline=" << blReprojectionError3DCalibrationMeanMm);
420  ++numberOfFailures;
421  }
422  double ratioCalibrationStdDev = 1.0 * blReprojectionError3DCalibrationStdDevMm / cReprojectionError3DCalibrationStdDevMm;
423  if ( ratioCalibrationStdDev > 1 + ERROR_THRESHOLD || ratioCalibrationStdDev < 1 - ERROR_THRESHOLD )
424  {
425  LOG_ERROR("ReprojectionError3DStatistics/CalibrationStdDevMm mismatch: current=" << cReprojectionError3DCalibrationStdDevMm << ", baseline=" << blReprojectionError3DCalibrationStdDevMm);
426  ++numberOfFailures;
427  }
428  } // </ReprojectionError3DStatistics>
429 
430  { // <ReprojectionError2DStatistics>
431  vtkXMLDataElement* reprojectionError2DStatisticsBaseline = errorReportBaseline->FindNestedElementWithName("ReprojectionError2DStatistics");
432  vtkXMLDataElement* reprojectionError2DStatistics = errorReport->FindNestedElementWithName("ReprojectionError2DStatistics");
433 
434  if ( reprojectionError2DStatisticsBaseline == NULL || reprojectionError2DStatistics == NULL )
435  {
436  LOG_ERROR("Reading ReprojectionError2DStatistics tag failed");
437  return ++numberOfFailures;
438  }
439 
440  // <Wire>
441  for ( int wireIndex = 0; wireIndex < reprojectionError2DStatisticsBaseline->GetNumberOfNestedElements(); ++wireIndex )
442  {
443  vtkXMLDataElement* wireBaseline = reprojectionError2DStatisticsBaseline->GetNestedElement(wireIndex);
444  vtkXMLDataElement* wire = reprojectionError2DStatistics->GetNestedElement(wireIndex);
445  if ( !wireBaseline || !wire || STRCASECMP( wireBaseline->GetName(), "Wire" ) != 0 || STRCASECMP( wire->GetName(), "Wire" ) != 0 )
446  {
447  LOG_ERROR("Invalid Wire element in ReprojectionError2DStatistics");
448  ++numberOfFailures;
449  continue;
450  }
451 
452  if ( STRCASECMP( wireBaseline->GetAttribute("Name"), wire->GetAttribute("Name") ) != 0 )
453  {
454  LOG_ERROR("Wire name mismatch: " << wireBaseline->GetAttribute("Name") << " <> " << wire->GetAttribute("Name"));
455  ++numberOfFailures;
456  }
457 
458  double blValidationMeanPx[2];
459  double blValidationStdDevPx[2];
460  if ( ! wireBaseline->GetVectorAttribute("ValidationMeanPx", 2, blValidationMeanPx)
461  || ! wireBaseline->GetVectorAttribute("ValidationStdDevPx", 2, blValidationStdDevPx) )
462  {
463  LOG_ERROR("Reading baseline validation ReprojectionError2DStatistics failed for wire " << wireIndex);
464  ++numberOfFailures;
465  continue;
466  }
467 
468  double cValidationMeanPx[2];
469  double cValidationStdDevPx[2];
470  if ( ! wire->GetVectorAttribute("ValidationMeanPx", 2, cValidationMeanPx)
471  || ! wire->GetVectorAttribute("ValidationStdDevPx", 2, cValidationStdDevPx) )
472  {
473  LOG_ERROR("Reading current validation ReprojectionError2DStatistics failed for wire " << wireIndex);
474  ++numberOfFailures;
475  continue;
476  }
477 
478  for ( int i = 0; i < 2; i++)
479  {
480  double ratioMean = 1.0 * blValidationMeanPx[i] / cValidationMeanPx[i];
481  if ( ratioMean > 1 + ERROR_THRESHOLD || ratioMean < 1 - ERROR_THRESHOLD )
482  {
483  LOG_ERROR("ValidationMeanPx mismatch for wire " << wireIndex << ": current=" << cValidationMeanPx[i] << ", baseline=" << blValidationMeanPx[i]);
484  ++numberOfFailures;
485  }
486  double ratioStdDev = 1.0 * blValidationStdDevPx[i] / cValidationStdDevPx[i];
487  if ( ratioStdDev > 1 + ERROR_THRESHOLD || ratioStdDev < 1 - ERROR_THRESHOLD )
488  {
489  LOG_ERROR("ValidationStdDevPx mismatch for wire " << wireIndex << ": current=" << cValidationStdDevPx[i] << ", baseline=" << blValidationStdDevPx[i]);
490  ++numberOfFailures;
491  }
492  }
493 
494  double blCalibrationMeanPx[2];
495  double blCalibrationStdDevPx[2];
496  if ( ! wireBaseline->GetVectorAttribute("CalibrationMeanPx", 2, blCalibrationMeanPx)
497  || ! wireBaseline->GetVectorAttribute("CalibrationStdDevPx", 2, blCalibrationStdDevPx) )
498  {
499  LOG_ERROR("Reading baseline calibration ReprojectionError2DStatistics failed for wire " << wireIndex);
500  ++numberOfFailures;
501  continue;
502  }
503 
504  double cCalibrationMeanPx[2];
505  double cCalibrationStdDevPx[2];
506  if ( ! wire->GetVectorAttribute("CalibrationMeanPx", 2, cCalibrationMeanPx)
507  || ! wire->GetVectorAttribute("CalibrationStdDevPx", 2, cCalibrationStdDevPx) )
508  {
509  LOG_ERROR("Reading current calibration ReprojectionError2DStatistics failed for wire " << wireIndex);
510  ++numberOfFailures;
511  continue;
512  }
513 
514  for ( int i = 0; i < 2; i++)
515  {
516  double ratioMean = 1.0 * blCalibrationMeanPx[i] / cCalibrationMeanPx[i];
517  if ( ratioMean > 1 + ERROR_THRESHOLD || ratioMean < 1 - ERROR_THRESHOLD )
518  {
519  LOG_ERROR("CalibrationMeanPx mismatch for wire " << wireIndex << ": current=" << cCalibrationMeanPx[i] << ", baseline=" << blCalibrationMeanPx[i]);
520  ++numberOfFailures;
521  }
522  double ratioStdDev = 1.0 * blCalibrationStdDevPx[i] / cCalibrationStdDevPx[i];
523  if ( ratioStdDev > 1 + ERROR_THRESHOLD || ratioStdDev < 1 - ERROR_THRESHOLD )
524  {
525  LOG_ERROR("CalibrationStdDevPx mismatch for wire " << wireIndex << ": current=" << cCalibrationStdDevPx[i] << ", baseline=" << blCalibrationStdDevPx[i]);
526  ++numberOfFailures;
527  }
528  }
529  } // </Wire>
530  } // </ReprojectionError2DStatistics>
531 
532  { // <ValidationData>
533  vtkXMLDataElement* validationDataBaseline = errorReportBaseline->FindNestedElementWithName("ValidationData");
534  vtkXMLDataElement* validationData = errorReport->FindNestedElementWithName("ValidationData");
535 
536  if ( validationDataBaseline == NULL || validationData == NULL )
537  {
538  LOG_ERROR("Reading ValidationData tag failed");
539  return ++numberOfFailures;
540  }
541 
542  for ( int frameIndex = 0; frameIndex < validationDataBaseline->GetNumberOfNestedElements(); ++frameIndex ) // <Frame>
543  {
544  vtkXMLDataElement* frameBaseline = validationDataBaseline->GetNestedElement(frameIndex);
545  vtkXMLDataElement* frame = validationData->GetNestedElement(frameIndex);
546  if ( !frameBaseline || !frame || STRCASECMP( frameBaseline->GetName(), "Frame" ) != 0 || STRCASECMP( frame->GetName(), "Frame" ) != 0 )
547  {
548  LOG_ERROR("Invalid Frame element #" << frameIndex);
549  ++numberOfFailures;
550  continue;
551  }
552 
553  const char* segmentationStatusBaseline = frameBaseline->GetAttribute("SegmentationStatus");
554  const char* segmentationStatus = frame->GetAttribute("SegmentationStatus");
555 
556  if ( STRCASECMP( segmentationStatusBaseline, segmentationStatus ) != 0 )
557  {
558  LOG_ERROR("SegmentationStatus mismatch in Frame #" << frameIndex << ": current=" << segmentationStatus << ", baseline=" << segmentationStatusBaseline);
559  ++numberOfFailures;
560  }
561 
562  if ( STRCASECMP( segmentationStatusBaseline, "OK" ) == 0 )
563  {
564  { // <SegmentedPoints>
565  vtkXMLDataElement* segmentedPointsBaseline = frameBaseline->FindNestedElementWithName("SegmentedPoints");
566  vtkXMLDataElement* segmentedPoints = frame->FindNestedElementWithName("SegmentedPoints");
567 
568  if ( segmentedPointsBaseline == NULL || segmentedPoints == NULL )
569  {
570  LOG_ERROR("Reading SegmentedPoints tag in Frame #" << frameIndex << "failed");
571  ++numberOfFailures;
572  continue;
573  }
574 
575  // <Point>
576  for ( int pointIndex = 0; pointIndex < segmentedPointsBaseline->GetNumberOfNestedElements(); ++pointIndex )
577  {
578  vtkXMLDataElement* pointBaseline = segmentedPointsBaseline->GetNestedElement(pointIndex);
579  vtkXMLDataElement* point = segmentedPoints->GetNestedElement(pointIndex);
580  if ( !pointBaseline || !point || STRCASECMP( pointBaseline->GetName(), "Point" ) != 0 || STRCASECMP( point->GetName(), "Point" ) != 0 )
581  {
582  LOG_ERROR("Invalid Point element in Frame #" << frameIndex);
583  ++numberOfFailures;
584  }
585 
586  if ( STRCASECMP( pointBaseline->GetAttribute("WireName"), point->GetAttribute("WireName") ) != 0 )
587  {
588  LOG_ERROR("Wire name mismatch: " << pointBaseline->GetAttribute("Name") << " <> " << point->GetAttribute("Name"));
589  ++numberOfFailures;
590  }
591 
592  double blPosition[3];
593  double cPosition[3];
594  if ( ! pointBaseline->GetVectorAttribute("Position", 3, blPosition)
595  || ! point->GetVectorAttribute("Position", 3, cPosition) )
596  {
597  LOG_ERROR("Reading Position of Point #" << pointIndex << " in Frame #" << frameIndex << "failed!");
598  ++numberOfFailures;
599  continue;
600  }
601 
602  for ( int i = 0; i < 3; i++)
603  {
604  double ratio = 1.0 * blPosition[i] / cPosition[i];
605  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
606  {
607  LOG_ERROR("Position component " << i << " mismatch: current=" << cPosition[i] << ", baseline=" << blPosition[i]);
608  ++numberOfFailures;
609  }
610  }
611  }
612  } // </SegmentedPoints>
613 
614  { // <ReprojectionError3DList>
615  vtkXMLDataElement* reprojectionError3DListBaseline = frameBaseline->FindNestedElementWithName("ReprojectionError3DList");
616  vtkXMLDataElement* reprojectionError3DList = frame->FindNestedElementWithName("ReprojectionError3DList");
617 
618  if ( reprojectionError3DListBaseline == NULL || reprojectionError3DList == NULL )
619  {
620  LOG_ERROR("Reading ReprojectionError3DList tag in Frame #" << frameIndex << " failed");
621  ++numberOfFailures;
622  continue;
623  }
624 
625  // <ReprojectionError3D>
626  for ( int reprojectionError3DIndex = 0; reprojectionError3DIndex < reprojectionError3DListBaseline->GetNumberOfNestedElements(); ++reprojectionError3DIndex )
627  {
628  vtkXMLDataElement* reprojectionError3DBaseline = reprojectionError3DListBaseline->GetNestedElement(reprojectionError3DIndex);
629  vtkXMLDataElement* reprojectionError3D = reprojectionError3DList->GetNestedElement(reprojectionError3DIndex);
630  if ( !reprojectionError3DBaseline || !reprojectionError3D || STRCASECMP( reprojectionError3DBaseline->GetName(), "ReprojectionError3D" ) != 0 || STRCASECMP( reprojectionError3D->GetName(), "ReprojectionError3D" ) != 0 )
631  {
632  LOG_ERROR("Invalid ReprojectionError3D element in Frame #" << frameIndex);
633  ++numberOfFailures;
634  continue;
635  }
636 
637  if ( STRCASECMP( reprojectionError3DBaseline->GetAttribute("WireName"), reprojectionError3D->GetAttribute("WireName") ) != 0 )
638  {
639  LOG_ERROR("Wire name mismatch: " << reprojectionError3DBaseline->GetAttribute("Name") << " <> " << reprojectionError3D->GetAttribute("Name"));
640  ++numberOfFailures;
641  }
642 
643  double blErrorMm = 0.0;
644  double cErrorMm = 0.0;
645  if ( ! reprojectionError3DBaseline->GetScalarAttribute("ErrorMm", blErrorMm)
646  || ! reprojectionError3D->GetScalarAttribute("ErrorMm", cErrorMm) )
647  {
648  LOG_ERROR("Reading ErrorMm in ReprojectionError3D #" << reprojectionError3DIndex << " in Frame #" << frameIndex << "failed!");
649  ++numberOfFailures;
650  continue;
651  }
652 
653  double ratio = 1.0 * blErrorMm / cErrorMm;
654  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
655  {
656  LOG_ERROR("ErrorMm mismatch: current=" << cErrorMm << ", baseline=" << blErrorMm);
657  ++numberOfFailures;
658  }
659  }
660  } // </ReprojectionError3DList>
661 
662  { // <ReprojectionError2DList>
663  vtkXMLDataElement* reprojectionError2DListBaseline = frameBaseline->FindNestedElementWithName("ReprojectionError2DList");
664  vtkXMLDataElement* reprojectionError2DList = frame->FindNestedElementWithName("ReprojectionError2DList");
665 
666  if ( reprojectionError2DListBaseline == NULL || reprojectionError2DList == NULL )
667  {
668  LOG_ERROR("Reading ReprojectionError2DList tag in Frame #" << frameIndex << "failed");
669  ++numberOfFailures;
670  continue;
671  }
672 
673  // <ReprojectionError2D>
674  for ( int reprojectionError2DIndex = 0; reprojectionError2DIndex < reprojectionError2DListBaseline->GetNumberOfNestedElements(); ++reprojectionError2DIndex )
675  {
676  vtkXMLDataElement* reprojectionError2DBaseline = reprojectionError2DListBaseline->GetNestedElement(reprojectionError2DIndex);
677  vtkXMLDataElement* reprojectionError2D = reprojectionError2DList->GetNestedElement(reprojectionError2DIndex);
678  if ( !reprojectionError2DBaseline || !reprojectionError2D || STRCASECMP( reprojectionError2DBaseline->GetName(), "ReprojectionError2D" ) != 0 || STRCASECMP( reprojectionError2D->GetName(), "ReprojectionError2D" ) != 0 )
679  {
680  LOG_ERROR("Invalid ReprojectionError2D element in Frame #" << frameIndex);
681  ++numberOfFailures;
682  continue;
683  }
684 
685  if ( STRCASECMP( reprojectionError2DBaseline->GetAttribute("WireName"), reprojectionError2D->GetAttribute("WireName") ) != 0 )
686  {
687  LOG_ERROR("Wire name mismatch: " << reprojectionError2DBaseline->GetAttribute("Name") << " <> " << reprojectionError2D->GetAttribute("Name"));
688  ++numberOfFailures;
689  }
690 
691  double blErrorPx[2];
692  double cErrorPx[2];
693  if ( ! reprojectionError2DBaseline->GetVectorAttribute("ErrorPx", 2, blErrorPx)
694  || ! reprojectionError2D->GetVectorAttribute("ErrorPx", 2, cErrorPx) )
695  {
696  LOG_ERROR("Reading ErrorPx of reprojectionError2D #" << reprojectionError2DIndex << " in Frame #" << frameIndex << "failed!");
697  ++numberOfFailures;
698  continue;
699  }
700 
701  for ( int i = 0; i < 2; i++)
702  {
703  double ratio = 1.0 * blErrorPx[i] / cErrorPx[i];
704  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
705  {
706  LOG_ERROR("ErrorPx component " << i << " mismatch: current=" << cErrorPx[i] << ", baseline=" << blErrorPx[i]);
707  ++numberOfFailures;
708  }
709  }
710  }
711  } // </ReprojectionError2DList>
712  } // If SegmentationStatus is OK
713  } // </Frame>
714  } // </ValidationData>
715 
716  { // <CalibrationData>
717  vtkXMLDataElement* calibrationDataBaseline = errorReportBaseline->FindNestedElementWithName("CalibrationData");
718  vtkXMLDataElement* calibrationData = errorReport->FindNestedElementWithName("CalibrationData");
719 
720  if ( calibrationDataBaseline == NULL || calibrationData == NULL )
721  {
722  LOG_ERROR("Reading CalibrationData tag failed");
723  return ++numberOfFailures;
724  }
725 
726  for ( int frameIndex = 0; frameIndex < calibrationDataBaseline->GetNumberOfNestedElements(); ++frameIndex ) // <Frame>
727  {
728  vtkXMLDataElement* frameBaseline = calibrationDataBaseline->GetNestedElement(frameIndex);
729  vtkXMLDataElement* frame = calibrationData->GetNestedElement(frameIndex);
730  if ( !frameBaseline || !frame || STRCASECMP( frameBaseline->GetName(), "Frame" ) != 0 || STRCASECMP( frame->GetName(), "Frame" ) != 0 )
731  {
732  LOG_ERROR("Invalid Frame element #" << frameIndex);
733  ++numberOfFailures;
734  continue;
735  }
736 
737  const char* segmentationStatusBaseline = frameBaseline->GetAttribute("SegmentationStatus");
738  const char* segmentationStatus = frame->GetAttribute("SegmentationStatus");
739 
740  if ( STRCASECMP( segmentationStatusBaseline, segmentationStatus ) != 0 )
741  {
742  LOG_ERROR("SegmentationStatus mismatch in Frame #" << frameIndex << ": current=" << segmentationStatus << ", baseline=" << segmentationStatusBaseline);
743  ++numberOfFailures;
744  }
745 
746  if ( STRCASECMP( segmentationStatusBaseline, "OK" ) == 0 )
747  {
748  { // <SegmentedPoints>
749  vtkXMLDataElement* segmentedPointsBaseline = frameBaseline->FindNestedElementWithName("SegmentedPoints");
750  vtkXMLDataElement* segmentedPoints = frame->FindNestedElementWithName("SegmentedPoints");
751 
752  if ( segmentedPointsBaseline == NULL || segmentedPoints == NULL )
753  {
754  LOG_ERROR("Reading SegmentedPoints tag in Frame #" << frameIndex << "failed");
755  ++numberOfFailures;
756  continue;
757  }
758 
759  // <Point>
760  for ( int pointIndex = 0; pointIndex < segmentedPointsBaseline->GetNumberOfNestedElements(); ++pointIndex )
761  {
762  vtkXMLDataElement* pointBaseline = segmentedPointsBaseline->GetNestedElement(pointIndex);
763  vtkXMLDataElement* point = segmentedPoints->GetNestedElement(pointIndex);
764  if ( !pointBaseline || !point || STRCASECMP( pointBaseline->GetName(), "Point" ) != 0 || STRCASECMP( point->GetName(), "Point" ) != 0 )
765  {
766  LOG_ERROR("Invalid Point element in Frame #" << frameIndex);
767  ++numberOfFailures;
768  continue;
769  }
770 
771  if ( STRCASECMP( pointBaseline->GetAttribute("WireName"), point->GetAttribute("WireName") ) != 0 )
772  {
773  LOG_ERROR("Wire name mismatch: " << pointBaseline->GetAttribute("Name") << " <> " << point->GetAttribute("Name"));
774  ++numberOfFailures;
775  }
776 
777  double blPosition[3];
778  double cPosition[3];
779  if ( ! pointBaseline->GetVectorAttribute("Position", 3, blPosition)
780  || ! point->GetVectorAttribute("Position", 3, cPosition) )
781  {
782  LOG_ERROR("Reading Position of Point #" << pointIndex << " in Frame #" << frameIndex << "failed!");
783  ++numberOfFailures;
784  continue;
785  }
786 
787  for ( int i = 0; i < 3; i++)
788  {
789  double ratio = 1.0 * blPosition[i] / cPosition[i];
790  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
791  {
792  LOG_ERROR("Position component " << i << " mismatch: current=" << cPosition[i] << ", baseline=" << blPosition[i]);
793  ++numberOfFailures;
794  }
795  }
796  }
797  } // </SegmentedPoints>
798 
799  { // <MiddleWires>
800  vtkXMLDataElement* middleWiresBaseline = frameBaseline->FindNestedElementWithName("MiddleWires");
801  vtkXMLDataElement* middleWires = frame->FindNestedElementWithName("MiddleWires");
802 
803  if ( middleWiresBaseline == NULL || middleWires == NULL )
804  {
805  LOG_ERROR("Reading MiddleWires tag in Frame #" << frameIndex << "failed");
806  ++numberOfFailures;
807  continue;
808  }
809 
810  // <MiddleWire>
811  for ( int middleWireIndex = 0; middleWireIndex < middleWiresBaseline->GetNumberOfNestedElements(); ++middleWireIndex )
812  {
813  vtkXMLDataElement* middleWireBaseline = middleWiresBaseline->GetNestedElement(middleWireIndex);
814  vtkXMLDataElement* middleWire = middleWires->GetNestedElement(middleWireIndex);
815  if ( !middleWireBaseline || !middleWire || STRCASECMP( middleWireBaseline->GetName(), "MiddleWire" ) != 0 || STRCASECMP( middleWire->GetName(), "MiddleWire" ) != 0 )
816  {
817  LOG_ERROR("Invalid MiddleWire element in Frame #" << frameIndex);
818  ++numberOfFailures;
819  continue;
820  }
821 
822  double blPositionInImageFrame[3];
823  double cPositionInImageFrame[3];
824  if ( ! middleWireBaseline->GetVectorAttribute("PositionInImageFrame", 3, blPositionInImageFrame)
825  || ! middleWire->GetVectorAttribute("PositionInImageFrame", 3, cPositionInImageFrame) )
826  {
827  LOG_ERROR("Reading PositionInImageFrame of MiddleWire #" << middleWireIndex << " in Frame #" << frameIndex << "failed!");
828  ++numberOfFailures;
829  continue;
830  }
831 
832  for ( int i = 0; i < 3; i++)
833  {
834  double ratio = 1.0 * blPositionInImageFrame[i] / cPositionInImageFrame[i];
835  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
836  {
837  LOG_ERROR("PositionInImageFrame component " << i << " mismatch (MiddleWire #" << middleWireIndex << " in Frame #" << frameIndex << "): current=" << cPositionInImageFrame[i] << ", baseline=" << blPositionInImageFrame[i]);
838  ++numberOfFailures;
839  }
840  }
841 
842  double blPositionInProbeFrame[3];
843  double cPositionInProbeFrame[3];
844  if ( ! middleWireBaseline->GetVectorAttribute("PositionInProbeFrame", 3, blPositionInProbeFrame)
845  || ! middleWire->GetVectorAttribute("PositionInProbeFrame", 3, cPositionInProbeFrame) )
846  {
847  LOG_ERROR("Reading PositionInProbeFrame of MiddleWire #" << middleWireIndex << " in Frame #" << frameIndex << "failed!");
848  ++numberOfFailures;
849  continue;
850  }
851 
852  for ( int i = 0; i < 3; i++)
853  {
854  double ratio = 1.0 * blPositionInProbeFrame[i] / cPositionInProbeFrame[i];
855  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
856  {
857  LOG_ERROR("PositionInProbeFrame component " << i << " mismatch (MiddleWire #" << middleWireIndex << " in Frame #" << frameIndex << "): current=" << cPositionInProbeFrame[i] << ", baseline=" << blPositionInProbeFrame[i]);
858  ++numberOfFailures;
859  }
860  }
861  }
862  } // </MiddleWires>
863 
864  { // <ReprojectionError3DList>
865  vtkXMLDataElement* reprojectionError3DListBaseline = frameBaseline->FindNestedElementWithName("ReprojectionError3DList");
866  vtkXMLDataElement* reprojectionError3DList = frame->FindNestedElementWithName("ReprojectionError3DList");
867 
868  if ( reprojectionError3DListBaseline == NULL || reprojectionError3DList == NULL )
869  {
870  LOG_ERROR("Reading ReprojectionError3DList tag in Frame #" << frameIndex << " failed");
871  ++numberOfFailures;
872  continue;
873  }
874 
875  // <ReprojectionError3D>
876  for ( int reprojectionError3DIndex = 0; reprojectionError3DIndex < reprojectionError3DListBaseline->GetNumberOfNestedElements(); ++reprojectionError3DIndex )
877  {
878  vtkXMLDataElement* reprojectionError3DBaseline = reprojectionError3DListBaseline->GetNestedElement(reprojectionError3DIndex);
879  vtkXMLDataElement* reprojectionError3D = reprojectionError3DList->GetNestedElement(reprojectionError3DIndex);
880  if ( !reprojectionError3DBaseline || !reprojectionError3D || STRCASECMP( reprojectionError3DBaseline->GetName(), "ReprojectionError3D" ) != 0 || STRCASECMP( reprojectionError3D->GetName(), "ReprojectionError3D" ) != 0 )
881  {
882  LOG_ERROR("Invalid ReprojectionError3D element in Frame #" << frameIndex);
883  ++numberOfFailures;
884  continue;
885  }
886 
887  if ( STRCASECMP( reprojectionError3DBaseline->GetAttribute("WireName"), reprojectionError3D->GetAttribute("WireName") ) != 0 )
888  {
889  LOG_ERROR("Wire name mismatch: " << reprojectionError3DBaseline->GetAttribute("Name") << " <> " << reprojectionError3D->GetAttribute("Name"));
890  ++numberOfFailures;
891  }
892 
893  double blErrorMm = 0.0;
894  double cErrorMm = 0.0;
895  if ( ! reprojectionError3DBaseline->GetScalarAttribute("ErrorMm", blErrorMm)
896  || ! reprojectionError3D->GetScalarAttribute("ErrorMm", cErrorMm) )
897  {
898  LOG_ERROR("Reading ErrorMm in ReprojectionError3D #" << reprojectionError3DIndex << " in Frame #" << frameIndex << "failed!");
899  ++numberOfFailures;
900  continue;
901  }
902 
903  double ratio = 1.0 * blErrorMm / cErrorMm;
904  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
905  {
906  LOG_ERROR("ReprojectionError3D ErrorMm mismatch (Frame #" << frameIndex <<"): current=" << cErrorMm << ", baseline=" << blErrorMm);
907  ++numberOfFailures;
908  }
909  }
910  } // </ReprojectionError3DList>
911 
912  { // <ReprojectionError2DList>
913  vtkXMLDataElement* reprojectionError2DListBaseline = frameBaseline->FindNestedElementWithName("ReprojectionError2DList");
914  vtkXMLDataElement* reprojectionError2DList = frame->FindNestedElementWithName("ReprojectionError2DList");
915 
916  if ( reprojectionError2DListBaseline == NULL || reprojectionError2DList == NULL )
917  {
918  LOG_ERROR("Reading ReprojectionError2DList tag in Frame #" << frameIndex << "failed");
919  ++numberOfFailures;
920  continue;
921  }
922 
923  // <ReprojectionError2D>
924  for ( int reprojectionError2DIndex = 0; reprojectionError2DIndex < reprojectionError2DListBaseline->GetNumberOfNestedElements(); ++reprojectionError2DIndex )
925  {
926  vtkXMLDataElement* reprojectionError2DBaseline = reprojectionError2DListBaseline->GetNestedElement(reprojectionError2DIndex);
927  vtkXMLDataElement* reprojectionError2D = reprojectionError2DList->GetNestedElement(reprojectionError2DIndex);
928  if ( !reprojectionError2DBaseline || !reprojectionError2D || STRCASECMP( reprojectionError2DBaseline->GetName(), "ReprojectionError2D" ) != 0 || STRCASECMP( reprojectionError2D->GetName(), "ReprojectionError2D" ) != 0 )
929  {
930  LOG_ERROR("Invalid ReprojectionError2D element in Frame #" << frameIndex);
931  ++numberOfFailures;
932  continue;
933  }
934 
935  if ( STRCASECMP( reprojectionError2DBaseline->GetAttribute("WireName"), reprojectionError2D->GetAttribute("WireName") ) != 0 )
936  {
937  LOG_ERROR("Wire name mismatch: " << reprojectionError2DBaseline->GetAttribute("Name") << " <> " << reprojectionError2D->GetAttribute("Name"));
938  ++numberOfFailures;
939  }
940 
941  double blErrorPx[2];
942  double cErrorPx[2];
943  if ( ! reprojectionError2DBaseline->GetVectorAttribute("ErrorPx", 2, blErrorPx)
944  || ! reprojectionError2D->GetVectorAttribute("ErrorPx", 2, cErrorPx) )
945  {
946  LOG_ERROR("Reading ErrorPx of reprojectionError2D #" << reprojectionError2DIndex << " in Frame #" << frameIndex << "failed!");
947  ++numberOfFailures;
948  continue;
949  }
950 
951  for ( int i = 0; i < 2; i++)
952  {
953  double ratio = 1.0 * blErrorPx[i] / cErrorPx[i];
954  if ( ratio > 1 + ERROR_THRESHOLD || ratio < 1 - ERROR_THRESHOLD )
955  {
956  LOG_ERROR("ReprojectionError2D ErrorPx component " << i << " mismatch (Frame #" << frameIndex << "): current=" << cErrorPx[i] << ", baseline=" << blErrorPx[i]);
957  ++numberOfFailures;
958  }
959  }
960  }
961  } // </ReprojectionError2DList>
962  } // If SegmentationStatus is OK
963  } // </Frame>
964  } // </CalibrationData>
965  } // </ErrorReport>
966 
967  return numberOfFailures;
968 }
int CompareCalibrationResultsWithBaseline(const char *baselineFileName, const char *currentResultFileName, double translationErrorThreshold, double rotationErrorThreshold)
std::string GetOutputPath(const std::string &subPath)
for i
int main(int argc, char *argv[])
#define PLUS_FAIL
Definition: PlusCommon.h:43
static vtkPlusConfig * GetInstance()
std::vector< PlusNWire > GetNWires()
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static vtkIGSIOLogger * Instance()
PlusFidLineFinder * GetFidLineFinder()
const double ERROR_THRESHOLD
PlusStatus RecognizePattern(vtkIGSIOTrackedFrameList *trackedFrameList, PatternRecognitionError &patternRecognitionError, int *numberOfSuccessfullySegmentedImages=NULL, std::vector< unsigned int > *segmentedFramesIndices=NULL)
void SetDeviceSetConfigurationData(vtkXMLDataElement *deviceSetConfigurationData)
PlusStatus ReadConfiguration(vtkXMLDataElement *rootConfigElement)
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)
Definition: PlusXmlUtils.h:23