PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusPlotter.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 
7 // Local includes
8 #include "PlusPlotter.h"
9 
10 // VTK includes
11 #include <vtkAxis.h>
12 #include <vtkChartXY.h>
13 #include <vtkContextScene.h>
14 #include <vtkContextView.h>
15 #include <vtkDataArray.h>
16 #include <vtkDelimitedTextWriter.h>
17 #include <vtkDoubleArray.h>
18 #include <vtkInformation.h>
19 #include <vtkMultiBlockDataSet.h>
20 #include <vtkPNGWriter.h>
21 #include <vtkPlot.h>
22 #include <vtkPlotBar.h>
23 #include <vtkPlotLine.h>
24 #include <vtkPlotPoints.h>
25 #include <vtkRenderWindow.h>
26 #include <vtkRenderer.h>
27 #include <vtkTable.h>
28 #include <vtkWindowToImageFilter.h>
29 
30 //----------------------------------------------------------------------------
31 PlusStatus PlusPlotter::WriteScatterChartToFile(const std::string& chartTitle,
32  const std::string& yAxisText,
33  vtkTable& inputTable,
34  int xColumnIndex,
35  int yColumnIndex,
36  int imageSize[2],
37  const std::string& outputImageFilename)
38 {
39  vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
40  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
41  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
42  view->GetScene()->AddItem(chart);
43 
44  vtkPlotPoints* scatterPlot = vtkPlotPoints::SafeDownCast(chart->AddPlot(vtkChart::POINTS));
45  scatterPlot->SetInputData(&inputTable, xColumnIndex, yColumnIndex);
46  scatterPlot->SetColor(0, 0, 1);
47  scatterPlot->SetMarkerStyle(vtkPlotPoints::CROSS);
48 
49  chart->SetShowLegend(false);
50 
51  chart->GetAxis(vtkAxis::LEFT)->SetTitle(yAxisText);
52  chart->GetAxis(vtkAxis::BOTTOM)->SetTitle(chartTitle);
53 
54  return WriteChartToFile(*view, imageSize, outputImageFilename);
55 }
56 
57 //----------------------------------------------------------------------------
58 PlusStatus PlusPlotter::WriteLineChartToFile(const std::string& chartTitle,
59  const std::string& yAxisText,
60  vtkTable& inputTable,
61  int xColumnIndex,
62  int y1ColumnIndex,
63  int y2ColumnIndex,
64  int imageSize[2],
65  const std::string& outputImageFilename)
66 {
67  vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
68  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
69  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
70  view->GetScene()->AddItem(chart);
71 
72  if (y1ColumnIndex >= 0)
73  {
74  vtkPlotLine* linePlot = vtkPlotLine::SafeDownCast(chart->AddPlot(vtkChart::LINE));
75  linePlot->SetInputData(&inputTable, xColumnIndex, y1ColumnIndex);
76  //linePlot->SetColor(0,0,1);
77  }
78 
79  if (y2ColumnIndex >= 0)
80  {
81  vtkPlotLine* linePlot = vtkPlotLine::SafeDownCast(chart->AddPlot(vtkChart::LINE));
82  linePlot->SetInputData(&inputTable, xColumnIndex, y2ColumnIndex);
83  //linePlot1->SetColor(0,0,1);
84  }
85 
86  chart->SetShowLegend(true);
87 
88  chart->GetAxis(vtkAxis::LEFT)->SetTitle(yAxisText);
89  chart->GetAxis(vtkAxis::BOTTOM)->SetTitle(chartTitle);
90 
91  return WriteChartToFile(*view, imageSize, outputImageFilename);
92 }
93 
94 //----------------------------------------------------------------------------
95 PlusStatus PlusPlotter::WriteHistogramChartToFile(const std::string& chartTitle,
96  vtkTable& inputTable,
97  int inputColumnIndex,
98  double valueRangeMin,
99  double valueRangeMax,
100  int numberOfBins,
101  int imageSize[2],
102  const std::string& outputImageFilename)
103 {
104  vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
105  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
106  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
107  view->GetScene()->AddItem(chart);
108 
109  vtkSmartPointer<vtkTable> histogramTable = vtkSmartPointer<vtkTable>::New();
110  if (ComputeHistogram(inputTable, inputColumnIndex, *histogramTable, valueRangeMin, valueRangeMax, numberOfBins) != PLUS_SUCCESS)
111  {
112  return PLUS_FAIL;
113  }
114 
115  vtkPlotBar* barPlot = vtkPlotBar::SafeDownCast(chart->AddPlot(vtkChart::BAR));
116  barPlot->SetInputData(histogramTable, 0 /* x column index */, 1 /* y column index */);
117  barPlot->SetColor(0, 0, 1);
118 
119  chart->SetShowLegend(false);
120 
121  chart->GetAxis(vtkAxis::LEFT)->SetTitle("Number of samples");
122  chart->GetAxis(vtkAxis::BOTTOM)->SetTitle(chartTitle);
123 
124  return WriteChartToFile(*view, imageSize, outputImageFilename);
125 }
126 
127 //----------------------------------------------------------------------------
129  int imageSize[2],
130  const std::string& outputImageFilename)
131 {
132  vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
133  renderWindow->AddRenderer(view.GetRenderer());
134  renderWindow->SetSize(imageSize);
135  renderWindow->OffScreenRenderingOn();
136 
137  vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
138  windowToImageFilter->SetInput(renderWindow);
139  windowToImageFilter->Update();
140 
141  vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
142  writer->SetFileName(outputImageFilename.c_str());
143  writer->SetInputData(windowToImageFilter->GetOutput());
144  writer->Write();
145 
146  return PLUS_SUCCESS;
147 }
148 
149 //----------------------------------------------------------------------------
151  int inputColumnIndex,
152  vtkTable& resultTable,
153  double valueRangeMin,
154  double valueRangeMax,
155  unsigned int numberOfBins)
156 {
157  vtkDataArray* inputArray = vtkDataArray::SafeDownCast(inputTable.GetColumn(inputColumnIndex));
158  if (inputArray == NULL)
159  {
160  LOG_ERROR("PlusMath::ComputeHistogram failed: cannot find a valid data in column " << inputColumnIndex);
161  }
162 
163  std::vector<int> histogramBins(numberOfBins, 0);
164  int numberOfValues = inputArray->GetNumberOfTuples();
165  const double binSize = (valueRangeMax - valueRangeMin) / numberOfBins;
166  for (int i = 0; i < numberOfValues; i++)
167  {
168  int histogramBinIndex = static_cast<int>(floor((inputArray->GetTuple(i)[0] - valueRangeMin) / binSize));
169  if (histogramBinIndex < 0)
170  {
171  histogramBinIndex = 0;
172  }
173 
174  unsigned int histogramBinIndexUint = static_cast<unsigned int>(histogramBinIndex);
175  if (histogramBinIndexUint >= numberOfBins)
176  {
177  histogramBinIndexUint = numberOfBins - 1;
178  }
179  ++histogramBins[histogramBinIndexUint];
180  }
181 
182  // Clear table
183  while (resultTable.GetNumberOfColumns() > 0)
184  {
185  resultTable.RemoveColumn(0);
186  }
187 
188  // Copy histogram to table
189  vtkSmartPointer<vtkDoubleArray> arrX = vtkSmartPointer<vtkDoubleArray>::New();
190  resultTable.AddColumn(arrX);
191  arrX->SetName("Histogram bin center value");
192  vtkSmartPointer<vtkDoubleArray> arrY = vtkSmartPointer<vtkDoubleArray>::New();
193  resultTable.AddColumn(arrY);
194  arrY->SetName("Number of items");
195  resultTable.SetNumberOfRows(numberOfBins);
196  for (unsigned int i = 0; i < numberOfBins; ++i)
197  {
198  resultTable.SetValue(i, 0, valueRangeMin + (i + 0.5)*binSize);
199  resultTable.SetValue(i, 1, histogramBins[i]);
200  }
201 
202  return PLUS_SUCCESS;
203 }
204 
205 //----------------------------------------------------------------------------
206 PlusStatus PlusPlotter::WriteTableToFile(vtkTable& table, const std::string& filename)
207 {
208  LOG_TRACE("PlusPlotter::WriteTableToFile");
209 
210  if (filename.empty())
211  {
212  LOG_ERROR("Failed to dump table to file - Input filename is empty!");
213  return PLUS_FAIL;
214  }
215 
216  vtkSmartPointer<vtkDelimitedTextWriter> textWriter = vtkSmartPointer<vtkDelimitedTextWriter>::New();
217  textWriter->SetFieldDelimiter("\t");
218  textWriter->SetUseStringDelimiter(false);
219  textWriter->SetFileName(filename.c_str());
220  textWriter->SetInputData(&table);
221  textWriter->Update();
222 
223  return PLUS_SUCCESS;
224 }
static PlusStatus WriteTableToFile(vtkTable &table, const std::string &filename)
static PlusStatus ComputeHistogram(vtkTable &inputTable, int inputColumnIndex, vtkTable &resultTable, double valueRangeMin, double valueRangeMax, unsigned int numberOfBins)
static PlusStatus WriteLineChartToFile(const std::string &chartTitle, const std::string &yAxisText, vtkTable &inputTable, int xColumnIndex, int y1ColumnIndex, int y2ColumnIndex, int imageSize[2], const std::string &outputImageFilename)
Definition: PlusPlotter.cxx:58
igsioStatus PlusStatus
Definition: PlusCommon.h:40
for i
static PlusStatus WriteChartToFile(vtkContextView &view, int imageSize[2], const std::string &outputImageFilename)
#define PLUS_FAIL
Definition: PlusCommon.h:43
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static PlusStatus WriteHistogramChartToFile(const std::string &chartTitle, vtkTable &inputTable, int inputColumnIndex, double valueRangeMin, double valueRangeMax, int numberOfBins, int imageSize[2], const std::string &outputImageFilename)
Definition: PlusPlotter.cxx:95
Definition: ATC3DGm.h:319
static PlusStatus WriteScatterChartToFile(const std::string &chartTitle, const std::string &yAxisText, vtkTable &inputTable, int xColumnIndex, int yColumnIndex, int imageSize[2], const std::string &outputImageFilename)
Definition: PlusPlotter.cxx:31