PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkSonixPortaVideoSourceTest.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 // Test basic connection to the Ultrasonix image acquisition
8 // If the --rendering-off switch is defined then the connection is established, images are
9 // transferred for a few seconds, then the connection is closed (useful for automatic testing).
10 // If the --rendering-off switch is not defined then the live ultrasound image is displayed
11 // in a window (useful for quick interactive testing of the image transfer).
12 
13 #include "PlusConfigure.h"
14 #include "vtkCallbackCommand.h"
15 #include "vtkCommand.h"
16 #include "vtkImageViewer.h"
17 #include "vtkPlusChannel.h"
18 #include "vtkPlusDataSource.h"
19 #include "vtkRenderWindowInteractor.h"
20 #include "vtkSmartPointer.h"
23 #include "vtksys/CommandLineArguments.hxx"
24 #include <stdlib.h>
25 
27 {
30 };
31 
32 /*=========================================================================*/
33 
34 #include "vtkRenderer.h"
35 #include "vtkRenderWindow.h"
36 #include "vtkChartXY.h"
37 #include "vtkPlot.h"
38 #include "vtkTable.h"
39 #include "vtkFloatArray.h"
40 #include "vtkContextView.h"
41 #include "vtkContextScene.h"
42 #include "vtkTableAlgorithm.h"
43 #include "vtkInformation.h"
44 #include "vtkInformationVector.h"
45 #include "vtkImageData.h"
46 
47 
48 //----------------------------------------------------------------------------
49 
50 class vtkExtractImageRow : public vtkTableAlgorithm
51 {
52 public:
53  static vtkExtractImageRow* New();
54  vtkTypeMacro(vtkExtractImageRow,vtkTableAlgorithm);
55  void PrintSelf(ostream& os, vtkIndent indent)
56  {
57  this->Superclass::PrintSelf(os, indent);
58  }
59 
60  // Description:
61  // Specify the first vtkGraph input and the second vtkSelection input.
62  int FillInputPortInformation(int port, vtkInformation* info)
63  {
64  if (port == 0)
65  {
66  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
67  return 1;
68  }
69  return 0;
70  }
71 
72 protected:
73  vtkExtractImageRow()
74  {
75  this->SetNumberOfInputPorts(1);
76  }
77  virtual ~vtkExtractImageRow()
78  {
79  }
80 
81  int RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector)
82  {
83  vtkImageData* inputImage = vtkImageData::GetData(inputVector[0]);
84  vtkInformation* outInfo = outputVector->GetInformationObject(0);
85  vtkTable* outputTable = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
86 
87  if(!inputImage)
88  {
89  LOG_ERROR("No input image is available");
90  return 0;
91  }
92 
93  // Create the tables if they haven't been created yet
94  if (outputTable->GetColumnByName("time")==NULL)
95  {
96  vtkSmartPointer<vtkFloatArray> arrXnew = vtkSmartPointer<vtkFloatArray>::New();
97  arrXnew->SetName("time");
98  outputTable->AddColumn(arrXnew);
99  }
100  if (outputTable->GetColumnByName("RF value")==NULL)
101  {
102  vtkSmartPointer<vtkFloatArray> arrRfValNew = vtkSmartPointer<vtkFloatArray>::New();
103  arrRfValNew->SetName("RF value");
104  outputTable->AddColumn(arrRfValNew);
105  }
106 
107  if (inputImage->GetScalarType()!=VTK_SHORT)
108  {
109  LOG_ERROR("Plotting is only supported for signed short data");
110  return 0;
111  }
112  int rowCount=inputImage->GetDimensions()[1]; // number of transducer crystals
113  int numPoints=inputImage->GetDimensions()[0]; // number of data points (RF data values) recorded for one crystal
114  int selectedRow=rowCount/2; // plot the center column of the image
115  short* pixelBuffer=reinterpret_cast<short*>(inputImage->GetScalarPointer())+selectedRow*numPoints;
116 
117  outputTable->SetNumberOfRows(numPoints);
118  int timeIndex=numPoints-1; // the RF data set starts with the latest time
119  for (int i = 0; i < numPoints; ++i)
120  {
121  outputTable->SetValue(i, 0, timeIndex);
122  short value=*pixelBuffer;
123  outputTable->SetValue(i, 1, value);
124  pixelBuffer++;
125  timeIndex--;
126  }
127 
128  return 1;
129  }
130 
131 private:
132  vtkExtractImageRow(const vtkExtractImageRow&); // Not implemented
133  void operator=(const vtkExtractImageRow&); // Not implemented
134 };
135 
136 vtkStandardNewMacro(vtkExtractImageRow);
137 
138 //---------------------------------------------------------------------------------
139 
140 class vtkMyPlotCallback : public vtkCommand
141 {
142 public:
143  static vtkMyPlotCallback *New() { return new vtkMyPlotCallback; }
144 
145  virtual void Execute(vtkObject *caller, unsigned long eventId, void* callData)
146  {
147  if (eventId==vtkCommand::KeyPressEvent)
148  {
149  if (m_Interactor->GetKeyCode()=='q')
150  {
151  m_Interactor->ExitCallback();
152  }
153  return;
154  }
155 
156  m_ImageToTableAdaptor->Update();
157  m_Viewer->Render();
158  //update the timer so it will trigger again
159  m_Interactor->CreateTimer(VTKI_TIMER_UPDATE);
160  }
161 
162  vtkRenderWindowInteractor *m_Interactor;
163  vtkContextView *m_Viewer;
164  vtkExtractImageRow *m_ImageToTableAdaptor;
165 
166 private:
167 
168  vtkMyPlotCallback()
169  {
170  m_Interactor=NULL;
171  m_Viewer=NULL;
172  m_ImageToTableAdaptor=NULL;
173  }
174 };
175 
176 //----------------------------------------------------------------------------
178 {
179  // Set up a 2D scene, add an XY chart to it
180  vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
181  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
182  view->GetRenderWindow()->SetSize(400, 300);
183  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
184  view->GetScene()->AddItem(chart);
185 
186  vtkSmartPointer<vtkExtractImageRow> imageToTableAdaptor=vtkSmartPointer<vtkExtractImageRow>::New();
187  imageToTableAdaptor->SetInputConnection(portaGrabber->GetOutputPort());
188  imageToTableAdaptor->Update();
189 
190  // Add multiple line plots, setting the colors etc
191  vtkPlot *line = chart->AddPlot(vtkChart::LINE);
192  line->SetInputData(imageToTableAdaptor->GetOutput(), 0, 1);
193  line->SetColor(0, 255, 0, 255);
194  line->SetWidth(1.0);
195 
196  vtkSmartPointer<vtkMyPlotCallback> call = vtkSmartPointer<vtkMyPlotCallback>::New();
197  call->m_Interactor=view->GetInteractor();
198  call->m_Viewer=view;
199  call->m_ImageToTableAdaptor=imageToTableAdaptor;
200 
201  view->GetInteractor()->Initialize();
202 
203  view->GetInteractor()->AddObserver(vtkCommand::TimerEvent, call);
204  view->GetInteractor()->CreateTimer(VTKI_TIMER_FIRST);
205 
206  view->GetInteractor()->AddObserver(vtkCommand::KeyPressEvent, call);
207 
208  view->GetInteractor()->Start();
209 
210 }
211 
212 //---------------------------------------------------------------------------------
213 
214 class vtkMyCallback : public vtkCommand
215 {
216 public:
217  static vtkMyCallback *New() { return new vtkMyCallback; }
218 
219  virtual void Execute(vtkObject *caller, unsigned long, void*)
220  {
221  m_Viewer->Render();
222 
223  //update the timer so it will trigger again
224  m_Interactor->CreateTimer(VTKI_TIMER_UPDATE);
225  }
226 
227  vtkRenderWindowInteractor *m_Interactor;
228  vtkImageViewer *m_Viewer;
229 
230 private:
231 
232  vtkMyCallback()
233  {
234  m_Interactor=NULL;
235  m_Viewer=NULL;
236  }
237 };
238 
239 //-------------------------------------------------------------------------------------------
240 
241 int main(int argc, char* argv[])
242 {
243  std::string LUTPath("C:/luts");
244  std::string PortaSettingPath("D:/devel/pltools/Ultrasonix/sdk-5.6.4/porta/dat/");
245  std::string LicensePath("D:/Ultrasonix Settings/licenses.txt");
246  std::string PortaFirmwarePath("D:/devel/pltools/Ultrasonix/sdk-5.6.4/porta/fw/");
247  int stepPerFrame = 16;
248  int FramePerVolume = 20;
249  bool renderingOff(false);
250 
251 
252  vtksys::CommandLineArguments args;
253  args.Initialize(argc, argv);
254 
255  int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
256 
257  args.AddArgument("--setting-path", vtksys::CommandLineArguments::NO_ARGUMENT, &PortaSettingPath, "Setting path.");
258  args.AddArgument("--lut-path", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &LUTPath, "LUT Path." );
259  args.AddArgument("--firmware-path", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &PortaFirmwarePath, "Firmware path.");
260  args.AddArgument("--license-path", vtksys::CommandLineArguments::NO_ARGUMENT, &LicensePath, "License path.");
261  args.AddArgument("--rendering-off", vtksys::CommandLineArguments::NO_ARGUMENT, &renderingOff, "Run test without rendering.");
262 
263  if ( !args.Parse() )
264  {
265  std::cerr << "Problem parsing arguments" << std::endl;
266  std::cout << "\n\nvtkPlusSonixPortaVideoSourceTest help:" << args.GetHelp() << std::endl;
267  exit(EXIT_FAILURE);
268  }
269 
270  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
271 
272  vtkSmartPointer<vtkPlusSonixPortaVideoSource> portaGrabber = vtkSmartPointer<vtkPlusSonixPortaVideoSource>::New();
273 
274  portaGrabber->SetStepPerFrame(stepPerFrame);
275  portaGrabber->SetFramePerVolume(FramePerVolume);
276  portaGrabber->SetPortaLUTPath(LUTPath.c_str());
277  portaGrabber->SetPortaFirmwarePath(PortaFirmwarePath.c_str());
278  portaGrabber->SetPortaLicensePath(LicensePath.c_str());
279  portaGrabber->SetPortaSettingPath(PortaSettingPath.c_str());
280 
281  DisplayMode displayMode=SHOW_IMAGE;
282 
283  LOG_DEBUG("Acquisition mode: B");
284  portaGrabber->SetImagingMode(vtkPlusUsImagingParameters::BMode);
285  displayMode=SHOW_IMAGE;
286 
287  portaGrabber->CreateDefaultOutputChannel();
288  vtkPlusDataSource* aSource(NULL);
289  if (portaGrabber->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS )
290  {
291  LOG_ERROR("Unable to retrieve the video source.");
292  exit(EXIT_FAILURE);
293  }
294  aSource->SetInputImageOrientation( US_IMG_ORIENT_UF );
295 
296  if ( portaGrabber->Connect()!=PLUS_SUCCESS )
297  {
298  LOG_ERROR( "Unable to connect to Porta" );
299  exit(EXIT_FAILURE);
300  }
301 
302  portaGrabber->StartRecording(); //start recording frame from the video
303 
304  if (renderingOff)
305  {
306  // just run the recording for a few seconds then exit
307  LOG_DEBUG("Rendering disabled. Wait for just a few seconds to acquire data before exiting");
308  Sleep(5000); // no need to use accurate timer, it's just an approximate delay
309  portaGrabber->StopRecording();
310  portaGrabber->Disconnect();
311  }
312  else
313  {
314 
315  // Show the live ultrasound image in a VTK renderer window
316 
317  vtkSmartPointer<vtkImageViewer> viewer = vtkSmartPointer<vtkImageViewer>::New();
318  viewer->SetInputConnection(portaGrabber->GetOutputPort(0)); //set image to the render and window
319  viewer->SetColorWindow(255);
320  viewer->SetColorLevel(127.5);
321  viewer->SetZSlice(0);
322 
323  //Create the interactor that handles the event loop
324  vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
325  iren->SetRenderWindow(viewer->GetRenderWindow());
326  viewer->SetupInteractor(iren);
327 
328  viewer->Render(); //must be called after iren and viewer are linked or there will be problems
329 
330  // Establish timer event and create timer to update the live image
331  vtkSmartPointer<vtkMyCallback> call = vtkSmartPointer<vtkMyCallback>::New();
332  call->m_Interactor=iren;
333  call->m_Viewer=viewer;
334  iren->AddObserver(vtkCommand::TimerEvent, call);
335  iren->CreateTimer(VTKI_TIMER_FIRST);
336 
337  //iren must be initialized so that it can handle events
338  iren->Initialize();
339  iren->Start();
340  }
341 
342 
343  portaGrabber->Disconnect();
344  return EXIT_SUCCESS;
345 }
346 
const char int line
Definition: phidget22.h:2458
vtkRenderWindowInteractor * iren
for i
virtual PlusStatus SetInputImageOrientation(US_IMAGE_ORIENTATION imageOrientation)
int port
Definition: phidget22.h:2454
int main(int argc, char *argv[])
Class providing VTK video input interface for SonixRP.
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
vtkImageViewer * viewer
void TestLinePlot(vtkPlusSonixPortaVideoSource *portaGrabber)
const char const char * value
Definition: phidget22.h:5111
static vtkIGSIOLogger * Instance()
vtkStandardNewMacro(vtkExtractImageRow)
Interface to a 3D positioning tool, video source, or generalized data stream.