PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusCapistranoVideoSource.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 #include "PlusConfigure.h"
8 #include "vtkImageData.h"
10 #include "vtkObjectFactory.h"
11 #include "vtkPlusChannel.h"
12 #include "vtkPlusDataSource.h"
13 #include "vtkPlusUSImagingParameters.h"
14 
15 #include "usbprobedll_net.h"
16 #include "BmodeDLL.h"
17 
18 #include <algorithm>
19 #include <PlusMath.h>
20 
22 
23 //----------------------------------------------------------------------------
24 // Define command strings
27 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_SET_BIDIRECTIONAL_MODE = "SetBidirectionalMode";
28 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_GET_BIDIRECTIONAL_MODE = "GetBidirectionalMode";
31 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_SET_JITTER_COMPENSATION = "SetJitterCompensation";
32 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_GET_JITTER_COMPENSATION = "GetJitterCompensation";
39 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_SET_DERIVATIVE_COMPENSATION = "SetDerivativeCompensation";
40 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_GET_DERIVATIVE_COMPENSATION = "GetDerivativeCompensation";
41 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_SET_SAMPLE_FREQUENCY = "SetSampleFrequency";
42 const char* vtkPlusCapistranoVideoSource::CAPISTRANO_GET_SAMPLE_FREQUENCY = "GetSampleFrequency";
47 
48 class vtkPlusCapistranoVideoSource::vtkInternal
49 {
50 public:
51  // ---------------------------------------------------------------------------
52  // Public member variables ---------------------------------------------------
54 
55  HWND ImageWindowHandle;
56  HBITMAP DataHandle;
57  HANDLE ProbeHandle;
58  std::vector<unsigned char> MemoryBitmapBuffer;
59  BITMAP Bitmap;
60  bmBITMAPINFO BitmapInfo;
61  BYTE* RfDataBuffer;
62  static const int samplesPerLine = 2048;
63 
64  /* ! A data structure to include the parameters of Probe's Servo */
65  typedef struct
66  {
67  int JitterComp;
68  int PositionScale;
69  float SweepAngle;
70  int ServoGain;
71  int Overscan;
72  int DerivativeCompensation;
73  } ProbeServo;
74 
75  /* ! A Combined data structure for ProbeParams */
76  typedef struct
77  {
78  ProbeType probetype;
79  ProbeServo probeservo;
80  int Samples;
81  int Filter;
82  bool Amode;
83  bool Preamp;
84  int DisplayOffset;
85  float PulseVoltage;
86  int ProbeID;
87  } ProbeParams;
88 
89  // Current Probe's parameters
90  ProbeParams USProbeParams;
91  // A database of probe's parameters
92  std::map<int, ProbeParams> USProbeParamsDB;
93 
94  // Current Probe's pulser
95  PULSER USProbePulserParams;
96 
97  // A database of probe's pulser
98  std::map<float, PULSER> USProbePulserParamsDB;
99 
100  // ---------------------------------------------------------------------------
101  // Public member functions --------------------------------------------------
103  vtkPlusCapistranoVideoSource::vtkInternal::vtkInternal(vtkPlusCapistranoVideoSource* external)
104  : External(external)
105  , RfDataBuffer(NULL)
106  , ProbeHandle(NULL)
107  {
108  this->CreateUSProbeParamsDB();
109  this->CreateUSProbePulserParamsDB();
110  }
111 
113  virtual vtkPlusCapistranoVideoSource::vtkInternal::~vtkInternal()
114  {
115  this->USProbeParamsDB.clear();
116  this->USProbePulserParamsDB.clear();
117 
118  this->External = NULL;
119  }
120 
121  /* Clear a linear TGC for US B-Mode image */
122  void vtkPlusCapistranoVideoSource::vtkInternal::CreateLinearTGC(int tgcMin, int tgcMax)
123  {
124  int tgc[samplesPerLine] = {0};
125  int b = tgcMin;
126  float m = (float)(tgcMax - tgcMin) / samplesPerLine;
127 
128  for (int x = 0; x < samplesPerLine; x++)
129  {
130  tgc[x] = (int)(m * (float) x) + b;
131  }
132 
133  bmSetTGC(tgc);
134  }
135 
136  /* Clear a linear TGC for US B-Mode image */
137  void vtkPlusCapistranoVideoSource::vtkInternal::CreateLinearTGC(int initialTGC, int midTGC, int farTGC)
138  {
139  /* A linear TGC function is created.
140  The initial point is initialTGC, then is linear until the
141  middle point (midTGC) and then linear until the maximum depth
142  where the compensation is equal to farTGC*/
143 
144  int tgc[samplesPerLine] = {0};
145  double firstSlope = (double)(midTGC - initialTGC) / (samplesPerLine / 2);
146  double secondSlope = (double)(farTGC - midTGC) / (samplesPerLine / 2);
147 
148  for (int x = 0; x < samplesPerLine / 2; x++)
149  {
150  tgc[x] = (int)(firstSlope * (double) x) + initialTGC;
151  tgc[samplesPerLine / 2 + x] = (int)(secondSlope * (double) x) + midTGC;
152  }
153 
154  bmSetTGC(tgc);
155  }
156 
157  /* Clear a Sine TGC for US B-Mode image */
158  void vtkPlusCapistranoVideoSource::vtkInternal::CreateSinTGC(int initialTGC, int midTGC, int farTGC)
159  {
160  /* A sine TGC function is created. */
161  int x, b;
162  float m, tgc, c;
163 
164  int TGC[samplesPerLine] = {0};
165 
166  b = initialTGC;
167  m = (float)(farTGC - initialTGC) / samplesPerLine;
168  c = (float)(midTGC) - (farTGC + initialTGC) / 2.0f;
169 
170  for (x = 0; x < samplesPerLine; x++)
171  {
172  tgc = (m * (float)x) + b;
173  TGC[x] = (int)(tgc + (float)c * std::sin(x * vtkMath::Pi() / samplesPerLine - 1.0f));
174  }
175 
176  bmSetTGC(TGC);
177  }
178 
179  static LRESULT CALLBACK vtkPlusCapistranoVideoSource::vtkInternal::ImageWindowProc(HWND hwnd,
180  UINT iMsg,
181  WPARAM wParam,
182  LPARAM lParam)
183  {
184  vtkPlusCapistranoVideoSource::vtkInternal* self =
185  (vtkPlusCapistranoVideoSource::vtkInternal*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
186  return DefWindowProc(hwnd, iMsg, wParam, lParam) ;
187  }
188 
189  /* Initialize DIB for US B-Mode image */
190  PlusStatus vtkPlusCapistranoVideoSource::vtkInternal::InitializeDIB(FrameSizeType imageSize)
191  {
192  this->BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
193  this->BitmapInfo.bmiHeader.biWidth = imageSize[0];
194  this->BitmapInfo.bmiHeader.biHeight = -static_cast<int>(imageSize[1]);
195  this->BitmapInfo.bmiHeader.biPlanes = 1;
196  this->BitmapInfo.bmiHeader.biBitCount = 8;
197  this->BitmapInfo.bmiHeader.biCompression = 0;
198  this->BitmapInfo.bmiHeader.biXPelsPerMeter = 0;
199  this->BitmapInfo.bmiHeader.biYPelsPerMeter = 0;
200  this->BitmapInfo.bmiHeader.biClrUsed = 0;
201  this->BitmapInfo.bmiHeader.biClrImportant = 0;
202 
203  // Compute the number of bytes in the array of color
204  // indices and store the result in biSizeImage.
205  // The width must be DWORD aligned unless the bitmap is RLE compressed.
206  this->BitmapInfo.bmiHeader.biSizeImage = ((imageSize[0] * 8 + 31) & ~31) / 8 * imageSize[1];
207 
208  for (int i = 0; i < 256; ++i)
209  {
210  this->BitmapInfo.bmiColors[i].rgbRed = i;
211  this->BitmapInfo.bmiColors[i].rgbBlue = i;
212  this->BitmapInfo.bmiColors[i].rgbGreen = i;
213  this->BitmapInfo.bmiColors[i].rgbReserved = 0;
214  }
215 
216  bmSetBitmapInfo(&BitmapInfo);
217  return PLUS_SUCCESS;
218  }
219 
220  /* Clear a linear LUT for US B-Mode image */
221  void CreateLinearLUT(BYTE lut[], int Level, int Window)
222  {
223  int center = Window / 2; // center of window
224  int left = Level - center; // left of window
225  int right = Level + center; // right of window
226 
227  // everything to our left is black
228  for (int x = 0; x < left; x++)
229  {
230  lut[x] = 0;
231  }
232 
233  // everything to our right is white
234  for (int x = right + 1; x < 256; x++)
235  {
236  lut[x] = 255;
237  }
238 
239  // everything in between is on the line
240  float m = 255.0f / ((float) Window);
241 
242  int startX = std::max(0, left);
243  int endX = std::min(right, 255);
244 
245  for (int x = startX; x <= endX; x++)
246  {
247  int y = (int)(m * (float)(x - left) + 0.5f);
248 
249  lut[x] = (BYTE)std::max(0, std::min(y, 255));
250  }
251  }
252 
253  /* Clear an LUT for US B-Mode image */
254  void CreateLUT(BYTE lut[], int Brightness, int Contrast, int Level, int Window)
255  {
256  int center = Window / 2; // center of window
257  int left = Level - center; // left of window
258  int right = Level + center; // right of window
259  for (int x = 0; x <= 255; x++)
260  {
261  int y = (int)((float)Contrast / 256.0f * (float)(x - 128) + Brightness);
262  lut[x] = std::min(255, std::max(y, 0));
263  }
264  }
265 
266  /* Clear BITMAP buffer for US B-Mode image */
267  void vtkPlusCapistranoVideoSource::vtkInternal::ClearBitmap()
268  {
269  bmClearBitmap(this->ImageWindowHandle, this->Bitmap);
270  }
271 
273  void vtkPlusCapistranoVideoSource::vtkInternal::CheckCapistranoUSHW()
274  {
275  if (usbHardwareDetected())
276  {
277  // get handle to hardware probe
278  usbProbeHandle(0, &ProbeHandle);
279  // and be sure it's selected as active rpobe
280  usbSelectProbe(ProbeHandle, 0);
281  }
282  else // no hardware present so use the "user probe"
283  {
284  ProbeHandle = usbUserProbeHandle();
285  usbSelectProbe(ProbeHandle, 0);
286  }
287  }
288 
290  void vtkPlusCapistranoVideoSource::vtkInternal::CreateUSProbeParamsDB()
291  {
292  USProbeParamsDB.clear();
293  ProbeParams pt;
294  // ID : 0 ---------------------------------------------------------------
295  pt.probetype.PFDistance = 20.0f; // pivot to face distance (mm)
296  pt.probetype.FFDistance = 1.0f; // transducer face to probe face distance
297  pt.probetype.Velocity = 1532.0f; // sound velocity (mm/us)
298  pt.probetype.NumVectors = 255; // number of vectors taken
299  pt.Samples = 2048;
300  pt.probetype.PulseFrequency = 35.0f; // current pulse frequency
301  pt.Filter = 22;
302  pt.probetype.SampleFrequency = 80.0f; // in MHz
303  pt.Amode = false;
304  pt.Preamp = false;
305  pt.probetype.DisplayAngle = // display angle from center (rad)
306  vtkMath::RadiansFromDegrees(30.0f / 2.0f);
307  sprintf(pt.probetype.Name, "WP"); // Name of this probe
308  pt.DisplayOffset = 0;
309  pt.PulseVoltage = 100.0f;
310  pt.probetype.OversampleRate = 0.0f; // Amount of oversampling in R
311  pt.probetype.PivFaceSamples = 0.0f; // calculated pivot to face samples
312  pt.probetype.MModeOffset = 0.0f; // Fudge Factor for MMode calibration (unused)
313  pt.probetype.ArcScan = 0; // Is this an ArcScan probe
314  pt.probetype.PFDOffset = 0; // offset added to FPD when delaying sampling
315  pt.probeservo.JitterComp = 25;
316  pt.probeservo.PositionScale = 60;
317  pt.probeservo.SweepAngle = 36.0f;
318  pt.probeservo.ServoGain = 60;
319  pt.probeservo.Overscan = 50;
320  pt.probeservo.DerivativeCompensation = 100;
321  pt.ProbeID = 0; // ProbeID
322  USProbeParamsDB[0] = pt;
323 
324  // ID : 1 ---------------------------------------------------------------
325  pt.probetype.PFDistance = 4.94f; // pivot to face distance (mm)
326  pt.probetype.FFDistance = 3.15; // transducer face to probe face distance
327  pt.probetype.Velocity = 1532.0f; // sound velocity (mm/us)
328  pt.probetype.NumVectors = 255; // number of vectors taken
329  pt.Samples = 2048;
330  pt.probetype.PulseFrequency = 12.0f; // current pulse frequency
331  pt.Filter = 8;
332  pt.probetype.SampleFrequency = 40.0f; // in MHz
333  pt.Amode = false;
334  pt.Preamp = false;
335  pt.probetype.DisplayAngle = // display angle from center (rad)
336  vtkMath::RadiansFromDegrees(60.0f / 2.0f);
337  sprintf(pt.probetype.Name, "OP10"); // Name of this probe
338  pt.DisplayOffset = 128;
339  pt.PulseVoltage = 75.0f;
340  pt.probetype.OversampleRate = 0.0f; // Amount of oversampling in R
341  pt.probetype.PivFaceSamples = 0.0f; // calculated pivot to face samples
342  pt.probetype.MModeOffset = 0.0f; // Fudge Factor for MMode calibration (unused)
343  pt.probetype.ArcScan = 0; // Is this an ArcScan probe
344  pt.probetype.PFDOffset = 0; // offset added to FPD when delaying sampling
345  pt.probeservo.JitterComp = 35;
346  pt.probeservo.PositionScale = 14;
347  pt.probeservo.SweepAngle = 70.0f;
348  pt.probeservo.ServoGain = 70;
349  pt.probeservo.Overscan = 25;
350  pt.probeservo.DerivativeCompensation = 30;
351  pt.ProbeID = 1; // ProbeID
352 
353  USProbeParamsDB[1] = pt;
354 
355  // ID : 2 ---------------------------------------------------------------
356  pt.probetype.PFDistance = 4.94f; // pivot to face distance (mm)
357  pt.probetype.FFDistance = 3.15; // transducer face to probe face distance
358  pt.probetype.Velocity = 1532.0f; // sound velocity (mm/us)
359  pt.probetype.NumVectors = 255; // number of vectors taken
360  pt.Samples = 2048;
361  pt.probetype.PulseFrequency = 16.0f; // current pulse frequency
362  pt.Filter = 8;
363  pt.probetype.SampleFrequency = 40.0f; // in MHz
364  pt.Amode = false;
365  pt.Preamp = false;
366  pt.probetype.DisplayAngle = // display angle from center (rad)
367  vtkMath::RadiansFromDegrees(60.0f / 2.0f);
368  sprintf(pt.probetype.Name, "OP20"); // Name of this probe
369  pt.DisplayOffset = 132;
370  pt.PulseVoltage = 100.0f;
371  pt.probetype.OversampleRate = 0.0f; // Amount of oversampling in R
372  pt.probetype.PivFaceSamples = 0.0f; // calculated pivot to face samples
373  pt.probetype.MModeOffset = 0.0f; // Fudge Factor for MMode calibration (unused)
374  pt.probetype.ArcScan = 0; // Is this an ArcScan probe
375  pt.probetype.PFDOffset = 0; // offset added to FPD when delaying sampling
376  pt.probeservo.JitterComp = 0;
377  pt.probeservo.PositionScale = 14;
378  pt.probeservo.SweepAngle = 72.0f;
379  pt.probeservo.ServoGain = 30;
380  pt.probeservo.Overscan = 25;
381  pt.probeservo.DerivativeCompensation = 20;
382  pt.ProbeID = 2; // ProbeID
383  USProbeParamsDB[2] = pt;
384 
385  // ID : 3 ---------------------------------------------------------------
386  pt.probetype.PFDistance = 4.94f; // pivot to face distance (mm)
387  pt.probetype.FFDistance = 3.15; // transducer face to probe face distance
388  pt.probetype.Velocity = 1532.0f; // sound velocity (mm/us)
389  pt.probetype.NumVectors = 255; // number of vectors taken
390  pt.Samples = 2048;
391  pt.probetype.PulseFrequency = 16.0f; // current pulse frequency
392  pt.Filter = 11;
393  pt.probetype.SampleFrequency = 40.0f; // in MHz
394  pt.Amode = false;
395  pt.Preamp = false;
396  pt.probetype.DisplayAngle = // display angle from center (rad)
397  vtkMath::RadiansFromDegrees(60.0f / 2.0f);
398  sprintf(pt.probetype.Name, "NoProbe"); // Name of this probe
399  pt.DisplayOffset = 0;
400  pt.PulseVoltage = 100.0f;
401  pt.probetype.OversampleRate = 0.0f; // Amount of oversampling in R
402  pt.probetype.PivFaceSamples = 0.0f; // calculated pivot to face samples
403  pt.probetype.MModeOffset = 0.0f; // Fudge Factor for MMode calibration (unused)
404  pt.probetype.ArcScan = 0; // Is this an ArcScan probe
405  pt.probetype.PFDOffset = 0; // offset added to FPD when delaying sampling
406  pt.probeservo.JitterComp = 25;
407  pt.probeservo.PositionScale = 14;
408  pt.probeservo.SweepAngle = 70.0f;
409  pt.probeservo.ServoGain = 40;
410  pt.probeservo.Overscan = 25;
411  pt.probeservo.DerivativeCompensation = 30;
412  pt.ProbeID = 3; // ProbeID
413 
414  USProbeParamsDB[3] = pt;
415  }
416 
418  bool vtkPlusCapistranoVideoSource::vtkInternal::SetUSProbeParamsFromDB(int probeID)
419  {
420  // Searching -----------------------------------------------------------
421  std::map<int, ProbeParams>::iterator it;
422  it = this->USProbeParamsDB.find(probeID);
423  if (it == this->USProbeParamsDB.end())
424  {
425  return false;
426  }
427 
428  // Check Capistrano US Hardware ----------------------------------------
429  CheckCapistranoUSHW();
430 
431  this->USProbeParams = it->second;
432 
433  // Set Capistrano US Probe ---------------------------------------------
434  // Update the sample delay
435  usbSetSampleDelay(this->USProbeParams.probetype.PFDOffset);
436  // Update the number of Scan vectors
437  usbSetProbeVectors(this->USProbeParams.probetype.NumVectors);
438  this->USProbeParams.probetype.NumVectors = usbProbeNumVectors(NULL);
439  // Update the filter
440  switch (this->USProbeParams.Filter)
441  {
442  case 8:
443  usbSetFilter(FILTER_8MHZ);
444  break;
445  case 11:
446  usbSetFilter(FILTER_11MHZ);
447  break;
448  case 15:
449  usbSetFilter(FILTER_15MHZ);
450  break;
451  case 18:
452  usbSetFilter(FILTER_18MHZ);
453  break;
454  default:
455  case 22:
456  usbSetFilter(FILTER_22MHZ);
457  break;
458  case 25:
459  usbSetFilter(FILTER_25MHZ);
460  break;
461  case 0:
462  usbSetFilter(FILTER_OFF);
463  break;
464  }
465  // Update the sample frequency
466  int s = (int)(80 / this->USProbeParams.probetype.SampleFrequency);
467  usbSetSampleClockDivider(s);
468  // set AMode
469  if (this->USProbeParams.Amode)
470  {
471  usbSetAMode(ON);
472  }
473  else
474  {
475  usbSetAMode(OFF);
476  }
477  // Update pulse voltage
478  usbSetPulseVoltage(this->USProbeParams.PulseVoltage);
479  // Update the value of jitter compensation
480  usbSetProbeJitterComp((unsigned char)this->USProbeParams.probeservo.JitterComp);
481  // Update the position scale value for the probe
482  usbSetProbePositionScale((unsigned char)this->USProbeParams.probeservo.PositionScale);
483  // Update the desired probe scan angle
484  //float sweepAngleRadian = vtkMath::RadiansFromDegrees(this->USProbeParams.probeservo.SweepAngle);
485  usbSetProbeAngle(usbProbeAngle());//sweepAngleRadian); //vtkMath::RadiansFromDegrees
486  //usbSetProbeAngle(vtkMath::RadiansFromDegrees(this->USProbeParams.probeservo.SweepAngle)); //vtkMath::RadiansFromDegrees
487 
488  // Update the gain value for the probe
489  usbSetProbeServoGain((unsigned char)this->USProbeParams.probeservo.ServoGain);
490  // Update the display offset value for the probe
491 
492  // unsigned char doffset = (unsigned char)(this->USProbeParams.DisplayOffset & 0xff);
493  // usbSetProbeDisplayOffset(doffset);
494 
495  // Update the desired overscan multiplier
496  int byteTemp = (int)(this->USProbeParams.probeservo.Overscan / 6.25f) - 1;
497  usbSetProbeOverscan(byteTemp);
498  // Update the desired probe servo derivative compensation
499  usbSetProbeDerivComp((unsigned char)this->USProbeParams.probeservo.DerivativeCompensation);
500 
501  return true;
502  }
503 
505  void vtkPlusCapistranoVideoSource::vtkInternal::CreateUSProbePulserParamsDB()
506  {
507  USProbePulserParamsDB.clear();
508  PULSER pulser;
509 
510 #if defined(CAPISTRANO_SDK2013)
511  // Frequency = 10.0f ----------------------------------------------------
512  pulser.MINDelay = 93;
513  pulser.MIDDelay = 94;
514  pulser.MAXDelay = 184;
515 
516  USProbePulserParamsDB[10.0f] = pulser;
517 
518  // Frequency = 12.0f ----------------------------------------------------
519  pulser.MINDelay = 13;
520  pulser.MIDDelay = 13;
521  pulser.MAXDelay = 13;
522 
523  USProbePulserParamsDB[12.0f] = pulser;
524 
525  // Frequency = 16.0f ----------------------------------------------------
526  pulser.MINDelay = 55;
527  pulser.MIDDelay = 56;
528  pulser.MAXDelay = 109;
529 
530  USProbePulserParamsDB[16.0f] = pulser;
531 
532  // Frequency = 18.0f ----------------------------------------------------
533  pulser.MINDelay = 49;
534  pulser.MIDDelay = 50;
535  pulser.MAXDelay = 96;
536 
537  USProbePulserParamsDB[18.0f] = pulser;
538 
539  // Frequency = 20.0f ----------------------------------------------------
540  pulser.MINDelay = 43;
541  pulser.MIDDelay = 44;
542  pulser.MAXDelay = 85;
543 
544  USProbePulserParamsDB[20.0f] = pulser;
545 
546  // Frequency = 25.0f ----------------------------------------------------
547  pulser.MINDelay = 33;
548  pulser.MIDDelay = 34;
549  pulser.MAXDelay = 65;
550 
551  USProbePulserParamsDB[25.0f] = pulser;
552 
553  // Frequency = 30.0f ----------------------------------------------------
554  pulser.MINDelay = 27;
555  pulser.MIDDelay = 28;
556  pulser.MAXDelay = 52;
557 
558  USProbePulserParamsDB[30.0f] = pulser;
559 
560  // Frequency = 35.0f ----------------------------------------------------
561  pulser.MINDelay = 23;
562  pulser.MIDDelay = 24;
563  pulser.MAXDelay = 48;
564 
565  USProbePulserParamsDB[35.0f] = pulser;
566 
567  // Frequency = 45.0f ----------------------------------------------------
568  pulser.MINDelay = 19;
569  pulser.MIDDelay = 20;
570  pulser.MAXDelay = 35;
571 
572  USProbePulserParamsDB[45.0f] = pulser;
573 
574  // Frequency = 50.0f ----------------------------------------------------
575  pulser.MINDelay = 15;
576  pulser.MIDDelay = 16;
577  pulser.MAXDelay = 29;
578 
579  USProbePulserParamsDB[50.0f] = pulser;
580 #else
581  // Frequency = 10.0f ----------------------------------------------------
582  pulser.MINDelay = 10;
583  pulser.MIDDelay = 10;
584  pulser.MAXDelay = 11;
585 
586  USProbePulserParamsDB[10.0f] = pulser;
587 
588  // Frequency = 12.0f ----------------------------------------------------
589  pulser.MINDelay = 8;
590  pulser.MIDDelay = 9;
591  pulser.MAXDelay = 10;
592 
593  USProbePulserParamsDB[12.0f] = pulser;
594 
595  // Frequency = 16.0f ----------------------------------------------------
596  pulser.MINDelay = 6;
597  pulser.MIDDelay = 7;
598  pulser.MAXDelay = 8;
599 
600  USProbePulserParamsDB[16.0f] = pulser;
601 
602  // Frequency = 18.0f ----------------------------------------------------
603  pulser.MINDelay = 5;
604  pulser.MIDDelay = 6;
605  pulser.MAXDelay = 7;
606 
607  USProbePulserParamsDB[18.0f] = pulser;
608 
609  // Frequency = 20.0f ----------------------------------------------------
610  pulser.MINDelay = 4;
611  pulser.MIDDelay = 5;
612  pulser.MAXDelay = 6;
613 
614  USProbePulserParamsDB[20.0f] = pulser;
615 
616  // Frequency = 25.0f ----------------------------------------------------
617  pulser.MINDelay = 3;
618  pulser.MIDDelay = 4;
619  pulser.MAXDelay = 5;
620 
621  USProbePulserParamsDB[25.0f] = pulser;
622 
623  // Frequency = 30.0f ----------------------------------------------------
624  pulser.MINDelay = 2;
625  pulser.MIDDelay = 3;
626  pulser.MAXDelay = 4;
627 
628  USProbePulserParamsDB[30.0f] = pulser;
629 
630  // Frequency = 35.0f ----------------------------------------------------
631  pulser.MINDelay = 2;
632  pulser.MIDDelay = 3;
633  pulser.MAXDelay = 4;
634 
635  USProbePulserParamsDB[35.0f] = pulser;
636 
637  // Frequency = 45.0f ----------------------------------------------------
638  pulser.MINDelay = 1;
639  pulser.MIDDelay = 2;
640  pulser.MAXDelay = 3;
641 
642  USProbePulserParamsDB[45.0f] = pulser;
643 
644  // Frequency = 50.0f ----------------------------------------------------
645  pulser.MINDelay = 1;
646  pulser.MIDDelay = 2;
647  pulser.MAXDelay = 3;
648 
649  USProbePulserParamsDB[50.0f] = pulser;
650 #endif
651  }
652 
654  bool vtkPlusCapistranoVideoSource::vtkInternal::SetUSProbePulserParamsFromDB(float freq)
655  {
657  std::map<float, PULSER>::iterator it;
658  it = this->USProbePulserParamsDB.find(freq);
659  if (it == this->USProbePulserParamsDB.end())
660  {
661  return false;
662  }
663 
664  this->USProbePulserParams = it->second;
666  usbSetPulseFrequency(&this->USProbePulserParams);
667  return true;
668  }
669 
670 };
671 
672 
673 // ----------------------------------------------------------------------------
674 // Global functions -----------------------------------------------------------
675 
677 //int CALLBACK ProbeAttached()
678 //{
679 // LOG_INFO("Probe attached");
680 // return 0;
681 //}
682 
684 //int CALLBACK ProbeDetached()
685 //{
686 // LOG_INFO("Probe detached");
687 // return 0;
688 //}
689 
690 // ----------------------------------------------------------------------------
691 // Public member operators ----------------------------------------------------
692 
693 // ----------------------------------------------------------------------------
694 void vtkPlusCapistranoVideoSource::PrintSelf(ostream& os, vtkIndent indent)
695 {
696  this->Superclass::PrintSelf(os, indent);
697 
698  os << indent << "Frozen: " << Frozen << std::endl;
699  os << indent << "UpdateParameters: " << UpdateParameters << std::endl;
700  os << indent << "BidirectionalMode: " << BidirectionalMode << std::endl;
701  os << indent << "ProbeID: " << ProbeID << std::endl;
702  os << indent << "ClockDivider: " << ClockDivider << std::endl;
703  os << indent << "CineBuffers: " << CineBuffers << std::endl;
704  os << indent << "SampleFrequency: " << SampleFrequency << std::endl;
705  os << indent << "WobbleRate: " << (int)GetWobbleRate() << std::endl;
706  os << indent << "JitterCompensation: " << (int)GetJitterCompensation() << std::endl;
707  os << indent << "PositionScale: " << (int)PositionScale << std::endl;
708  os << indent << "SweepAngle: " << GetSweepAngle() << std::endl;
709  os << indent << "ServoGain: " << (int)GetServoGain() << std::endl;
710  os << indent << "Overscan: " << GetOverscan() << std::endl;
711  os << indent << "DerivativeCompensation: " << (int)GetDerivativeCompensation() << std::endl;
712  os << indent << "Interpolate: " << Interpolate << std::endl;
713  os << indent << "AverageMode: " << AverageMode << std::endl;
714  os << indent << "CurrentBModeViewOption: " << CurrentBModeViewOption << std::endl;
715  os << indent << "LutCenter: " << LutCenter << std::endl;
716  os << indent << "LutWindow: " << LutWindow << std::endl;
717 }
718 
719 // ----------------------------------------------------------------------------
720 PlusStatus vtkPlusCapistranoVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
721 {
722  LOG_TRACE("vtkPlusCapistranoVideoSource::ReadConfiguration");
723  if (!this->Initialized)
724  {
726  {
727  LOG_ERROR("Failed to initialize Capistrano US Probe");
728  }
729  this->Initialized = true;
730  }
731  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
732 
733  // Load US probe parameters -----------------------------------------------
734  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(UpdateParameters, deviceConfig);
735  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(BidirectionalMode, deviceConfig);
736  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, CineBuffers, deviceConfig);
737  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, SampleFrequency, deviceConfig);
738  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, WobbleRate, deviceConfig);
739  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, JitterCompensation, deviceConfig);
740  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, PositionScale, deviceConfig);
741  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, SweepAngle, deviceConfig);
742  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, ServoGain, deviceConfig);
743  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, Overscan, deviceConfig);
744  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, DerivativeCompensation, deviceConfig);
745 
746  // Load US B-mode parameters -----------------------------------------------
747  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(Interpolate, deviceConfig);
748  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(AverageMode, deviceConfig);
749  int bModeViewOption;
750  if (deviceConfig->GetScalarAttribute("CurrentBModeViewOption", bModeViewOption))
751  {
752  this->CurrentBModeViewOption = (unsigned int)bModeViewOption;
753  }
754  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(double, LutCenter, deviceConfig);
755  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(double, LutWindow, deviceConfig);
756 
757  XML_READ_VECTOR_ATTRIBUTE_OPTIONAL(double, 3, CurrentPixelSpacingMm, deviceConfig);
758 
759  this->ImagingParameters->ReadConfiguration(deviceConfig);
760 
761  return PLUS_SUCCESS;
762 }
763 
764 // ----------------------------------------------------------------------------
766 {
767  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
768 
769  deviceConfig->SetAttribute("BidirectionalMode", BidirectionalMode ? "TRUE" : "FALSE");
770  deviceConfig->SetAttribute("UpdateParameters", UpdateParameters ? "TRUE" : "FALSE");
771  deviceConfig->SetIntAttribute("CurrentBModeViewOption", this->CurrentBModeViewOption);
772  deviceConfig->SetIntAttribute("WobbleRate", this->GetWobbleRate());
773  deviceConfig->SetIntAttribute("JitterCompensation", this->GetJitterCompensation());
774  deviceConfig->SetIntAttribute("PositionScale", this->GetPositionScale());
775  deviceConfig->SetFloatAttribute("SweepAngle", this->GetSweepAngle());
776  deviceConfig->SetIntAttribute("ServoGain", this->GetServoGain());
777  deviceConfig->SetIntAttribute("Overscan", this->GetOverscan());
778  deviceConfig->SetIntAttribute("DerivativeCompensation", this->GetDerivativeCompensation());
779  deviceConfig->SetDoubleAttribute("LutCenter", this->LutCenter);
780  deviceConfig->SetDoubleAttribute("LutWindow", this->LutWindow);
781 
782  this->ImagingParameters->WriteConfiguration(deviceConfig);
783 
784  return PLUS_SUCCESS;
785 }
786 
787 // ----------------------------------------------------------------------------
789 {
790  if (this->OutputChannels.size() > 1)
791  {
792  LOG_WARNING("vtkPlusCapistranoVideoSource is expecting one output channel and there are "
793  << this->OutputChannels.size() << " channels. First output channel will be used.");
794  }
795 
796  if (this->OutputChannels.empty())
797  {
798  LOG_ERROR("No output channels defined for vtkPlusCapistranoVideoSource. Cannot proceed.");
799  this->CorrectlyConfigured = false;
800  return PLUS_FAIL;
801  }
802 
803  return PLUS_SUCCESS;
804 }
805 
806 // ----------------------------------------------------------------------------
808 {
809  std::ostringstream versionString;
810  versionString << "Capistrano BmodeUSB DLL v" << bmDLLVer() << ", USBprobe DLL v" << usbDLLVer() << std::ends;
811  return versionString.str();
812 }
813 
814 // ----------------------------------------------------------------------------
816 {
817 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2) || defined(CAPISTRANO_SDK2019) || defined(CAPISTRANO_SDK2018)
818  HardwareVersion = usbHardwareVersion();
819  return PLUS_SUCCESS;
820 #else
821  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
822  return PLUS_FAIL;
823 #endif
824 }
825 
826 // ----------------------------------------------------------------------------
828 {
829 #if defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2) || defined(CAPISTRANO_SDK2019) || defined(CAPISTRANO_SDK2018)
830  HighPassFilter = usbHighPassFilter();
831  return PLUS_SUCCESS;
832 #else
833  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
834  return PLUS_FAIL;
835 #endif
836 }
837 
838 // ----------------------------------------------------------------------------
840 {
841 #ifdef CAPISTRANO_SDK2018
842  LowPassFilter = usbLowPassFilter();
843  return PLUS_SUCCESS;
844 #else
845  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
846  return PLUS_FAIL;
847 #endif
848 }
849 
850 
851 // ------------------------------------------------------------------------
852 // Protected member operators ---------------------------------------------
853 
854 // ----------------------------------------------------------------------------
856  : Frozen(true)
857  , Internal(new vtkInternal(this))
858 {
860 
861  this->UpdateParameters = true;
862 
863  // Initialize US probe parameters ----------------------------------------
864  this->MISMode = false;
865  this->PulsePeriod = 0;
866  this->HardwareVersion = 0;
867  this->HighPassFilter = 0;
868  this->LowPassFilter = 0;
869  this->BidirectionalMode = false;
870  this->ProbeID = 0;
871  this->ClockDivider = 2; //1
872  this->CineBuffers = 32;
873  this->SampleFrequency = 40.0f;
874  this->PositionScale = 0; // no function to read it from the SDK, has to be specified
875  this->ImagingParameters->SetFrequencyMhz(12.0f);
876  this->ImagingParameters->SetProbeVoltage(30.0f);
877  this->ImagingParameters->SetSoundVelocity(1532.0f);
878  this->ImagingParameters->SetDepthMm(36); // mm
879 
880  // Initialize US B-Mode parameters ------------------------------------------
881  this->Interpolate = true;
882  this->AverageMode = true;
883  this->CurrentBModeViewOption = STANDARDVIEW;
884  FrameSizeType imageSize = {640, 800, 1};
885  this->ImagingParameters->SetImageSize(imageSize);
886  this->ImagingParameters->SetIntensity(128);
887  this->ImagingParameters->SetContrast(256);
888  this->ImagingParameters->SetZoomFactor(1.0);
889  double tgc[3] = {-128, -128, -128};
891  this->LutCenter = 128; //192
892  this->LutWindow = 256; //128
893 
894  // No callback function provided by the device,
895  // so the data capture thread will be used
896  // to poll the hardware and add new items to the buffer
897  this->StartThreadForInternalUpdates = true;
898  this->AcquisitionRate = 5;
899  this->CurrentPixelSpacingMm[0] = 1.0;
900  this->CurrentPixelSpacingMm[1] = 1.0;
901  this->CurrentPixelSpacingMm[2] = 1.0;
902 
903  // Initialize the rest of standard Plus imaging parameters, which are ignored in Capistrano's implementation
904  // This is to avoid errors in vtkPlusGetUsParameterCommand::Execute()
907  this->ImagingParameters->SetGainPercent(100);
908  this->ImagingParameters->SetPowerDb(0.0);
909  this->ImagingParameters->SetDynRangeDb(100);
910 }
911 
912 // ----------------------------------------------------------------------------
914 {
915  if (!this->Connected)
916  {
917  this->Disconnect();
918  }
919 
920  delete this->Internal;
921  this->Internal = NULL;
922 }
923 
924 // ----------------------------------------------------------------------------
926 {
927 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2) || defined(CAPISTRANO_SDK2019) || defined(CAPISTRANO_SDK2018)
928  int numberOfAttachedBoards = usbNumberAttachedBoards();
929 #else //cSDK2013 or cSDK2016
930  int numberOfAttachedBoards = usbNumberAttachedProbes();
931 #endif
932  LOG_DEBUG("Number of attached boards: " << numberOfAttachedBoards);
933  return numberOfAttachedBoards > 0;
934 }
935 
936 // Initialize Capistrano US Probe ---------------------------------------------
937 
938 // ----------------------------------------------------------------------------
940 {
941  // Before any probe can be initialized with usbInitializeProbes,
942  // they must be detected. usbFindProbes()
943  // will detect all attached probes and initialize the driver.
944  // After a successful call to usbFindProbes, other probe-related functions may be called.
945  // These include: usbInitializeProbes, usbProbeHandle, usbSelectProbe.
946  usbErrorString errorStatus = {0};
947 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3)
948  wchar_t* appData = _wgetenv(L"APPDATA");
949  std::wstring path = appData + std::wstring(L"\\CLI");
950  wchar_t* filename_uni = L"debug.txt";
951  usbUseFileNamePath((LPTSTR)filename_uni, (LPTSTR)path.c_str());
952 #endif
953  ULONG status = usbFindProbes(errorStatus);
954  LOG_DEBUG("Find USB probes: status=" << status << ", details: " << errorStatus);
955  if (status != ERROR_SUCCESS)
956  {
957  LOG_ERROR("Capistrano finding probes failed");
958  return PLUS_FAIL;
959  }
960 
961  // Setup Callback functions ----------------------------------------------
962  //usbSetProbeAttachCallback(&ProbeAttached);
963  //usbSetProbeDetachCallback(&ProbeDetached);
964 
965  // Check updateUSProbeParameters -----------------------------------------
966  if (usbSetCineBuffers(this->CineBuffers) != this->CineBuffers)
967  {
968  LOG_ERROR("Could not allocate Cine buffers.");
969  return PLUS_FAIL;
970  }
971 
972  // Setup Capistrano US Probe ---------------------------------------------
973  double startTime = vtkIGSIOAccurateTimer::GetSystemTime();
974  while (!this->IsBoardAttached() && (vtkIGSIOAccurateTimer::GetSystemTime() - startTime < 5))
975  {
976  // With the cSDK2023 drivers, if the device is connected by USB and power cycled it will be observed in Windows Device Manager as
977  // "Capistrano Labs USBIAB Firmware Loader". Upon establishing a connection to the device, "Device found: Uploading Firmware"
978  // message will be observed followed by a "Downloaded firmware" message as output by the device API. The device then needs time to
979  // re-enumerate and be discovered as a "Capistrano Labs USBIAB Ultrasound Probe" device in Windows Device Manager.
980  // The enumeration should be successful within the specified timeout period of 5 seconds.
981  continue;
982  }
983  if (this->SetupProbe(0) == PLUS_FAIL)
984  {
985  LOG_ERROR("Failed to setup Capistrano US Probe");
986  return PLUS_FAIL;
987  }
988 
989  return PLUS_SUCCESS;
990 }
991 
992 // ----------------------------------------------------------------------------
994 {
995  FrameSizeType imageSize = this->ImagingParameters->GetImageSize();
996 
997  // Get ProbeID of an attached Capistrano US Probe ------------------------
998  this->ProbeID = usbAttachedProbeID();
999  LOG_DEBUG("Probe ID =" << ProbeID);
1000 
1001  if (this->ProbeID == 255) // no probe attached
1002  {
1003  this->ProbeID = 1;
1004  LOG_ERROR("Capistrano finding probes failed");
1005  return PLUS_FAIL;
1006  }
1007 
1008  // Check How many US boards are connected. --------------------------------
1009 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2) || defined(CAPISTRANO_SDK2019) || defined(CAPISTRANO_SDK2018)
1010  int numberOfAttachedBoards = usbNumberAttachedBoards();
1011 #else //cSDK2013 or cSDK2016
1012  int numberOfAttachedBoards = usbNumberAttachedProbes();
1013 #endif
1014  LOG_DEBUG("Number of attached boards: " << numberOfAttachedBoards);
1015  if (numberOfAttachedBoards == 0)
1016  {
1017  LOG_ERROR("No Capistrano boards are attached");
1018  return PLUS_FAIL;
1019  }
1020  if (numberOfAttachedBoards > 1)
1021  {
1022  LOG_WARNING("Multiple Capistrano boards are attached, using the first one");
1023  }
1024 
1025  // Set US Probe directional mode -----------------------------------------
1026  usbSetUnidirectionalMode();
1027 
1028  // Turn on USB data synchronization checking ------------------------------
1029  usbTurnOnSync();
1030 
1031  // Read probe parameters from the DB
1032  // Update Probe structure with the detected ProbeID ----------------------
1033  this->Internal->SetUSProbeParamsFromDB(this->ProbeID);
1034 
1035  // Update pulserParams structure with the PulseFrequency of
1036  // the Updated Probe structure -------------------------------------------
1037  this->Internal->SetUSProbePulserParamsFromDB(
1038  this->Internal->USProbeParams.probetype.PulseFrequency);
1039 
1040  // Update the values of ProbeType structure -------------------------------
1041  Internal->USProbeParams.probetype.OversampleRate = 2048.0f / imageSize[1];
1042  Internal->USProbeParams.probetype.SampleFrequency = 80.f / usbSampleClockDivider();
1043  Internal->USProbeParams.probetype.PivFaceSamples =
1044  Internal->USProbeParams.probetype.PFDistance *
1045  1000.0f * Internal->USProbeParams.probetype.SampleFrequency
1046  / (0.5f * Internal->USProbeParams.probetype.Velocity);
1047 
1048  return PLUS_SUCCESS;
1049 }
1050 
1051 // ----------------------------------------------------------------------------
1053 {
1054  FrameSizeType imageSize = this->ImagingParameters->GetImageSize();
1055 
1056  // Initialize Display -----------------------------------------------------
1057  HANDLE display = bmInitializeDisplay(imageSize[0] * imageSize[1], 0);
1058  if (display == NULL)
1059  {
1060  LOG_ERROR("Could not initialize the display");
1061  return PLUS_FAIL;
1062  }
1063 
1064  // Initialize DIB -----------------------------------------------------------
1065  this->Internal->InitializeDIB(imageSize);
1066 
1067  // Initialize vtkPlusDataSource ---------------------------------------------
1068  vtkPlusDataSource* aSource = NULL;
1069 
1070  if (this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS)
1071  {
1072  LOG_ERROR("Unable to retrieve the video source in the CapistranoVideo device.");
1073  return PLUS_FAIL;
1074  }
1075 
1076  // Create Window Handle -----------------------------------------------------
1077  HINSTANCE hInst = GetModuleHandle(NULL);
1078 
1079  WNDCLASSEX wndclass = {};
1080  wndclass.cbSize = sizeof(wndclass);
1081  wndclass.style = CS_CLASSDC;
1083  wndclass.cbClsExtra = 0;
1084  wndclass.cbWndExtra = 0;
1085  wndclass.hInstance = hInst;
1086  wndclass.hIcon = NULL;
1087  wndclass.hCursor = NULL;
1088  wndclass.hbrBackground = NULL;
1089  wndclass.lpszMenuName = NULL ;
1090  wndclass.lpszClassName = TEXT("ImageWindow");
1091  wndclass.hIconSm = NULL;
1092  RegisterClassEx(&wndclass);
1093 
1094  if (this->Internal->ImageWindowHandle != NULL)
1095  {
1096  bool b = DestroyWindow(this->Internal->ImageWindowHandle);
1097  }
1098 
1099  this->Internal->ImageWindowHandle =
1100  CreateWindow(TEXT("ImageWindow"), TEXT("Ultrasound"),
1101  WS_OVERLAPPEDWINDOW,
1102  0, 0,
1103  static_cast<int>(imageSize[0]),
1104  static_cast<int>(imageSize[1]),
1105  NULL, NULL, hInst, NULL);
1106 
1107  if (this->Internal->ImageWindowHandle == NULL)
1108  {
1109  LOG_ERROR("Failed to create capture window");
1110  return PLUS_FAIL;
1111  }
1112 
1113  // Create a bitmap for use in our DIB ---------------------------------------
1114  HDC hdc = GetDC(this->Internal->ImageWindowHandle) ;
1115  RECT rect;
1116  GetClientRect(this->Internal->ImageWindowHandle, &rect) ;
1117  int cx = static_cast<int>(imageSize[0]);//rect.right - rect.left;
1118  int cy = static_cast<int>(imageSize[1]);//rect.bottom - rect.top;
1119  this->Internal->DataHandle = CreateCompatibleBitmap(hdc, cx, cy);
1120  GetObject(this->Internal->DataHandle, sizeof(BITMAP), (LPVOID) &this->Internal->Bitmap) ;
1121 
1122  // zero indexed window including borders
1123  this->Internal->MemoryBitmapBuffer.resize(imageSize[0]*imageSize[1], 0);
1124  this->Internal->Bitmap.bmBits = &this->Internal->MemoryBitmapBuffer[0];
1125 
1126  return PLUS_SUCCESS;
1127 }
1128 
1129 // ----------------------------------------------------------------------------
1131 {
1132  BYTE lut[256];
1133  double intensity = this->ImagingParameters->GetIntensity();
1134  double contrast = this->ImagingParameters->GetContrast();
1135 
1136  this->Internal->CreateLUT(lut, intensity, contrast,
1137  this->LutCenter, this->LutWindow);
1138 
1139  bmCreatebLUT(lut);
1140 
1141  return PLUS_SUCCESS;
1142 }
1143 
1144 // ----------------------------------------------------------------------------
1146 {
1147  std::vector<double> tgcVec;
1148  tgcVec = this->ImagingParameters->GetTimeGainCompensation();
1149  double gain[3] = {tgcVec[0], tgcVec[1], tgcVec[2]};
1150 
1151  if (gain[0] >= 0 && gain[1] >= 0 && gain[2] >= 0)
1152  {
1153  this->SetGainPercentDevice(gain);
1154  }
1155 
1156  return PLUS_SUCCESS;
1157 }
1158 
1159 // Device-specific functions --------------------------------------------------
1160 
1162 {
1163  // Initialize vtkPlusDataSource ---------------------------------------------
1164  vtkPlusDataSource* aSource = NULL;
1165 
1166  if (this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS)
1167  {
1168  LOG_ERROR("Unable to retrieve the video source in the CapistranoVideo device.");
1169  return PLUS_FAIL;
1170  }
1171 
1172  // Clear buffer on connect because the new frames that we will
1173  // acquire might have a different size
1174  aSource->Clear();
1175  FrameSizeType frameSizeInPx = this->ImagingParameters->GetImageSize();
1176  //aSource->SetInputImageOrientation(US_IMG_ORIENT_NU);
1177  aSource->SetImageType(US_IMG_BRIGHTNESS);
1178  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
1179  aSource->SetInputFrameSize(frameSizeInPx[0], frameSizeInPx[1], 1);// frameSizeInPx[2]);
1180 
1181  // Initialize display ----------------------------------------------------
1183  {
1184  LOG_ERROR("Failed to initialize Image Window");
1185  return PLUS_FAIL;
1186  }
1187 
1188  // Initialize Capistrano US Probe ----------------------------------------
1189  if (!this->Initialized)
1190  {
1192  {
1193  LOG_ERROR("Failed to initialize Capistrano US Probe");
1194  }
1195  this->Initialized = true;
1196  }
1197 
1198  // Update US parameters --------------------------------------------------
1199  if (this->UpdateParameters)
1200  {
1201  if (this->UpdateUSProbeParameters() == PLUS_FAIL)
1202  {
1203  LOG_ERROR("Failed to UpdateUSProbeParameters");
1204  return PLUS_FAIL;
1205  }
1206 
1207  if (this->UpdateUSBModeParameters() == PLUS_FAIL)
1208  {
1209  LOG_ERROR("Failed to UpdateUSBModeParameters");
1210  return PLUS_FAIL;
1211  }
1212  }
1213  else
1214  {
1215  // Initialize the gain and lut now that we have our default values ---
1216  this->InitializeLUT();
1217  this->InitializeTGC();
1218 
1219  // Update the scan depth of B-Mode Image -----------------------------
1220  if (this->UpdateDepthMode(this->ClockDivider) == PLUS_FAIL)
1221  {
1222  LOG_ERROR("Failed to update Depth Mode");
1223  return PLUS_FAIL;
1224  }
1225 
1226  }
1227 
1228  // Check the connection of the Capistrano US Hardware --------------------
1229  if (!usbHardwareDetected())
1230  {
1231  LOG_ERROR("No Capistrano US Hardware");
1232  return PLUS_FAIL;
1233  }
1234 
1235  usbSetUnidirectionalMode();
1236  usbSetPulseVoltage(this->ImagingParameters->GetProbeVoltage());
1237 
1238  // Set the Size of CineBuffer -----------------------------------------------
1239  // Setup the display offsets now that we have the probe and DISPLAY data
1240  bmSetDisplayOffset(0);
1241 
1242  this->Internal->RfDataBuffer = usbCurrentCineFrame();
1243  bmClearBitmap(this->Internal->ImageWindowHandle, this->Internal->Bitmap);
1244 
1245  // Set the sample Delay -----------------------------------------------------
1246  usbSetSampleDelay(1);
1247 
1248  // DEBUG LOG : Get the name of a current probe
1249  std::string probeName;
1250  GetProbeNameDevice(probeName);
1251  LOG_DEBUG("Capistrano probe name: " << probeName << ", ID: " << usbProbeID(this->Internal->ProbeHandle));
1252 
1253  // Initialize Custom Field of this data source
1254  this->CustomFields.clear();
1255  std::ostringstream spacingStream;
1256  unsigned int numSpaceDimensions = 3;
1257  for (unsigned int i = 0; i < numSpaceDimensions ; ++i)
1258  {
1259  spacingStream << this->CurrentPixelSpacingMm[i];
1260  if (i != numSpaceDimensions - 1)
1261  {
1262  spacingStream << " ";
1263  }
1264  }
1265  this->CustomFields["ElementSpacing"].first = FRAMEFIELD_FORCE_SERVER_SEND;
1266  this->CustomFields["ElementSpacing"].second = spacingStream.str();
1267 
1268  return PLUS_SUCCESS;
1269 }
1270 
1271 // ----------------------------------------------------------------------------
1273 {
1274  LOG_TRACE("vtkPlusCapistranoVideoSource::InternalConnect");
1275  LOG_DEBUG("Capistrano Bmode DLL version " << bmDLLVer() << ", USB probe DLL version " << usbDLLVer());
1276 
1278  {
1279  return PLUS_FAIL;
1280  }
1281  // some parameters might have changed while we were disconnected
1282  this->Connected = true;
1283  return this->InternalApplyImagingParameterChange();
1284 }
1285 
1286 // ----------------------------------------------------------------------------
1288 {
1289  LOG_DEBUG("Disconnect from Capistrano");
1290 
1291  FreezeDevice(true);
1292  bmCloseDisplay();
1293 
1294  return PLUS_SUCCESS;
1295 }
1296 
1297 // ----------------------------------------------------------------------------
1299 {
1300  FreezeDevice(false);
1301  return PLUS_SUCCESS;
1302 }
1303 
1304 // ----------------------------------------------------------------------------
1306 {
1307  FreezeDevice(true);
1308  return PLUS_SUCCESS;
1309 }
1310 
1311 // ----------------------------------------------------------------------------
1313 {
1314  if (!this->Recording)
1315  {
1316  // drop the frame, we are not recording data now
1317  return PLUS_SUCCESS;
1318  }
1319 
1320  WaitForFrame();
1321 
1322  this->FrameNumber = usbCineFrameNumber();
1323 
1324  this->Internal->RfDataBuffer = usbCurrentCineFrame();
1325 
1326  this->Internal->DataHandle = bmDrawImage(this->Internal->ImageWindowHandle,
1327  this->Internal->RfDataBuffer,
1328  this->Internal->Bitmap,
1329  true, FALSE,
1330  NULL, bmDI_DRAW, 0, TRUE);
1331 
1332  GetObject(this->Internal->DataHandle, sizeof(BITMAP), &this->Internal->Bitmap);
1333 
1334  vtkPlusDataSource* aSource = NULL;
1335  RETURN_WITH_FAIL_IF(this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS,
1336  "Unable to retrieve the video source in the Capistrano device.");
1337 
1338  FrameSizeType frameSizeInPx = this->ImagingParameters->GetImageSize();
1339 
1340  // If the buffer is empty, set the pixel type and frame size
1341  // to the first received properties
1342  if (aSource->GetNumberOfItems() == 0)
1343  {
1344  LOG_DEBUG("Set up image buffer for Capistrano");
1345  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
1346  aSource->SetImageType(US_IMG_BRIGHTNESS);
1347  aSource->SetInputFrameSize(frameSizeInPx);
1348 
1349  float depthScale = -1;
1350  usbProbeDepthScale(this->Internal->ProbeHandle, &depthScale);
1351 
1352  std::string probeName;
1353  GetProbeNameDevice(probeName);
1354 
1355  LOG_INFO("Frame size: " << frameSizeInPx[0] << "x" << frameSizeInPx[1]
1356  << ", pixel type: " << vtkImageScalarTypeNameMacro(aSource->GetPixelType())
1357  << ", probe sample frequency (Hz): " << this->Internal->USProbeParams.probetype.SampleFrequency
1358  << ", probe name: " << probeName
1359  << ", display zoom: " << bmDisplayZoom()
1360  << ", probe depth scale (mm/sample):" << depthScale
1361  << ", buffer image orientation: "
1362  << igsioCommon::GetStringFromUsImageOrientation(aSource->GetInputImageOrientation()));
1363  }
1364 
1365  //igsioTrackedFrame::FieldMapType customFields;
1366  const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
1367 
1368  if (this->MISMode)
1369  {
1370  switch (usbWriteSpecialFunction(0x6d697303, 0))
1371  {
1372  // NOTE: One should always check this and not assume the frames alternate.
1373  // While alternating is normal, if a probe is dropped, bumped or some related event happens,
1374  // a frame could be missed but this will self correct if the function to check is used.
1375  case 0: // B-Mode image
1376  // drop the frame
1377  return PLUS_SUCCESS;
1378  case 1: // MIS image
1379  break;
1380  }
1381  }
1382 
1383  RETURN_WITH_FAIL_IF(aSource->AddItem((void*)this->Internal->Bitmap.bmBits,
1384  aSource->GetInputImageOrientation(),
1385  frameSizeInPx, VTK_UNSIGNED_CHAR,
1386  1, US_IMG_BRIGHTNESS, 0,
1387  this->FrameNumber,
1388  unfilteredTimestamp,
1389  unfilteredTimestamp,
1390  &this->CustomFields
1391  ) != PLUS_SUCCESS,
1392  "Error adding item to video source " << aSource->GetSourceId());
1393 
1394  this->Modified();
1395 
1396  return PLUS_SUCCESS;
1397 }
1398 
1399 // ----------------------------------------------------------------------------
1401 {
1402  RETURN_WITH_FAIL_IF(this->Internal->ProbeHandle == NULL,
1403  "vtkPlusCapistranoVideoSource::FreezeDevice failed: device not connected");
1404  RETURN_WITH_FAIL_IF(!usbHardwareDetected(),
1405  "Freeze failed, no hardware is detected");
1406 
1407  if (this->Frozen == freeze) //already in desired mode
1408  {
1409  return PLUS_SUCCESS;
1410  }
1411 
1412  this->Frozen = freeze;
1413  if (this->Frozen)
1414  {
1415  usbProbe(STOP);
1416  }
1417  else
1418  {
1419  usbClearCineBuffers();
1420  this->FrameNumber = 0;
1421  RETURN_WITH_FAIL_IF(this->UpdateUSParameters() == PLUS_FAIL,
1422  "Failed to update US parameters");
1423  usbProbe(RUN);
1424  }
1425 
1426  return PLUS_SUCCESS;
1427 }
1428 
1429 // ----------------------------------------------------------------------------
1431 {
1432  return Frozen;
1433 }
1434 
1435 // ----------------------------------------------------------------------------
1437 {
1438  bool nextFrameReady = (usbWaitFrame() == 1);
1439  DWORD usbErrorCode = usbError();
1440 
1441  if (this->Frozen)
1442  {
1443  return PLUS_SUCCESS;
1444  }
1445 
1446  static bool messagePrinted = false;
1447 
1448  switch (usbErrorCode)
1449  {
1450  case USB_SUCCESS:
1451  messagePrinted = false;
1452  break;
1453  case USB_FAILED:
1454  if (!messagePrinted)
1455  {
1456  LOG_ERROR("USB: FAILURE. Probe was removed?");
1457  messagePrinted = true;
1458  }
1459  return PLUS_FAIL;
1460  case USB_TIMEOUT2A:
1461  case USB_TIMEOUT2B:
1462  case USB_TIMEOUT6A:
1463  case USB_TIMEOUT6B:
1464  if (nextFrameReady) // timeout is fine if we're in synchronized mode, so only log error if next frame is ready
1465  {
1466  LOG_WARNING("USB timeout");
1467  }
1468  break;
1469  case USB_NOTSEQ:
1470  if (!messagePrinted)
1471  {
1472  LOG_ERROR("Lost Probe Synchronization. Please check probe cables and restart.");
1473  messagePrinted = true;
1474  }
1475  FreezeDevice(true);
1476  FreezeDevice(false);
1477  break;
1478  case USB_STOPPED:
1479  if (!messagePrinted)
1480  {
1481  LOG_ERROR("USB: Stopped. Check probe and restart.");
1482  messagePrinted = true;
1483  }
1484  break;
1485  default:
1486  if (!messagePrinted)
1487  {
1488  LOG_ERROR("USB: Unknown USB error: " << usbErrorCode);
1489  messagePrinted = true;
1490  }
1491  FreezeDevice(true);
1492  FreezeDevice(false);
1493  break;
1494  }
1495 
1496  return PLUS_SUCCESS;
1497 }
1498 
1499 // Setup US Probe parameters --------------------------------------------------
1500 
1501 // ----------------------------------------------------------------------------
1503 {
1504  this->UpdateParameters = b;
1505  return PLUS_SUCCESS;
1506 }
1507 
1508 // ----------------------------------------------------------------------------
1510 {
1511 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2)
1512  this->MISMode = mode;
1513  usbWriteSpecialFunction(0x6d697300, mode);
1514  this->BidirectionalMode = mode;
1515  return PLUS_SUCCESS;
1516 #else
1517  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
1518  return PLUS_FAIL;
1519 #endif
1520 }
1521 // ----------------------------------------------------------------------------
1523 {
1524 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2)
1525  MISMode = this->MISMode;
1526  return PLUS_SUCCESS;
1527 #else
1528  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
1529  return PLUS_FAIL;
1530 #endif
1531 }
1532 
1533 // ----------------------------------------------------------------------------
1535 {
1536 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2)
1537  usbWriteSpecialFunction(0x6d697301, val);
1538  return PLUS_SUCCESS;
1539 #else
1540  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
1541  return PLUS_FAIL;
1542 #endif
1543 }
1544 // ----------------------------------------------------------------------------
1546 {
1547 #if defined(CAPISTRANO_SDK2023) || defined(CAPISTRANO_SDK2019_3) || defined(CAPISTRANO_SDK2019_2)
1548  PulsePeriod = usbWriteSpecialFunction(0x6d697302, 0);
1549  return PLUS_SUCCESS;
1550 #else
1551  LOG_ERROR("This method is not supported with this version of Capistrano SDK.");
1552  return PLUS_FAIL;
1553 #endif
1554 }
1555 
1556 // ----------------------------------------------------------------------------
1558 {
1559  if (mode != this->BidirectionalMode)
1560  {
1561  this->BidirectionalMode = mode;
1562  if (this->Connected && !this->MISMode) // One should not return to unidirectional mode while MIS mode is on.
1563  {
1564  if (mode)
1565  {
1566  usbSetBidirectionalMode();
1567  }
1568  else
1569  {
1570  usbSetUnidirectionalMode();
1571  }
1572  }
1573  }
1574  return PLUS_SUCCESS;
1575 }
1576 
1577 // ----------------------------------------------------------------------------
1579 {
1580  return this->BidirectionalMode;
1581 }
1582 
1583 // ----------------------------------------------------------------------------
1585 {
1586  this->CineBuffers = cinebuffer;
1587  return PLUS_SUCCESS;
1588 }
1589 
1590 // ----------------------------------------------------------------------------
1592 {
1593  this->SampleFrequency = sf;
1594  return PLUS_SUCCESS;
1595 }
1596 
1597 // ----------------------------------------------------------------------------
1599 {
1600  if (this->Internal->SetUSProbePulserParamsFromDB(pf)) // this frequency is supported
1601  {
1603  }
1604  return PLUS_SUCCESS;
1605 }
1606 
1607 // ----------------------------------------------------------------------------
1609 {
1610  usbSetProbeSpeed(wr);
1611  return PLUS_SUCCESS;
1612 }
1613 
1615 {
1616  return usbProbeSpeed();
1617 }
1618 
1619 // ----------------------------------------------------------------------------
1621 {
1622  usbSetProbeJitterComp(jitterComp);
1623  return PLUS_SUCCESS;
1624 }
1625 
1627 {
1628  return usbProbeJitterComp();
1629 }
1630 
1631 // ----------------------------------------------------------------------------
1633 {
1634  this->PositionScale = scale;
1635  usbSetProbePositionScale(scale);
1636  return PLUS_SUCCESS;
1637 }
1638 
1640 {
1641  return this->PositionScale;
1642 }
1643 
1644 // ----------------------------------------------------------------------------
1646 {
1647  usbSetProbeAngle(sweepAngle);
1648  return PLUS_SUCCESS;
1649 }
1650 
1652 {
1653  return usbProbeAngle();
1654 }
1655 
1656 // ----------------------------------------------------------------------------
1658 {
1659  usbSetProbeServoGain(servoGain);
1660  return PLUS_SUCCESS;
1661 }
1662 
1664 {
1665  return usbProbeServoGain();
1666 }
1667 
1668 // ----------------------------------------------------------------------------
1670 {
1671  usbSetProbeOverscan(state);
1672  return PLUS_SUCCESS;
1673 }
1674 
1676 {
1677  return usbProbeOverscan();
1678 }
1679 
1680 // ----------------------------------------------------------------------------
1682 {
1683  usbSetProbeDerivComp(derComp);
1684  return PLUS_SUCCESS;
1685 }
1686 
1688 {
1689  return usbProbeDerivComp();
1690 }
1691 
1692 // ----------------------------------------------------------------------------
1694 {
1695  usbSetPulseVoltage(pv);
1697  return PLUS_SUCCESS;
1698 }
1699 
1701 {
1702  return usbPulseVoltage();
1703 }
1704 
1705 // ----------------------------------------------------------------------------
1707 {
1708  return this->ImagingParameters->SetSoundVelocity(ss);
1709 }
1710 
1711 // ----------------------------------------------------------------------------
1713 {
1714  return this->ImagingParameters->SetDepthMm(sd * 10);
1715 }
1716 
1717 // setup USBmode parameters ---------------------------------------------------
1718 
1719 // ----------------------------------------------------------------------------
1721 {
1722  this->Interpolate = interpolate;
1723  return PLUS_SUCCESS;
1724 }
1725 
1726 // ----------------------------------------------------------------------------
1728 {
1729  this->AverageMode = averageMode;
1730  return PLUS_SUCCESS;
1731 }
1732 
1733 // ----------------------------------------------------------------------------
1735 {
1736  this->CurrentBModeViewOption = (unsigned int) bModeViewOption;
1737  return PLUS_SUCCESS;
1738 }
1739 
1740 // ----------------------------------------------------------------------------
1742 {
1743  return this->ImagingParameters->SetImageSize(imageSize[0], imageSize[1], imageSize[2]);
1744 }
1745 
1746 // ----------------------------------------------------------------------------
1748 {
1749  return this->ImagingParameters->SetIntensity(value);
1750 }
1751 
1752 // ----------------------------------------------------------------------------
1754 {
1755  return this->ImagingParameters->SetContrast(value);
1756 }
1757 
1758 // ----------------------------------------------------------------------------
1760 {
1761  return this->ImagingParameters->SetZoomFactor(zoomfactor);
1762 }
1763 
1764 // ----------------------------------------------------------------------------
1766 {
1767  if (this->Internal->ProbeHandle == NULL)
1768  {
1769  LOG_ERROR("vtkPlusCapistranoVideoSource::SetDisplayZoomDevice failed: device not connected");
1770  return PLUS_FAIL;
1771  }
1772  this->SetZoomFactor(zoom);
1773 
1774  bmSetDisplayZoom(zoom);
1775  LOG_TRACE("New zoom is " << bmDisplayZoom());
1776  return PLUS_SUCCESS;
1777 }
1778 
1779 // ----------------------------------------------------------------------------
1781 {
1782  this->LutCenter = lutcenter;
1783  return PLUS_SUCCESS;
1784 }
1785 
1786 // ----------------------------------------------------------------------------
1788 {
1789  this->LutWindow = lutwindow;
1790  return PLUS_SUCCESS;
1791 }
1792 
1793 // ----------------------------------------------------------------------------
1795 {
1796  this->ImagingParameters->SetTimeGainCompensation(gainPercent, 3);
1797  return PLUS_SUCCESS;
1798 }
1799 
1800 // ----------------------------------------------------------------------------
1802 {
1803  if (this->Internal->ProbeHandle == NULL)
1804  {
1805  LOG_ERROR("vtkPlusCapistranoVideoSource::SetGainPercentDevice failed: device not connected");
1806  return PLUS_FAIL;
1807  }
1808  SetGainPercent(gainPercent);
1809  /* The following commented code is useful when using an RF probe with an analog TGC control.
1810  It sets the value, in dB, for the gain at the last sample taken. */
1811 
1812  /* If the above code is executed the gain values are changed but it has no effect on the image. Probably it is because the probe
1813  does not have analog TGC control.
1814  The code below sets a linear TGC curve based on three values (initial, middle and end) of the curve.*/
1815 
1816  double initialGain, midGain, farGain;
1817  double maximumTGC = 512;
1818  if (gainPercent[0] >= 0 && gainPercent[1] >= 0 && gainPercent[2] >= 0)
1819  {
1820  initialGain = -255 + gainPercent[0] * maximumTGC / 100 ;
1821  midGain = -255 + gainPercent[1] * maximumTGC / 100 ;
1822  farGain = -255 + gainPercent[2] * maximumTGC / 100 ;
1823  }
1824 
1825  this->Internal->CreateLinearTGC(initialGain, midGain, farGain);
1826 
1827  bmTurnOnTGC();
1828  return PLUS_SUCCESS;
1829 }
1830 
1831 // ----------------------------------------------------------------------------
1833 {
1834  int temp = (int)(depthMm / 18.0f);
1835 
1836  temp = std::max(temp, 1);
1837  temp = std::min(temp, 4);
1838 
1839  // Update the current scan depth with an available scan depth
1840  this->SetDepthMm((float)temp * 18.0f);
1841 
1842  // Update Sample clock divider
1843  this->ClockDivider = temp;
1844 
1845  // Update Depth Mode
1846  if (this->UpdateDepthMode(this->ClockDivider) == PLUS_FAIL)
1847  {
1848  LOG_ERROR("Invalid scan depth.");
1849  return PLUS_FAIL;
1850  }
1851 
1852  return PLUS_SUCCESS;
1853 }
1854 
1855 // ----------------------------------------------------------------------------
1857 {
1858  return this->ImagingParameters->SetDepthMm(depthMm);
1859 }
1860 
1861 // Update US parameters before acquiring US-BMode images -----------------------
1862 // ----------------------------------------------------------------------------
1864 {
1865  RETURN_WITH_FAIL_IF(this->UpdateUSProbeParameters() == PLUS_FAIL,
1866  "Failed to Update US probe parameters");
1867  RETURN_WITH_FAIL_IF(this->UpdateUSBModeParameters() == PLUS_FAIL,
1868  "Failed to Update US BMode parameters");
1869  return PLUS_SUCCESS;
1870 }
1871 
1872 // ----------------------------------------------------------------------------
1874 {
1875  // Set US Probe scan mode -------------------------------------------------
1876  if (this->BidirectionalMode)
1877  {
1878  usbSetBidirectionalMode();
1879  }
1880  else
1881  {
1882  usbSetUnidirectionalMode();
1883  }
1884 
1885  // set the size of CineBuffers -------------------------------------------
1886  if (usbSetCineBuffers(this->CineBuffers) != this->CineBuffers)
1887  {
1888  LOG_ERROR("Could not allocate Cine buffers.");
1889  return PLUS_FAIL;
1890  }
1891 
1892  // Update SoundVelocity --------------------------------------------------
1893  this->Internal->USProbeParams.probetype.Velocity = this->ImagingParameters->GetSoundVelocity();
1894 
1895  // Update PulseFrequency
1896  if (!this->Internal->SetUSProbePulserParamsFromDB(this->ImagingParameters->GetFrequencyMhz()))
1897  {
1898  LOG_ERROR("Invalid pulse frequency. Possible pulse frequencies: 10.0, 12.0, 16.0, 18.0, 20.0, 25.0, 30.0, 35.0, 45.0, 50");
1899  return PLUS_FAIL;
1900  }
1901 
1902  // Update PulseVoltage ----------------------------------------------------
1903  this->Internal->USProbeParams.PulseVoltage = this->ImagingParameters->GetProbeVoltage();
1904  usbSetPulseVoltage(this->Internal->USProbeParams.PulseVoltage);
1905 
1906 
1907  // Setup ScanDpthe -------------------------------------------------------
1908  if (this->SetDepthMmDevice((float)this->ImagingParameters->GetDepthMm()) == PLUS_FAIL)
1909  {
1910  LOG_ERROR("Could not setup Scan Depth");
1911  return PLUS_FAIL;
1912  }
1913 
1914  return PLUS_SUCCESS;
1915 }
1916 
1917 // ----------------------------------------------------------------------------
1919 {
1920  this->InitializeLUT();
1921  this->InitializeTGC();
1922 
1923  // Set zoom factor
1925  {
1926  LOG_ERROR("SetDisplayZoomDevice failed");
1927  return PLUS_FAIL;
1928  }
1929  return PLUS_SUCCESS;
1930 }
1931 
1932 // ----------------------------------------------------------------------------
1934 {
1935  return this->CalculateDisplay(STANDARDVIEW);
1936 }
1937 
1938 // ----------------------------------------------------------------------------
1940 {
1941  POINT ptCenter; // Points for Zoomed Display
1942  FrameSizeType imageSize = this->ImagingParameters->GetImageSize();
1943  ptCenter.x = imageSize[0] / 2;
1944  ptCenter.y = imageSize[1] / 2;
1945 
1946  this->CurrentBModeViewOption = bBModeViewOption;
1947 
1948  this->Internal->USProbeParams.probetype.OversampleRate = 2048.0f / imageSize[1];
1949 
1950  if (bmCalculateZoomDisplay(imageSize[0], imageSize[1], ptCenter,
1951  this->Internal->USProbeParams.probetype, (unsigned int)imageSize[0],
1952  this->CurrentBModeViewOption) == ERROR)
1953  {
1954  LOG_ERROR("CalculateDisplay ERROR: Bad Theta Value");
1955  return PLUS_FAIL;
1956  }
1957 
1958  return PLUS_SUCCESS;
1959 }
1960 
1961 // ----------------------------------------------------------------------------
1963 {
1964  // Update the values of ProbeType structure
1965  FrameSizeType imageSize = this->ImagingParameters->GetImageSize();
1966  Internal->USProbeParams.probetype.OversampleRate = 2048.0f / imageSize[1];
1967  Internal->USProbeParams.probetype.SampleFrequency = 80.f / usbSampleClockDivider();
1968  Internal->USProbeParams.probetype.PivFaceSamples =
1969  Internal->USProbeParams.probetype.PFDistance * 1000.0f *
1970  Internal->USProbeParams.probetype.SampleFrequency /
1971  (0.5f * Internal->USProbeParams.probetype.Velocity);
1972 
1973  this->SampleFrequency = Internal->USProbeParams.probetype.SampleFrequency;
1974 
1975  usbClearCineBuffers();
1977  {
1978  LOG_ERROR("CalculateDisplay ERROR: Bad Theta Value");
1979  return PLUS_FAIL;
1980  }
1981 
1982  this->Internal->ClearBitmap();
1983 
1984  return PLUS_SUCCESS;
1985 }
1986 
1987 // ----------------------------------------------------------------------------
1989 {
1990  usbSetSampleClockDivider(clockdivider);
1991  return this->UpdateDepthMode();
1992 }
1993 
1994 // Get US probe/B-Mode parameters ---------------------------------------------
1995 
1996 // ----------------------------------------------------------------------------
1998 {
1999  if (this->Internal->ProbeHandle == NULL)
2000  {
2001  LOG_ERROR("vtkPlusCapistranoVideoSource::GetSampleFrequencyDevice failed: device not connected");
2002  return PLUS_FAIL;
2003  }
2004 
2005  aFreq = this->Internal->USProbeParams.probetype.SampleFrequency;
2006  LOG_TRACE("Current frequency is " << aFreq);
2007  return PLUS_SUCCESS;
2008 }
2009 
2010 // ----------------------------------------------------------------------------
2012 // ToDo: Check this function
2013 {
2014  if (this->Internal->ProbeHandle == NULL)
2015  {
2016  LOG_ERROR("vtkPlusICapistranoVideoSource::GetProbeVelocityDevice failed: device not connected");
2017  return PLUS_FAIL;
2018  }
2019 
2020  aVel = this->Internal->USProbeParams.probetype.Velocity;
2021  LOG_TRACE("Current velocity is " << aVel);
2022  return PLUS_SUCCESS;
2023 }
2024 
2025 // ----------------------------------------------------------------------------
2027 {
2028  if (this->Internal->ProbeHandle == NULL)
2029  {
2030  LOG_ERROR("vtkPlusCapistranoVideoSource::SetGainPercentDevice failed: device not connected");
2031  return PLUS_FAIL;
2032  }
2033 
2034  // usbProbeNameString supposed to be able to store the USB probe name
2035  // but if we use that buffer then it leads to stack corruption,
2036  // so we use a much larger buffer (the usbProbeNameString buffer size is 20)
2037  typedef TCHAR usbProbeNameStringSafe[1000];
2038 
2039  usbProbeNameStringSafe probeNameWideStringPtr = {0};
2040  usbProbeName(this->Internal->ProbeHandle, probeNameWideStringPtr);
2041 
2042  // Probe name is stored in a wide-character string, convert it to a multi-byte character string
2043  char probeNamePrintable[usbProbeNameMaxLength + 1] = {0};
2044  wcstombs(probeNamePrintable, (wchar_t*)probeNameWideStringPtr, usbProbeNameMaxLength);
2045 
2046  probeName = probeNamePrintable;
2047 
2048  return PLUS_SUCCESS;
2049 }
2050 
2051 //----------------------------------------------------------------------------
2053 {
2054  if (!this->Connected)
2055  {
2056  // trying to apply parameters when not connected leads to crashes
2057  return PLUS_SUCCESS;
2058  }
2059 
2060  PlusStatus status = PLUS_SUCCESS;
2061 
2064  {
2066  {
2068  }
2069  else
2070  {
2071  LOG_ERROR("Failed to set depth imaging parameter");
2072  status = PLUS_FAIL;
2073  }
2074  }
2075 
2078  {
2080  {
2082  }
2083  else
2084  {
2085  LOG_ERROR("Failed to set frequency imaging parameter");
2086  status = PLUS_FAIL;
2087  }
2088  }
2089 
2092  {
2093  std::vector<double> tgcVec;
2095  double tgc[3] = { tgcVec[0], tgcVec[1], tgcVec[2] };
2096 
2097  if (this->SetGainPercentDevice(tgc) == PLUS_SUCCESS)
2098  {
2100  }
2101  else
2102  {
2103  LOG_ERROR("Failed to set time gain compensation parameter");
2104  status = PLUS_FAIL;
2105  }
2106  }
2107 
2110  {
2111  FrameSizeType imageSizeVec;
2112  this->ImagingParameters->GetImageSize(imageSizeVec);
2113 
2114  if (this->SetImageSize(imageSizeVec) == PLUS_SUCCESS)
2115  {
2117  }
2118  else
2119  {
2120  LOG_ERROR("Failed to set image size parameter");
2121  status = PLUS_FAIL;
2122  }
2123  }
2124 
2127  {
2129  {
2131  }
2132  else
2133  {
2134  LOG_ERROR("Failed to set intensity parameter");
2135  status = PLUS_FAIL;
2136  }
2137  }
2138 
2141  {
2142  if (this->SetContrast(this->ImagingParameters->GetContrast()) == PLUS_SUCCESS)
2143  {
2145  }
2146  else
2147  {
2148  LOG_ERROR("Failed to set contrast parameter");
2149  status = PLUS_FAIL;
2150  }
2151  }
2152 
2155  {
2157  {
2159  }
2160  else
2161  {
2162  LOG_ERROR("Failed to set zoom parameter");
2163  status = PLUS_FAIL;
2164  }
2165  }
2166 
2169  {
2171  {
2173  }
2174  else
2175  {
2176  LOG_ERROR("Failed to set sound velocity parameter");
2177  status = PLUS_FAIL;
2178  }
2179  }
2180 
2183  {
2185  {
2187  }
2188  else
2189  {
2190  LOG_ERROR("Failed to set voltage parameter");
2191  status = PLUS_FAIL;
2192  }
2193  }
2194 
2195  return PLUS_SUCCESS;
2196 }
PlusStatus GetHighPassFilter(int &HighPassFilter)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *deviceConfig)
bool IsPending(const std::string &paramName) const
PlusStatus GetLowPassFilter(int &LowPassFilter)
vtkStandardNewMacro(vtkPlusCapistranoVideoSource)
static const char * CAPISTRANO_SET_SAMPLE_FREQUENCY
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
static const char * CAPISTRANO_GET_JITTER_COMPENSATION
Phidget_MeshMode mode
Definition: phidget22.h:1332
PlusStatus SetSweepAngle(float sweepAngle)
std::string GetSourceId() const
int
Definition: phidget22.h:3069
PlusStatus SetGainPercent(double gainPercent[3])
PlusStatus GetMISPulsePeriod(unsigned int &PulsePeriod)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus SetContrast(double aContrast)
PlusStatus SetWobbleRate(unsigned char wobbleRate)
PlusStatus GetDepthMm(double &aDepthMm) const
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
PlusStatus SetServoGain(unsigned char servoGain)
PlusStatus GetSoundVelocity(float &aSoundVelocity) const
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
bool RequireImageOrientationInConfiguration
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
for i
double AcquisitionRate
PlusStatus SetPending(const std::string &paramName, bool pending)
void PrintSelf(ostream &os, vtkIndent indent) override
double CurrentPixelSpacingMm[3]
Values used in calculation of image to transducer matrix.
PlusStatus SetGainPercentDevice(double gainPercent[3])
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
static const char * CAPISTRANO_SET_BIDIRECTIONAL_MODE
PlusStatus SetTimeGainCompensation(const std::vector< double > &tgc)
static const char * CAPISTRANO_SET_MIS_PULSE_PERIOD
Initial rotation matrix b
Definition: algo3.m:25
PlusStatus SetImageSize(const FrameSizeType &imageSize)
static const char * CAPISTRANO_SET_DERIVATIVE_COMPENSATION
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)
#define FALSE
Definition: ATC3DGm.h:220
PlusStatus SetPowerDb(double aPower)
unsigned long FrameNumber
PlusStatus ReadConfiguration(vtkXMLDataElement *config) override
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
PlusStatus SetJitterCompensation(unsigned char jitterComp)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
double contrast
Definition: phidget22.h:4297
PlusStatus GetProbeNameDevice(std::string &probeName)
PlusStatus GetHardwareVersion(int &HardwareVersion)
PlusStatus InternalApplyImagingParameterChange() override
PlusStatus SetProbeVoltage(float aVoltage)
int * state
Definition: phidget22.h:3207
PlusStatus SetBModeViewOption(unsigned int bmodeviewoption)
PlusStatus GetContrast(double &aContrast) const
PlusStatus GetSampleFrequencyDevice(float &aFreq)
PlusStatus SetGainPercent(double aGainPercent)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
PlusStatus SetImageSize(const FrameSizeType &imageSize)
PlusStatus SetDynRangeDb(double aDynRangeDb)
PlusStatus SetSectorPercent(double aSectorPercent)
int x
Definition: phidget22.h:4265
PlusStatus GetImageSize(FrameSizeType &imageSize) const
PlusStatus WriteConfiguration(vtkXMLDataElement *config) override
PlusStatus SetInterpolate(bool interpolate)
PlusStatus GetZoomFactor(double &aZoomFactor) const
const char const char * value
Definition: phidget22.h:5111
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
static const char * CAPISTRANO_GET_MIS_PULSE_PERIOD
unsigned long ULONG
Definition: ATC3DGm.h:432
PlusStatus GetProbeVoltage(float &aVoltage) const
bool StartThreadForInternalUpdates
static const char * CAPISTRANO_GET_BIDIRECTIONAL_MODE
PlusStatus SetDerivativeCompensation(unsigned char derivativeCompensation)
PlusStatus SetIntensity(double aIntensity)
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
PlusStatus SetLutWindow(double lutwindow)
ChannelContainer OutputChannels
PlusStatus SetPositionScale(unsigned char scale)
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
PlusStatus SetFocusDepthPercent(double aFocusDepthPercent)
#define TRUE
Definition: ATC3DGm.h:219
Direction vectors of rods y
Definition: algo3.m:15
PlusStatus SetZoomFactor(double aZoomFactor)
PlusStatus GetIntensity(double &aIntensity) const
static LRESULT CALLBACK ImageWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
bool IsSet(const std::string &paramName) const
PlusStatus SetAverageMode(bool averagemode)
Class for acquiring ultrasound images from Capistrano Labs USB ultrasound systems.
unsigned char BYTE
Definition: ATC3DGm.h:449
PlusStatus SetZoomFactor(double zoomfactor)
static const char * CAPISTRANO_GET_SAMPLE_FREQUENCY
static const char * CAPISTRANO_SET_JITTER_COMPENSATION
PlusStatus SetMISPulsePeriod(unsigned int val)
PlusStatus SetDepthMm(double aDepthMm)
PlusStatus SetSoundVelocity(float aSoundVelocity)
static const char * CAPISTRANO_GET_DERIVATIVE_COMPENSATION
virtual int GetNumberOfItems()
PlusStatus SetLutCenter(double lutcenter)
bool CorrectlyConfigured
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *deviceConfig)
Interface to a 3D positioning tool, video source, or generalized data stream.