PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkCapistranoVideoSourceTest.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 
18 #include "PlusConfigure.h"
19 
20 #include "vtkAxis.h"
21 
22 #include "vtkCallbackCommand.h"
23 
24 #include "vtkChartXY.h"
25 
26 #include "vtkCommand.h"
27 
28 #include "vtkContextScene.h"
29 #include "vtkContextView.h"
30 #include "vtkFloatArray.h"
31 
32 #include "vtkImageData.h"
33 #include "vtkImageViewer.h"
34 
35 #include "vtkInformation.h"
36 
37 #include "vtkInformationVector.h"
38 #include "vtkPlot.h"
39 #include "vtkRenderWindow.h"
40 #include "vtkRenderWindowInteractor.h"
41 #include "vtkRenderer.h"
42 #include "vtkSmartPointer.h"
44 #include "vtkPlusDataSource.h"
45 
46 #include "vtkTable.h"
47 #include "vtkTableAlgorithm.h"
48 
49 #include "vtkXMLUtilities.h"
50 #include "vtksys/CommandLineArguments.hxx"
51 #include <stdlib.h>
52 
53 //----------------------------------------------------------------------------
54 
56 {
59 };
60 
61 //----------------------------------------------------------------------------
62 
63 class vtkExtractImageRow : public vtkTableAlgorithm
64 {
65 public:
66  static vtkExtractImageRow* New();
67  vtkTypeMacro(vtkExtractImageRow, vtkTableAlgorithm);
68  void PrintSelf(ostream& os, vtkIndent indent)
69  {
70  this->Superclass::PrintSelf(os, indent);
71  }
72 
73  // Description:
74  // Specify the first vtkGraph input and the second vtkSelection input.
75  int FillInputPortInformation(int port, vtkInformation* info)
76  {
77  if (port == 0)
78  {
79  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
80  return 1;
81  }
82  return 0;
83  }
84 
85 protected:
86  vtkExtractImageRow()
87  {
88  this->SetNumberOfInputPorts(1);
89  }
90  virtual ~vtkExtractImageRow()
91  {
92  }
93 
94  int RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector)
95  {
96  vtkImageData* inputImage = vtkImageData::GetData(inputVector[0]);
97  vtkInformation* outInfo = outputVector->GetInformationObject(0);
98  vtkTable* outputTable = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
99 
100  if (!inputImage)
101  {
102  LOG_ERROR("No input image is available");
103  return 0;
104  }
105 
106  // Create the tables if they haven't been created yet
107  if (outputTable->GetColumnByName("time") == NULL)
108  {
109  vtkSmartPointer<vtkFloatArray> arrXnew = vtkSmartPointer<vtkFloatArray>::New();
110  arrXnew->SetName("time");
111  outputTable->AddColumn(arrXnew);
112  }
113  if (outputTable->GetColumnByName("RF value") == NULL)
114  {
115  vtkSmartPointer<vtkFloatArray> arrRfValNew = vtkSmartPointer<vtkFloatArray>::New();
116  arrRfValNew->SetName("RF value");
117  outputTable->AddColumn(arrRfValNew);
118  }
119 
120  if (inputImage->GetScalarType() != VTK_SHORT)
121  {
122  LOG_ERROR("Plotting is only supported for signed short data");
123  return 0;
124  }
125  int rowCount = inputImage->GetDimensions()[1]; // number of transducer crystals
126  int numPoints = inputImage->GetDimensions()[0]; // number of data points (RF data values) recorded for one crystal
127  int selectedRow = rowCount / 2; // plot the center column of the image
128  short* pixelBuffer = reinterpret_cast<short*>(inputImage->GetScalarPointer()) + selectedRow * numPoints;
129 
130  outputTable->SetNumberOfRows(numPoints);
131  int timeIndex = numPoints - 1; // the RF data set starts with the latest time
132  for (int i = 0; i < numPoints; ++i)
133  {
134  outputTable->SetValue(i, 0, timeIndex);
135  short value = *pixelBuffer;
136  outputTable->SetValue(i, 1, value);
137  pixelBuffer++;
138  timeIndex--;
139  }
140 
141  return 1;
142  }
143 
144 private:
145  vtkExtractImageRow(const vtkExtractImageRow&); // Not implemented
146  void operator=(const vtkExtractImageRow&); // Not implemented
147 };
148 
149 vtkStandardNewMacro(vtkExtractImageRow);
150 
151 
152 //---------------------------------------------------------------------------------
153 
154 class vtkMyPlotCallback : public vtkCommand
155 {
156 public:
157  static vtkMyPlotCallback* New()
158  {
159  return new vtkMyPlotCallback;
160  }
161 
162  virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData)
163  {
164  if (eventId == vtkCommand::KeyPressEvent)
165  {
166  if (m_Interactor->GetKeyCode() == 'q')
167  {
168  m_Interactor->ExitCallback();
169  }
170  return;
171  }
172 
173  m_ImageToTableAdaptor->Update();
174  m_Viewer->Render();
175  //update the timer so it will trigger again
176  m_Interactor->CreateTimer(VTKI_TIMER_UPDATE);
177  }
178 
179  vtkRenderWindowInteractor* m_Interactor;
180  vtkContextView* m_Viewer;
181  vtkExtractImageRow* m_ImageToTableAdaptor;
182 
183 private:
184 
185  vtkMyPlotCallback()
186  {
187  m_Interactor = NULL;
188  m_Viewer = NULL;
189  m_ImageToTableAdaptor = NULL;
190  }
191 };
192 
193 //---------------------------------------------------------------------------------
194 
195 class vtkMyCallback : public vtkCommand
196 {
197 public:
198  static vtkMyCallback* New()
199  {
200  return new vtkMyCallback;
201  }
202 
203  virtual void Execute(vtkObject* caller, unsigned long, void*)
204  {
205  m_Viewer->Render();
206 
207  //update the timer so it will trigger again
208  m_Interactor->CreateTimer(VTKI_TIMER_UPDATE);
209  }
210 
211  vtkRenderWindowInteractor* m_Interactor;
212  vtkImageViewer* m_Viewer;
213 
214 private:
215 
216  vtkMyCallback()
217  {
218  m_Interactor = NULL;
219  m_Viewer = NULL;
220  }
221 };
222 
223 //-------------------------------------------------------------------------------------------
224 
225 int main(int argc, char* argv[])
226 {
227  int left;
228  left = -1;
229  int startX_01 = left < 0 ? 0 : left;
230  left = 10;
231  int startX_02 = left < 0 ? 0 : left;
232 
233  bool printHelp(false);
234  bool renderingOff(false);
235 
236  bool printParams(false);
237 
238  std::string inputConfigFileName;
239  std::string outputFileName("CapistranoTest.mha");
240 
241  double depthCm = -1;
242  double dynRangeDb = -1;
243 
244  double frequencyMhz = -1;
245 
246  // ToDo: check the next line
247  std::string acqMode("B");
248 
249  vtksys::CommandLineArguments args;
250  args.Initialize(argc, argv);
251 
252  int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
253 
254  args.AddArgument("--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp, "Print this help.");
255  args.AddArgument("--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName, "Config file containing the device configuration.");
256 
257  args.AddArgument("--acq-mode", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &acqMode, "Acquisition mode: B or RF (Default: B).");
258  args.AddArgument("--depth", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &depthCm, "Depth in cm.");
259 
260  args.AddArgument("--frequencyMhz", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &frequencyMhz, "Frequency in MHz");
261 
262  args.AddArgument("--dynRangeDb", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &dynRangeDb, "BMode Dynamic Range. 1 corresponds to the maximum dynamic range.");
263 
264  args.AddArgument("--rendering-off", vtksys::CommandLineArguments::NO_ARGUMENT, &renderingOff, "Run test without rendering.");
265  args.AddArgument("--output-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputFileName, "Filename of the output video buffer sequence metafile (Default: CapistranoTest.mha)");
266  args.AddArgument("--print-params", vtksys::CommandLineArguments::NO_ARGUMENT, &printParams, "Print all the supported imaging parameters (for diagnostic purposes only).");
267  args.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level 1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
268 
269  if (!args.Parse())
270  {
271  std::cerr << "Problem parsing arguments" << std::endl;
272  std::cout << "\n\nvtkPlusCapistranoVideoSourceTest1 help:" << args.GetHelp() << std::endl;
273  exit(EXIT_FAILURE);
274  }
275 
276 
277  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
278 
279  if (printHelp)
280  {
281  std::cout << "\n\nvtkPlusCapistranoVideoSourceTest help:" << args.GetHelp() << std::endl;
282  exit(EXIT_SUCCESS);
283  }
284 
285 
286  vtkSmartPointer< vtkPlusCapistranoVideoSource > capistranoDevice =
287  vtkSmartPointer< vtkPlusCapistranoVideoSource >::New();
288  capistranoDevice->SetDeviceId("VideoDevice");
289 
290  vtkIndent indent;
291 
292 
293  // Read config file
294  if (STRCASECMP(inputConfigFileName.c_str(), "") != 0)
295  {
296  LOG_DEBUG("Reading config file...");
297  vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
298 
299  if (PlusXmlUtils::ReadDeviceSetConfigurationFromFile(configRootElement, inputConfigFileName.c_str()) == PLUS_FAIL)
300  {
301  LOG_ERROR("Unable to read configuration from file " << inputConfigFileName.c_str());
302  return EXIT_FAILURE;
303  }
304 
305  capistranoDevice->ReadConfiguration(configRootElement);
306  }
307  capistranoDevice->PrintSelf(std::cout, indent);
308 
309 
310  DisplayMode displayMode = SHOW_IMAGE;
311 
312  if (STRCASECMP(acqMode.c_str(), "B") == 0)
313  {
314  LOG_DEBUG("Acquisition mode: B");
315  displayMode = SHOW_IMAGE;
316  }
317  else
318  {
319  LOG_ERROR("Unsupported Acquisition mode requested: " << acqMode);
320  exit(EXIT_FAILURE);
321  }
322 
323 
324  if (capistranoDevice->Connect() != PLUS_SUCCESS)
325  {
326  LOG_ERROR("Unable to connect to Capistrano Probe");
327  exit(EXIT_FAILURE);
328  }
329 
330  LOG_INFO("SDK version: " << capistranoDevice->GetSdkVersion());
331 
332  int retval = 0;
333 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2) || defined(CAPISTRANO_SDK2019) || defined(CAPISTRANO_SDK2018)
334  capistranoDevice->GetHardwareVersion(retval);
335  LOG_INFO("Hardware version: " << retval);
336 #endif
337 
338  if (printParams)
339  {
340  LOG_INFO("List of supported imaging parameters:");
341  // ToDo: Implement the following function
342  //capistranoDevice->PrintListOfImagingParameters();
343  }
344 
345  capistranoDevice->StartRecording(); //start recording frame from the video
346 
347  if (renderingOff)
348  {
349  // just run the recording for a few seconds then exit
350  LOG_DEBUG("Rendering disabled. Wait for just a few seconds to acquire data before exiting");
351  Sleep(2500); // no need to use accurate timer, it's just an approximate delay
352  capistranoDevice->StopRecording();
353  capistranoDevice->Disconnect();
354  vtkPlusDataSource* source(nullptr);
355  capistranoDevice->GetVideoSource("Video", source);
356  source->WriteToSequenceFile(outputFileName.c_str());
357  }
358  else
359  {
360  // Show the live ultrasound image in a VTK renderer window
361 
362  vtkSmartPointer<vtkImageViewer> viewer = vtkSmartPointer<vtkImageViewer>::New();
363  viewer->SetInputConnection(capistranoDevice->GetOutputPort()); //set image to the render and window
364  viewer->SetColorWindow(255);
365  viewer->SetColorLevel(127.5);
366  viewer->SetZSlice(0);
367 
368  //Create the interactor that handles the event loop
369  vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
370  iren->SetRenderWindow(viewer->GetRenderWindow());
371  viewer->SetupInteractor(iren);
372 
373  viewer->Render(); //must be called after iren and viewer are linked or there will be problems
374 
375  // Establish timer event and create timer to update the live image
376  vtkSmartPointer<vtkMyCallback> call = vtkSmartPointer<vtkMyCallback>::New();
377  call->m_Interactor = iren;
378  call->m_Viewer = viewer;
379  iren->AddObserver(vtkCommand::TimerEvent, call);
380  iren->CreateTimer(VTKI_TIMER_FIRST);
381 
382  //iren must be initialized so that it can handle events
383  iren->Initialize();
384  iren->Start();
385  }
386 
387  capistranoDevice->Disconnect();
388 
389  return EXIT_SUCCESS;
390 }
391 
int main(int argc, char *argv[])
const char * source
Definition: phidget22.h:2461
vtkStandardNewMacro(vtkExtractImageRow)
vtkRenderWindowInteractor * iren
for i
#define PLUS_FAIL
Definition: PlusCommon.h:43
int port
Definition: phidget22.h:2454
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
vtkImageViewer * viewer
const char const char * value
Definition: phidget22.h:5111
static vtkIGSIOLogger * Instance()
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)
Definition: PlusXmlUtils.h:23
Interface to a 3D positioning tool, video source, or generalized data stream.