PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusWinProbeVideoSource.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"
9 #include "vtkPlusChannel.h"
10 #include "vtkPlusDataSource.h"
11 #include "vtkPlusUSImagingParameters.h"
12 
13 #include "WinProbe.h"
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <PlusMath.h>
18 
19 //----------------------------------------------------------------------------
21 
22  //----------------------------------------------------------------------------
23  // Define command strings
24 const char* vtkPlusWinProbeVideoSource::SET_FREEZE = "SetFrozen";
25 const char* vtkPlusWinProbeVideoSource::GET_FREEZE = "GetFrozen";
26 const char* vtkPlusWinProbeVideoSource::SET_TGC = "SetTGC";
27 const char* vtkPlusWinProbeVideoSource::GET_TGC = "GetTGC";
28 const char* vtkPlusWinProbeVideoSource::SET_ALL_FOCAL_DEPTHS = "SetAllFocalDepths";
29 const char* vtkPlusWinProbeVideoSource::SET_FOCAL_DEPTH = "SetFocalDepth";
30 const char* vtkPlusWinProbeVideoSource::GET_FOCAL_DEPTH = "GetFocalDepth";
31 const char* vtkPlusWinProbeVideoSource::SET_ALL_ARFI_FOCAL_DEPTHS = "SetAllARFIFocalDepths";
32 const char* vtkPlusWinProbeVideoSource::SET_ARFI_FOCAL_DEPTH = "SetARFIFocalDepth";
33 const char* vtkPlusWinProbeVideoSource::GET_ARFI_FOCAL_DEPTH = "GetARFIFocalDepth";
34 const char* vtkPlusWinProbeVideoSource::SET_B_MULTIFOCAL_ZONE_COUNT = "SetBMultifocalZoneCount";
35 const char* vtkPlusWinProbeVideoSource::GET_B_MULTIFOCAL_ZONE_COUNT = "GetBMultifocalZoneCount";
36 const char* vtkPlusWinProbeVideoSource::SET_FIRST_GAIN_VALUE = "SetFirstGainValue";
37 const char* vtkPlusWinProbeVideoSource::GET_FIRST_GAIN_VALUE = "GetFirstGainValue";
38 const char* vtkPlusWinProbeVideoSource::SET_TGC_OVERALL_GAIN = "SetTGCOverallGain";
39 const char* vtkPlusWinProbeVideoSource::GET_TGC_OVERALL_GAIN = "GetTGCOverallGain";
40 const char* vtkPlusWinProbeVideoSource::SET_SPATIAL_COMPOUND_ENABLED = "SetSpatialCompoundEnabled";
41 const char* vtkPlusWinProbeVideoSource::GET_SPATIAL_COMPOUND_ENABLED = "GetSpatialCompoundEnabled";
42 const char* vtkPlusWinProbeVideoSource::GET_SPATIAL_COMPOUND_ANGLE = "GetSpatialCompoundAngle";
43 const char* vtkPlusWinProbeVideoSource::SET_SPATIAL_COMPOUND_COUNT = "SetSpatialCompoundCount";
44 const char* vtkPlusWinProbeVideoSource::GET_SPATIAL_COMPOUND_COUNT = "GetSpatialCompoundCount";
45 const char* vtkPlusWinProbeVideoSource::SET_MMODE_ENABLED = "SetMModeEnabled";
46 const char* vtkPlusWinProbeVideoSource::GET_MMODE_ENABLED = "GetMModeEnabled";
47 const char* vtkPlusWinProbeVideoSource::SET_M_REVOLVING_ENABLED = "SetMRevolvingEnabled";
48 const char* vtkPlusWinProbeVideoSource::GET_M_REVOLVING_ENABLED = "GetMRevolvingEnabled";
49 const char* vtkPlusWinProbeVideoSource::SET_RF_MODE_ENABLED = "SetRfModeEnabled";
50 const char* vtkPlusWinProbeVideoSource::GET_RF_MODE_ENABLED = "GetRfModeEnabled";
51 const char* vtkPlusWinProbeVideoSource::SET_MPR_FREQUENCY = "SetMPRFrequency";
52 const char* vtkPlusWinProbeVideoSource::GET_MPR_FREQUENCY = "GetMPRFrequency";
53 const char* vtkPlusWinProbeVideoSource::SET_M_LINE_INDEX = "SetMLineIndex";
54 const char* vtkPlusWinProbeVideoSource::GET_M_LINE_INDEX = "GetMLineIndex";
55 const char* vtkPlusWinProbeVideoSource::SET_M_LINE_COUNT = "SetMLineCount";
56 const char* vtkPlusWinProbeVideoSource::GET_M_LINE_COUNT = "GetMLineCount";
57 const char* vtkPlusWinProbeVideoSource::SET_M_WIDTH = "SetMWidth";
58 const char* vtkPlusWinProbeVideoSource::GET_M_WIDTH = "GetMWidth";
59 const char* vtkPlusWinProbeVideoSource::SET_M_DEPTH = "SetMDepth";
60 const char* vtkPlusWinProbeVideoSource::GET_M_DEPTH = "GetMDepth";
61 const char* vtkPlusWinProbeVideoSource::SET_DECIMATION = "SetDecimation";
62 const char* vtkPlusWinProbeVideoSource::GET_DECIMATION = "GetDecimation";
63 const char* vtkPlusWinProbeVideoSource::GET_B_PRF = "GetBPRF";
64 const char* vtkPlusWinProbeVideoSource::SET_B_FRAME_RATE_LIMIT = "SetBFrameRateLimit";
65 const char* vtkPlusWinProbeVideoSource::GET_B_FRAME_RATE_LIMIT = "GetBFrameRateLimit";
66 const char* vtkPlusWinProbeVideoSource::SET_B_HARMONIC_ENABLED = "SetBHarmonicEnabled";
67 const char* vtkPlusWinProbeVideoSource::GET_B_HARMONIC_ENABLED = "GetBHarmonicEnabled";
68 const char* vtkPlusWinProbeVideoSource::SET_B_BUBBLE_CONTRAST_ENABLED = "SetBBubbleContrastEnabled";
69 const char* vtkPlusWinProbeVideoSource::GET_B_BUBBLE_CONTRAST_ENABLED = "GetBBubbleContrastEnabled";
70 const char* vtkPlusWinProbeVideoSource::SET_B_AMPLITUDE_MODULATION_ENABLED = "SetBAmplitudeModulationEnabled";
71 const char* vtkPlusWinProbeVideoSource::GET_B_AMPLITUDE_MODULATION_ENABLED = "GetBAmplitudeModulationEnabled";
72 const char* vtkPlusWinProbeVideoSource::SET_B_TRANSMIT_LOCKED = "SetBTransmitLocked";
73 const char* vtkPlusWinProbeVideoSource::GET_B_TRANSMIT_LOCKED = "GetBTransmitLocked";
74 const char* vtkPlusWinProbeVideoSource::SET_B_TRANSMIT_CURRENT = "SetBTransmitCurrent";
75 const char* vtkPlusWinProbeVideoSource::GET_B_TRANSMIT_CURRENT = "GetBTransmitCurrent";
76 const char* vtkPlusWinProbeVideoSource::SET_B_TRANSMIT_CYCLE_COUNT = "SetBTransmitCycleCount";
77 const char* vtkPlusWinProbeVideoSource::GET_B_TRANSMIT_CYCLE_COUNT = "GetBTransmitCycleCount";
78 const char* vtkPlusWinProbeVideoSource::SET_B_TRANSMIT_FNUMBER = "SetBTransmitFNumber";
79 const char* vtkPlusWinProbeVideoSource::GET_B_TRANSMIT_FNUMBER = "GetBTransmitFNumber";
80 const char* vtkPlusWinProbeVideoSource::SET_B_APODIZATION_FNUMBER = "SetBApodizationFNumber";
81 const char* vtkPlusWinProbeVideoSource::GET_B_APODIZATION_FNUMBER = "GetBApodizationFNumber";
82 const char* vtkPlusWinProbeVideoSource::SET_B_BUBBLE_DESTRUCTION_ENABLED = "SetBBubbleDestructionEnabled";
83 const char* vtkPlusWinProbeVideoSource::GET_B_BUBBLE_DESTRUCTION_ENABLED = "GetBBubbleDestructionEnabled";
84 const char* vtkPlusWinProbeVideoSource::SET_B_BUBBLE_DESTRUCTION_CYCLE_COUNT = "SetBBubbleDestructionCycleCount";
85 const char* vtkPlusWinProbeVideoSource::GET_B_BUBBLE_DESTRUCTION_CYCLE_COUNT = "GetBBubbleDestructionCycleCount";
86 const char* vtkPlusWinProbeVideoSource::SET_B_TX_FILTER_COEFFICIENT_SET = "SetBTXFilterCoefficientSet";
87 const char* vtkPlusWinProbeVideoSource::GET_B_TX_FILTER_COEFFICIENT_SET = "GetBTXFilterCoefficientSet";
88 const char* vtkPlusWinProbeVideoSource::GET_TRANSDUCER_INTERNAL_ID = "GetTransducerInternalID";
89 const char* vtkPlusWinProbeVideoSource::SET_ARFI_ENABLED = "SetARFIEnabled";
90 const char* vtkPlusWinProbeVideoSource::GET_ARFI_ENABLED = "GetARFIEnabled";
91 const char* vtkPlusWinProbeVideoSource::SET_ARFI_START_SAMPLE = "SetARFIStartSample";
92 const char* vtkPlusWinProbeVideoSource::GET_ARFI_START_SAMPLE = "GetARFIStartSample";
93 const char* vtkPlusWinProbeVideoSource::SET_ARFI_STOP_SAMPLE = "SetARFIStopSample";
94 const char* vtkPlusWinProbeVideoSource::GET_ARFI_STOP_SAMPLE = "GetARFIStopSample";
95 const char* vtkPlusWinProbeVideoSource::SET_ARFI_PRE_PUSH_LINE_REPEAT_COUNT = "SetARFIPrePushLineRepeatCount";
96 const char* vtkPlusWinProbeVideoSource::GET_ARFI_PRE_PUSH_LINE_REPEAT_COUNT = "GetARFIPrePushLineRepeatCount";
97 const char* vtkPlusWinProbeVideoSource::SET_ARFI_POST_PUSH_LINE_REPEAT_COUNT = "SetARFIPostPushLineRepeatCount";
98 const char* vtkPlusWinProbeVideoSource::GET_ARFI_POST_PUSH_LINE_REPEAT_COUNT = "GetARFIPostPushLineRepeatCount";
99 const char* vtkPlusWinProbeVideoSource::GET_ARFI_INTER_SET_DELAY = "GetARFIInterSetDelay";
100 const char* vtkPlusWinProbeVideoSource::SET_ARFI_INTER_SET_DELAY = "SetARFIInterSetDelay";
101 const char* vtkPlusWinProbeVideoSource::GET_ARFI_INTER_PUSH_DELAY = "GetARFIInterPushDelay";
102 const char* vtkPlusWinProbeVideoSource::SET_ARFI_INTER_PUSH_DELAY = "SetARFIInterPushDelay";
103 const char* vtkPlusWinProbeVideoSource::SET_ARFI_LINE_TIMER = "SetARFILineTimer";
104 const char* vtkPlusWinProbeVideoSource::GET_ARFI_LINE_TIMER = "GetARFILineTimer";
105 const char* vtkPlusWinProbeVideoSource::SET_ARFI_TX_CYCLE_COUNT = "SetARFITxCycleCount";
106 const char* vtkPlusWinProbeVideoSource::GET_ARFI_TX_CYCLE_COUNT = "GetARFITxCycleCount";
107 const char* vtkPlusWinProbeVideoSource::SET_ARFI_TX_CYCLE_WIDTH = "SetARFITxCycleWidth";
108 const char* vtkPlusWinProbeVideoSource::GET_ARFI_TX_CYCLE_WIDTH = "GetARFITxCycleWidth";
109 const char* vtkPlusWinProbeVideoSource::SET_ARFI_TX_TX_CYCLE_COUNT = "SetARFITxTxCycleCount";
110 const char* vtkPlusWinProbeVideoSource::GET_ARFI_TX_TX_CYCLE_COUNT = "GetARFITxTxCycleCount";
111 const char* vtkPlusWinProbeVideoSource::SET_ARFI_TX_TX_CYCLE_WIDTH = "SetARFITxTxCycleWidth";
112 const char* vtkPlusWinProbeVideoSource::GET_ARFI_TX_TX_CYCLE_WIDTH = "GetARFITxTxCycleWidth";
113 const char* vtkPlusWinProbeVideoSource::SET_ARFI_PUSH_CONFIG = "SetARFIPushConfigurationString";
114 const char* vtkPlusWinProbeVideoSource::GET_ARFI_PUSH_CONFIG = "GetARFIPushConfigurationString";
115 const char* vtkPlusWinProbeVideoSource::GET_FPGA_REV_DATE_STRING = "GetFPGARevDateString";
116 const char* vtkPlusWinProbeVideoSource::GET_X8BF_ENABLED = "IsX8BFEnabled";
117 const char* vtkPlusWinProbeVideoSource::UV_SEND_COMMAND = "UVSendCommand";
118 const char* vtkPlusWinProbeVideoSource::IS_SCANNING = "IsScanning";
119 
120 int32_t focalCountFromDepthsArray(float* depths, unsigned arraySize)
121 {
122  std::vector<float> nonZeroes;
123  for (unsigned i = 0; i < arraySize; i++)
124  {
125  if (depths[i] != 0)
126  {
127  nonZeroes.push_back(depths[i]);
128  }
129  }
130  std::sort(nonZeroes.begin(), nonZeroes.end());
131 
132  unsigned i = 1;
133  while (i < nonZeroes.size())
134  {
135  if (nonZeroes[i] == nonZeroes[i - 1])
136  {
137  nonZeroes.erase(nonZeroes.begin() + i); // remove duplicate
138  }
139  else // check next index
140  {
141  ++i;
142  }
143  }
144  if (nonZeroes.size() == 0)
145  {
146  nonZeroes.push_back(depths[0]); // Need to specify at least one focal depth even if all depths are 0 mm
147  }
148  int32_t count = nonZeroes.size();
149 
150  // copy sorted non-zero array back into original array
151  for (i = 0; i < nonZeroes.size(); i++)
152  {
153  depths[i] = nonZeroes[i];
154  }
155  // fill rest of the array with zeroes
156  for (; i < arraySize; i++)
157  {
158  depths[i] = 0;
159  }
160 
161  return count;
162 }
163 
164 // ----------------------------------------------------------------------------
165 void vtkPlusWinProbeVideoSource::PrintSelf(ostream& os, vtkIndent indent)
166 {
167  this->Superclass::PrintSelf(os, indent);
168  os << indent << "MinValue: " << this->m_MinValue << std::endl;
169  os << indent << "MaxValue: " << this->m_MaxValue << std::endl;
170  os << indent << "LogLinearKnee: " << this->m_Knee << std::endl;
171  os << indent << "LogMax: " << static_cast<unsigned>(this->m_OutputKnee) << std::endl;
172  os << indent << "TransducerID: " << this->m_TransducerID << std::endl;
173  os << indent << "Frozen: " << this->IsFrozen() << std::endl;
174  os << indent << "Voltage: " << static_cast<unsigned>(this->GetVoltage()) << std::endl;
175  os << indent << "Frequency: " << this->GetTransmitFrequencyMHz() << std::endl;
176  os << indent << "Depth: " << this->GetScanDepthMm() << std::endl;
177  os << indent << "Mode: " << this->ModeToString(this->GetMode()) << std::endl;
178  for(int i = 0; i < 8; i++)
179  {
180  os << indent << "TGC" << i << ": " << m_TimeGainCompensation[i] << std::endl;
181  }
182  for(int i = 0; i < 4; i++)
183  {
184  os << indent << "FocalPointDepth" << i << ": " << m_FocalPointDepth[i] << std::endl;
185  }
186  for(int i = 0; i < 6; i++)
187  {
188  os << indent << "ARFIFocalPointDepth" << i << ": " << m_ARFIFocalPointDepth[i] << std::endl;
189  }
190 
191  os << indent << "CustomFields: " << std::endl;
192  vtkIndent indent2 = indent.GetNextIndent();
193  igsioFieldMapType::iterator it;
194  for(it = m_CustomFields.begin(); it != m_CustomFields.end(); ++it)
195  {
196  os << indent2 << it->first << ": " << it->second.second << std::endl;
197  }
198 }
199 
200 // ----------------------------------------------------------------------------
201 PlusStatus vtkPlusWinProbeVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
202 {
203  LOG_TRACE("vtkPlusWinProbeVideoSource::ReadConfiguration");
204  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
205 
206  XML_READ_STRING_ATTRIBUTE_REQUIRED(TransducerID, deviceConfig);
207  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(UseDeviceFrameReconstruction, deviceConfig);
208  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(SpatialCompoundEnabled, deviceConfig);
209  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(BHarmonicEnabled, deviceConfig);
210  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(MRevolvingEnabled, deviceConfig);
211  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, TransmitFrequencyMHz, deviceConfig);
212  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, ScanDepthMm, deviceConfig);
213  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, SpatialCompoundCount, deviceConfig);
214  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, MPRFrequency, deviceConfig);
215  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, MLineIndex, deviceConfig);
216  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, MWidth, deviceConfig);
217  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int32_t, MWidthLines, deviceConfig);
218  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, MAcousticLineCount, deviceConfig);
219  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, MDepth, deviceConfig);
220  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, Voltage, deviceConfig); //implicit type conversion
221  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, MinValue, deviceConfig); //implicit type conversion
222  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, MaxValue, deviceConfig); //implicit type conversion
223  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, LogLinearKnee, deviceConfig); //implicit type conversion
224  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, LogMax, deviceConfig); //implicit type conversion
225  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(unsigned long, SSDecimation, deviceConfig); //implicit type conversion
226  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(double, FirstGainValue, deviceConfig);
227  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(double, OverallTimeGainCompensation, deviceConfig);
228  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, BFrameRateLimit, deviceConfig);
229 
230 
231  const char* strMode = deviceConfig->GetAttribute("Mode");
232  if(strMode)
233  {
234  m_Mode = this->StringToMode(strMode);
235  }
236  if(m_Mode == Mode::M)
237  {
238  const char* mwidthSeconds_string = deviceConfig->GetAttribute("MWidth");
239  if(mwidthSeconds_string)
240  {
241  int mwidthSeconds = std::stoi(mwidthSeconds_string);
242  if(mwidthSeconds > 0)
243  {
244  m_MWidth = this->MWidthFromSeconds(mwidthSeconds);
245  }
246  }
247  }
248 
249  deviceConfig->GetVectorAttribute("TimeGainCompensation", 8, m_TimeGainCompensation);
250 
251  m_BMultiTxCount = deviceConfig->GetVectorAttribute("FocalPointDepth", 4, m_FocalPointDepth);
252  if (m_BMultiTxCount) // examine for duplicates
253  {
255  }
256  deviceConfig->GetVectorAttribute("ARFIFocalPointDepth", 6, m_ARFIFocalPointDepth);
257  // m_ARFIMultiTxCount = deviceConfig->GetVectorAttribute("ARFIFocalPointDepth", 6, m_ARFIFocalPointDepth);
258  // if (m_ARFIMultiTxCount) // examine for duplicates
259  // {
260  // m_ARFIMultiTxCount = focalCountFromDepthsArray(&m_ARFIFocalPointDepth[1], m_ARFIMultiTxCount - 1); // first value is special
261  // }
262 
263  return PLUS_SUCCESS;
264 }
265 
266 // ----------------------------------------------------------------------------
267 PlusStatus vtkPlusWinProbeVideoSource::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
268 {
269  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
270 
271  deviceConfig->SetAttribute("TransducerID", this->m_TransducerID.c_str());
272  deviceConfig->SetAttribute("UseDeviceFrameReconstruction", this->m_UseDeviceFrameReconstruction ? "TRUE" : "FALSE");
273  deviceConfig->SetAttribute("SpatialCompoundEnabled", this->GetSpatialCompoundEnabled() ? "TRUE" : "FALSE");
274  deviceConfig->SetAttribute("HarmonicEnabled", this->GetBHarmonicEnabled() ? "TRUE" : "FALSE");
275  deviceConfig->SetAttribute("MRevolvingEnabled", this->GetMRevolvingEnabled() ? "TRUE" : "FALSE");
276  deviceConfig->SetFloatAttribute("TransmitFrequencyMHz", this->GetTransmitFrequencyMHz());
277  deviceConfig->SetFloatAttribute("ScanDepthMm", this->GetScanDepthMm());
278  deviceConfig->SetFloatAttribute("SpatialCompoundAngle", this->GetSpatialCompoundAngle());
279  deviceConfig->SetIntAttribute("SpatialCompoundCount", this->GetSpatialCompoundCount());
280  deviceConfig->SetIntAttribute("MPRFrequency", this->GetMPRFrequency());
281  deviceConfig->SetIntAttribute("MLineIndex", this->GetMLineIndex());
282  deviceConfig->SetIntAttribute("MWidth", this->MSecondsFromWidth(this->m_MWidth));
283  deviceConfig->SetIntAttribute("MWidthLines", this->m_MWidth);
284  deviceConfig->SetIntAttribute("MAcousticLineCount", this->GetMAcousticLineCount());
285  deviceConfig->SetIntAttribute("MDepth", this->GetMDepth());
286  deviceConfig->SetIntAttribute("BTransmitCurrent", this->GetBTransmitCurrent());
287  deviceConfig->SetIntAttribute("BTransmitCycleCount", this->GetBTransmitCycleCount());
288  deviceConfig->SetUnsignedLongAttribute("Voltage", this->GetVoltage());
289  deviceConfig->SetUnsignedLongAttribute("MinValue", this->GetMinValue());
290  deviceConfig->SetUnsignedLongAttribute("MaxValue", this->GetMaxValue());
291  deviceConfig->SetUnsignedLongAttribute("LogLinearKnee", this->GetLogLinearKnee());
292  deviceConfig->SetUnsignedLongAttribute("LogMax", this->GetLogMax());
293  deviceConfig->SetUnsignedLongAttribute("SSDecimation", this->GetSSDecimation());
294  deviceConfig->SetAttribute("Mode", ModeToString(this->m_Mode).c_str());
295  deviceConfig->SetDoubleAttribute("FirstGainValue", this->GetFirstGainValue());
296  deviceConfig->SetDoubleAttribute("OverallTimeGainCompensation", this->GetOverallTimeGainCompensation());
297  deviceConfig->SetDoubleAttribute("BTransmitFNumber", this->GetBTransmitFNumber());
298  deviceConfig->SetIntAttribute("BFrameRateLimit", this->GetBFrameRateLimit());
299 
300  deviceConfig->SetVectorAttribute("TimeGainCompensation", 8, m_TimeGainCompensation);
301  deviceConfig->SetVectorAttribute("FocalPointDepth", 4, m_FocalPointDepth);
302  deviceConfig->SetVectorAttribute("ARFIFocalPointDepth", 6, m_ARFIFocalPointDepth);
303 
304  return PLUS_SUCCESS;
305 }
306 
307 // ----------------------------------------------------------------------------
309 {
310  if(modeString.empty())
311  {
312  LOG_WARNING("Empty mode string defaults to B mode");
313  return Mode::B;
314  }
315 
316  // convert to uppercase for easy comparison
317  std::transform(modeString.begin(), modeString.end(), modeString.begin(), ::toupper);
318 
319  if(modeString == "B")
320  { return Mode::B; }
321  else if(modeString == "BRF")
322  { return Mode::BRF; }
323  else if(modeString == "RF")
324  { return Mode::RF; }
325  else if(modeString == "M")
326  { return Mode::M; }
327  else if(modeString == "PW")
328  { return Mode::PW; }
329  else if(modeString == "ARFI")
330  { return Mode::ARFI; }
331  else if(modeString == "CFD")
332  { return Mode::CFD; }
333  else
334  { LOG_ERROR("Unrecognized mode: " << modeString); }
335 
336  return Mode::B; // default mode
337 }
338 
339 // ----------------------------------------------------------------------------
341 {
342  switch(mode)
343  {
344  case Mode::B:
345  return "B";
346  break;
347  case Mode::BRF:
348  return "BRF";
349  break;
350  case Mode::RF:
351  return "RF";
352  break;
353  case Mode::M:
354  return "M";
355  break;
356  case Mode::PW:
357  return "PW";
358  break;
359  case Mode::ARFI:
360  return "ARFI";
361  break;
362  case Mode::CFD:
363  return "CFD";
364  break;
365  default:
366  LOG_ERROR("Invalid mode passed: " << int(mode));
367  return "B";
368  break;
369  }
370 }
371 
372 // ----------------------------------------------------------------------------
374 {
375  int32_t mlineWidth = pow(2, round(std::log(value * m_MPRF) / std::log(2)));
376  return mlineWidth;
377 }
378 
380 {
381  int mwidthSeconds = floor(value / m_MPRF);
382  return mwidthSeconds;
383 }
384 
385 // ----------------------------------------------------------------------------
387 int32_t quadBFCount = 1; // number of 4x beamformers
388 
389 //-----------------------------------------------------------------------------
390 // This callback function is invoked after each frame is ready
391 int __stdcall frameCallback(int length, char* data, char* hHeader, char* hGeometry, char* hModeFrameHeader)
392 {
393  thisPtr->FrameCallback(length, data, hHeader, hGeometry);
394  return length;
395 }
396 
397 //-----------------------------------------------------------------------------
398 void vtkPlusWinProbeVideoSource::ReconstructFrame(char* data, std::vector<uint8_t>& buffer, const FrameSizeType& frameSize)
399 {
400  uint16_t* frame = reinterpret_cast<uint16_t*>(data + 16);
401  assert(buffer.size() == frameSize[0] * frameSize[1]);
402  const float logFactor = m_OutputKnee / std::log(1 + m_Knee);
403 
404  #pragma omp parallel for
405  for(unsigned t = 0; t < frameSize[0]; t++)
406  {
407  for(unsigned s = 0; s < frameSize[1]; s++)
408  {
409  uint16_t val = frame[t * frameSize[1] + s];
410  if(val <= m_MinValue) // subtract noise floor
411  {
412  val = 0;
413  }
414  else
415  {
416  val -= m_MinValue;
417  }
418  if(val > m_MaxValue) //apply ceiling
419  {
420  val = m_MaxValue;
421  }
422 
423  float cVal;
424  if(val < m_Knee)
425  {
426  cVal = logFactor * std::log(float(1 + val));
427  }
428  else //linear mapping
429  {
430  cVal = m_OutputKnee + (val - m_Knee) * float(255 - m_OutputKnee) / (m_MaxValue - m_Knee);
431  }
432  buffer[s * frameSize[0] + t] = static_cast<uint8_t>(cVal);
433  }
434  }
435 }
436 
437 void vtkPlusWinProbeVideoSource::FlipTexture(char* data, const FrameSizeType& frameSize, int rowPitch)
438 {
439  #pragma omp parallel for
440  for(unsigned t = 0; t < frameSize[0]; t++)
441  {
442  for(unsigned s = 0; s < frameSize[1]; s++)
443  {
444  m_PrimaryBuffer[s * frameSize[0] + t] = data[t * rowPitch + s];
445  }
446  }
447 }
448 
449 
450 // ----------------------------------------------------------------------------
451 void vtkPlusWinProbeVideoSource::FrameCallback(int length, char* data, char* hHeader, char* hGeometry)
452 {
453  CineModeFrameHeader* header = (CineModeFrameHeader*)hHeader;
454  CFDGeometryStruct* cfdGeometry = (CFDGeometryStruct*)hGeometry;
455  GeometryStruct* brfGeometry = (GeometryStruct*)hGeometry; //B-mode and RF
456  MGeometryStruct* mGeometry = (MGeometryStruct*)hGeometry;
457  PWGeometryStruct* pwGeometry = (PWGeometryStruct*)hGeometry;
458  ARFIGeometryStruct* arfiGeometry = (ARFIGeometryStruct*)hGeometry;
459  int callbackFrameNumber = header->TotalFrameCounter;
460  InputSourceBindings usMode = header->InputSourceBinding;
461  FrameSizeType frameSize = { 1, 1, 1 };
462 
463  if(header->TotalFrameCounter == 0)
464  {
465  first_timestamp = header->TimeStamp / 1000.0;
466  m_TimestampOffset = vtkIGSIOAccurateTimer::GetSystemTime();
467  LOG_DEBUG("First frame timestamp: "<< first_timestamp);
468  }
469 
470  if(usMode & CFD)
471  {
472  frameSize[0] = cfdGeometry->LineCount;
473  frameSize[1] = cfdGeometry->SamplesPerKernel;
474  }
475  else if(usMode & B || usMode & BFRFALineImage_SampleData)
476  {
478  {
479  return;
480  }
481  frameSize[0] = brfGeometry->LineCount;
482  frameSize[1] = brfGeometry->SamplesPerLine;
483  if(frameSize[1] != m_PrimaryFrameSize[1])
484  {
485  LOG_INFO("SamplesPerLine has changed from " << m_PrimaryFrameSize[1]
486  << " to " << frameSize[1] << ". Adjusting spacing and buffer sizes.");
487  m_PrimaryFrameSize[1] = frameSize[1];
489  AdjustSpacing(false);
490  }
491  else if(this->CurrentPixelSpacingMm[1] != m_ScanDepth / (m_PrimaryFrameSize[1] - 1)) // we might need approximate equality check
492  {
493  LOG_INFO("Scan Depth changed. Adjusting spacing.");
494  AdjustSpacing(false);
495  }
496  }
497  else if(usMode & ARFI)
498  {
499  int timestampsPerLineRepeat = (4 / quadBFCount);
500  int lineRepeatCount = arfiGeometry->PrePushLineRepeatCount + arfiGeometry->PostPushLineRepeatCount;
501  int timeblock = timestampsPerLineRepeat * lineRepeatCount * m_ARFIPushConfigurationCount * sizeof(int32_t);
502  int arfiDataSize = (m_ARFIStopSample - m_ARFIStartSample) * arfiGeometry->LineCount * lineRepeatCount * m_ARFIPushConfigurationCount * sizeof(int32_t);
503  assert(length == arfiDataSize + timeblock);
504  frameSize[0] = (arfiDataSize + timeblock) / sizeof(int32_t); // we want to include all data to be saved
505  frameSize[1] = 1;
506  frameSize[2] = 1;
507  if(frameSize != m_ExtraFrameSize)
508  {
509  LOG_INFO("ARFI frame size updated. Adjusting buffer size and spacing.");
510  m_ExtraFrameSize = frameSize;
512  AdjustSpacing(true);
513  }
514  else if(this->CurrentPixelSpacingMm[0] != m_ScanDepth / (m_ExtraFrameSize[1] * 1)) // we might need approximate equality check
515  {
516  LOG_INFO("Scan Depth changed. Adjusting spacing.");
517  AdjustSpacing(true);
518  }
519  }
520  else if(usMode & BFRFALineImage_RFData)
521  {
522  int harmonic_multiplier = 1; // RF data contains more lines when the harmonic flags are turned on because it includes data for each transmit
524  {
525  harmonic_multiplier = 3;
526  }
528  {
529  harmonic_multiplier = 2;
530  }
531 
532  frameSize[0] = brfGeometry->SamplesPerLine * brfGeometry->Decimation;
533  frameSize[1] = brfGeometry->LineCount * harmonic_multiplier;
534  if(frameSize != m_ExtraSources[0]->GetInputFrameSize())
535  {
536  LOG_INFO("Rf frame size updated. Adjusting buffer size and spacing.");
537  m_ExtraFrameSize[0] = frameSize[0];
538  m_ExtraFrameSize[1] = frameSize[1];
539  m_SSDecimation = brfGeometry->Decimation;
541  AdjustSpacing(true);
542  }
543  else if(this->CurrentPixelSpacingMm[0] != m_ScanDepth / (m_ExtraFrameSize[1] * m_SSDecimation - 1)) // we might need approximate equality check
544  {
545  LOG_INFO("Scan Depth changed. Adjusting spacing.");
546  AdjustSpacing(true);
547  }
548  }
549  else if(usMode & M_PostProcess)
550  {
551  frameSize[0] = mGeometry->LineCount;
552  frameSize[1] = mGeometry->SamplesPerLine;
553  if(m_ExtraSources.empty())
554  {
555  return; //the source is not defined, do not waste time on processing this frame
556  }
557  if(frameSize != m_ExtraSources[0]->GetInputFrameSize())
558  {
559  LOG_INFO("SamplesPerLine has changed from " << m_ExtraFrameSize[0] << "x" << m_ExtraFrameSize[1]
560  << " to " << frameSize[0] << "x" << frameSize[1] << ". Adjusting buffer size.");
561  m_ExtraFrameSize = frameSize;
563  AdjustSpacing(false);
564  }
565  else if(this->CurrentPixelSpacingMm[1] != m_ScanDepth / (m_ExtraFrameSize[1] - 1)) // we might need approximate equality check
566  {
567  LOG_INFO("Scan Depth changed. Adjusting spacing.");
568  AdjustSpacing(false);
569  }
570  }
571  else if(usMode & PWD_PostProcess)
572  {
573  frameSize[0] = pwGeometry->NumberOfImageLines;
574  frameSize[1] = pwGeometry->NumberOfImageSamples;
575  }
576  else
577  {
578  LOG_INFO("Unsupported frame type: " << std::hex << usMode);
579  return;
580  }
581  //timestamp counters are in milliseconds since last sequencer restart
582  double timestamp = (header->TimeStamp / 1000.0) - first_timestamp;
583  if(timestamp <= 0.0) // some change is being applied, so this frame is not valid
584  {
585  LOG_DEBUG("Timestamp is <= 0 so ignoring this frame.");
586  return; // ignore this frame
587  }
589  LOG_DEBUG("Frame: " << callbackFrameNumber << ". Mode: " << std::setw(4) << std::hex << usMode << ". Timestamp: " << timestamp << ". UseDeviceFrameReconstruction: " << m_UseDeviceFrameReconstruction);
590 
591  if(usMode & B && !m_PrimarySources.empty() // B-mode and primary source is defined
592  || usMode & M_PostProcess && !m_ExtraSources.empty() // M-mode and extra source is defined
593  || usMode & BFRFALineImage_SampleData && !m_PrimarySources.empty() // B-mode and primary source is defined, if in RF/BRF mode
594  )
595  {
596  assert(length == frameSize[0] * frameSize[1] * sizeof(uint16_t) + 16); //frame + header
597 
598  if(usMode & M_PostProcess)
599  {
600  this->ReconstructFrame(data, m_ExtraBuffer, frameSize);
601  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
602  {
603  frameSize[0] = m_ExtraFrameSize[0];
604  if(m_ExtraSources[i]->AddItem(&m_ExtraBuffer[0],
605  US_IMG_ORIENT_MF,
606  frameSize, VTK_UNSIGNED_CHAR,
607  1, US_IMG_BRIGHTNESS, 0,
608  callbackFrameNumber,
609  timestamp,
610  timestamp, //no timestamp filtering needed
611  &this->m_CustomFields) != PLUS_SUCCESS)
612  {
613  LOG_WARNING("Error adding item to extra video source " << m_ExtraSources[i]->GetSourceId());
614  }
615  }
616  }
617  else // B-mode
618  {
620  {
621  return;
622  }
623  this->ReconstructFrame(data, m_PrimaryBuffer, frameSize);
624 
625  for(unsigned i = 0; i < m_PrimarySources.size(); i++)
626  {
627  if(m_PrimarySources[i]->AddItem(&m_PrimaryBuffer[0],
628  US_IMG_ORIENT_MF,
629  frameSize, VTK_UNSIGNED_CHAR,
630  1, US_IMG_BRIGHTNESS, 0,
631  this->FrameNumber,
632  timestamp,
633  timestamp, //no timestamp filtering needed
634  &this->m_CustomFields) != PLUS_SUCCESS)
635  {
636  LOG_WARNING("Error adding item to primary video source " << m_PrimarySources[i]->GetSourceId());
637  }
638  }
639  } // B-mode
640  }
641  else if(usMode & B) //this is B frame, but B-mode source is NOT defined
642  {
643  LOG_DEBUG("Frame ignored - B-mode source not defined. Got mode: " << std::hex << usMode);
644  return;
645  }
646  else if(usMode & ARFI)
647  {
648  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
649  {
650  // send the ARFI data as one long 2D frame to be processed downstream
651  int32_t* tempData = reinterpret_cast<int32_t*>(data);
652  // need to spoof the timestamps since the arfi data comes a few seconds after the push
653  double currentTime = vtkIGSIOAccurateTimer::GetSystemTime();
654  if(m_ExtraSources[i]->AddItem(tempData,
655  US_IMG_ORIENT_FM,
656  frameSize, VTK_INT,
657  1, US_IMG_RF_REAL, 0,
658  callbackFrameNumber,
659  currentTime,
660  currentTime,
662  {
663  LOG_WARNING("Error adding item to ARFI video source " << m_ExtraSources[i]->GetSourceId());
664  }
665  else
666  {
667  LOG_INFO("Success adding item to ARFI video source " << m_ExtraSources[i]->GetSourceId());
668  }
669  }
670  }
671  else if(usMode & BFRFALineImage_RFData)
672  {
673  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
674  {
675  assert(length == frameSize[0] * frameSize[1] * sizeof(int32_t));
676  if(m_ExtraSources[i]->AddItem(data,
677  US_IMG_ORIENT_FM,
678  frameSize, VTK_INT,
679  1, US_IMG_RF_REAL, 0,
680  this->FrameNumber,
681  timestamp,
682  timestamp,
684  {
685  LOG_WARNING("Error adding item to RF video source " << m_ExtraSources[i]->GetSourceId());
686  }
687  }
688  }
689  else if(usMode & CFD)
690  {
691  //TODO
692  }
693  else
694  {
695  LOG_INFO("Frame ignored. Got mode: " << std::hex << usMode);
696  return;
697  }
698 
699  this->Modified();
700 }
701 
702 //----------------------------------------------------------------------------
704 {
705  FrameSizeType frameSize = m_PrimaryFrameSize;
706 
707  for(unsigned i = 0; i < m_PrimarySources.size(); i++)
708  {
709  m_PrimarySources[i]->Clear(); // clear current buffer content
710  m_PrimarySources[i]->SetPixelType(VTK_UNSIGNED_CHAR);
711  m_PrimarySources[i]->SetImageType(US_IMG_BRIGHTNESS);
712  m_PrimarySources[i]->SetOutputImageOrientation(US_IMG_ORIENT_MF);
713  m_PrimarySources[i]->SetInputImageOrientation(US_IMG_ORIENT_MF);
714  m_PrimarySources[i]->SetInputFrameSize(frameSize);
715  LOG_INFO("SourceID: " << m_PrimarySources[i]->GetId() << ", "
716  << "Frame size: " << frameSize[0] << "x" << frameSize[1]
717  << ", pixel type: " << vtkImageScalarTypeNameMacro(m_PrimarySources[i]->GetPixelType())
718  << ", buffer image orientation: "
719  << igsioCommon::GetStringFromUsImageOrientation(m_PrimarySources[i]->GetInputImageOrientation()));
721  }
722 
723  frameSize = m_ExtraFrameSize;
724 
725  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
726  {
727  if(m_Mode == Mode::RF || m_Mode == Mode::BRF || m_Mode == Mode::ARFI)
728  {
729  m_ExtraSources[i]->SetPixelType(VTK_INT);
730  m_ExtraSources[i]->SetImageType(US_IMG_RF_REAL);
731  m_ExtraSources[i]->SetOutputImageOrientation(US_IMG_ORIENT_FM);
732  m_ExtraSources[i]->SetInputImageOrientation(US_IMG_ORIENT_FM);
733  m_ExtraBuffer.swap(std::vector<uint8_t>()); // deallocate the buffer
734  }
735  else if(m_Mode == Mode::M)
736  {
737  frameSize[0] = m_MWidth;
738  m_ExtraSources[i]->SetPixelType(VTK_UNSIGNED_CHAR);
739  m_ExtraSources[i]->SetImageType(US_IMG_BRIGHTNESS);
740  m_ExtraSources[i]->SetOutputImageOrientation(US_IMG_ORIENT_MF);
741  m_ExtraSources[i]->SetInputImageOrientation(US_IMG_ORIENT_MF);
742  if(m_ExtraBuffer.size() != m_MWidth * m_ExtraFrameSize[1])
743  {
745  std::fill(m_ExtraBuffer.begin(), m_ExtraBuffer.end(), 0);
746  }
747  }
748 
749  if(m_ExtraSources[i]->GetInputFrameSize() != frameSize)
750  {
751  m_ExtraSources[i]->Clear(); // clear current buffer content
752  m_ExtraSources[i]->SetInputFrameSize(frameSize);
753  LOG_INFO("SourceID: " << m_ExtraSources[i]->GetId() << ", "
754  << "Frame size: " << frameSize[0] << "x" << frameSize[1] << "x" << frameSize[2]
755  << ", pixel type: " << vtkImageScalarTypeNameMacro(m_ExtraSources[i]->GetPixelType())
756  << ", buffer image orientation: "
757  << igsioCommon::GetStringFromUsImageOrientation(m_ExtraSources[i]->GetInputImageOrientation()));
758  }
759  }
760 }
761 
762 //----------------------------------------------------------------------------
764 {
765  unsigned int numSpaceDimensions = 3;
766  std::vector<double> spacing;
767  if(rf_mode)
768  {
769  spacing = GetExtraSourceSpacing();
770  }
771  else
772  {
773  spacing = GetPrimarySourceSpacing();
774  }
775 
776  for(unsigned int i = 0; i < numSpaceDimensions; ++i)
777  {
778  this->CurrentPixelSpacingMm[i] = spacing[i];
779  }
780 
781  std::ostringstream spacingStream;
782 
783  for(unsigned int i = 0; i < numSpaceDimensions; ++i)
784  {
785  spacingStream << this->CurrentPixelSpacingMm[i];
786  if(i != numSpaceDimensions - 1)
787  {
788  spacingStream << " ";
789  }
790  }
791  this->m_CustomFields["ElementSpacing"].first = FRAMEFIELD_FORCE_SERVER_SEND;
792  this->m_CustomFields["ElementSpacing"].second = spacingStream.str();
793  LOG_DEBUG("Adjusted spacing: " << spacingStream.str());
794 }
795 
796 // ----------------------------------------------------------------------------
798 {
800 
801  for(int i = 0; i < 8; i++)
802  {
803  m_TimeGainCompensation[i] = 0.0;
804  }
805 
806  for(int i = 0; i < 4; i++)
807  {
808  m_FocalPointDepth[i] = 0.0f;
809  }
810 
811  AdjustSpacing(false);
812 
813  Callback funcPtr = &frameCallback;
814  thisPtr = this;
815  WPSetCallback(funcPtr);
816 
818  {
819  // Device reconstructed frames are polled instead of sent via callback
820  this->StartThreadForInternalUpdates = true;
821  }
822 }
823 
824 // ----------------------------------------------------------------------------
826 {
827  if(this->Connected)
828  {
829  this->Disconnect();
830  }
831 }
832 
833 // ----------------------------------------------------------------------------
835 {
836  WPInitialize();
839  if(m_ExtraSources.empty() && m_PrimarySources.empty())
840  {
841  vtkPlusDataSource* aSource = NULL;
842  if(this->GetFirstActiveOutputVideoSource(aSource) != PLUS_SUCCESS || aSource == NULL)
843  {
844  LOG_ERROR("Neither B-mode nor RF-mode data sources are defined, and unable to retrieve the video source in the capturing device.");
845  return PLUS_FAIL;
846  }
847  m_PrimarySources.push_back(aSource); //else consider this the only output of B-mode type
848  }
849 
850  LOG_DEBUG("Connect to WinProbe");
851  if(!WPConnect())
852  {
853  LOG_ERROR("Failed connecting to WinProbe!");
854  return PLUS_FAIL;
855  }
856  if(!WPLoadDefault())
857  {
858  LOG_ERROR("Failed loading defaults!");
859  return PLUS_FAIL;
860  }
861  if(this->GetTransducerInternalID() == 15) // 15 corresponds to the "No transducer" entry in the Transducers.xml
862  {
863  LOG_ERROR("Transducer not connected!");
864  return PLUS_FAIL;
865  }
866  LOG_DEBUG("Setting transducer ID: " << this->m_TransducerID);
867  WPSetTransducerID(this->m_TransducerID.c_str());
868 
869  std::string presetPath = "Default.xml";
870  LOG_DEBUG("Loading Default Presets. " << presetPath);
871  if(!LoadXmlPreset(presetPath.c_str()))
872  {
873  LOG_ERROR("Failed loading default presets!")
874  return PLUS_FAIL;
875  }
876  if(::GetARFIIsX8BFEnabled())
877  {
878  quadBFCount = 2;
879  }
880  else
881  {
882  quadBFCount = 1;
883  }
885  LOG_INFO("FPGA Version: " << m_FPGAVersion);
886 
887  m_ADCfrequency = GetADCSamplingRate();
888  this->m_CustomFields["SamplingRate"].first = FRAMEFIELD_FORCE_SERVER_SEND;
889  this->m_CustomFields["SamplingRate"].second = std::to_string(m_ADCfrequency);
890  m_PrimaryFrameSize[0] = GetSSElementCount();
891  SetSCCompoundAngleCount(0);
892 
893  LOG_DEBUG("GetHandleBRFInternally: " << GetHandleBRFInternally());
894  LOG_DEBUG("GetBFRFImageCaptureMode: " << GetBFRFImageCaptureMode());
895 
896  if(m_Mode == Mode::BRF || m_Mode == Mode::RF)
897  {
898  SetHandleBRFInternally(false);
899  SetBFRFImageCaptureMode(2);
900  }
901  else
902  {
903  SetHandleBRFInternally(true);
904  SetBFRFImageCaptureMode(0);
905  }
906  if(m_Mode != Mode::RF) // all modes except pure RF require primary source
907  {
908  if(m_PrimarySources.empty())
909  {
910  LOG_ERROR("Primary source is not defined!");
911  }
912  }
913  if(m_Mode == Mode::RF || m_Mode == Mode::BRF || m_Mode == Mode::ARFI)
914  {
915  if(m_ExtraSources.empty())
916  {
917  LOG_ERROR("RF source is not defined!");
918  }
919  }
920  if(m_Mode == Mode::PW)
921  {
922  SetPWIsEnabled(true);
923  }
924  if(m_Mode == Mode::ARFI)
925  {
926  this->SetARFIEnabled(true);
927  }
928  if(m_Mode == Mode::CFD)
929  {
930  SetVoltage(70);
931  SetCFSamplesPerKernel(2);
932  // ...
933  // more setup required
934  SetCFIsEnabled(true);
935  }
936  //TODO handle additional modes
937 
938  LOG_DEBUG("GetHandleBRFInternally: " << GetHandleBRFInternally());
939  LOG_DEBUG("GetBFRFImageCaptureMode: " << GetBFRFImageCaptureMode());
940  SetPendingRecreateTables(true);
941  this->Connected = true; // the setters and getters check this
942 
943  //apply requested settings
944  for(int i = 0; i < 8; i++)
945  {
946  SetTGC(i, m_TimeGainCompensation[i]);
947  m_TimeGainCompensation[i] = GetTGC(i);
948  }
949  SetTGCFirstGainValue(m_FirstGainValue);
950  //SetPendingTGCUpdate(true);
952  for(int i = 0; i < 4; i++)
953  {
956  }
957 
958  if (quadBFCount == 2)
959  {
960  for(int i = 0; i < 6; i++)
961  {
964  }
965 
978  }
979 
981  this->SetVoltage(m_Voltage);
983  // Update decimation variable on start, based on scan depth
985  this->SetSpatialCompoundEnabled(m_SpatialCompoundEnabled); // also takes care of angle and count
996 
997  //setup size for DirectX image
998  LOG_DEBUG("Setting output size to " << m_PrimaryFrameSize[0] << "x" << m_PrimaryFrameSize[1]);
999  char* sessionPtr = GetSessionPtr();
1000  bool success = WPVPSetSession(sessionPtr);
1001  if(!success)
1002  {
1003  LOG_WARNING("Failed setting session pointer!");
1004  WPDisconnect();
1005  return PLUS_FAIL;
1006  }
1007  WPSetSize(m_PrimaryFrameSize[0], m_PrimaryFrameSize[1]);
1008  SetMaxDmaTransferSize(0x100000);
1009 
1011  {
1012  WPDXSetIsGetSpatialCompoundedTexEnabled(true);
1013  WPDXSetFusedTexBufferMax(16);
1014  }
1015  WPDXSetDrawTextLayer(false);
1016  WPDXSetDrawScalesAndBars(false);
1017  std::this_thread::sleep_for(std::chrono::milliseconds(100));
1018  if(m_Mode == Mode::M)
1019  {
1020  SetMIsEnabled(true);
1021  SetMIsRevolving(m_MRevolvingEnabled);
1022  SetMPRF(m_MPRF);
1023  SetMAcousticLineIndex(m_MLineIndex);
1026  }
1027 
1028  m_TimestampOffset = vtkIGSIOAccurateTimer::GetSystemTime();
1029  LOG_DEBUG("GetPendingRecreateTables: " << GetPendingRecreateTables());
1030  LOG_DEBUG("GetPendingRestartSequencer: " << GetPendingRestartSequencer());
1031  LOG_DEBUG("GetPendingRun30Frames: " << GetPendingRun30Frames());
1032 
1033  return PLUS_SUCCESS;
1034 }
1035 
1036 // ----------------------------------------------------------------------------
1038 {
1039  LOG_DEBUG("Disconnecting from WinProbe");
1040  if(IsRecording())
1041  {
1042  this->InternalStopRecording();
1043  }
1044  WPDisconnect();
1045  LOG_DEBUG("Disconnect from WinProbe finished");
1046  WPDXDispose();
1047  WPDispose();
1048  return PLUS_SUCCESS;
1049 }
1050 
1051 // ----------------------------------------------------------------------------
1053 {
1054  this->FrameNumber = 0;
1055  WPExecute();
1056  return PLUS_SUCCESS;
1057 }
1058 
1059 // ----------------------------------------------------------------------------
1061 {
1062  WPStopScanning();
1063  return PLUS_SUCCESS;
1064 }
1065 
1066 // ----------------------------------------------------------------------------
1068 {
1070  {
1071  return PLUS_SUCCESS;
1072  }
1073 
1074  // Handle manual probe disconnections
1075  if (GetTransducerInternalID() == 0xF) // probe has been disconnected from the engine
1076  {
1077  if (IsScanning())
1078  {
1079  WPStopScanning();
1080  }
1081  LOG_WARNING("Probe has been disconnected from the engine!");
1082  return PLUS_SUCCESS;
1083  }
1084  else
1085  {
1086  if (!IsScanning())
1087  {
1088  WPExecute();
1089  }
1090  }
1091 
1092  if (!m_PrimarySources.empty()) // mode shouldn't matter here, we are always polling B-mode into primary
1093  {
1094  // Grab processed frame data
1095  char* texture = nullptr;
1096  int slicePitch;
1097  int rowPitch;
1098  int tLength = WPDXGetFusedTexData(&texture, &slicePitch, &rowPitch);
1099  if (tLength == 0)
1100  {
1101  LOG_DEBUG("B Mode buffer empty");
1102  return PLUS_FAIL;
1103  }
1104 
1105  // Adjust buffer sizes
1106  FrameSizeType frameSize = { 1, 1, 1 };
1107  frameSize[0] = tLength / rowPitch;
1108  frameSize[1] = rowPitch;
1109  if(frameSize[1] != m_PrimaryFrameSize[1])
1110  {
1111  LOG_INFO("SamplesPerLine has changed from " << m_PrimaryFrameSize[1]
1112  << " to " << frameSize[1] << ". Adjusting spacing and buffer sizes.");
1113  m_PrimaryFrameSize[1] = frameSize[1];
1115  AdjustSpacing(false);
1116  }
1117  else if(this->CurrentPixelSpacingMm[1] != m_ScanDepth / (m_PrimaryFrameSize[1] - 1)) // we might need approximate equality check
1118  {
1119  LOG_INFO("Scan Depth changed. Adjusting spacing.");
1120  AdjustSpacing(false);
1121  }
1122 
1123  // True post-processing timestamp is packed into the data
1124  double timestamp = 0;
1125  unsigned int temp = 0;
1126  temp = (texture[0] & 0xff);
1127  timestamp += temp;
1128  temp = (texture[1] & 0xff);
1129  timestamp += (temp << 8);
1130  temp = (texture[2] & 0xff);
1131  timestamp += (temp << 16);
1132  temp = (texture[3] & 0xff);
1133  timestamp += (temp << 24);
1134 
1135  //timestamp counters are in milliseconds since last sequencer restart
1136  timestamp = (timestamp / 1000) - first_timestamp;
1137  if(timestamp <= 0.0) // some change is being applied, so this frame is not valid
1138  {
1139  m_RenderedTimestampOffset = vtkIGSIOAccurateTimer::GetSystemTime();
1140  LOG_DEBUG("Timestamp is <= 0 so ignoring this frame.");
1141  this->FrameNumber += 1;
1142  WPFreePointer(texture);
1143  return PLUS_SUCCESS; // ignore this frame
1144  }
1145 
1146  double currentTime = m_RenderedTimestampOffset + timestamp;
1147  this->FlipTexture(texture, frameSize, rowPitch);
1148  for(unsigned i = 0; i < m_PrimarySources.size(); i++)
1149  {
1150  if(m_PrimarySources[i]->AddItem(&m_PrimaryBuffer[0],
1151  US_IMG_ORIENT_MF,
1152  frameSize, VTK_UNSIGNED_CHAR,
1153  1, US_IMG_BRIGHTNESS, 0,
1154  this->FrameNumber,
1155  currentTime,
1156  currentTime, //no timestamp filtering needed
1157  &this->m_CustomFields) != PLUS_SUCCESS)
1158  {
1159  LOG_WARNING("Error adding item to primary video source " << m_PrimarySources[i]->GetSourceId());
1160  }
1161  this->FrameNumber += 1;
1162  }
1163  WPFreePointer(texture);
1164  this->Modified();
1165  }
1166  return PLUS_SUCCESS;
1167 }
1168 
1169 // ----------------------------------------------------------------------------
1171 {
1172  if(!IsRecording() == freeze) //already in desired mode
1173  {
1174  return PLUS_SUCCESS;
1175  }
1176 
1177  if(IsRecording())
1178  {
1179  this->StopRecording();
1180  }
1181  else
1182  {
1183  this->StartRecording();
1184  }
1185 
1186  return PLUS_SUCCESS;
1187 }
1188 
1189 // ----------------------------------------------------------------------------
1191 {
1192  return !IsRecording();
1193 }
1194 
1195 // ----------------------------------------------------------------------------
1197 {
1198  return WPGetIsScanningProperty();
1199 }
1200 
1201 // ----------------------------------------------------------------------------
1203 {
1205  if(Connected)
1206  {
1207  ::SetTxFreq(frequency);
1208  SetPendingRecreateTables(true);
1209 
1210  //what we requested might be only approximately satisfied
1211  m_Frequency = ::GetTxFreq();
1212  }
1213  return PLUS_SUCCESS;
1214 }
1215 
1216 //----------------------------------------------------------------------------
1218 {
1219  if(Connected)
1220  {
1221  m_Frequency = ::GetTxFreq();
1222  }
1223  return m_Frequency;
1224 }
1225 
1226 //----------------------------------------------------------------------------
1228 {
1229  m_Voltage = voltage;
1230  if(Connected)
1231  {
1233  //what we requested might be only approximately satisfied
1234  m_Voltage = ::GetVoltage();
1235  }
1236  return PLUS_SUCCESS;
1237 }
1238 
1239 //----------------------------------------------------------------------------
1241 {
1242  if(Connected)
1243  {
1244  m_Voltage = ::GetVoltage();
1245  }
1246  return m_Voltage;
1247 }
1248 
1249 //----------------------------------------------------------------------------
1251 {
1252  if(Connected)
1253  {
1255  SetPendingRecreateTables(true);
1256  //what we requested might be only approximately satisfied
1258  }
1259  return PLUS_SUCCESS;
1260 }
1261 
1262 //----------------------------------------------------------------------------
1264 {
1265  if(Connected)
1266  {
1268  }
1269  return m_SSDecimation;
1270 }
1271 
1272 //----------------------------------------------------------------------------
1274 {
1275  m_ScanDepth = depth;
1276  if(Connected)
1277  {
1278  ::SetSSDepth(depth);
1279  SetPendingRecreateTables(true);
1280  //what we requested might be only approximately satisfied
1281  m_ScanDepth = ::GetSSDepth();
1282  // Update decimation with scan depth
1284  }
1285  return PLUS_SUCCESS;
1286 }
1287 
1288 //----------------------------------------------------------------------------
1290 {
1291  if(Connected)
1292  {
1293  m_ScanDepth = ::GetSSDepth();
1294  }
1295  return m_ScanDepth;
1296 }
1297 
1298 //----------------------------------------------------------------------------
1300 {
1301  if(Connected)
1302  {
1303  m_TransducerWidth = ::GetTWidth();
1304  }
1305  return m_TransducerWidth;
1306 }
1307 
1308 //----------------------------------------------------------------------------
1310 {
1311  return this->CurrentPixelSpacingMm;
1312 }
1313 
1314 //----------------------------------------------------------------------------
1316 {
1317  assert(index >= 0 && index < 8);
1318  if(Connected)
1319  {
1320  m_TimeGainCompensation[index] = GetTGC(index);
1321  }
1322  return m_TimeGainCompensation[index];
1323 }
1324 
1325 //----------------------------------------------------------------------------
1327 {
1328  assert(index >= 0 && index < 8);
1329  m_TimeGainCompensation[index] = value;
1330  if(Connected)
1331  {
1332  SetTGC(index, value);
1333  SetPendingTGCUpdate(true);
1334  //what we requested might be only approximately satisfied
1335  m_TimeGainCompensation[index] = GetTGC(index);
1336  }
1337  return PLUS_SUCCESS;
1338 }
1339 
1340 //----------------------------------------------------------------------------
1342 {
1343  if(Connected)
1344  {
1345  m_FirstGainValue = GetTGCFirstGainValue();
1346  }
1347  return m_FirstGainValue;
1348 }
1349 
1350 //----------------------------------------------------------------------------
1352 {
1354  if(Connected)
1355  {
1356  SetTGCFirstGainValue(value);
1357  // SetPendingTGCUpdate(true);
1358  //what we requested might be only approximately satisfied
1359  m_FirstGainValue = GetTGCFirstGainValue();
1360  }
1361  return PLUS_SUCCESS;
1362 }
1363 
1364 //----------------------------------------------------------------------------
1366 {
1367  if(Connected)
1368  {
1369  m_OverallTimeGainCompensation = GetTGCOverallGain();
1370  }
1372 }
1373 
1374 //----------------------------------------------------------------------------
1376 {
1377  if(Connected)
1378  {
1379  SetTGCOverallGain(value);
1380  SetPendingTGCUpdate(true);
1381  //what we requested might be only approximately satisfied
1382  for (int tgcIndex=0; tgcIndex < 8; tgcIndex += 1)
1383  {
1384  m_TimeGainCompensation[tgcIndex] = GetTGC(tgcIndex);
1385  }
1386  }
1387  return PLUS_SUCCESS;
1388 }
1389 
1390 //----------------------------------------------------------------------------
1392 {
1393  assert(index >= 0 && index < 4);
1394  if(Connected)
1395  {
1396  m_FocalPointDepth[index] = ::GetFocalPointDepth(index);
1397  }
1398  return m_FocalPointDepth[index];
1399 }
1400 
1401 //----------------------------------------------------------------------------
1403 {
1404  assert(index >= 0 && index < 4);
1405  m_FocalPointDepth[index] = depth;
1406  if(Connected)
1407  {
1408  ::SetFocalPointDepth(index, depth);
1409  SetPendingRecreateTables(true);
1410  //what we requested might be only approximately satisfied
1411  m_FocalPointDepth[index] = ::GetFocalPointDepth(index);
1412  }
1413  return PLUS_SUCCESS;
1414 }
1415 
1416 //----------------------------------------------------------------------------
1418 {
1419  assert(index >= 0 && index < 6);
1420  if(Connected)
1421  {
1422  m_ARFIFocalPointDepth[index] = WPGetARFIFocalDepth(index);
1423  }
1424  return m_ARFIFocalPointDepth[index];
1425 }
1426 
1427 //----------------------------------------------------------------------------
1429 {
1430  assert(index >= 0 && index < 6);
1431  m_ARFIFocalPointDepth[index] = depth;
1432  if(Connected)
1433  {
1434  WPSetARFIFocalDepth(index, depth);
1435  SetPendingRecreateTables(true);
1436  //what we requested might be only approximately satisfied
1437  m_ARFIFocalPointDepth[index] = WPGetARFIFocalDepth(index);
1438  }
1439  return PLUS_SUCCESS;
1440 }
1441 
1442 //----------------------------------------------------------------------------
1444 {
1445  if(Connected)
1446  {
1447  m_BMultiTxCount = GetBMultiTxCount();
1448  }
1449  return m_BMultiTxCount;
1450 }
1451 
1452 //----------------------------------------------------------------------------
1454 {
1455  assert(count > 0 && count <= 4);
1457  if(Connected)
1458  {
1459  SetBMultiTxCount(count);
1460  SetPendingRecreateTables(true);
1461  }
1462  return PLUS_SUCCESS;
1463 }
1464 
1466 {
1467  if(Connected)
1468  {
1469  quadBFCount = ::GetARFIIsX8BFEnabled() ? 2 : 1;
1470  }
1471  return quadBFCount == 2;
1472 }
1473 
1474 //----------------------------------------------------------------------------
1476 {
1477  assert(propertyValue > 0 && propertyValue <= 16);
1478  m_ARFITxTxCycleCount = propertyValue;
1479  if(Connected)
1480  {
1481  ::SetARFITxTxCycleCount(propertyValue);
1482  SetPendingRecreateTables(true);
1483  }
1484  return PLUS_SUCCESS;
1485 }
1486 
1488 {
1489  if(Connected)
1490  {
1492  }
1493  return m_ARFITxTxCycleCount;
1494 }
1495 
1496 //----------------------------------------------------------------------------
1498 {
1499  assert(propertyValue > 0 && propertyValue <= 255);
1500  m_ARFITxTxCycleWidth = propertyValue;
1501  if(Connected)
1502  {
1503  ::SetARFITxTxCycleWidth(propertyValue);
1504  SetPendingRecreateTables(true);
1505  }
1506  return PLUS_SUCCESS;
1507 }
1508 
1510 {
1511  if(Connected)
1512  {
1514  }
1515  return m_ARFITxTxCycleWidth;
1516 }
1517 
1518 //----------------------------------------------------------------------------
1520 {
1521  m_ARFITxCycleCount = propertyValue;
1522  if(Connected)
1523  {
1524  ::SetARFITxCycleCount(propertyValue);
1525  SetPendingRecreateTables(true);
1526  }
1527  return PLUS_SUCCESS;
1528 }
1529 
1531 {
1532  if(Connected)
1533  {
1535  }
1536  return m_ARFITxCycleCount;
1537 }
1538 
1539 //----------------------------------------------------------------------------
1541 {
1542  m_ARFITxCycleWidth = propertyValue;
1543  if(Connected)
1544  {
1545  ::SetARFITxCycleWidth(propertyValue);
1546  SetPendingRecreateTables(true);
1547  }
1548  return PLUS_SUCCESS;
1549 }
1550 
1552 {
1553  if(Connected)
1554  {
1556  }
1557  return m_ARFITxCycleWidth;
1558 }
1559 
1560 //----------------------------------------------------------------------------
1562 {
1563  if(Connected)
1564  {
1565  SetSCIsEnabled(value);
1566  if(value)
1567  {
1569  }
1570  else
1571  {
1573  }
1574  }
1576 }
1577 
1579 {
1580  if(Connected)
1581  {
1582  m_SpatialCompoundEnabled = GetSCIsEnabled();
1583  }
1584  return m_SpatialCompoundEnabled;
1585 }
1586 
1588 {
1589  if(Connected)
1590  {
1591  m_SpatialCompoundAngle = GetSCCompoundAngle();
1592  }
1593  return m_SpatialCompoundAngle;
1594 }
1595 
1597 {
1598  if(Connected)
1599  {
1600  SetSCCompoundAngleCount(value);
1601  SetPendingRecreateTables(true);
1602  }
1604 }
1605 
1607 {
1608  if(Connected)
1609  {
1610  m_SpatialCompoundCount = GetSCCompoundAngleCount();
1611  }
1612  return m_SpatialCompoundCount;
1613 }
1614 
1615 //----------------------------------------------------------------------------
1617 {
1618  if((GetBRFEnabled() && mode == Mode::BRF) || (GetMModeEnabled() && mode == Mode::M) || (GetARFIEnabled() && mode == Mode::ARFI))
1619  {
1620  return PLUS_SUCCESS;
1621  }
1622  SetMIsEnabled(mode == Mode::M);
1623  SetARFIIsEnabled(mode == Mode::ARFI);
1624 
1625  if(mode == Mode::BRF)
1626  {
1627  SetHandleBRFInternally(false);
1628  SetBFRFImageCaptureMode(2);
1629  }
1630  else
1631  {
1632  SetHandleBRFInternally(true);
1633  SetBFRFImageCaptureMode(0);
1634  }
1635 
1636  if(mode == Mode::M)
1637  {
1638  SetMIsRevolving(m_MRevolvingEnabled);
1639  SetMPRF(m_MPRF);
1640  SetMAcousticLineIndex(m_MLineIndex);
1643  }
1644  else if(mode == Mode::ARFI)
1645  {
1646  m_Mode = Mode::ARFI;
1647  int samplesPerLine = m_ARFIStopSample - m_ARFIStartSample;
1648  int lineCount = 16;
1650  unsigned arfiDataSize = samplesPerLine * lineCount * lineRepeatCount * m_ARFIPushConfigurationCount;
1651 
1652  int timestampsPerLineRepeat = (4 / quadBFCount);
1653  unsigned timeblockSize = timestampsPerLineRepeat * lineRepeatCount * m_ARFIPushConfigurationCount;
1654  m_ExtraFrameSize = { arfiDataSize + timeblockSize, 1, 1 };
1655  this->AdjustBufferSizes();
1656  std::vector<int32_t> zeroData(m_ExtraFrameSize[0] * m_ExtraFrameSize[1] * m_ExtraFrameSize[2], 0);
1657  // add a fake zero-filled frame immediately, because the first frame seems to get lost somehow
1658  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
1659  {
1660  double timestamp = vtkIGSIOAccurateTimer::GetSystemTime();
1661  if(m_ExtraSources[i]->AddItem(&zeroData[0],
1662  US_IMG_ORIENT_FM,
1663  m_ExtraFrameSize, VTK_INT,
1664  1, US_IMG_RF_REAL, 0,
1665  this->FrameNumber,
1666  timestamp,
1667  timestamp,
1669  {
1670  LOG_WARNING("Error adding fake zeros item to ARFI video source " << m_ExtraSources[i]->GetSourceId());
1671  }
1672  else
1673  {
1674  LOG_WARNING("Success adding fake zeros item to ARFI video source ");
1675  }
1676  }
1677  }
1678  SetPendingRecreateTables(true);
1679  LOG_INFO("Mode changed to: " << this->ModeToString(mode));
1680  m_Mode = mode;
1681  return PLUS_SUCCESS;
1682 }
1683 
1684 //----------------------------------------------------------------------------
1686 {
1687  if(value)
1688  {
1690  }
1691  else
1692  {
1694  }
1695 }
1696 
1697 //----------------------------------------------------------------------------
1699 {
1700  if(value)
1701  {
1703  }
1704  else
1705  {
1707  }
1708 }
1709 
1710 //----------------------------------------------------------------------------
1712 {
1713  if(value)
1714  {
1716  }
1717  else
1718  {
1720  }
1721 }
1722 
1723 //----------------------------------------------------------------------------
1725 {
1726  bool brfEnabled = (m_Mode == Mode::BRF);
1727  if(Connected)
1728  {
1729  brfEnabled = (GetBFRFImageCaptureMode() == 2);
1730  if(brfEnabled)
1731  {
1732  m_Mode = Mode::BRF;
1733  }
1734  }
1735  return brfEnabled;
1736 }
1737 
1739 {
1740  if(Connected)
1741  {
1742  SetBIsHarmonic(value);
1743  SetPendingRecreateTables(true);
1744  }
1745  m_BHarmonicEnabled = GetBIsHarmonic();
1746 }
1747 
1749 {
1750  if(Connected)
1751  {
1752  m_BHarmonicEnabled = GetBIsHarmonic();
1753  }
1754  return m_BHarmonicEnabled;
1755 }
1756 
1758 {
1759  if(Connected)
1760  {
1761  SetBIsBubbleContrast(value);
1762  SetPendingRecreateTables(true);
1763  }
1764  m_BBubbleContrastEnabled = GetBIsBubbleContrast();
1765 }
1766 
1768 {
1769  if(Connected)
1770  {
1771  m_BBubbleContrastEnabled = GetBIsBubbleContrast();
1772  }
1773  return m_BBubbleContrastEnabled;
1774 }
1775 
1777 {
1778  if(Connected)
1779  {
1780  SetBIsAmplitudeModulation(value);
1781  SetPendingRecreateTables(true);
1782  }
1783  m_BAmplitudeModulationEnabled = GetBIsAmplitudeModulation();
1784 }
1785 
1787 {
1788  if(Connected)
1789  {
1790  m_BAmplitudeModulationEnabled = GetBIsAmplitudeModulation();
1791  }
1793 }
1794 
1796 {
1797  if(Connected)
1798  {
1799  SetBIsTransmitLocked(value);
1800  SetPendingRecreateTables(true);
1801  }
1802  m_BTransmitLocked = GetBIsTransmitLocked();
1803 }
1804 
1806 {
1807  if(Connected)
1808  {
1809  m_BTransmitLocked = GetBIsTransmitLocked();
1810  }
1811  return m_BTransmitLocked;
1812 }
1813 
1814 
1816 {
1817  if(Connected)
1818  {
1819  SetBTxCurrent(value);
1820  SetPendingRecreateTables(true);
1821  }
1822  m_BTransmitCurrent = GetBTxCurrent();
1823 }
1824 
1826 {
1827  if(Connected)
1828  {
1829  m_BTransmitCurrent = GetBTxCurrent();
1830  }
1831  return m_BTransmitCurrent;
1832 }
1833 
1835 {
1836  if(Connected)
1837  {
1838  SetTxTxCycleCount(value);
1839  SetPendingRecreateTables(true);
1840  }
1842 }
1843 
1845 {
1846  if(Connected)
1847  {
1848  m_BTransmitCycleCount = GetTxTxCycleCount();
1849  }
1850  return m_BTransmitCycleCount;
1851 }
1852 
1854 {
1855  if(Connected)
1856  {
1857  SetTxTxFNumber(value);
1858  SetPendingRecreateTables(true);
1859  }
1861 }
1862 
1864 {
1865  if(Connected)
1866  {
1867  m_BTransmitFNumber = GetTxTxFNumber();
1868  }
1869  return m_BTransmitFNumber;
1870 }
1871 
1873 {
1874  if(Connected)
1875  {
1876  SetApodizationFNumber(value);
1877  SetPendingRecreateTables(true);
1878  }
1879  m_BApodizationFNumber = GetApodizationFNumber();
1880 }
1881 
1883 {
1884  if(Connected)
1885  {
1886  m_BApodizationFNumber = GetApodizationFNumber();
1887  }
1888  return m_BApodizationFNumber;
1889 }
1890 
1892 {
1893  if(Connected)
1894  {
1895  SetBisBubblePop(value);
1896  }
1897  m_BBubbleDestructionEnabled = GetBisBubblePop();
1898 }
1899 
1901 {
1902  if(Connected)
1903  {
1904  m_BBubbleDestructionEnabled = GetBisBubblePop();
1905  }
1907 }
1908 
1910 {
1911  if(Connected)
1912  {
1913  SetTxBubblePopCycleCount(value);
1914  SetPendingRecreateTables(true);
1915  }
1916  m_BBubbleDestructionCycleCount = GetTxBubblePopCycleCount();
1917 }
1918 
1920 {
1921  if(Connected)
1922  {
1923  m_BBubbleDestructionCycleCount = GetTxBubblePopCycleCount();
1924  }
1926 }
1927 
1929 {
1930  if(Connected)
1931  {
1932  SetTxFilterCoefficientSet(value);
1933  }
1934  m_BTXFilterCoefficientSet = GetTxFilterCoefficientSet();
1935 }
1936 
1938 {
1939  if(Connected)
1940  {
1941  m_BTXFilterCoefficientSet = GetTxFilterCoefficientSet();
1942  }
1944 }
1945 
1947 {
1948  bool mmodeEnabled = (m_Mode == Mode::M);
1949  if(Connected)
1950  {
1951  mmodeEnabled = GetMIsEnabled();
1952  if(mmodeEnabled)
1953  {
1954  m_Mode = Mode::M;
1955  }
1956  }
1957  return mmodeEnabled;
1958 }
1959 
1960 
1962 {
1963  if(Connected)
1964  {
1965  SetMIsRevolving(value);
1966  SetPendingRecreateTables(true);
1967  }
1969 }
1970 
1972 {
1973  if(Connected)
1974  {
1975  m_MRevolvingEnabled = GetMIsRevolving();
1976  }
1977  return m_MRevolvingEnabled;
1978 }
1979 
1981 {
1982  if(Connected)
1983  {
1984  SetMPRF(value);
1985  SetPendingRecreateTables(true);
1986  }
1987  m_MPRF = value;
1988 }
1989 
1991 {
1992  if(Connected)
1993  {
1994  m_MPRF = GetMPRF();
1995  }
1996  return m_MPRF;
1997 }
1998 
2000 {
2001  if(Connected)
2002  {
2003  SetMAcousticLineIndex(value);
2004  SetPendingRecreateTables(true);
2005  }
2006  m_MLineIndex = value;
2007 }
2008 
2010 {
2011  if(Connected)
2012  {
2013  m_MLineIndex = GetMAcousticLineIndex();
2014  }
2015  return m_MLineIndex;
2016 }
2017 
2019 {
2020  if(Connected)
2021  {
2022  int32_t mwidth = this->MWidthFromSeconds(value);
2023  ::SetMWidth(mwidth);
2024  SetPendingRecreateTables(true);
2025  m_MWidth = mwidth;
2026  }
2027 }
2028 
2030 {
2031  int mwidthSeconds = 0;
2032  if(Connected)
2033  {
2034  m_MWidth = ::GetMWidth();
2035  mwidthSeconds = this->MSecondsFromWidth(m_MWidth);
2036  }
2037  return mwidthSeconds;
2038 }
2039 
2041 {
2042  if(Connected)
2043  {
2044  ::SetMWidth(value);
2045  SetPendingRecreateTables(true);
2046  }
2047  m_MWidth = value;
2048 }
2049 
2051 {
2052  if(Connected)
2053  {
2054  m_MWidth = ::GetMWidth();
2055  }
2056  return m_MWidth;
2057 }
2058 
2060 {
2061  if(Connected)
2062  {
2064  SetPendingRecreateTables(true);
2065  }
2067 }
2068 
2070 {
2071  if(Connected)
2072  {
2074  }
2075  return m_MAcousticLineCount;
2076 }
2077 
2079 {
2080  if(Connected)
2081  {
2082  ::SetMDepth(value);
2083  SetPendingRecreateTables(true);
2084  }
2085  m_MDepth = value;
2086 }
2087 
2089 {
2090  if(Connected)
2091  {
2092  m_MDepth = ::GetMDepth();
2093  }
2094  return m_MDepth;
2095 }
2096 
2097 //----------------------------------------------------------------------------
2099 {
2100  if(Connected)
2101  {
2104  SetPendingRecreateTables(true);
2105  }
2106 }
2107 
2109 {
2110  if(Connected)
2111  {
2113  }
2114  return m_ARFIStartSample;
2115 }
2116 
2117 //----------------------------------------------------------------------------
2119 {
2120  if(Connected)
2121  {
2124  SetPendingRecreateTables(true);
2125  }
2126 }
2127 
2129 {
2130  if(Connected)
2131  {
2133  }
2134  return m_ARFIStopSample;
2135 }
2136 
2137 //----------------------------------------------------------------------------
2139 {
2140 
2141  if(Connected)
2142  {
2143  if(propertyValue > 2000)
2144  {
2145  LOG_ERROR("The maximum ARFI line timer is 2000. Ignoring call to change to " << propertyValue);
2146  return PLUS_FAIL;
2147  }
2148  m_ARFILineTimer = propertyValue;
2149  ::SetARFILineTimer(propertyValue);
2150  SetPendingRecreateTables(true);
2151  return PLUS_SUCCESS;
2152  }
2153  return PLUS_FAIL;
2154 }
2155 
2157 {
2158  if(Connected)
2159  {
2161  }
2162  return m_ARFILineTimer;
2163 }
2164 
2165 //----------------------------------------------------------------------------
2167 {
2168  if(Connected)
2169  {
2170  m_ARFIPrePushLineRepeatCount = propertyValue;
2171  ::SetARFIPrePushLineRepeatCount(propertyValue);
2172  SetPendingRecreateTables(true);
2173  return PLUS_SUCCESS;
2174  }
2175  return PLUS_FAIL;
2176 }
2177 
2179 {
2180  if(Connected)
2181  {
2183  }
2185 }
2186 
2187 //----------------------------------------------------------------------------
2189 {
2190  if(Connected)
2191  {
2192  m_ARFIPostPushLineRepeatCount = propertyValue;
2193  ::SetARFIPostPushLineRepeatCount(propertyValue);
2194  SetPendingRecreateTables(true);
2195  return PLUS_SUCCESS;
2196  }
2197  return PLUS_FAIL;
2198 }
2199 
2201 {
2202  if(Connected)
2203  {
2205  }
2207 }
2208 
2209 //----------------------------------------------------------------------------
2211 {
2212  if(Connected)
2213  {
2214  if(propertyValue > 250 * 250)
2215  {
2216  LOG_ERROR("The maximum ARFI inter set delay is 250*250. Ignoring call to change to " << propertyValue);
2217  return PLUS_FAIL;
2218  }
2219  else if (propertyValue == 0)
2220  {
2221  LOG_WARNING("ARFI inter set delay defaulting to clinical delay mode of approximately 1 second.");
2222  }
2223  m_ARFIInterSetDelay = propertyValue;
2224  ::SetARFIInterSetDelay(propertyValue); // API call includes SetPendingRecreateTables(true). Really just need SetPendingRestartSequencer(true);
2225  return PLUS_SUCCESS;
2226  }
2227  return PLUS_FAIL;
2228 }
2229 
2231 {
2232  if(Connected)
2233  {
2235  }
2236  return m_ARFIInterSetDelay;
2237 }
2238 
2239 //----------------------------------------------------------------------------
2241 {
2242  if(Connected)
2243  {
2244  if(propertyValue > 250)
2245  {
2246  LOG_ERROR("The maximum ARFI inter push delay is 250. Ignoring call to change to " << propertyValue);
2247  return PLUS_FAIL;
2248  }
2249  m_ARFIInterPushDelay = propertyValue;
2250  ::SetARFIInterPushDelay(propertyValue); // API call includes SetPendingRecreateTables(true). Really just need SetPendingRestartSequencer(true);
2251  return PLUS_SUCCESS;
2252  }
2253  return PLUS_FAIL;
2254 }
2255 
2257 {
2258  if(Connected)
2259  {
2261  }
2262  return m_ARFIInterPushDelay;
2263 }
2264 
2265 //----------------------------------------------------------------------------
2267 {
2268  if(Connected)
2269  {
2270  m_ARFIPushConfigurationCount = std::count(pushConfiguration.begin(), pushConfiguration.end(), ';') + 1;
2271  if(quadBFCount == 1)
2272  {
2273  LOG_ERROR("A X4BF does not support ARFI mode.");
2274  }
2275  WPSetARFIPushConfigurationString(pushConfiguration.c_str());
2276  SetPendingRecreateTables(true);
2277  }
2278 }
2279 
2280 //----------------------------------------------------------------------------
2282 {
2283  if(Connected)
2284  {
2285  char* temp = new char[50];
2286  WPGetARFIPushConfigurationString(temp);
2287  m_ARFIPushConfigurationString.assign(temp);
2288  delete[] temp;
2289  }
2291 }
2292 
2293 //----------------------------------------------------------------------------
2295 {
2296  char* temp = new char[20];
2297  WPGetFPGARevDateString(temp);
2298  m_FPGAVersion.assign(temp);
2299  delete[] temp;
2300  return m_FPGAVersion;
2301 }
2302 
2303 //----------------------------------------------------------------------------
2305 {
2306  this->m_TransducerID = guid;
2307  if(Connected)
2308  {
2309  WPSetTransducerID(guid.c_str());
2310  SetPendingRecreateTables(true);
2311  }
2312  return PLUS_SUCCESS;
2313 }
2314 
2315 //----------------------------------------------------------------------------
2317 {
2318  int transducer_id = ::GetTransducerInternalID();
2319  return transducer_id;
2320 }
2321 
2322 //----------------------------------------------------------------------------
2324 {
2325  std::vector<double> spacing = { 0.0, 0.0, 1.0};
2326  if(!m_PrimarySources.empty())
2327  {
2328  spacing[0] = this->GetTransducerWidthMm() / (m_PrimaryFrameSize[0] - 1);
2329  spacing[1] = m_ScanDepth / (m_PrimaryFrameSize[1] - 1);
2330  }
2331  return spacing;
2332 }
2333 
2335 {
2336  std::vector<double> spacing = { 0.0, 0.0, 1.0};
2337  if(!m_ExtraSources.empty())
2338  {
2339  if(GetBRFEnabled())
2340  {
2341  spacing[0] = m_ScanDepth / (m_ExtraFrameSize[0] - 1);
2342  spacing[1] = this->GetTransducerWidthMm() / (m_ExtraFrameSize[1] - 1);
2343  }
2344  else
2345  {
2346  spacing = GetPrimarySourceSpacing();
2347  }
2348  }
2349  return spacing;
2350 }
2351 
2353 {
2354  bool arfiEnabled = false;
2355  if(Connected)
2356  {
2357  arfiEnabled = (m_Mode == Mode::ARFI) && GetARFIIsEnabled();
2358  }
2359  return arfiEnabled;
2360 }
2361 
2362 PlusStatus vtkPlusWinProbeVideoSource::ARFIPush(uint8_t maximumVoltage /* = 50 */)
2363 {
2364  if (this->Connected && m_Mode == Mode::ARFI)
2365  {
2366  for(unsigned i = 0; i < m_ExtraSources.size(); i++)
2367  {
2368  m_ExtraSources[i]->Clear(); // clear the rf buffer to ensure frames in the buffer are current
2369  }
2370  if(m_FPGAVersion != "2020-10-24 24")
2371  {
2372  LOG_ERROR("The FPGA version must be '2020-10-24 24' to ARFIPush. Current version: " << m_FPGAVersion);
2373  return PLUS_FAIL;
2374  }
2375 
2376  // Mitigate risk of burning out probes with high voltage pushes
2377  // and ensure we're using the voltage that we think we are
2378  uint8_t cappedVoltage = this->GetVoltage();
2379  if (cappedVoltage > maximumVoltage)
2380  {
2381  LOG_WARNING("Voltage was higher than 50V before sending ARFI push. Capping voltage to " << std::to_string(maximumVoltage) << "V.");
2382  cappedVoltage = maximumVoltage;
2383  }
2384  this->SetVoltage(cappedVoltage);
2385  this->ImagingParameters->SetProbeVoltage(cappedVoltage);
2386 
2387  ::ARFIPush();
2388  return PLUS_SUCCESS;
2389  }
2390  return PLUS_FAIL;
2391 }
2392 
2394 {
2395  return this->m_TransducerID;
2396 }
2397 
2399 {
2400  if (Connected)
2401  {
2402  m_BPRF = ::GetBPRF();
2403  }
2404  return m_BPRF;
2405 }
2406 
2408 {
2409  if (Connected)
2410  {
2412  }
2414 }
2415 
2417 {
2418  if (Connected)
2419  {
2421  }
2422  return m_BFrameRateLimit;
2423 }
2424 
2426 {
2427  if (Connected)
2428  {
2429  ::SendCommand(command);
2430  return PLUS_SUCCESS;
2431  }
2432  return PLUS_FAIL;
2433 }
2434 
2435 //----------------------------------------------------------------------------
2437 {
2438  if (!this->Connected)
2439  {
2440  // trying to apply parameters when not connected leads to crashes
2441  LOG_ERROR("Cannot apply changes while not connected.")
2442  return PLUS_FAIL;
2443  }
2444 
2445  PlusStatus status = PLUS_SUCCESS;
2446 
2449  {
2451  {
2453  }
2454  else
2455  {
2456  LOG_ERROR("Failed to set depth imaging parameter");
2457  status = PLUS_FAIL;
2458  }
2459  }
2460 
2463  {
2465  {
2467  }
2468  else
2469  {
2470  LOG_ERROR("Failed to set voltage parameter");
2471  status = PLUS_FAIL;
2472  }
2473  }
2474 
2477  {
2479  {
2481  }
2482  else
2483  {
2484  LOG_ERROR("Failed to set frequency parameter");
2485  status = PLUS_FAIL;
2486  }
2487  }
2488  return status;
2489 }
void SetARFIPushConfigurationString(std::string pushConfiguration)
const uint32_t * data
Definition: phidget22.h:3971
static const char * SET_SPATIAL_COMPOUND_COUNT
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
static const std::string RFMODE_PORT_NAME
Definition: vtkPlusDevice.h:68
vtkPlusWinProbeVideoSource * thisPtr
PlusStatus ARFIPush(uint8_t maximumVoltage=50)
static const char * GET_B_TRANSMIT_CURRENT
PhidgetRCServo_Voltage voltage
Definition: phidget22.h:3331
bool IsPending(const std::string &paramName) const
static const char * GET_B_BUBBLE_CONTRAST_ENABLED
static const char * SET_ARFI_TX_TX_CYCLE_WIDTH
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
static const char * GET_ARFI_POST_PUSH_LINE_REPEAT_COUNT
static const char * SET_B_AMPLITUDE_MODULATION_ENABLED
virtual PlusStatus GetInputFrameSize(vtkPlusChannel &aChannel, unsigned int &x, unsigned int &y, unsigned int &z) const
static const char * GET_SPATIAL_COMPOUND_ANGLE
int32_t quadBFCount
double * timestamp
Definition: phidget22.h:3432
PlusStatus SetARFITxTxCycleWidth(uint8_t propertyValue)
void FrameCallback(int length, char *data, char *hHeader, char *hGeometry)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
PlusStatus SetARFITxCycleCount(uint16_t propertyValue)
PlusStatus SendCommand(const char *command)
Phidget_MeshMode mode
Definition: phidget22.h:1332
static const char * GET_SPATIAL_COMPOUND_COUNT
static const char * SET_B_TX_FILTER_COEFFICIENT_SET
static const char * GET_B_FRAME_RATE_LIMIT
PlusStatus SetVoltage(uint8_t voltage)
static const char * GET_B_HARMONIC_ENABLED
int __stdcall frameCallback(int length, char *data, char *hHeader, char *hGeometry, char *hModeFrameHeader)
virtual PlusStatus StartRecording()
static const char * SET_ARFI_TX_TX_CYCLE_COUNT
igsioStatus PlusStatus
Definition: PlusCommon.h:40
static const std::string BMODE_PORT_NAME
Definition: vtkPlusDevice.h:67
static const char * GET_B_MULTIFOCAL_ZONE_COUNT
PlusStatus GetDepthMm(double &aDepthMm) const
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
static const char * SET_SPATIAL_COMPOUND_ENABLED
friend int __stdcall frameCallback(int length, char *data, char *hHeader, char *hGeometry, char *hModeFrameHeader)
PlusStatus SetFocalPointDepth(int index, float depth)
std::string to_string(ClariusAvailability avail)
virtual PlusStatus InternalDisconnect() VTK_OVERRIDE
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
bool RequireImageOrientationInConfiguration
PlusStatus SetTimeGainCompensation(int index, double value)
for i
static const char * SET_B_TRANSMIT_CURRENT
PlusStatus SetPending(const std::string &paramName, bool pending)
static const char * GET_B_BUBBLE_DESTRUCTION_ENABLED
static const char * GET_B_APODIZATION_FNUMBER
static const char * GET_ARFI_TX_TX_CYCLE_WIDTH
double CurrentPixelSpacingMm[3]
Values used in calculation of image to transducer matrix.
#define PLUS_FAIL
Definition: PlusCommon.h:43
static const char * GET_B_BUBBLE_DESTRUCTION_CYCLE_COUNT
std::vector< uint8_t > m_PrimaryBuffer
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
static const char * GET_SPATIAL_COMPOUND_ENABLED
static const char * SET_ARFI_PRE_PUSH_LINE_REPEAT_COUNT
static const char * SET_B_BUBBLE_CONTRAST_ENABLED
void SetBBubbleDestructionCycleCount(int16_t value)
virtual PlusStatus Disconnect()
Class for acquiring ultrasound images from WinProbe ultrasound systems.
PlusStatus GetFirstActiveOutputVideoSource(vtkPlusDataSource *&aVideoSource)
void ReconstructFrame(char *data, std::vector< uint8_t > &buffer, const FrameSizeType &frameSize)
static const char * GET_ARFI_INTER_PUSH_DELAY
void FlipTexture(char *data, const FrameSizeType &frameSize, int rowPitch)
unsigned long FrameNumber
PlusStatus SetBMultiFocalZoneCount(int32_t count)
PlusStatus SetARFIPrePushLineRepeatCount(int32_t propertyValue)
PlusStatus SetTransducerID(std::string guid)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus SetFirstGainValue(double value)
PlusStatus SetARFIPostPushLineRepeatCount(int32_t propertyValue)
static const char * GET_FPGA_REV_DATE_STRING
PlusStatus SetARFITxTxCycleCount(uint16_t propertyValue)
static const char * GET_B_TRANSMIT_CYCLE_COUNT
PlusStatus SetARFIInterPushDelay(int32_t propertyValue)
PlusStatus SetProbeVoltage(float aVoltage)
PlusStatus SetSSDecimation(uint8_t value)
virtual PlusStatus StopRecording()
PlusStatus SetARFIFocalPointDepth(int index, float depth)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
virtual PlusStatus InternalStartRecording() VTK_OVERRIDE
std::vector< vtkPlusDataSource * > m_ExtraSources
static const char * SET_B_BUBBLE_DESTRUCTION_CYCLE_COUNT
PlusStatus SetTransmitFrequencyMHz(float frequency)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
const char const char * value
Definition: phidget22.h:5111
Phidget_ChannelClass uint32_t * count
Definition: phidget22.h:1321
PlusStatus GetProbeVoltage(float &aVoltage) const
PlusStatus SetARFIInterSetDelay(int32_t propertyValue)
virtual bool IsRecording() const
static const char * SET_B_BUBBLE_DESTRUCTION_ENABLED
Mode StringToMode(std::string modeString)
bool StartThreadForInternalUpdates
static const char * SET_B_MULTIFOCAL_ZONE_COUNT
PlusStatus SetARFITxCycleWidth(uint8_t propertyValue)
static const char * SET_ALL_ARFI_FOCAL_DEPTHS
PlusStatus InternalApplyImagingParameterChange() override
std::vector< vtkPlusDataSource * > m_PrimarySources
static const char * GET_B_AMPLITUDE_MODULATION_ENABLED
static const char * GET_B_TRANSMIT_FNUMBER
static const char * SET_ARFI_INTER_SET_DELAY
static const char * GET_M_REVOLVING_ENABLED
static const char * SET_B_TRANSMIT_CYCLE_COUNT
PlusStatus SetOverallTimeGainCompensation(double value)
virtual PlusStatus InternalStopRecording() VTK_OVERRIDE
static const char * SET_ARFI_POST_PUSH_LINE_REPEAT_COUNT
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
std::vector< double > GetExtraSourceSpacing()
static const char * SET_ARFI_INTER_PUSH_DELAY
static const char * GET_B_TX_FILTER_COEFFICIENT_SET
virtual igsioCommon::VTKScalarPixelType GetPixelType(vtkPlusChannel &aChannel)
static const char * SET_B_HARMONIC_ENABLED
std::vector< double > GetPrimarySourceSpacing()
virtual PlusStatus InternalConnect() VTK_OVERRIDE
static const char * SET_B_FRAME_RATE_LIMIT
bool IsSet(const std::string &paramName) const
double frequency
Definition: phidget22.h:3246
for t
Definition: exploreFolders.m:9
static const char * SET_B_TRANSMIT_FNUMBER
int32_t focalCountFromDepthsArray(float *depths, unsigned arraySize)
PlusStatus SetARFILineTimer(uint16_t propertyValue)
static const char * GET_ARFI_PRE_PUSH_LINE_REPEAT_COUNT
vtkStandardNewMacro(vtkPlusWinProbeVideoSource)
static const char * SET_M_REVOLVING_ENABLED
static const char * GET_ARFI_INTER_SET_DELAY
static const char * GET_ARFI_TX_TX_CYCLE_COUNT
static const char * SET_B_APODIZATION_FNUMBER
Interface to a 3D positioning tool, video source, or generalized data stream.
static const char * GET_TRANSDUCER_INTERNAL_ID