PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusIntersonVideoSource.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 <PlusConfigure.h>
9 #include <vtkPlusChannel.h>
10 #include <vtkPlusDataSource.h>
13 
14 // VTK includes
15 #include <vtkImageData.h>
16 #include <vtkObjectFactory.h>
17 
18 // Order matters, leave these at the bottom
19 #include <BmodeDLL.h>
20 #include <usbProbeDLL_net.h>
21 
22 // Interson's OEM ID (probes released by Interson have this OEM ID)
23 #define OEM_ID_INTERSON 0x00
24 #define TOLERANCE 0.001
25 
26 //----------------------------------------------------------------------------
27 
29 
30 //----------------------------------------------------------------------------
31 
32 class vtkPlusIntersonVideoSource::vtkInternal
33 {
34 public:
36 
37  // TODO : move any of these into imaging parameters?
38  bool Interpolate;
39  bool BidirectionalScan;
40  bool Frozen;
41 
42  int ClockDivider;
43  double ClockFrequencyMHz;
44  int PulseFrequencyDivider;
45 
46  double LutCenter;
47  double LutWindow;
48 
49  // ProbeButtonPressCount is incremented each time the button on the probe is pressed
50  // The value is available in the output channel in the translation component of the ProbeButtonToDummyTransform
51  int ProbeButtonPressCount;
52  bool EnableProbeButtonMonitoring;
53 
54  HWND ImageWindowHandle;
55  HBITMAP DataHandle;
56  HANDLE ProbeHandle;
57  std::vector<unsigned char> MemoryBitmapBuffer;
58  BITMAP Bitmap;
59  bmBITMAPINFO BitmapInfo;
60  BYTE* RfDataBuffer;
61  static const int samplesPerLine = 2048;
62 
63  //----------------------------------------------------------------------------
64  vtkPlusIntersonVideoSource::vtkInternal::vtkInternal(vtkPlusIntersonVideoSource* external)
65  : External(external)
66  , RfDataBuffer(NULL)
67  , ProbeHandle(NULL)
68  {
69 
70  }
71 
72  //----------------------------------------------------------------------------
73  virtual vtkPlusIntersonVideoSource::vtkInternal::~vtkInternal()
74  {
75  }
76 
77  //----------------------------------------------------------------------------
78  void vtkPlusIntersonVideoSource::vtkInternal::PrintSelf(ostream& os, vtkIndent indent)
79  {
80  this->External->PrintSelf(os, indent);
81 
82  os << indent << "Interpolate: " << this->Interpolate << std::endl;
83  os << indent << "BidirectionalScan: " << this->BidirectionalScan << std::endl;
84  os << indent << "Frozen: " << this->Frozen << std::endl;
85  os << indent << "ClockDivider: " << this->ClockDivider << std::endl;
86  os << indent << "ClockFrequencyMHz: " << this->ClockFrequencyMHz << std::endl;
87  os << indent << "PulseFrequencyDivider: " << this->PulseFrequencyDivider << std::endl;
88  os << indent << "LutCenter: " << this->LutCenter << std::endl;
89  os << indent << "LutWindow: " << this->LutWindow << std::endl;
90  os << indent << "ProbeButtonPressCount: " << this->ProbeButtonPressCount << std::endl;
91  os << indent << "EnableProbeButtonMonitoring: " << this->EnableProbeButtonMonitoring << std::endl;
92  }
93 
94  //----------------------------------------------------------------------------
95  void vtkPlusIntersonVideoSource::vtkInternal::CreateLinearTGC(int tgcMin, int tgcMax)
96  {
97  int tgc[samplesPerLine] = { 0 };
98  int b = tgcMin;
99  float m = (float)(tgcMax - tgcMin) / samplesPerLine;
100  for (int x = 0; x < samplesPerLine; x++)
101  {
102  tgc[x] = (int)(m * (float)x) + b;
103  }
104  bmSetTGC(tgc);
105  }
106 
107  //----------------------------------------------------------------------------
108  void vtkPlusIntersonVideoSource::vtkInternal::CreateLinearTGC(int initialTGC, int midTGC, int farTGC)
109  {
110  /* A linear TGC function is created. The initial point is initialTGC, then is linear until the
111  middle point (midTGC) and then linear until the maximum depth where the compensation is equal to farTGC*/
112 
113  int tgc[samplesPerLine] = { 0 };
114  double firstSlope = (double)(midTGC - initialTGC) / (samplesPerLine / 2);
115  double secondSlope = (double)(farTGC - midTGC) / (samplesPerLine / 2);
116  for (int x = 0; x < samplesPerLine / 2; x++)
117  {
118  tgc[x] = (int)(firstSlope * (double)x) + initialTGC;
119  tgc[samplesPerLine / 2 + x] = (int)(secondSlope * (double)x) + midTGC;
120  }
121  bmSetTGC(tgc);
122  }
123 
124  //----------------------------------------------------------------------------
125  static LRESULT CALLBACK vtkPlusIntersonVideoSource::vtkInternal::ImageWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
126  {
127  vtkPlusIntersonVideoSource::vtkInternal* self = (vtkPlusIntersonVideoSource::vtkInternal*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
128  return DefWindowProc(hwnd, iMsg, wParam, lParam);
129  }
130 
131  //----------------------------------------------------------------------------
132  PlusStatus vtkPlusIntersonVideoSource::vtkInternal::InitializeDIB(const FrameSizeType imageSize)
133  {
134  this->BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
135  this->BitmapInfo.bmiHeader.biWidth = imageSize[0];
136  this->BitmapInfo.bmiHeader.biHeight = -imageSize[1];
137  this->BitmapInfo.bmiHeader.biPlanes = 1;
138  this->BitmapInfo.bmiHeader.biBitCount = 8;
139  this->BitmapInfo.bmiHeader.biCompression = 0;
140  this->BitmapInfo.bmiHeader.biXPelsPerMeter = 0;
141  this->BitmapInfo.bmiHeader.biYPelsPerMeter = 0;
142  this->BitmapInfo.bmiHeader.biClrUsed = 0;
143  this->BitmapInfo.bmiHeader.biClrImportant = 0;
144 
145  // Compute the number of bytes in the array of color
146  // indices and store the result in biSizeImage.
147  // The width must be DWORD aligned unless the bitmap is RLE compressed.
148  this->BitmapInfo.bmiHeader.biSizeImage = ((imageSize[0] * 8 + 31) & ~31) / 8 * imageSize[1];
149 
150  for (int i = 0; i < 256; i++)
151  {
152  this->BitmapInfo.bmiColors[i].rgbRed = i;
153  this->BitmapInfo.bmiColors[i].rgbBlue = i;
154  this->BitmapInfo.bmiColors[i].rgbGreen = i;
155  this->BitmapInfo.bmiColors[i].rgbReserved = 0;
156  }
157 
158  return PLUS_SUCCESS;
159  }
160 
161  //----------------------------------------------------------------------------
162  void CreateLinearLUT(BYTE lut[], int level, int window)
163  {
164  int center = window / 2; // center of window
165  int left = level - center; // left of window
166  int right = level + center; // right of window
167 
168  // everything to our left is black
169  for (int x = 0; x < left; x++)
170  {
171  lut[x] = 0;
172  }
173 
174  // everything to our right is white
175  for (int x = right + 1; x < 256; x++)
176  {
177  lut[x] = 255;
178  }
179 
180  // everything in between is on the line
181  float m = 255.0f / ((float)window);
182 
183  int startX = left;
184  if (startX < 0)
185  {
186  startX = 0;
187  }
188  int endX = right;
189  if (endX > 255)
190  {
191  endX = 255;
192  }
193  for (int x = startX; x <= endX; x++)
194  {
195  int y = (int)(m * (float)(x - left) + 0.5f);
196  if (y < 0)
197  {
198  y = 0;
199  }
200  else if (y > 255)
201  {
202  y = 255;
203  }
204  lut[x] = y;
205  }
206  }
207 
208  //----------------------------------------------------------------------------
209  void CreateLUT(BYTE lut[])
210  {
211  int center = this->LutWindow / 2; // center of window
212  int left = this->LutCenter - center; // left of window
213  int right = this->LutCenter + center; // right of window
214  double contrast;
215  this->External->ImagingParameters->GetContrast(contrast);
216  double brightness;
217  this->External->ImagingParameters->GetIntensity(brightness);
218  for (int x = 0; x <= 255; x++)
219  {
220  int y = (int)((float)contrast / 256.0f * (float)(x - 128) + brightness);
221  if (y < left)
222  {
223  y = 0;
224  }
225  else if (y > right)
226  {
227  y = 255;
228  }
229  lut[x] = y;
230  }
231  }
232 };
233 
234 //----------------------------------------------------------------------------
236  : vtkPlusUsDevice()
237  , Internal(new vtkInternal(this))
238 {
239  this->Internal->Interpolate = true;
240  this->Internal->BidirectionalScan = true;
241  this->Internal->Frozen = true;
242 
244 
245  this->Internal->ClockDivider = 1;
246  this->Internal->PulseFrequencyDivider = 2;
247 
248  this->ImagingParameters->SetIntensity(128.0);
249  this->ImagingParameters->SetContrast(256.0);
250  this->Internal->LutCenter = 128;
251  this->Internal->LutWindow = 256;
252 
253  this->ImagingParameters->SetImageSize(800, 512, 1);
254  this->ImagingParameters->SetProbeVoltage(30.0f);
255 
256  // No callback function provided by the device, so the data capture thread will be used to poll the hardware and add new items to the buffer
257  this->StartThreadForInternalUpdates = true;
258  this->AcquisitionRate = 30;
259 
260  this->Internal->EnableProbeButtonMonitoring = false;
261  this->Internal->ProbeButtonPressCount = 0;
262 }
263 
264 //----------------------------------------------------------------------------
266 {
267  if (!this->Connected)
268  {
269  this->Disconnect();
270  }
271 
272  delete this->Internal;
273  this->Internal = NULL;
274 }
275 
276 //----------------------------------------------------------------------------
277 void vtkPlusIntersonVideoSource::PrintSelf(ostream& os, vtkIndent indent)
278 {
279  this->Superclass::PrintSelf(os, indent);
280  this->Internal->PrintSelf(os, indent);
281 }
282 
283 //----------------------------------------------------------------------------
284 int CALLBACK ProbeAttached()
285 {
286  LOG_INFO("Probe attached");
287  return 0;
288 }
289 
290 //----------------------------------------------------------------------------
291 int CALLBACK ProbeDetached()
292 {
293  LOG_INFO("Probe detached");
294  return 0;
295 }
296 
297 //----------------------------------------------------------------------------
299 {
300  LOG_TRACE("vtkPlusIntersonVideoSource::InternalConnect");
301 
302  LOG_DEBUG("Interson Bmode DLL version " << bmDLLVer() << ", USB probe DLL version " << usbDLLVer());
303 
304  usbSetProbeAttachCallback(&ProbeAttached);
305  usbSetProbeDetachCallback(&ProbeDetached);
306 
307  // Before any probe can be initialized with usbInitializeProbes, they must be detected. usbFindProbes()
308  // will detect all attached probes and initialize the driver. After a successful call to usbFindProbes,
309  // other probe-related functions may be called. These include: usbInitializeProbes, usbProbeHandle,
310  // usbSelectProbe.
311  usbErrorString errorStatus = { 0 };
312  ULONG status = usbFindProbes(errorStatus);
313  LOG_DEBUG("Find USB probes: status=" << status << ", details: " << errorStatus);
314  if (status != ERROR_SUCCESS)
315  {
316  LOG_ERROR("Interson finding probes failed");
317  return PLUS_FAIL;
318  }
319 
320  usbInitializeProbes();
321 
322  // Turn on USB data synchronization checking
323  usbTurnOnSync();
324 
325  int numberOfAttachedProbes = usbNumberAttachedProbes();
326  LOG_DEBUG("Number of attached probes: " << numberOfAttachedProbes);
327  if (numberOfAttachedProbes == 0)
328  {
329  LOG_ERROR("No Interson probes are attached");
330  return PLUS_FAIL;
331  }
332  if (numberOfAttachedProbes > 1)
333  {
334  LOG_WARNING("Multiple Interson probes are attached, using the first one");
335  }
336 
337  FrameSizeType imageSize;
338  this->ImagingParameters->GetImageSize(imageSize);
339 
340  PVOID display = bmInitializeDisplay(imageSize[0] * imageSize[1]);
341  if (display == NULL)
342  {
343  LOG_ERROR("Could not initialize the display");
344  return PLUS_FAIL;
345  }
346 
347  this->Internal->InitializeDIB(imageSize);
348 
349  BYTE currentOemId = usbProbeOEMID();
350  if (currentOemId != OEM_ID_INTERSON)
351  {
352  LOG_WARNING("Probe OEM ID mismatch: " << OEM_ID_INTERSON << " (Interson) is expected, got " << currentOemId);
353  }
354 
355  // get the first probe
356  usbProbeHandle(0, &this->Internal->ProbeHandle);
357  // if there is hardware attached, this enables it
358  usbSelectProbe(this->Internal->ProbeHandle);
359  // set the display window depth for this probe
360  usbSetWindowDepth(this->Internal->ProbeHandle, imageSize[1]);
361  // set the assumed velocity (m/s)
362  float soundVelocity = -1;
363  this->ImagingParameters->GetSoundVelocity(soundVelocity);
364  if (soundVelocity > 0)
365  {
366  this->SetSoundVelocityDevice(soundVelocity);
367  }
368  double depth = -1;
369  this->ImagingParameters->GetDepthMm(depth);
370  if (depth > 0)
371  {
372  this->SetDepthMmDevice(depth);
373  }
374 
375  // Setup the display offsets now that we have the probe and DISPLAY data
376  bmSetDisplayOffset(0);
377 
378  if (usbSetCineBuffers(32) != 32)
379  {
380  LOG_ERROR("Could not allocate Cine buffers.");
381  return PLUS_FAIL;
382  }
383  this->Internal->RfDataBuffer = usbCurrentCineFrame();
384 
385  usbSetUnidirectionalMode();
386  usbSetPulseVoltage(this->ImagingParameters->GetProbeVoltage());
387 
388  POINT ptCenter; // Points for Zoomed Display
389  ptCenter.x = imageSize[0] / 2;
390  ptCenter.y = imageSize[1] / 2;
391  int rotation = 0;
392 
393  if (bmCalculateDisplay(imageSize[0], imageSize[1], ptCenter, this->Internal->ProbeHandle, imageSize[0], rotation) == ERROR)
394  {
395  LOG_ERROR("CalculateDisplay failed");
396  }
397 
398  std::string probeName;
399  GetProbeNameDevice(probeName);
400  LOG_DEBUG("Interson probe name: " << probeName << ", ID: " << usbProbeID(this->Internal->ProbeHandle));
401 
402  vtkPlusDataSource* aSource = NULL;
403  if (this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS)
404  {
405  LOG_ERROR("Unable to retrieve the video source in the IntersonVideo device.");
406  return PLUS_FAIL;
407  }
408 
409  // Clear buffer on connect because the new frames that we will acquire might have a different size
410  aSource->Clear();
411  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
412  aSource->SetInputFrameSize(imageSize[0], imageSize[1], 1);
413 
414  HINSTANCE hInst = GetModuleHandle(NULL);
415 
416  WNDCLASSEX wndclass;
417  wndclass.cbSize = sizeof(wndclass);
418  wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
420  wndclass.cbClsExtra = 0;
421  wndclass.cbWndExtra = 0;
422  wndclass.hInstance = hInst;
423  wndclass.hIcon = NULL;
424  wndclass.hCursor = NULL;
425  wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
426  wndclass.lpszMenuName = NULL;
427  wndclass.lpszClassName = TEXT("ImageWindow");
428  wndclass.hIconSm = NULL;
429  RegisterClassEx(&wndclass);
430 
431  int cxFixedFrameSize = GetSystemMetrics(SM_CXFIXEDFRAME);
432  int cyFixedFrameSize = GetSystemMetrics(SM_CYFIXEDFRAME);
433  int cxBorderSize = GetSystemMetrics(SM_CXSIZE);
434  int cyBorderSize = GetSystemMetrics(SM_CYSIZE);
435  int cxSize = GetSystemMetrics(SM_CXBORDER);
436  int cySize = GetSystemMetrics(SM_CYBORDER);
437 
438  this->Internal->ImageWindowHandle = CreateWindow(TEXT("ImageWindow"), TEXT("Ultrasound"),
439  WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
440  imageSize[0] + 2 * cxFixedFrameSize + cxBorderSize + cxSize,
441  imageSize[1] + 2 * cyFixedFrameSize + cyBorderSize + cySize,
442  NULL, NULL, hInst, NULL);
443 
444  if (this->Internal->ImageWindowHandle == NULL)
445  {
446  LOG_ERROR("Failed to create capture window");
447  return PLUS_FAIL;
448  }
449 
450  SetWindowLongPtr(this->Internal->ImageWindowHandle, GWLP_USERDATA, (LONG)this->Internal);
451 
452  // Create a bitmap for use in our DIB
453  HDC hdc = GetDC(this->Internal->ImageWindowHandle);
454  RECT rect;
455  GetClientRect(this->Internal->ImageWindowHandle, &rect);
456  int cx = rect.right - rect.left;
457  int cy = rect.bottom - rect.top;
458  this->Internal->DataHandle = CreateCompatibleBitmap(hdc, cx, cy);
459  GetObject(this->Internal->DataHandle, sizeof(BITMAP), (LPVOID) &this->Internal->Bitmap);
460  // zero indexed window including borders
461  size_t toAllocate = (this->Internal->Bitmap.bmWidth + 16) * (this->Internal->Bitmap.bmHeight + 4);
462  this->Internal->MemoryBitmapBuffer.resize(toAllocate, 0);
463 
464  std::vector<double> gain;
466  if (gain.size() == 3)
467  {
468  double tgc[3] = { gain[0], gain[1], gain[2] };
470  }
471 
473  return PLUS_SUCCESS;
474 }
475 
476 //----------------------------------------------------------------------------
478 {
479  LOG_DEBUG("Disconnect from Interson");
480 
481  this->StopRecording();
482 
483  usbProbe(STOP);
484  Sleep(250); // allow time for the imaging to stop
485 
486  // usbStopHardware() should be called here but the issue is that if the method is called, no probe is detected after connecting again.
487 
488  bmCloseDisplay();
489 
490  DeleteObject(this->Internal->ProbeHandle);
491  DeleteObject(this->Internal->DataHandle);
492  DeleteObject(this->Internal->ImageWindowHandle);
493 
494  return PLUS_SUCCESS;
495 }
496 
497 //----------------------------------------------------------------------------
499 {
500  FreezeDevice(false);
501  return PLUS_SUCCESS;
502 }
503 
504 //----------------------------------------------------------------------------
506 {
507  FreezeDevice(true);
508  return PLUS_SUCCESS;
509 }
510 
511 //----------------------------------------------------------------------------
513 {
514  bool nextFrameReady = (usbWaitFrame() == 1);
515  DWORD usbErrorCode = usbError();
516 
517  switch (usbErrorCode)
518  {
519  case USB_SUCCESS:
520  break;
521  case USB_FAILED:
522  LOG_ERROR("USB: FAILURE. Probe was removed?");
523  return PLUS_FAIL;
524  case USB_TIMEOUT2A:
525  case USB_TIMEOUT2B:
526  case USB_TIMEOUT6A:
527  case USB_TIMEOUT6B:
528  if (nextFrameReady) // timeout is fine if we're in synchronized mode, so only log error if next frame is ready
529  {
530  LOG_WARNING("USB timeout");
531  }
532  break;
533  case USB_NOTSEQ:
534  LOG_ERROR("Lost Probe Synchronization. Please check probe cables and restart.");
535  break;
536  case USB_STOPPED:
537  LOG_ERROR("USB: Stopped. Check probe and restart.");
538  break;
539  default:
540  LOG_ERROR("USB: Unknown USB error: " << usbErrorCode);
541  break;
542  }
543 
544  return PLUS_SUCCESS;
545 }
546 
547 //----------------------------------------------------------------------------
549 {
550  if (!this->Recording)
551  {
552  // drop the frame, we are not recording data now
553  return PLUS_SUCCESS;
554  }
555 
556  if (usbProbeButtonPressed() && this->Internal->EnableProbeButtonMonitoring)
557  {
558  this->Internal->ProbeButtonPressCount++;
559  }
560 
561  WaitForFrame();
562 
563  this->Internal->RfDataBuffer = usbCurrentCineFrame();
564 
565  bmDrawImage(this->Internal->ImageWindowHandle, this->Internal->RfDataBuffer, this->Internal->Bitmap, &(this->Internal->MemoryBitmapBuffer[0]), &this->Internal->BitmapInfo, this->Internal->Interpolate, this->Internal->BidirectionalScan);
566 
567  this->FrameNumber++;
568 
569  std::vector<vtkPlusDataSource*> sources;
570  vtkPlusDataSource* aSource(NULL);
571  if (this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS)
572  {
573  LOG_ERROR("Unable to retrieve the video source in the ICCapturing device.");
574  return PLUS_FAIL;
575  }
576  sources.push_back(aSource);
577 
578  FrameSizeType imageSize;
579  this->ImagingParameters->GetImageSize(imageSize);
580 
581  // If the buffer is empty, set the pixel type and frame size to the first received properties
582  if (aSource->GetNumberOfItems() == 0)
583  {
584  LOG_DEBUG("Set up image buffer for Interson");
585  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
586  aSource->SetImageType(US_IMG_BRIGHTNESS);
587  aSource->SetInputFrameSize(imageSize);
588 
589  float depthScale = -1;
590  usbProbeDepthScale(this->Internal->ProbeHandle, &depthScale);
591 
592  std::string probeName;
593  GetProbeNameDevice(probeName);
594 
595  LOG_INFO("Frame size: " << imageSize[0] << "x" << imageSize[1]
596  << ", pixel type: " << vtkImageScalarTypeNameMacro(aSource->GetPixelType())
597  << ", probe sample frequency (Hz): " << usbProbeSampleFrequency(this->Internal->ProbeHandle)
598  << ", probe name: " << probeName
599  << ", display zoom: " << bmDisplayZoom()
600  << ", probe depth scale (mm/sample):" << depthScale
601  << ", buffer image orientation: " << igsioCommon::GetStringFromUsImageOrientation(aSource->GetInputImageOrientation()));
602  }
603 
604  igsioFieldMapType customFields;
605 
606  if (this->Internal->EnableProbeButtonMonitoring)
607  {
608  std::ostringstream probeButtonPressCountString;
609  probeButtonPressCountString << this->Internal->ProbeButtonPressCount;
610  customFields["ProbeButtonToDummyTransform"].second = std::string("1 0 0 ") + probeButtonPressCountString.str() + " 0 1 0 0 0 0 1 0 0 0 0 1";
611  customFields["ProbeButtonToDummyTransformStatus"].second = "OK";
612  }
613 
614  if (this->AddVideoItemToVideoSources(sources, (void*) & (this->Internal->MemoryBitmapBuffer[0]), aSource->GetInputImageOrientation(),
615  imageSize, VTK_UNSIGNED_CHAR, 1, US_IMG_BRIGHTNESS, 0, this->FrameNumber, UNDEFINED_TIMESTAMP, UNDEFINED_TIMESTAMP, &customFields) != PLUS_SUCCESS)
616  {
617  LOG_ERROR("Error adding item to video source " << aSource->GetSourceId());
618  return PLUS_FAIL;
619  }
620  this->Modified();
621 
622  return PLUS_SUCCESS;
623 }
624 
625 //-----------------------------------------------------------------------------
626 PlusStatus vtkPlusIntersonVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
627 {
628  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
629 
630  if (Superclass::ReadConfiguration(deviceConfig) != PLUS_SUCCESS)
631  {
632  if (deviceConfig->GetAttribute("TimeGainCompensationPercent") != NULL)
633  {
634  double tgc[3];
635  deviceConfig->GetVectorAttribute("TimeGainCompensationPercent", 3, tgc);
636  std::vector<double> tgcVec;
637  tgcVec.assign(tgc, tgc + 3);
639  }
640 
641  if (deviceConfig->GetAttribute("Intensity") != NULL)
642  {
643  double intensity;
644  deviceConfig->GetScalarAttribute("Intensity", intensity);
645  this->ImagingParameters->SetIntensity(intensity);
646  }
647 
648  if (deviceConfig->GetAttribute("Contrast") != NULL)
649  {
650  double contrast;
651  deviceConfig->GetScalarAttribute("Contrast", contrast);
652  this->ImagingParameters->SetContrast(contrast);
653  }
654 
655  if (deviceConfig->GetAttribute("DepthMm") != NULL)
656  {
657  double depthMm;
658  deviceConfig->GetScalarAttribute("DepthMm", depthMm);
659  this->ImagingParameters->SetDepthMm(depthMm);
660  }
661 
662  if (deviceConfig->GetAttribute("SoundVelocity") != NULL)
663  {
664  double soundVel;
665  deviceConfig->GetScalarAttribute("SoundVelocity", soundVel);
666  this->ImagingParameters->SetSoundVelocity(soundVel);
667  }
668 
669  if (deviceConfig->GetAttribute("ImageSize") != NULL)
670  {
671  int imageSize[2] = { 0,0 };
672  deviceConfig->GetVectorAttribute("ImageSize", 2, imageSize);
673  this->ImagingParameters->SetImageSize(imageSize[0], imageSize[1], 1);
674  }
675  }
676 
677  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(EnableProbeButtonMonitoring, deviceConfig);
678 
679  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL("Interpolate", this->Internal->Interpolate, deviceConfig);
680  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL("BidirectionalScan", this->Internal->BidirectionalScan, deviceConfig);
681  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "ClockDivider", this->Internal->ClockDivider, deviceConfig);
682  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "PulseFrequencyDivider", this->Internal->PulseFrequencyDivider, deviceConfig);
683  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(double, "LutCenter", this->Internal->LutCenter, deviceConfig);
684  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(double, "LutWindow", this->Internal->LutWindow, deviceConfig);
685 
686  return PLUS_SUCCESS;
687 }
688 
689 //-----------------------------------------------------------------------------
690 PlusStatus vtkPlusIntersonVideoSource::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
691 {
692  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
693 
694  deviceConfig->SetAttribute("EnableProbeButtonMonitoring", this->Internal->EnableProbeButtonMonitoring ? "true" : "false");
695 
696  Superclass::WriteConfiguration(deviceConfig);
697 
698  XML_WRITE_BOOL_ATTRIBUTE(EnableProbeButtonMonitoring, deviceConfig);
699 
700  XML_WRITE_BOOL_ATTRIBUTE_NONMEMBER("Interpolate", this->Internal->Interpolate, deviceConfig);
701  XML_WRITE_BOOL_ATTRIBUTE_NONMEMBER("BidirectionalScan", this->Internal->BidirectionalScan, deviceConfig);
702  deviceConfig->SetIntAttribute("ClockDivider", this->Internal->ClockDivider);
703  deviceConfig->SetIntAttribute("PulseFrequencyDivider", this->Internal->PulseFrequencyDivider);
704  deviceConfig->SetDoubleAttribute("LutCenter", this->Internal->LutCenter);
705  deviceConfig->SetDoubleAttribute("LutWindow", this->Internal->LutWindow);
706 
707  return PLUS_SUCCESS;
708 }
709 
710 //----------------------------------------------------------------------------
712 {
713  if (this->OutputChannels.size() > 1)
714  {
715  LOG_WARNING("vtkPlusIntersonVideoSource is expecting one output channel and there are " << this->OutputChannels.size() << " channels. First output channel will be used.");
716  }
717 
718  if (this->OutputChannels.empty())
719  {
720  LOG_ERROR("No output channels defined for vtkPlusIntersonVideoSource. Cannot proceed.");
721  this->CorrectlyConfigured = false;
722  return PLUS_FAIL;
723  }
724 
726 }
727 
728 //----------------------------------------------------------------------------
730 {
731  if (this->Internal->ProbeHandle == NULL)
732  {
733  LOG_ERROR("vtkPlusIntersonVideoSource::FreezeDevice failed: device not connected");
734  return PLUS_FAIL;
735  }
736  if (!usbHardwareDetected())
737  {
738  LOG_ERROR("Freeze failed, no hardware is detected");
739  return PLUS_FAIL;
740  }
741  this->Internal->Frozen = freeze;
742  if (this->Internal->Frozen)
743  {
744  usbProbe(STOP);
745  }
746  else
747  {
748  usbClearCineBuffers();
749  usbSetProbeFrequency(usbProbeScanFrequency(this->Internal->ProbeHandle));
750  usbProbe(RUN);
751  }
752  return PLUS_SUCCESS;
753 }
754 
755 //----------------------------------------------------------------------------
757 {
758  std::ostringstream versionString;
759  versionString << "Interson Bmode DLL v" << bmDLLVer() << ", USB Probe DLL v" << usbDLLVer() << std::ends;
760  return versionString.str();
761 }
762 
763 //----------------------------------------------------------------------------
765 {
766  if (this->Internal->ProbeHandle == NULL)
767  {
768  LOG_ERROR("vtkPlusIntersonVideoSource::GetSampleFrequencyDevice failed: device not connected");
769  return PLUS_FAIL;
770  }
771  aFreq = usbProbeSampleFrequency(this->Internal->ProbeHandle);
772  LOG_TRACE("Current frequency is " << aFreq);
773  return PLUS_SUCCESS;
774 }
775 
776 //----------------------------------------------------------------------------
778 {
779  if (this->Internal->ProbeHandle == NULL)
780  {
781  LOG_ERROR("vtkPlusIntersonVideoSource::SetWindowDepthDevice failed: device not connected");
782  return PLUS_FAIL;
783  }
784  aVel = usbProbeVelocity(this->Internal->ProbeHandle);
785  this->SetSoundVelocity(aVel);
786  return PLUS_SUCCESS;
787 }
788 
789 //----------------------------------------------------------------------------
791 {
792  if (this->Internal->ProbeHandle == NULL)
793  {
794  LOG_ERROR("vtkPlusIntersonVideoSource::GetProbeVelocityDevice failed: device not connected");
795  return PLUS_FAIL;
796  }
797  aVel = usbProbeVelocity(this->Internal->ProbeHandle);
798  LOG_TRACE("Current velocity is " << aVel);
799  return PLUS_SUCCESS;
800 }
801 
802 //----------------------------------------------------------------------------
804 {
805  if (this->Internal->ProbeHandle == NULL)
806  {
807  LOG_ERROR("vtkPlusIntersonVideoSource::SetWindowDepthDevice failed: device not connected");
808  return PLUS_FAIL;
809  }
810  usbSetWindowDepth(this->Internal->ProbeHandle, height);
811  return PLUS_SUCCESS;
812 }
813 
814 //----------------------------------------------------------------------------
816 {
817  if (this->Internal->ProbeHandle == NULL)
818  {
819  LOG_ERROR("vtkPlusIntersonVideoSource::SetDepthMmDevice failed: device not connected");
820  return PLUS_FAIL;
821  }
822 
823  std::vector<std::pair<double, double>> allowedModes;
824  this->GetProbeAllowedModes(allowedModes);
825  int numberOfAllowedModes = allowedModes.size();
826  std::vector<int> possibleModes;
827  double chosenFrequencyMhz = -1;
828  double chosenDepthCm = -1;
829  for (int i = 0; i < numberOfAllowedModes; i++)
830  {
831  if (allowedModes[i].second == depthMm / 10)
832  {
833  possibleModes.push_back(i);
834  }
835  }
836  if (possibleModes.size() == 1)
837  {
838  chosenFrequencyMhz = allowedModes[possibleModes[0]].first;
839  chosenDepthCm = allowedModes[possibleModes[0]].second;
840  }
841  else if (possibleModes.size() == 0)
842  {
843  chosenDepthCm = 5;
844  double clockDivider = usbClockDivider();
845  double sampleFrequency = usbProbeSampleFrequency(this->Internal->ProbeHandle);
846  double divider = usbPulseFrequency();
847  chosenFrequencyMhz = sampleFrequency / divider;
848  this->Internal->PulseFrequencyDivider = sampleFrequency / chosenFrequencyMhz;
849  LOG_INFO("The probe does not allow the required depth." << chosenDepthCm << " cm depth was chosen instead.");
850  }
851 
852  if ((fabs(chosenDepthCm - 5) < TOLERANCE) || fabs(chosenDepthCm - 10) < TOLERANCE || fabs(chosenDepthCm - 15) < TOLERANCE || fabs(chosenDepthCm - 20) < TOLERANCE)
853  {
854  // select the 30MHz clock
855  usbSet30MHzClock(this->Internal->ProbeHandle);
856  this->Internal->ClockFrequencyMHz = 30;
857  this->Internal->ClockDivider = chosenDepthCm / 5;
858  // set the clock divider for
859  // 1: ~5cm @ 30MHz and 1540m/s velocity
860  // 3: ~15cm @ 30MHz;
861  // 4: ~20cm @ 30MHz
862  }
863  if (fabs(chosenDepthCm - 3) < TOLERANCE || fabs(chosenDepthCm - 6) < TOLERANCE || fabs(chosenDepthCm - 9) < TOLERANCE || fabs(chosenDepthCm - 12) < TOLERANCE)
864  {
865  // select the 48MHz clock
866  usbSet48MHzClock(this->Internal->ProbeHandle);
867  this->Internal->ClockFrequencyMHz = 48;
868  this->Internal->ClockDivider = chosenDepthCm / 3;
869  }
870 
871  this->Internal->PulseFrequencyDivider = this->Internal->ClockFrequencyMHz / chosenFrequencyMhz;
872  usbSetPulseFrequency(this->Internal->PulseFrequencyDivider);
873  usbSetClockDivider(this->Internal->ProbeHandle, this->Internal->ClockDivider);
874  this->SetFrequencyMhz(chosenFrequencyMhz);
875  this->Internal->ClockDivider = usbClockDivider();
876  //pulseFrequency = usbPulseFrequency();
877  this->SetDepthMm(depthMm);
878  return PLUS_SUCCESS;
879 }
880 
881 //----------------------------------------------------------------------------
883 {
884  if (this->Internal->ProbeHandle == NULL)
885  {
886  LOG_ERROR("vtkPlusIntersonVideoSource::SetProbeFrequencyDevice failed: device not connected");
887  return PLUS_FAIL;
888  }
889 
890  this->SetFrequencyMhz(aFreq);
891  usbSetProbeFrequency(aFreq);
892  return PLUS_SUCCESS;
893 }
894 
895 //----------------------------------------------------------------------------
897 {
898  return this->ImagingParameters->SetDepthMm(depthMm);
899 }
900 
901 //----------------------------------------------------------------------------
903 {
904  FrameSizeType frameSize = { imageSize[0], imageSize[1], 1 };
905  return this->ImagingParameters->SetImageSize(frameSize);
906 }
907 
908 //----------------------------------------------------------------------------
910 {
911  return this->Internal->EnableProbeButtonMonitoring;
912 }
913 
914 //----------------------------------------------------------------------------
916 {
917  this->Internal->EnableProbeButtonMonitoring = _arg;
918 }
919 
920 //----------------------------------------------------------------------------
922 {
923  if (this->Internal->ProbeHandle == NULL)
924  {
925  LOG_ERROR("vtkPlusIntersonVideoSource::GetProbeVelocityDevice failed: device not connected");
926  return PLUS_FAIL;
927  }
928 
929  this->ImagingParameters->SetSoundVelocity(value);
930  usbSetVelocity(this->Internal->ProbeHandle, value);
931  return PLUS_SUCCESS;
932 }
933 
934 //----------------------------------------------------------------------------
936 {
937  this->ImagingParameters->SetSoundVelocity(value);
938  return PLUS_SUCCESS;
939 }
940 
941 //----------------------------------------------------------------------------
943 {
944  this->ImagingParameters->SetFrequencyMhz(freq);
945  return PLUS_SUCCESS;
946 }
947 
948 //----------------------------------------------------------------------------
950 {
951  this->ImagingParameters->SetSectorPercent(value);
952  return PLUS_SUCCESS;
953 }
954 
955 //----------------------------------------------------------------------------
957 {
958  this->ImagingParameters->SetIntensity(value);
959  return PLUS_SUCCESS;
960 }
961 
962 //----------------------------------------------------------------------------
964 {
965  this->ImagingParameters->SetContrast(value);
966  return PLUS_SUCCESS;
967 }
968 
969 //----------------------------------------------------------------------------
971 {
972  this->ImagingParameters->SetDynRangeDb(value);
973  return PLUS_SUCCESS;
974 }
975 
976 //----------------------------------------------------------------------------
978 {
979  if (gainPercent[0] < 0 || gainPercent[1] < 0 || gainPercent[2] < 0)
980  {
981  LOG_ERROR("vtkPlusIntersonVideoSource::SetTimeGainCompensationPercent failed: Invalid values sent.")
982  return PLUS_FAIL;
983  }
984 
985  std::vector<double> tgc;
986  tgc.assign(gainPercent, gainPercent + 3);
988  return PLUS_SUCCESS;
989 }
990 
991 //----------------------------------------------------------------------------
993 {
994  if (this->Internal->ProbeHandle == NULL)
995  {
996  LOG_ERROR("vtkPlusIntersonVideoSource::SetTimeGainCompensationPercentDevice failed: device not connected");
997  return PLUS_FAIL;
998  }
999 
1000  if (gainPercent[0] < 0 || gainPercent[1] < 0 || gainPercent[2] < 0)
1001  {
1002  LOG_ERROR("vtkPlusIntersonVideoSource::SetTimeGainCompensationPercentDevice failed: Invalid values sent.");
1003  return PLUS_FAIL;
1004  }
1005  /* The following commented code is useful when using an RF probe with an analog TGC control.
1006  It sets the value, in dB, for the gain at the last sample taken. */
1007  /*
1008  initialGain = usbInitialGain();
1009  midGain = usbMidGain();
1010  farGain = usbFarGain();
1011  usbSetInitialGain(this->InitialGain);
1012  usbSetMidGain(this->MidGain);
1013  usbSetFarGain(this->FarGain);
1014  initialGain = usbInitialGain();
1015  midGain = usbMidGain();
1016  farGain = usbFarGain();
1017  */
1018 
1019  /* If the above code is executed the gain values are changed but it has no effect on the image.
1020  Probably it is because the probe does not have analog TGC control.
1021  The code below sets a linear TGC curve based on three values (initial, middle and end) of the curve.
1022  */
1023 
1024  const double MAX_TGC(512);
1025 
1026  int nearGain = -255 + gainPercent[0] * MAX_TGC / 100;
1027  int midGain = -255 + gainPercent[1] * MAX_TGC / 100;
1028  int farGain = -255 + gainPercent[2] * MAX_TGC / 100;
1029 
1030  this->Internal->CreateLinearTGC(nearGain, midGain, farGain);
1031 
1032  bmTurnOnTGC();
1033 
1034  return PLUS_SUCCESS;
1035 }
1036 
1037 //----------------------------------------------------------------------------
1039 {
1040  this->ImagingParameters->SetZoomFactor(zoomFactor);
1041  return PLUS_SUCCESS;
1042 }
1043 
1044 //----------------------------------------------------------------------------
1046 {
1047  if (this->Internal->ProbeHandle == NULL)
1048  {
1049  LOG_ERROR("vtkPlusIntersonVideoSource::SetDisplayZoomDevice failed: device not connected");
1050  return PLUS_FAIL;
1051  }
1052  this->SetZoomFactor(zoomFactor);
1053  bmSetDisplayZoom(zoomFactor);
1054  LOG_TRACE("New zoom is " << bmDisplayZoom());
1055  return PLUS_SUCCESS;
1056 }
1057 
1058 //----------------------------------------------------------------------------
1060 {
1061  BYTE lut[256];
1062  this->Internal->CreateLUT(lut);
1063  bmCreatebLUT(lut);
1064  this->ImagingParameters->SetIntensity(intensity);
1065  this->ImagingParameters->SetContrast(contrast);
1066  return PLUS_SUCCESS;
1067 }
1068 
1069 //----------------------------------------------------------------------------
1070 PlusStatus vtkPlusIntersonVideoSource::GetProbeAllowedModes(std::vector< std::pair<double, double> >& allowedModes)
1071 {
1072  double clockDivider = usbClockDivider();
1073  double sampleFrequency = usbProbeSampleFrequency(this->Internal->ProbeHandle);
1074  double divider = usbPulseFrequency();
1075  unsigned is24MHz, is15MHz, is12MHz, is8MHz, is7_5MHz, is6MHz, is5MHz, is3_75MHz;
1076  std::pair<double, double> pair;
1077  is24MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P24MHZ;
1078  if (is24MHz & CLKDIV1)
1079  {
1080  // now we know the 24 MHz pulse frequency is good and 3 cm mode is good
1081  LOG_INFO("24 Mhz pulse frequency and 3 cm depth is an allowed mode for this probe");
1082  pair.first = 24;
1083  pair.second = 3;
1084  allowedModes.push_back(pair);
1085  }
1086  if (is24MHz & CLKDIV2)
1087  {
1088  // now we know the 24 MHz pulse frequency is good and 6 cm mode is good
1089  LOG_INFO("24 Mhz pulse frequency and 6 cm depth is an allwoed mode for this probe");
1090  }
1091  if (is24MHz & CLKDIV3)
1092  {
1093  // now we know the 24 MHz pulse frequency is good and 9 cm mode is good
1094  LOG_INFO("24 Mhz pulse frequency and 9 cm depth is an allwoed mode for this probe");
1095  }
1096  if (is24MHz & CLKDIV4)
1097  {
1098  // now we know the 24 MHz pulse frequency is good and 12 cm mode is good
1099  LOG_INFO("24 Mhz pulse frequency and 12 cm depth is an allowed mode for this probe");
1100  }
1101 
1102  is15MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P15MHZ;
1103  if (is15MHz & CLKDIV1)
1104  {
1105  // now we know the 15 MHz pulse frequency is good and 5 cm mode is good
1106  LOG_INFO("15 Mhz pulse frequency and 5 cm depth is an allowed mode for this probe");
1107  }
1108  if (is15MHz & CLKDIV2)
1109  {
1110  // now we know the 15 MHz pulse frequency is good and 10 cm mode is good
1111  LOG_INFO("15 Mhz pulse frequency and 10 cm depth is an allowed mode for this probe");
1112  }
1113  if (is15MHz & CLKDIV3)
1114  {
1115  // now we know the 15 MHz pulse frequency is good and 15 cm mode is good
1116  LOG_INFO("15 Mhz pulse frequency and 15 cm depth is an allowed mode for this probe");
1117  }
1118  if (is15MHz & CLKDIV4)
1119  {
1120  // now we know the 15 MHz pulse frequency is good and 20 cm mode is good
1121  LOG_INFO("15 Mhz pulse frequency and 20 cm depth is an allowed mode for this probe");
1122  }
1123 
1124  is12MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P12MHZ;
1125  if (is12MHz & CLKDIV1)
1126  {
1127  // now we know the 12 MHz pulse frequency is good and 5 cm mode is good
1128  LOG_INFO("12 Mhz pulse frequency and 5 cm depth is an allowed mode for this probe");
1129  }
1130  if (is12MHz & CLKDIV2)
1131  {
1132  // now we know the 12 MHz pulse frequency is good and 10 cm mode is good
1133  LOG_INFO("12 Mhz pulse frequency and 10 cm depth is an allowed mode for this probe");
1134  }
1135  if (is12MHz & CLKDIV3)
1136  {
1137  // now we know the 12 MHz pulse frequency is good and 15 cm mode is good
1138  LOG_INFO("12 Mhz pulse frequency and 15 cm depth is an allowed mode for this probe");
1139  }
1140  if (is12MHz & CLKDIV4)
1141  {
1142  // now we know the 12 MHz pulse frequency is good and 20 cm mode is good
1143  LOG_INFO("12 Mhz pulse frequency and 20 cm depth is an allowed mode for this probe");
1144  }
1145  is8MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P8MHZ;
1146  if (is8MHz & CLKDIV1)
1147  {
1148  // now we know the 8 MHz pulse frequency is good and 3 cm mode is good
1149  LOG_INFO("8 Mhz pulse frequency and 3 cm depth is an allowed mode for this probe");
1150  }
1151  if (is8MHz & CLKDIV2)
1152  {
1153  // now we know the 8 MHz pulse frequency is good and 6 cm mode is good
1154  LOG_INFO("8 Mhz pulse frequency and 6 cm depth is an allowed mode for this probe");
1155  }
1156  if (is8MHz & CLKDIV3)
1157  {
1158  // now we know the 8 MHz pulse frequency is good and 9 cm mode is good
1159  LOG_INFO("8 Mhz pulse frequency and 9 cm depth is an allowed mode for this probe");
1160  }
1161  if (is8MHz & CLKDIV4)
1162  {
1163  // now we know the 8 MHz pulse frequency is good and 12 cm mode is good
1164  LOG_INFO("8 Mhz pulse frequency and 12 cm depth is an allowed mode for this probe");
1165  }
1166  is7_5MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P7_5MHZ;
1167  if (is7_5MHz & CLKDIV1)
1168  {
1169  // now we know the 7.5 MHz pulse frequency is good and 5 cm mode is good
1170  LOG_INFO("7.5 Mhz pulse frequency and 5 cm depth is an allowed mode for this probe");
1171  }
1172  if (is7_5MHz & CLKDIV2)
1173  {
1174  // now we know the 7.5 MHz pulse frequency is good and 10 cm mode is good
1175  LOG_INFO("7.5 Mhz pulse frequency and 10 cm depth is an allowed mode for this probe");
1176  }
1177  if (is7_5MHz & CLKDIV3)
1178  {
1179  // now we know the 7.5 MHz pulse frequency is good and 15 cm mode is good
1180  LOG_INFO("7.5 Mhz pulse frequency and 15 cm depth is an allowed mode for this probe");
1181  }
1182  if (is7_5MHz & CLKDIV4)
1183  {
1184  // now we know the 7.5 MHz pulse frequency is good and 20 cm mode is good
1185  LOG_INFO("7.5 Mhz pulse frequency and 20 cm depth is an allowed mode for this probe");
1186  }
1187  is6MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P6MHZ;
1188  if (is6MHz & CLKDIV1)
1189  {
1190  // now we know the 6 MHz pulse frequency is good and 3 cm mode is good
1191  LOG_INFO("6 Mhz pulse frequency and 3 cm depth is an allowed mode for this probe");
1192  }
1193  if (is6MHz & CLKDIV2)
1194  {
1195  // now we know the 6 MHz pulse frequency is good and 6 cm mode is good
1196  LOG_INFO("6 Mhz pulse frequency and 6 cm depth is an allowed mode for this probe");
1197  }
1198  if (is6MHz & CLKDIV3)
1199  {
1200  // now we know the 6 MHz pulse frequency is good and 9 cm mode is good
1201  LOG_INFO("6 Mhz pulse frequency and 9 cm depth is an allowed mode for this probe");
1202  }
1203  if (is6MHz & CLKDIV4)
1204  {
1205  // now we know the 6 MHz pulse frequency is good and 12 cm mode is good
1206  LOG_INFO("6 Mhz pulse frequency and 12 cm depth is an allowed mode for this probe");
1207  }
1208  is5MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P5MHZ;
1209  if (is5MHz & CLKDIV1)
1210  {
1211  // now we know the 5 MHz pulse frequency is good and 5 cm mode is good
1212  LOG_INFO("5 Mhz pulse frequency and 5 cm depth is an allowed mode for this probe");
1213  }
1214  if (is5MHz & CLKDIV2)
1215  {
1216  // now we know the 5 MHz pulse frequency is good and 10 cm mode is good
1217  LOG_INFO("5 Mhz pulse frequency and 10 cm depth is an allowed mode for this probe");
1218  }
1219  if (is5MHz & CLKDIV3)
1220  {
1221  // now we know the 5 MHz pulse frequency is good and 15 cm mode is good
1222  LOG_INFO("5 Mhz pulse frequency and 15 cm depth is an allowed mode for this probe");
1223  }
1224  if (is5MHz & CLKDIV4)
1225  {
1226  // now we know the 5 MHz pulse frequency is good and 20 cm mode is good
1227  LOG_INFO("5 Mhz pulse frequency and 20 cm depth is an allowed mode for this probe");
1228  }
1229  is3_75MHz = usbProbeAllowedModes(this->Internal->ProbeHandle) & P3_75MHZ;
1230  if (is3_75MHz & CLKDIV1)
1231  {
1232  // now we know the 3.75 MHz pulse frequency is good and 5 cm mode is good
1233  LOG_INFO("3.75 Mhz pulse frequency and 5 cm depth is an allowed mode for this probe");
1234  pair.first = 3.75;
1235  pair.second = 5;
1236  allowedModes.push_back(pair);
1237  }
1238  if (is3_75MHz & CLKDIV2)
1239  {
1240  // now we know the 3.75 MHz pulse frequency is good and 10 cm mode is good
1241  LOG_INFO("3.75 Mhz pulse frequency and 10 cm depth is an allowed mode for this probe");
1242  pair.first = 3.75;
1243  pair.second = 10;
1244  allowedModes.push_back(pair);
1245  }
1246  if (is3_75MHz & CLKDIV3)
1247  {
1248  // now we know the 3.75 MHz pulse frequency is good and 15 cm mode is good
1249  pair.first = 3.75;
1250  pair.second = 15;
1251  allowedModes.push_back(pair);
1252  LOG_INFO("3.75 Mhz pulse frequency and 15 cm depth is an allowed mode for this probe");
1253  }
1254  if (is3_75MHz & CLKDIV4)
1255  {
1256  // now we know the 3.75 MHz pulse frequency is good and 20 cm mode is good
1257  pair.first = 3.75;
1258  pair.second = 20;
1259  allowedModes.push_back(pair);
1260  LOG_INFO("3.75 Mhz pulse frequency and 20 cm depth is an allowed mode for this probe");
1261  }
1262  //allowedModes = usbProbeAllowedModes(this->Internal->ProbeHandle);
1263  //LOG_TRACE("Allowed modes are" << allowedModes);
1264  return PLUS_SUCCESS;
1265 }
1266 
1267 //----------------------------------------------------------------------------
1269 {
1270  if (this->Internal->ProbeHandle == NULL)
1271  {
1272  LOG_ERROR("vtkPlusIntersonVideoSource::GetProbeNameDevice failed: device not connected");
1273  return PLUS_FAIL;
1274  }
1275 
1276  // usbProbeNameString supposed to be able to store the USB probe name
1277  // but if we use that buffer then it leads to stack corruption,
1278  // so we use a much larger buffer (the usbProbeNameString buffer size is 20)
1279  typedef TCHAR usbProbeNameStringSafe[1000];
1280 
1281  usbProbeNameStringSafe probeNameWideStringPtr = { 0 };
1282  usbProbeName(this->Internal->ProbeHandle, probeNameWideStringPtr);
1283 
1284  // Probe name is stored in a wide-character string, convert it to a multi-byte character string
1285  char probeNamePrintable[usbProbeNameMaxLength + 1] = { 0 };
1286  wcstombs(probeNamePrintable, (wchar_t*)probeNameWideStringPtr, usbProbeNameMaxLength);
1287 
1288  probeName = probeNamePrintable;
1289 
1290  return PLUS_SUCCESS;
1291 }
1292 
1293 //----------------------------------------------------------------------------
1295 {
1296  if (Superclass::SetNewImagingParameters(newImagingParameters) != PLUS_SUCCESS)
1297  {
1298  LOG_ERROR("Unable to store incoming parameter set.");
1299  return PLUS_FAIL;
1300  }
1301 
1302  return PLUS_SUCCESS;
1303 }
1304 
1305 //----------------------------------------------------------------------------
1307 {
1308  PlusStatus status = PLUS_SUCCESS;
1309 
1312  {
1314  {
1316  }
1317  else
1318  {
1319  LOG_ERROR("Failed to set depth imaging parameter");
1320  status = PLUS_FAIL;
1321  }
1322  }
1325  {
1327  {
1329  }
1330  else
1331  {
1332  LOG_ERROR("Failed to set frequency imaging parameter");
1333  status = PLUS_FAIL;
1334  }
1335  }
1338  {
1339  std::vector<double> tgcVec;
1341  double tgc[3] = { tgcVec[0], tgcVec[1], tgcVec[2] };
1342 
1344  {
1346  }
1347  else
1348  {
1349  LOG_ERROR("Failed to set time gain compensation parameter");
1350  status = PLUS_FAIL;
1351  }
1352  }
1356  {
1358  {
1361  }
1362  else
1363  {
1364  LOG_ERROR("Failed to set intensity and contrast parameters");
1365  status = PLUS_FAIL;
1366  }
1367  }
1370  {
1372  {
1374  }
1375  else
1376  {
1377  LOG_ERROR("Failed to set zoom parameter");
1378  status = PLUS_FAIL;
1379  }
1380  }
1383  {
1385  {
1387  }
1388  else
1389  {
1390  LOG_ERROR("Failed to set sound velocity parameter");
1391  status = PLUS_FAIL;
1392  }
1393  }
1394  return status;
1395 }
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
PlusStatus SetTimeGainCompensationPercentDevice(double gainPercent[3])
const char int const char const char Phidget_LogLevel level
Definition: phidget22.h:2458
bool IsPending(const std::string &paramName) const
PlusStatus GetSampleFrequencyDevice(double &aFreq)
This class is used to store a configuration of the imaging parameters of an ultrasound video device....
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
PlusStatus SetTimeGainCompensationPercent(double gainPercent[3])
std::string GetSourceId() const
int
Definition: phidget22.h:3069
#define TOLERANCE
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus SetContrast(double aContrast)
PlusStatus GetDepthMm(double &aDepthMm) const
PlusStatus SetZoomFactor(float zoomFactor)
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
PlusStatus SetLookupTableDevice(double intensity, double contrast)
PlusStatus GetSoundVelocity(float &aSoundVelocity) const
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
bool RequireImageOrientationInConfiguration
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
for i
PlusStatus SetSoundVelocity(double value)
double AcquisitionRate
PlusStatus SetPending(const std::string &paramName, bool pending)
virtual PlusStatus AddVideoItemToVideoSources(const std::vector< vtkPlusDataSource * > &videoSources, const igsioVideoFrame &frame, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL) override
virtual PlusStatus SetNewImagingParameters(const vtkPlusUsImagingParameters &newImagingParameters)
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
PlusStatus SetTimeGainCompensation(const std::vector< double > &tgc)
PlusStatus SetImageSize(int imageSize[2])
Initial rotation matrix b
Definition: algo3.m:25
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *)
virtual igsioCommon::VTKScalarPixelType GetPixelType()
virtual PlusStatus Disconnect()
unsigned long DWORD
Definition: ATC3DGm.h:451
PlusStatus GetTimeGainCompensation(std::vector< double > &tgc) const
PlusStatus GetFirstActiveOutputVideoSource(vtkPlusDataSource *&aVideoSource)
int CALLBACK ProbeAttached()
PlusStatus SetWindowDepthDevice(int height)
unsigned long FrameNumber
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
double contrast
Definition: phidget22.h:4297
PlusStatus SetProbeVoltage(float aVoltage)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
PlusStatus GetContrast(double &aContrast) const
virtual PlusStatus StopRecording()
int CALLBACK ProbeDetached()
PlusStatus SetFrequencyMhzDevice(float aFreq)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
PlusStatus SetImageSize(const FrameSizeType &imageSize)
virtual PlusStatus SetNewImagingParameters(const vtkPlusUsImagingParameters &newImagingParameters)
PlusStatus SetDynRangeDb(double aDynRangeDb)
PlusStatus GetSoundVelocity(double &aVel)
PlusStatus SetSectorPercent(double aSectorPercent)
int x
Definition: phidget22.h:4265
vtkStandardNewMacro(vtkPlusIntersonVideoSource)
PlusStatus GetImageSize(FrameSizeType &imageSize) const
PlusStatus GetProbeAllowedModes(std::vector< std::pair< double, double > > &allowedModes)
PlusStatus GetZoomFactor(double &aZoomFactor) const
const char const char * value
Definition: phidget22.h:5111
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
unsigned long ULONG
Definition: ATC3DGm.h:432
PlusStatus GetProbeVoltage(float &aVoltage) const
bool StartThreadForInternalUpdates
PhidgetLCD_Font int int * height
Definition: phidget22.h:4275
virtual PlusStatus InternalApplyImagingParameterChange()
PlusStatus SetIntensity(double aIntensity)
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
#define OEM_ID_INTERSON
ChannelContainer OutputChannels
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
Direction vectors of rods y
Definition: algo3.m:15
PlusStatus SetZoomFactor(double aZoomFactor)
virtual PlusStatus NotifyConfigured()
PlusStatus SetDepthMmDevice(double depthMm)
PlusStatus SetSoundVelocityDevice(double velocity)
PlusStatus GetIntensity(double &aIntensity) const
static LRESULT CALLBACK ImageWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
bool IsSet(const std::string &paramName) const
unsigned char BYTE
Definition: ATC3DGm.h:449
Abstract interface for ultrasound video devices.
PlusStatus GetProbeNameDevice(std::string &probeName)
PlusStatus SetZoomFactorDevice(float zoomFactor)
PlusStatus SetDynRangeDb(double value)
PlusStatus SetSectorPercent(double value)
PlusStatus SetDepthMm(double aDepthMm)
Class for acquiring ultrasound images from Interson USB ultrasound systems.
PlusStatus SetSoundVelocity(float aSoundVelocity)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
PlusStatus GetSoundVelocityDevice(float &aVel)
virtual int GetNumberOfItems()
bool CorrectlyConfigured
PlusStatus SetDepthMm(double depthMm)
Interface to a 3D positioning tool, video source, or generalized data stream.