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