7 #include "PlusConfigure.h" 10 #ifdef PLUS_RENDERING_ENABLED 14 #include "vtkObjectFactory.h" 15 #include "vtkIGSIOTrackedFrameList.h" 16 #include "igsioTrackedFrame.h" 17 #include "vtkPoints.h" 18 #include "vtksys/SystemTools.hxx" 20 #include "vtkDoubleArray.h" 21 #include "vtkVariantArray.h" 23 #include "vtkOrderStatistics.h" 49 this->Superclass::PrintSelf(os, indent);
50 os << indent <<
"Update time: " <<
UpdateTime.GetMTime() << std::endl;
51 os << indent <<
"Spacing: " << this->
Spacing[0] <<
" " << this->
Spacing[1] << std::endl;
52 os << indent <<
"Calibration error: mean=" << this->
ErrorMean <<
" stdev=" << this->
ErrorStdev << std::endl;
56 os << indent <<
"TrackedFrameList:" << std::endl;
62 os << indent <<
"ReportTable:" << std::endl;
71 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::SetInputs");
81 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::GetSpacing");
94 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::GetError");
107 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::Update");
109 if (this->GetMTime() < this->
UpdateTime.GetMTime())
111 LOG_DEBUG(
"Spacing calibration result is up-to-date!");
118 LOG_ERROR(
"Failed to perform calibration - tracked frame list is invalid");
124 std::vector<vnl_vector<double> > aMatrix;
125 std::vector<double> bVector;
130 LOG_ERROR(
"Unable to construct linear equations for spacing calibration!");
134 if (aMatrix.size() == 0 || bVector.size() == 0)
136 LOG_ERROR(
"Spacing calibration failed, no data found!");
140 vnl_vector<double> scalingCalibResult(2, 0);
143 LOG_WARNING(
"Failed to run LSQRMinimize!");
147 if (scalingCalibResult.empty() || scalingCalibResult.size() < 2)
149 LOG_ERROR(
"Unable to calibrate spacing! Minimizer returned empty result.");
155 this->
Spacing[0] = sqrt(scalingCalibResult[0]);
156 this->
Spacing[1] = sqrt(scalingCalibResult[1]);
169 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::ConstructLinearEquationForCalibration");
175 LOG_ERROR(
"Failed to construct linear equation for spacing calibration - tracked frame list is NULL!");
180 if (this->
NWires.size() < 2)
182 LOG_ERROR(
"Failed to construct linear equation for spacing calibration - phantom wire definition is not correct!");
186 std::vector<double> verticalDistanceMm;
187 std::vector<double> horizontalDistanceMm;
188 for (
unsigned int i = 0;
i < this->
NWires.size() - 1; ++
i)
191 double hd = fabs(this->
NWires[
i].GetWires()[0].EndPointFront[0] - this->
NWires[
i].GetWires()[2].EndPointFront[0]);
192 horizontalDistanceMm.push_back(hd);
195 double vd = fabs(this->
NWires[
i].GetWires()[2].EndPointFront[1] - this->
NWires[
i + 1].GetWires()[2].EndPointFront[1]);
196 verticalDistanceMm.push_back(vd);
199 for (
unsigned int frame = 0; frame < this->
TrackedFrameList->GetNumberOfTrackedFrames(); ++frame)
201 igsioTrackedFrame* trackedFrame = this->
TrackedFrameList->GetTrackedFrame(frame);
202 if (trackedFrame == NULL)
204 LOG_ERROR(
"Unable to get tracked frame from the list - tracked frame is NULL (position in the list: " << frame <<
")!");
208 vtkPoints* fiduacialPointsCoordinatePx = trackedFrame->GetFiducialPointsCoordinatePx();
209 if (fiduacialPointsCoordinatePx == NULL)
211 LOG_ERROR(
"Unable to get segmented fiducial points from tracked frame - FiducialPointsCoordinatePx is NULL, frame is not yet segmented (position in the list: " << frame <<
")!");
215 if (fiduacialPointsCoordinatePx->GetNumberOfPoints() == 0)
217 LOG_DEBUG(
"Unable to get segmented fiducial points from tracked frame - couldn't segment image (position in the list: " << frame <<
")!");
221 for (
unsigned int w = 0; w < this->
NWires.size() - 1; ++w)
223 double wRightPx[3] = {0};
224 fiduacialPointsCoordinatePx->GetPoint(w * 3, wRightPx);
226 double wLeftPx[3] = {0};
227 fiduacialPointsCoordinatePx->GetPoint(w * 3 + 2, wLeftPx);
229 double wTopPx[3] = {0};
230 fiduacialPointsCoordinatePx->GetPoint((w + 1) * 3 + 2, wTopPx);
232 double wBottomPx[3] = {0};
233 fiduacialPointsCoordinatePx->GetPoint(w * 3 + 2, wBottomPx);
236 double xHorizontalDistance = fabs(wRightPx[0] - wLeftPx[0]);
237 double yHorizontalDistance = fabs(wRightPx[1] - wLeftPx[1]);
240 vnl_vector<double> scaleFactorHorizontal(2, 0);
241 scaleFactorHorizontal.put(0, pow(xHorizontalDistance, 2));
242 scaleFactorHorizontal.put(1, pow(yHorizontalDistance, 2));
243 aMatrix.push_back(scaleFactorHorizontal);
246 bVector.push_back(pow(horizontalDistanceMm[w], 2));
249 double xVerticalDistance = fabs(wBottomPx[0] - wTopPx[0]);
250 double yVerticalDistance = fabs(wBottomPx[1] - wTopPx[1]);
253 vnl_vector<double> scaleFactorVertical(2, 0);
254 scaleFactorVertical.put(0, pow(xVerticalDistance, 2));
255 scaleFactorVertical.put(1, pow(yVerticalDistance, 2));
256 aMatrix.push_back(scaleFactorVertical);
259 bVector.push_back(pow(verticalDistanceMm[w], 2));
269 const std::vector<double>& bVector,
270 const vnl_vector<double>& resultVector)
272 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::UpdateReportTable");
285 const double sX = resultVector[0];
286 const double sY = resultVector[1];
288 const int numberOfAxes(2);
290 for (
unsigned int row = 0; row < bVector.size(); row = row + numberOfAxes)
292 vtkSmartPointer<vtkVariantArray> tableRow = vtkSmartPointer<vtkVariantArray>::New();
294 tableRow->InsertNextValue(sqrt(aMatrix[row].get(0) * sX + aMatrix[row].get(1) * sY) - sqrt(bVector[row]));
295 tableRow->InsertNextValue(sqrt(bVector[row]));
296 tableRow->InsertNextValue(sqrt(aMatrix[row + 1].get(0) * sX + aMatrix[row + 1].get(1) * sY) - sqrt(bVector[row + 1]));
297 tableRow->InsertNextValue(sqrt(bVector[row + 1]));
299 if (tableRow->GetNumberOfTuples() == this->
ReportTable->GetNumberOfColumns())
305 LOG_WARNING(
"Unable to insert new row to translation axis calibration report table, number of columns are different (" 306 << tableRow->GetNumberOfTuples() <<
" vs. " << this->
ReportTable->GetNumberOfColumns() <<
").");
318 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
322 if (columnName == NULL)
324 LOG_ERROR(
"Failed to add new column to table - column name is NULL!");
328 if (this->
ReportTable->GetColumnByName(columnName) != NULL)
330 LOG_WARNING(
"Column name " << columnName <<
" already exist!");
335 vtkSmartPointer<vtkDoubleArray> col = vtkSmartPointer<vtkDoubleArray>::New();
336 col->SetName(columnName);
345 LOG_TRACE(
"vtkPlusSpacingCalibAlgo::GenerateReport");
347 if (htmlReport == NULL)
349 LOG_ERROR(
"vtkPlusSpacingCalibAlgo::GenerateReport failed: HTML report generator is invalid");
356 LOG_ERROR(
"Unable to generate report - spacing calibration failed!");
362 std::ostringstream report;
363 report <<
"Image spacing (mm/px): " << this->
Spacing[0] <<
" " << this->
Spacing[1] <<
"</br>" ;
364 report <<
"Mean error (mm): " << this->
ErrorMean <<
"</br>" ;
365 report <<
"Standard deviation (mm): " << this->
ErrorStdev <<
"</br>" ;
368 double valueRangeMin = -2.5;
369 double valueRangeMax = 2.5;
370 int numberOfBins = 41;
371 int imageSize[2] = {800, 400};
373 std::string outputImageFilename = htmlReport->
AddImageAutoFilename(
"ErrorHistogramX.png",
"X spacing calculation error histogram");
374 #ifdef PLUS_RENDERING_ENABLED 379 outputImageFilename = htmlReport->
AddImageAutoFilename(
"ErrorHistogramY.png",
"Y spacing calculation error histogram");
380 #ifdef PLUS_RENDERING_ENABLED vtkStandardNewMacro(vtkPlusSpacingCalibAlgo)
virtual void AddText(const char *text, HEADINGS h, const char *style=NULL)
virtual PlusStatus UpdateReportTable(const std::vector< vnl_vector< double > > &aMatrix, const std::vector< double > &bVector, const vnl_vector< double > &resultVector)
static PlusStatus LSQRMinimize(const std::vector< std::vector< double > > &aMatrix, const std::vector< double > &bVector, vnl_vector< double > &resultVector, double *mean=NULL, double *stdev=NULL, vnl_vector< unsigned int > *notOutliersIndices=NULL)
vtkPlusSpacingCalibAlgo()
virtual PlusStatus ConstructLinearEquationForCalibration(std::vector< vnl_vector< double > > &aMatrix, std::vector< double > &bVector)
PlusStatus AddNewColumnToReportTable(const char *columnName)
virtual void AddHorizontalLine()
virtual ~vtkPlusSpacingCalibAlgo()
virtual void SetTrackedFrameList(vtkIGSIOTrackedFrameList *)
virtual void SetReportTable(vtkTable *)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
virtual PlusStatus GenerateReport(vtkPlusHTMLGenerator *htmlReport)
virtual void SetInputs(vtkIGSIOTrackedFrameList *trackedFrameList, const std::vector< PlusNWire > &nWires)
virtual void AddParagraph(const char *paragraph)
vtkIGSIOTrackedFrameList * TrackedFrameList
static PlusStatus WriteHistogramChartToFile(const std::string &chartTitle, vtkTable &inputTable, int inputColumnIndex, double valueRangeMin, double valueRangeMax, int numberOfBins, int imageSize[2], const std::string &outputImageFilename)
virtual PlusStatus GetError(double &mean, double &stdev)
virtual std::string AddImageAutoFilename(const char *filenamePostfix, const char *description, const int widthPx=0, const int heightPx=0)
virtual PlusStatus GetSpacing(double spacing[2])
std::vector< PlusNWire > NWires
virtual PlusStatus Update()
class for generating basic html tags
virtual void SetSpacing(double, double)
Calculates ultrasound image spacing from phantom definition file.