PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusSonixVideoSource.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 /*=========================================================================
8 The following copyright notice is applicable to parts of this file:
9 Copyright (c) 2008, Queen's University, Kingston, Ontario, Canada
10 All rights reserved.
11 Authors include:
12 Danielle Pace (Robarts Research Institute, The University of Western Ontario)
13 Siddharth Vikal (Queen's University, Kingston, Ontario, Canada)
14 Adam Rankin (Robarts Research Institute, The University of Western Ontario)
15 Andras Lasso (Queen's University, Kingston, Ontario, Canada)
16 =========================================================================*/
17 
18 // Local includes
19 #include "PlusConfigure.h"
20 #include "vtkPlusChannel.h"
21 #include "vtkPlusDataSource.h"
23 
24 // Ulterius includes
25 #include <ImagingModes.h> // Ulterius imaging modes
26 #include <ulterius_def.h>
27 
28 // VTK includes
29 #include <vtkImageData.h>
30 #include <vtkInformation.h>
31 #include <vtkInformationVector.h>
32 #include <vtkMultiThreader.h>
33 #include <vtkObjectFactory.h>
34 #include <vtkStreamingDemandDrivenPipeline.h>
35 #include <vtkTimerLog.h>
36 #include <vtkUnsignedCharArray.h>
38 #include <vtksys/SystemTools.hxx>
39 
40 // OS includes
41 #include <ctype.h>
42 
43 // STL includes
44 #include <string>
45 #include <vector>
46 
47 //----------------------------------------------------------------------------
48 
49 vtkPlusSonixVideoSource* vtkPlusSonixVideoSource::ActiveSonixDevice = NULL;
50 
51 //----------------------------------------------------------------------------
52 
54 
55 //----------------------------------------------------------------------------
56 
57 #if ( _MSC_VER >= 1300 ) // Visual studio .NET
58  #pragma warning ( disable : 4311 )
59  #pragma warning ( disable : 4312 )
60  #define vtkGetWindowLong GetWindowLongPtr
61  #define vtkSetWindowLong SetWindowLongPtr
62  #define vtkGWL_USERDATA GWLP_USERDATA
63 #else // regular Visual studio
64  #define vtkGetWindowLong GetWindowLong
65  #define vtkSetWindowLong SetWindowLong
66  #define vtkGWL_USERDATA GWL_USERDATA
67 #endif //
68 
69 static const int CONNECT_RETRY = 5;
70 static const int CONNECT_RETRY_DELAY_SEC = 1.0;
71 
72 //----------------------------------------------------------------------------
74  : Superclass()
75  , Ult(new ulterius)
76  , AcquisitionDataType(udtBPost)
77  , ImagingMode(BMode)
78  , OutputFormat(-1)
79  , CompressionStatus(0)
80  , Timeout(-1)
81  , ConnectionSetupDelayMs(3000)
82  , SharedMemoryStatus(0)
83  , RfAcquisitionMode(RF_ACQ_RF_ONLY)
84  , ImageGeometryChanged(false)
85  , SonixIP(NULL)
86  , UlteriusConnected(false)
87  , AutoClipEnabled(false)
88  , ImageGeometryOutputEnabled(false)
89  , ImagingParameterChanged(false)
90 {
91  this->SetSonixIP("127.0.0.1");
92  this->StartThreadForInternalUpdates = false;
93 
95 
96  // This effectively forces only one vtkPlusSonixVideoSource at a time, but it paves the way
97  // for a non-singleton architecture when the SDK supports it
98  if (vtkPlusSonixVideoSource::ActiveSonixDevice != NULL)
99  {
100  LOG_WARNING("There is already an active vtkPlusSonixVideoSource device. Ultrasonix SDK only supports one connection at a time, so the existing device is now deactivated and the newly created class is activated instead.");
101  }
102  vtkPlusSonixVideoSource::ActiveSonixDevice = this;
103 }
104 
105 //----------------------------------------------------------------------------
107 {
108  vtkPlusSonixVideoSource::ActiveSonixDevice = NULL;
109 
110  this->SetSonixIP(NULL);
111  delete this->Ult;
112  this->Ult = NULL;
113 }
114 
115 //----------------------------------------------------------------------------
117 {
118  std::ostringstream version;
119  version << "UltrasonixSDK-" << PLUS_ULTRASONIX_SDK_MAJOR_VERSION << "." << PLUS_ULTRASONIX_SDK_MINOR_VERSION << "." << PLUS_ULTRASONIX_SDK_PATCH_VERSION;
120  return version.str();
121 }
122 
123 //----------------------------------------------------------------------------
124 void vtkPlusSonixVideoSource::PrintSelf(ostream& os, vtkIndent indent)
125 {
126  this->Superclass::PrintSelf(os, indent);
127 }
128 
129 //----------------------------------------------------------------------------
130 // the callback function used when there is a new frame of data received
131 bool vtkPlusSonixVideoSource::vtkPlusSonixVideoSourceNewFrameCallback(void* data, int type, int sz, bool cine, int frmnum)
132 {
133  if (data == NULL || sz == 0)
134  {
135  LOG_DEBUG("vtkPlusSonixVideoSourceNewFrameCallback: called without data");
136  return false;
137  }
138 
139  if (vtkPlusSonixVideoSource::ActiveSonixDevice != NULL)
140  {
141  vtkPlusSonixVideoSource::ActiveSonixDevice->AddFrameToBuffer(data, type, sz, cine, frmnum);
142  }
143  else
144  {
145  LOG_ERROR("vtkPlusSonixVideoSource data callback but the ActiveSonixDevice is NULL. Disconnect between device and SDK.");
146  return false;
147  }
148 
149  return true;;
150 }
151 
152 //----------------------------------------------------------------------------
153 // the callback when parameters change on a device
154 bool vtkPlusSonixVideoSource::vtkPlusSonixVideoSourceParamCallback(void* paramId, int ptX, int ptY)
155 {
156  char* paramName = (char*)paramId;
157 
158  if (vtkPlusSonixVideoSource::ActiveSonixDevice == NULL)
159  {
160  LOG_ERROR("vtkPlusSonixVideoSource data callback but the ActiveSonixDevice is NULL. Disconnect between device and SDK.");
161  return false;
162  }
163 
164  vtkPlusSonixVideoSource::ActiveSonixDevice->ImagingParameterChanged = true;
165  vtkPlusSonixVideoSource::ActiveSonixDevice->ChangedImagingParameters[paramName] = true;
166 
167  if (STRCASECMP(paramName, "b-depth") == 0)
168  {
169  // we cannot query parameter values here, so just set a flag
170  // and get the value when getting the frame
171  vtkPlusSonixVideoSource::ActiveSonixDevice->ImageGeometryChanged = true;
172  return true;
173  }
174  else if (STRCASECMP(paramName, "probe id") == 0)
175  {
176  char probeName[200] = {0};
177  if (!vtkPlusSonixVideoSource::ActiveSonixDevice->Ult->getActiveProbe(probeName, 200))
178  {
179  LOG_ERROR("Unable to retrieve probe name: " << vtkPlusSonixVideoSource::ActiveSonixDevice->GetLastUlteriusError());
180  return false;
181  }
182  std::string probeString(probeName);
183  return true;
184  }
185  else if (STRCASECMP(paramName, "") == 0)
186  {
187  return true;
188  }
189  return false;
190 }
191 
192 //----------------------------------------------------------------------------
193 // Update imaging parameters from device
195 {
196  this->ImagingParameterChanged = false;
197  for (std::map<std::string, bool>::iterator changedParameterIt = this->ChangedImagingParameters.begin(); changedParameterIt != this->ChangedImagingParameters.end(); ++changedParameterIt)
198  {
199  bool parameterChanged = changedParameterIt->second;
200  if (!parameterChanged)
201  {
202  continue;
203  }
204  changedParameterIt->second = false;
205 
206  std::string parameterName = changedParameterIt->first;
207  if (parameterName == "b-freq")
208  {
209  double unused = 0;
210  this->GetFrequencyDevice(unused);
211  }
212  else if (parameterName == "b-depth")
213  {
214  int unused = 0;
215  this->GetDepthDevice(unused);
216  }
217  else if (parameterName == "b-gain")
218  {
219  int unused = 0;
220  this->GetGainDevice(unused);
221  }
222  else if (parameterName == "b-dyn log factor")
223  {
224  int unused = 0;
225  this->GetDynRangeDevice(unused);
226  }
227  else if (parameterName == "b-initial zoom")
228  {
229  int unused = 0;
230  this->GetZoomDevice(unused);
231  }
232  else if (parameterName == "sector")
233  {
234  int unused = 0;
235  this->GetSectorDevice(unused);
236  }
237  else if (parameterName == "b-tgc")
238  {
239  Plus_uTGC unused;
240  this->GetTimeGainCompensationDevice(unused);
241  }
242  else if (parameterName == "soundvelocity")
243  {
244  float unused = 0;
245  this->GetSoundVelocityDevice(unused);
246  }
247  }
248 }
249 
250 //----------------------------------------------------------------------------
251 // copy the Device Independent Bitmap from the VFW framebuffer into the
252 // vtkVideoSource framebuffer (don't do the unpacking yet)
253 PlusStatus vtkPlusSonixVideoSource::AddFrameToBuffer(void* dataPtr, int type, int sz, bool cine, int frmnum)
254 {
255 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 4)
256  LOG_ERROR("Minimum required Ultasonix SDK version is 5.x");
257  return PLUS_FAIL;
258 #endif
259 
260  if (!this->Recording)
261  {
262  // drop the frame, we are not recording data now
263  return PLUS_SUCCESS;
264  }
265 
266  std::vector<vtkPlusDataSource*> sources;
267  igsioCommon::VTKScalarPixelType pixelType = VTK_VOID;
268  US_IMAGE_TYPE imgType = US_IMG_TYPE_XX;
269 
270  if ((uData)type == udtBPost && this->GetVideoSourcesByPortName(vtkPlusDevice::BMODE_PORT_NAME, sources) == PLUS_SUCCESS)
271  {
272  pixelType = VTK_UNSIGNED_CHAR;
273  imgType = US_IMG_BRIGHTNESS;
274  }
275  else if ((uData)type == udtRF && this->GetVideoSourcesByPortName(vtkPlusDevice::RFMODE_PORT_NAME, sources) == PLUS_SUCCESS)
276  {
277  pixelType = VTK_SHORT;
278  imgType = US_IMG_RF_I_LINE_Q_LINE;
279  }
280  else
281  {
282  LOG_ERROR("Received data type \'" << type << "\' is unsupported. Please report this to the PLUS team.");
283  return PLUS_FAIL;
284  }
285 
286  // use the information about data type and frmnum to do cross checking that you are maintaining correct frame index, & receiving
287  // expected data type
288  this->FrameNumber = frmnum;
289 
290  vtkPlusDataSource* aSource = sources[0];
291 
292  FrameSizeType frameSize = aSource->GetInputFrameSize();
293  int frameBufferBytesPerPixel = aSource->GetNumberOfBytesPerPixel();
294  const unsigned int frameSizeInBytes = frameSize[0] * frameSize[1] * frameBufferBytesPerPixel;
295 
296  // for frame containing FC (frame count) in the beginning for data coming from cine, jump 2 bytes
297  int numberOfBytesToSkip = 0;
298 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 5) || (PLUS_ULTRASONIX_SDK_MAJOR_VERSION == 5 && PLUS_ULTRASONIX_SDK_MINOR_VERSION < 7)
299  if ((type == udtBPre) || (type == udtRF)
300  || (type == udtMPre) || (type == udtPWRF)
301  || (type == udtColorRF)
302  )
303  {
304  numberOfBytesToSkip = 4;
305  }
306 #else
307  // It's Ulterius 5.7 or newer.
308  // RF images don't have a 4-byte header. It's possible that none of the types have the 4-byte header anymore.
309  if ((type == udtBPre)
310  || (type == udtMPre) || (type == udtPWRF)
311  || (type == udtColorRF)
312  )
313  {
314  numberOfBytesToSkip = 4;
315  }
316 #endif
317 
318  if (sz != frameSizeInBytes + numberOfBytesToSkip)
319  {
320  // This typically occurs when Plus with Ultrasonix SDK 5.7.x is used with Exam software 6.0.7 or later
321  LOG_ERROR("Received frame size (" << sz << " bytes) doesn't match the buffer size (" << frameSizeInBytes + numberOfBytesToSkip << " bytes). Make sure the Ultrasonix SDK version used in Plus (" << GetSdkVersion() << ") is compatible with the Exam software running on the ultrasound device.");
322  return PLUS_FAIL;
323  }
324 
325  if (this->ImageGeometryChanged)
326  {
327  this->ImageGeometryChanged = false;
328  int currentDepth = -1;
329  if (!vtkPlusSonixVideoSource::ActiveSonixDevice->Ult->getParamValue("b-depth", currentDepth))
330  {
331  LOG_WARNING("Failed to retrieve b-depth parameter");
332  }
333  uPoint currentPixelSpacingMicron;
334  currentPixelSpacingMicron.x = -1;
335  currentPixelSpacingMicron.y = -1;
336  if (!vtkPlusSonixVideoSource::ActiveSonixDevice->Ult->getParamValue("microns", currentPixelSpacingMicron))
337  {
338  LOG_WARNING("Failed to retrieve bb-microns parameter");
339  }
340  uPoint currentTransducerOriginPixels;
341  currentTransducerOriginPixels.x = -1;
342  currentTransducerOriginPixels.y = -1;
343  if (!vtkPlusSonixVideoSource::ActiveSonixDevice->Ult->getParamValue("origin", currentTransducerOriginPixels))
344  {
345  LOG_WARNING("Failed to retrieve bb-origin parameter");
346  }
347 
348  this->ImagingParameters->SetDepthMm(currentDepth);
350  //TODO: Trigger parameter changed command
351 
352  this->CurrentPixelSpacingMm[0] = 0.001 * currentPixelSpacingMicron.x;
353  this->CurrentPixelSpacingMm[1] = 0.001 * currentPixelSpacingMicron.y;
354  // Use the mean spacing as Z spacing to minimize out-of-plane distortion
355  // when using this information for transforming non-planar objects
356  this->CurrentPixelSpacingMm[2] = (this->CurrentPixelSpacingMm[0] + this->CurrentPixelSpacingMm[1]) / 2.0;
357 
358  std::array<int, 3> clipRectangleOrigin = aSource->GetClipRectangleOrigin();
359  this->CurrentTransducerOriginPixels[0] = currentTransducerOriginPixels.x - clipRectangleOrigin[0];
360  this->CurrentTransducerOriginPixels[1] = currentTransducerOriginPixels.y - clipRectangleOrigin[1];
361  this->CurrentTransducerOriginPixels[2] = 0;
362  }
363 
364  if (this->ImagingParameterChanged)
365  {
367  }
368 
369  igsioFieldMapType customFields;
370 
371  if (this->ImageGeometryOutputEnabled)
372  {
373  std::ostringstream depthStr;
374  depthStr << this->ImagingParameters->GetDepthMm();
375  customFields["DepthMm"].first = FRAMEFIELD_FORCE_SERVER_SEND;
376  customFields["DepthMm"].second = depthStr.str();
377 
378  std::ostringstream pixelSpacingStr;
379  pixelSpacingStr << this->CurrentPixelSpacingMm[0] << " " << this->CurrentPixelSpacingMm[1];
380  customFields["PixelSpacingMm"].first = FRAMEFIELD_FORCE_SERVER_SEND;
381  customFields["PixelSpacingMm"].second = pixelSpacingStr.str();
382 
383  std::ostringstream transducerOriginStr;
384  transducerOriginStr << this->CurrentTransducerOriginPixels[0] << " " << this->CurrentTransducerOriginPixels[1];
385  // TODO : OpenIGTLink v3 will eliminate this short form necessity
386  customFields["TransducerOriginPix"].first = FRAMEFIELD_FORCE_SERVER_SEND;
387  customFields["TransducerOriginPix"].second = transducerOriginStr.str(); // "TransducerOriginPixels" would be over the 20-char limit of OpenIGTLink device name
388  }
389 
390  // get the pointer to actual incoming data on to a local pointer
391  unsigned char* deviceDataPtr = static_cast<unsigned char*>(dataPtr);
392 
393  PlusStatus status = this->AddVideoItemToVideoSources(sources, deviceDataPtr, aSource->GetInputImageOrientation(), frameSize, pixelType, 1, imgType, numberOfBytesToSkip, this->FrameNumber, UNDEFINED_TIMESTAMP, UNDEFINED_TIMESTAMP, &customFields);
394  this->Modified();
395 
396  return status;
397 }
398 
399 //----------------------------------------------------------------------------
401 {
402  this->Ult->setMessaging(false); // don't print messages on stdout
403 
404  int requestedImagingDataType = 0;
405  if (GetRequestedImagingDataTypeFromSources(requestedImagingDataType) != PLUS_SUCCESS)
406  {
407  LOG_ERROR("Failed to connect to sonix video device");
408  return PLUS_FAIL;
409  }
410 
411  switch (requestedImagingDataType)
412  {
414  LOG_DEBUG("Imaging mode set: BMode");
415  this->ImagingMode = BMode;
417  this->AcquisitionDataType = udtBPost;
418  break;
420  LOG_DEBUG("Imaging mode set: RfMode");
421 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 6)
422  this->ImagingMode = RfMode;
423 #else
424  this->ImagingMode = 0; // RfMode is always enabled for SDK 6.x
425 #endif
427  this->AcquisitionDataType = udtRF;
428  break;
430  LOG_DEBUG("Imaging mode set: BAndRfMode");
431 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 6)
432  this->ImagingMode = RfMode;
433 #else
434  this->ImagingMode = BMode; // RfMode is always enabled for SDK 6.x
435 #endif
437  this->AcquisitionDataType = udtBPost | udtRF;
438  break;
439  default:
440  LOG_ERROR("Unsupported imaging data types are requested: " << requestedImagingDataType);
441  return PLUS_FAIL;
442  }
443 
444  // Connect to device. Sometimes it just fails so try to make it more robust by retrying
445  // the connection a few times.
446  int connectionTried = 0;
447  bool initializationCompleted = false;
448  while (!initializationCompleted)
449  {
450  if (this->UlteriusConnected)
451  {
452  // a previous connection setup attempt failed after connection has been made, so
453  // disconnect before trying to connect again
454  this->Ult->setDataToAcquire(0); // without this Ulterius 5.x may crash
455  this->Ult->disconnect();
456  vtkIGSIOAccurateTimer::Delay(0.5); // without this Ulterius 6.x may crash
457  this->UlteriusConnected = false;
458  }
459  if (connectionTried > 0)
460  {
461  // this is a connection retry attempt
462  if (connectionTried >= CONNECT_RETRY)
463  {
464  LOG_ERROR("Failed to connect to sonix video device");
465  return PLUS_FAIL;
466  }
467  LOG_DEBUG("Failed to connect to sonix video device, retry (" << connectionTried << ")");
468  vtkIGSIOAccurateTimer::Delay(CONNECT_RETRY_DELAY_SEC);
469  }
470  connectionTried++;
471 
472  if (this->SonixIP == NULL)
473  {
474  LOG_ERROR("Sonix host IP address is undefined");
475  continue;
476  }
477 
478  // Connect to the imaging device
479  if (!this->Ult->connect(this->SonixIP))
480  {
481  LOG_ERROR("Initialize: couldn't connect to Ultrasonix at " << this->SonixIP << " address (error message: " << GetLastUlteriusError() << ")");
482  continue;
483  }
484  this->UlteriusConnected = true;
485 
486  // Set the imaging mode
487  if (SetImagingModeDevice(this->ImagingMode) != PLUS_SUCCESS) { continue; }
488 
489  // We need to wait for a little while before the mode actually gets selected
490  vtkIGSIOAccurateTimer::Delay(0.001 * this->ConnectionSetupDelayMs);
491 
492  // Double-check to see if the mode has actually been set
493  int actualImagingMode = -1;
494  if (GetImagingModeDevice(actualImagingMode) != PLUS_SUCCESS)
495  {
496  LOG_ERROR("Initialize: Cannot check actual imaging mode");
497  continue;
498  }
499  if (this->ImagingMode != actualImagingMode)
500  {
501  LOG_ERROR("Initialize: Requested imaging mode could not be selected (requested: " << this->ImagingMode << ", actual: " << actualImagingMode);
502  continue;
503  }
504 
505  // Set up imaging parameters
506  // Parameter value <0 means that the parameter should be kept unchanged
507  if (this->ImagingParameters->GetFrequencyMhz() >= 0 && this->SetFrequencyDevice(this->ImagingParameters->GetFrequencyMhz()) != PLUS_SUCCESS) { continue; }
508  if (this->ImagingParameters->GetDepthMm() >= 0 && this->SetDepthDevice(this->ImagingParameters->GetDepthMm()) != PLUS_SUCCESS) { continue; }
509  if (this->ImagingParameters->GetSectorPercent() >= 0 && this->SetSectorDevice(this->ImagingParameters->GetSectorPercent()) != PLUS_SUCCESS) { continue; }
510  if (this->ImagingParameters->GetGainPercent() >= 0 && this->SetGainDevice(this->ImagingParameters->GetGainPercent()) != PLUS_SUCCESS) { continue; }
511  if (this->ImagingParameters->GetDynRangeDb() >= 0 && this->SetDynRangeDevice(this->ImagingParameters->GetDynRangeDb()) != PLUS_SUCCESS) { continue; }
512  if (this->ImagingParameters->GetZoomFactor() >= 0 && this->SetZoomDevice(this->ImagingParameters->GetZoomFactor()) != PLUS_SUCCESS) { continue; }
513  if (this->CompressionStatus >= 0 && this->SetCompressionStatus(this->CompressionStatus) != PLUS_SUCCESS) { continue; }
515 
516  if (this->AcquisitionRate <= 0)
517  {
518  // AcquisitionRate has not been specified, set it to match the frame rate
519  int aFrameRate = 10;
520  if (this->Ult->getParamValue("frame rate", aFrameRate))
521  {
522  this->AcquisitionRate = aFrameRate;
523  }
524  }
525 
526  Ult->setSharedMemoryStatus(this->SharedMemoryStatus);
527 
528 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 6)
529  // RF acquisition mode is always enabled on Ultrasonix SDK 6.x and above, so we only need to change it if it's an earlier SDK version
530  if (this->ImagingMode == RfMode)
531  {
533  {
534  LOG_ERROR("Initialize: Cannot set RF acquisition mode");
535  continue;
536  }
537  RfAcquisitionModeType actualRfAcquisitionMode = RF_UNKNOWN;
538  if (GetRfAcquisitionModeDevice(actualRfAcquisitionMode) != PLUS_SUCCESS)
539  {
540  LOG_ERROR("Initialize: Cannot check actual RF acquisition mode");
541  continue;
542  }
543  if (this->RfAcquisitionMode != actualRfAcquisitionMode)
544  {
545  LOG_ERROR("Initialize: Requested RF acquisition mode could not be selected (requested: " << this->RfAcquisitionMode << ", actual: " << actualRfAcquisitionMode);
546  continue;
547  }
548  }
549 #endif
550 
551  // Wait for the depth change to take effect before calling ConfigureVideoSource()
552  // (it is especially important if auto clipping is enabled because then we need accurate frame size)
553  Sleep(1000);
554 
555  // Configure video sources
556  if (this->WantDataType(udtBPost))
557  {
558  if (!this->HasDataType(udtBPost))
559  {
560  // This typically occurs when Plus with Ultrasonix SDK 6.1.0 is used with Exam software 6.0.2
561  LOG_ERROR("No B-mode data is available. Make sure the Ultrasonix SDK version used in Plus (" << GetSdkVersion() << ") is compatible with the Exam software running on the ultrasound device.");
562  continue;
563  }
564  if (this->ConfigureVideoSource(udtBPost) != PLUS_SUCCESS)
565  {
566  LOG_ERROR("Unable to configure B-mode video source");
567  continue;
568  }
569  }
570  if (this->WantDataType(udtRF))
571  {
572  if (!this->HasDataType(udtRF))
573  {
574  LOG_ERROR("No Rf-mode data is available");
575  continue;
576  }
577  if (this->ConfigureVideoSource(udtRF) != PLUS_SUCCESS)
578  {
579  LOG_ERROR("Unable to configure Rf-mode video source");
580  continue;
581  }
582  }
583 
584  // Actually request data, now that its available
585  if (!this->Ult->setDataToAcquire(this->AcquisitionDataType))
586  {
587  LOG_ERROR("Setting AcquisitionDataType failed: couldn't request the data aquisition type " << this->AcquisitionDataType << ", " << GetLastUlteriusError());
588  return PLUS_FAIL;
589  }
590 
591  // Set callback and timeout for receiving new frames
592  this->Ult->setCallback(vtkPlusSonixVideoSourceNewFrameCallback);
593  if (this->Timeout >= 0 && this->SetTimeout(this->Timeout) != PLUS_SUCCESS)
594  {
595  continue;
596  }
597 
598  // Set the param callback so we can observe depth and plane changes
599  this->Ult->setParamCallback(vtkPlusSonixVideoSourceParamCallback);
600 
601  initializationCompleted = true;
602  this->ImageGeometryChanged = true; // trigger an initial update of geometry info
603  this->ImagingParameterChanged = true; // trigger an initial update of the following parameters
604  this->ChangedImagingParameters["b-freq"] = true;
605  this->ChangedImagingParameters["b-depth"] = true;
606  this->ChangedImagingParameters["b-gain"] = true;
607  this->ChangedImagingParameters["b-dyn log factor"] = true;
608  this->ChangedImagingParameters["b-initial zoom"] = true;
609  this->ChangedImagingParameters["sector"] = true;
610  this->ChangedImagingParameters["b-tgc"] = true;
611  this->ChangedImagingParameters["soundvelocity"] = true;
612  } // while (!initializationCompleted)
613 
614  LOG_DEBUG("Successfully connected to sonix video device");
615  return PLUS_SUCCESS;
616 }
617 
618 //----------------------------------------------------------------------------
620 {
621  this->UlteriusConnected = false;
622  this->Ult->setDataToAcquire(0); // without this Ulterius 5.x may crash
623  this->Ult->disconnect();
624  vtkIGSIOAccurateTimer::Delay(0.5); // without this Ulterius 6.x may crash
625  return PLUS_SUCCESS;
626 }
627 
628 //----------------------------------------------------------------------------
630 {
631  // Unfreeze
632  if (this->Ult->getFreezeState())
633  {
634  this->Ult->toggleFreeze();
635  }
636 
637  return PLUS_SUCCESS;
638 }
639 
640 //----------------------------------------------------------------------------
642 {
643  // Freeze
644  if (!this->Ult->getFreezeState())
645  {
646  this->Ult->toggleFreeze();
647  }
648 
649  return PLUS_SUCCESS;
650 }
651 
652 //-----------------------------------------------------------------------------
653 PlusStatus vtkPlusSonixVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
654 {
655  LOG_TRACE("vtkPlusSonixVideoSource::ReadConfiguration");
656 
657  vtkXMLDataElement* deviceConfig = this->FindThisDeviceElement(rootConfigElement);
658  if (deviceConfig == NULL)
659  {
660  LOG_ERROR("Unable to continue configuration of " << this->GetClassName() << ". Could not find corresponding element.");
661  return PLUS_FAIL;
662  }
663 
664  const char* ipAddress = deviceConfig->GetAttribute("IP");
665  if (ipAddress != NULL)
666  {
667  this->SetSonixIP(ipAddress);
668  LOG_DEBUG("Sonix Video IP: " << ipAddress);
669  }
670  else
671  {
672  LOG_WARNING("Ultrasonix IP address is not defined. Defaulting to " << this->GetSonixIP());
673  }
674 
675  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(AutoClipEnabled, deviceConfig);
676  XML_READ_BOOL_ATTRIBUTE_OPTIONAL(ImageGeometryOutputEnabled, deviceConfig);
677 
678  if (Superclass::ReadConfiguration(rootConfigElement) != PLUS_SUCCESS)
679  {
680  int depth;
681  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "Depth", depth, deviceConfig);
682  this->ImagingParameters->SetDepthMm(depth);
683  int tgc[8];
684  XML_READ_VECTOR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, 8, "TimeGainCompensation", tgc, deviceConfig);
685  std::vector<double> tgcVec(tgc, tgc + 8);
687  int sector;
688  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "Sector", sector, deviceConfig);
689  this->ImagingParameters->SetSectorPercent(sector);
690  int gain;
691  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "Gain", gain, deviceConfig);
692  this->ImagingParameters->SetGainPercent(gain);
693  int dynRange;
694  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "DynRange", dynRange, deviceConfig);
695  this->ImagingParameters->SetDynRangeDb(dynRange);
696  int zoom;
697  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "Zoom", zoom, deviceConfig);
698  this->ImagingParameters->SetZoomFactor(zoom);
699  int freq;
700  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "Frequency", freq, deviceConfig);
701  this->ImagingParameters->SetFrequencyMhz(freq);
702  int soundVel;
703  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, "SoundVelocity", soundVel, deviceConfig);
704  this->ImagingParameters->SetSoundVelocity(soundVel);
705  }
706 
707  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, CompressionStatus, deviceConfig);
708  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, SharedMemoryStatus, deviceConfig);
709  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, Timeout, deviceConfig);
710  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(double, ConnectionSetupDelayMs, deviceConfig);
711 
713  {
714  LOG_ERROR("Failed to change imaging parameters in the device");
715  return PLUS_FAIL;
716  }
717 
718  return PLUS_SUCCESS;
719 }
720 
721 //-----------------------------------------------------------------------------
723 {
724  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfig);
725 
726  if (this->ImagingMode == BMode)
727  {
728  deviceConfig->SetAttribute("ImagingMode", "BMode");
729  }
730 #if (PLUS_ULTRASONIX_SDK_MAJOR_VERSION < 6) // RF acquisition mode is not supported on Ultrasonix SDK 6.x and above - see #489 in https://plustoolkit.github.io/legacytickets
731  else if (this->ImagingMode == RfMode)
732  {
733  deviceConfig->SetAttribute("ImagingMode", "RfMode");
734  }
735 #endif
736  else
737  {
738  LOG_ERROR("Saving of unsupported ImagingMode requested!");
739  }
740 
741  deviceConfig->SetAttribute("IP", this->SonixIP);
742  deviceConfig->SetIntAttribute("CompressionStatus", this->CompressionStatus);
743  deviceConfig->SetIntAttribute("Timeout", this->Timeout);
744  deviceConfig->SetDoubleAttribute("ConnectionSetupDelayMs", this->ConnectionSetupDelayMs);
745 
746  XML_WRITE_BOOL_ATTRIBUTE(AutoClipEnabled, deviceConfig);
747  XML_WRITE_BOOL_ATTRIBUTE(ImageGeometryOutputEnabled, deviceConfig);
748 
749  Superclass::WriteConfiguration(deviceConfig);
750 
751  return PLUS_SUCCESS;
752 }
753 
754 //----------------------------------------------------------------------------
756 {
757  const unsigned int MAX_ULTERIUS_ERROR_MSG_LENGTH = 256;
758  char err[MAX_ULTERIUS_ERROR_MSG_LENGTH + 1];
759  err[MAX_ULTERIUS_ERROR_MSG_LENGTH] = 0; // make sure the string is null-terminated
760  this->Ult->getLastError(err, MAX_ULTERIUS_ERROR_MSG_LENGTH);
761 
762  return err;
763 }
764 
765 //----------------------------------------------------------------------------
766 PlusStatus vtkPlusSonixVideoSource::SetParamValueDevice(char* paramId, int paramValue, int& validatedParamValue)
767 {
768  if (!this->UlteriusConnected)
769  {
770  // Connection has not been established yet. Parameter value will be set upon connection.
771  validatedParamValue = paramValue;
772  return PLUS_SUCCESS;
773  }
774  if (!this->Ult->setParamValue(paramId, paramValue))
775  {
776  LOG_ERROR("vtkPlusSonixVideoSource::SetParamValue failed (paramId=" << paramId << ", paramValue=" << paramValue << ") " << GetLastUlteriusError());
777  return PLUS_FAIL;
778  }
779  validatedParamValue = paramValue;
780  return PLUS_SUCCESS;
781 }
782 
783 //----------------------------------------------------------------------------
784 PlusStatus vtkPlusSonixVideoSource::SetParamValueDevice(char* paramId, Plus_uTGC& paramValue, Plus_uTGC& validatedParamValue)
785 {
786  if (!this->UlteriusConnected)
787  {
788  // Connection has not been established yet. Parameter value will be set upon connection.
789  validatedParamValue = paramValue;
790  return PLUS_SUCCESS;
791  }
792  if (!this->Ult->setParamValue(paramId, paramValue))
793  {
794  std::stringstream ss;
795  ss << paramValue.v1 << ", " << paramValue.v2 << ", " << paramValue.v3 << ", " << paramValue.v4 << ", " << paramValue.v5 << ", " <<
796  paramValue.v6 << ", " << paramValue.v7 << ", " << paramValue.v8;
797  LOG_ERROR("vtkPlusSonixVideoSource::SetParamValue failed (paramId=" << paramId << ", paramValue=" << ss.str() << ") " << GetLastUlteriusError());
798  return PLUS_FAIL;
799  }
800  validatedParamValue = paramValue;
801  return PLUS_SUCCESS;
802 }
803 
804 //----------------------------------------------------------------------------
805 PlusStatus vtkPlusSonixVideoSource::GetParamValueDevice(char* paramId, int& paramValue, int& validatedParamValue)
806 {
807  if (!this->UlteriusConnected)
808  {
809  // Connection has not been established yet. Returned the cached value.
810  paramValue = validatedParamValue;
811  return PLUS_SUCCESS;
812  }
813  paramValue = -1;
814  if (!this->Ult->getParamValue(paramId, paramValue))
815  {
816  LOG_ERROR("vtkPlusSonixVideoSource::GetParamValue failed (paramId=" << paramId << ", paramValue=" << paramValue << ") " << GetLastUlteriusError());
817  return PLUS_FAIL;
818  }
819  validatedParamValue = paramValue;
820  return PLUS_SUCCESS;
821 }
822 
823 //----------------------------------------------------------------------------
824 PlusStatus vtkPlusSonixVideoSource::GetParamValueDevice(char* paramId, Plus_uTGC& paramValue, Plus_uTGC& validatedParamValue)
825 {
826  if (!this->UlteriusConnected)
827  {
828  // Connection has not been established yet. Returned the cached value.
829  paramValue = validatedParamValue;
830  return PLUS_SUCCESS;
831  }
832  if (!this->Ult->getParamValue(paramId, paramValue))
833  {
834  std::stringstream ss;
835  ss << paramValue.v1 << ", " << paramValue.v2 << ", " << paramValue.v3 << ", " << paramValue.v4 << ", " << paramValue.v5 << ", " <<
836  paramValue.v6 << ", " << paramValue.v7 << ", " << paramValue.v8;
837  LOG_ERROR("vtkPlusSonixVideoSource::GetParamValue failed (paramId=" << paramId << ", paramValue=" << ss.str() << ") " << GetLastUlteriusError());
838  return PLUS_FAIL;
839  }
840  validatedParamValue = paramValue;
841  return PLUS_SUCCESS;
842 }
843 
844 //----------------------------------------------------------------------------
846 {
847  // Convert frequency between MHz and Hz
848  int frequencyHz = aFrequencyMHz * 1000000;
849  PlusStatus result = this->SetParamValueDevice("b-freq", frequencyHz, frequencyHz);
850  aFrequencyMHz = frequencyHz / 1000000.0;
851  if (result == PLUS_SUCCESS)
852  {
853  this->ImagingParameters->SetFrequencyMhz(aFrequencyMHz);
855  }
856  return result;
857 }
858 
859 //----------------------------------------------------------------------------
861 {
862  // Convert frequency between MHz and Hz
863  int frequencyHz = aFrequencyMHz * 1000000;
864  PlusStatus result = this->GetParamValueDevice("b-freq", frequencyHz, frequencyHz);
865  aFrequencyMHz = frequencyHz / 1000000.0;
866  if (result == PLUS_SUCCESS)
867  {
868  this->ImagingParameters->SetFrequencyMhz(aFrequencyMHz);
870  }
871  return result;
872 }
873 
874 //----------------------------------------------------------------------------
876 {
877  PlusStatus result = SetParamValueDevice("b-depth", aDepth, aDepth);
878  if (result == PLUS_SUCCESS)
879  {
880  this->ImagingParameters->SetDepthMm(aDepth);
882  }
883  return result;
884 }
885 
886 //----------------------------------------------------------------------------
888 {
889  PlusStatus result = GetParamValueDevice("b-depth", aDepth, aDepth);
890  if (result == PLUS_SUCCESS)
891  {
892  this->ImagingParameters->SetDepthMm(aDepth);
894  }
895  return result;
896 }
897 
898 //----------------------------------------------------------------------------
900 {
901  // Ultrasonix uses values of -3000 for 0% and +3000 for 100%
902  // Need to convert between the different units
903  int gainUltrasonixUnits = 6000 * (aGainPercent / 100.0) - 3000;
904  PlusStatus result = SetParamValueDevice("b-gain", gainUltrasonixUnits, gainUltrasonixUnits);
905  aGainPercent = ((gainUltrasonixUnits + 3000.0) / 6000.0) * 100.0;
906  if (result == PLUS_SUCCESS)
907  {
908  this->ImagingParameters->SetGainPercent(aGainPercent);
910  }
911  return result;
912 }
913 
914 //----------------------------------------------------------------------------
916 {
917  // Ultrasonix uses values of -3000 for 0% and +3000 for 100%
918  // Need to convert between the different units
919  int gainUltrasonixUnits = 6000 * (aGainPercent / 100.0) - 3000;
920  PlusStatus result = this->GetParamValueDevice("b-gain", gainUltrasonixUnits, gainUltrasonixUnits);
921  aGainPercent = ((gainUltrasonixUnits + 3000.0) / 6000.0) * 100.0;
922  if (result == PLUS_SUCCESS)
923  {
924  this->ImagingParameters->SetGainPercent(aGainPercent);
926  }
927  return result;
928 }
929 
930 //----------------------------------------------------------------------------
932 {
933  PlusStatus result = this->SetParamValueDevice("b-dyn log factor", aDynRange, aDynRange);
934  if (result == PLUS_SUCCESS)
935  {
936  this->ImagingParameters->SetDynRangeDb(aDynRange);
938  }
939  return result;
940 }
941 
942 //----------------------------------------------------------------------------
944 {
945  PlusStatus result = this->GetParamValueDevice("b-dyn log factor", aDynRange, aDynRange);
946  if (result == PLUS_SUCCESS)
947  {
948  this->ImagingParameters->SetDynRangeDb(aDynRange);
950  }
951  return result;
952 }
953 
954 //----------------------------------------------------------------------------
956 {
957  PlusStatus result = SetParamValueDevice("b-initial zoom", aZoom, aZoom);
958  if (result == PLUS_SUCCESS)
959  {
960  this->ImagingParameters->SetZoomFactor(aZoom);
962  }
963  return result;
964 }
965 
966 //----------------------------------------------------------------------------
968 {
969  PlusStatus result = GetParamValueDevice("b-initial zoom", aZoom, aZoom);
970  if (result == PLUS_SUCCESS)
971  {
972  this->ImagingParameters->SetZoomFactor(aZoom);
974  }
975  return result;
976 }
977 
978 //----------------------------------------------------------------------------
980 {
981  PlusStatus result = SetParamValueDevice("sector", aSector, aSector);
982  if (result == PLUS_SUCCESS)
983  {
984  this->ImagingParameters->SetSectorPercent(aSector);
986  }
987  return result;
988 }
989 
990 //----------------------------------------------------------------------------
992 {
993  PlusStatus result = GetParamValueDevice("sector", aSector, aSector);
994  if (result == PLUS_SUCCESS)
995  {
996  this->ImagingParameters->SetSectorPercent(aSector);
998  }
999  return result;
1000 }
1001 
1002 //----------------------------------------------------------------------------
1004 {
1005  Plus_uTGC tgcStruct;
1006  tgcStruct.v1 = tgc[0];
1007  tgcStruct.v2 = tgc[1];
1008  tgcStruct.v3 = tgc[2];
1009  tgcStruct.v4 = tgc[3];
1010  tgcStruct.v5 = tgc[4];
1011  tgcStruct.v6 = tgc[5];
1012  tgcStruct.v7 = tgc[6];
1013  tgcStruct.v8 = tgc[7];
1014  // todo validate this parameter name
1015  PlusStatus result = this->SetParamValueDevice("b-tgc", tgcStruct, tgcStruct);
1016  if (result == PLUS_SUCCESS)
1017  {
1018  std::vector<int> vec = tgcStruct.toVector();
1019  std::vector<double> vecDouble(vec.begin(), vec.end());
1020  this->ImagingParameters->SetTimeGainCompensation(vecDouble);
1022  }
1023  return result;
1024 }
1025 
1026 //----------------------------------------------------------------------------
1028 {
1029  Plus_uTGC local = tgc;
1030  PlusStatus result = this->SetParamValueDevice("b-tgc", local, local);
1031  if (result == PLUS_SUCCESS)
1032  {
1033  std::vector<int> vec = local.toVector();
1034  std::vector<double> vecDouble(vec.begin(), vec.end());
1035  this->ImagingParameters->SetTimeGainCompensation(vecDouble);
1037  }
1038  return result;
1039 }
1040 
1041 //----------------------------------------------------------------------------
1043 {
1044  Plus_uTGC tgcStruct;
1045  PlusStatus result = GetParamValueDevice("b-tgc", tgcStruct, tgcStruct);
1046  if (result == PLUS_SUCCESS)
1047  {
1048  // Cache the value of this request
1049  std::vector<int> vec = tgcStruct.toVector();
1050  std::vector<double> vecDouble(vec.begin(), vec.end());
1051  this->ImagingParameters->SetTimeGainCompensation(vecDouble);
1053  std::copy(tgcStruct.toVector().begin(), tgcStruct.toVector().end(), tgc);
1054  }
1055  return result;
1056 }
1057 
1058 //----------------------------------------------------------------------------
1060 {
1061  PlusStatus result = GetParamValueDevice("b-tgc", tgc, tgc);
1062  if (result == PLUS_SUCCESS)
1063  {
1064  // Cache the value of this request
1065  std::vector<int> vec = tgc.toVector();
1066  std::vector<double> vecDouble(vec.begin(), vec.end());
1067  this->ImagingParameters->SetTimeGainCompensation(vecDouble);
1069  }
1070  return result;
1071 }
1072 
1073 //----------------------------------------------------------------------------
1075 {
1076  int soundVelocity = int(_arg);
1077  PlusStatus result = this->SetParamValueDevice("soundvelocity", soundVelocity, soundVelocity);
1078  if (result == PLUS_SUCCESS)
1079  {
1080  this->ImagingParameters->SetSoundVelocity(_arg);
1082  }
1083  return result;
1084 }
1085 
1086 //----------------------------------------------------------------------------
1088 {
1089  int soundVel;
1090  PlusStatus result = GetParamValueDevice("soundvelocity", soundVel, soundVel);
1091  if (result == PLUS_SUCCESS)
1092  {
1093  soundVelocity = float(soundVel);
1094  this->ImagingParameters->SetSoundVelocity(soundVelocity);
1096  }
1097  return result;
1098 }
1099 
1100 //----------------------------------------------------------------------------
1102 {
1103  if (!this->UlteriusConnected)
1104  {
1105  // Connection has not been established yet. Parameter value will be set upon connection.
1106  this->CompressionStatus = aCompressionStatus;
1107  return PLUS_SUCCESS;
1108  }
1109  if (!this->Ult->setCompressionStatus(aCompressionStatus))
1110  {
1111  LOG_ERROR("vtkPlusSonixVideoSource::SetCompressionStatus failed: (compressionStatus=" << aCompressionStatus << ") " << GetLastUlteriusError());
1112  return PLUS_FAIL;
1113  }
1114  this->CompressionStatus = aCompressionStatus;
1115  return PLUS_SUCCESS;
1116 
1117 }
1118 
1119 //----------------------------------------------------------------------------
1121 {
1122  if (!this->UlteriusConnected)
1123  {
1124  // Connection has not been established yet. Parameter value will be set upon connection.
1125  aCompressionStatus = this->CompressionStatus;
1126  return PLUS_SUCCESS;
1127  }
1128  aCompressionStatus = this->Ult->getCompressionStatus();
1129  this->CompressionStatus = aCompressionStatus;
1130  return PLUS_SUCCESS;
1131 }
1132 
1133 //----------------------------------------------------------------------------
1135 {
1136  if (!this->UlteriusConnected)
1137  {
1138  // Connection has not been established yet. Parameter value will be set upon connection.
1139  this->Timeout = aTimeout;
1140  return PLUS_SUCCESS;
1141  }
1142  if (aTimeout < 0)
1143  {
1144  LOG_ERROR("vtkPlusSonixVideoSource::setTimeout failed: (aTimeout=" << aTimeout << ") " << GetLastUlteriusError());
1145  return PLUS_FAIL;
1146  }
1147  this->Ult->setTimeout(aTimeout);
1148  this->Timeout = aTimeout;
1149  return PLUS_SUCCESS;
1150 }
1151 
1152 //----------------------------------------------------------------------------
1154 {
1155  if (!this->UlteriusConnected)
1156  {
1157  // Connection has not been established yet. Parameter value will be set upon connection.
1158  this->AcquisitionDataType = aAcquisitionDataType;
1159  return PLUS_SUCCESS;
1160  }
1161  // Check if the desired acquisition type is actually available on desired imaging mode
1162  if (!this->Ult->isDataAvailable((uData)(aAcquisitionDataType)))
1163  {
1164  LOG_ERROR("vtkPlusSonixVideoSource::SetAcquisitionDataType failed: Requested the data aquisition type not available for selected imaging mode(" << GetLastUlteriusError() << ")");
1165  return PLUS_FAIL;
1166  }
1167  // actually request data, now that its available
1168  if (!this->Ult->setDataToAcquire(aAcquisitionDataType))
1169  {
1170  LOG_ERROR("vtkPlusSonixVideoSource::SetAcquisitionDataType failed: couldn't request the data aquisition type " << aAcquisitionDataType << ", " << GetLastUlteriusError());
1171  return PLUS_FAIL;
1172  }
1173  this->AcquisitionDataType = aAcquisitionDataType;
1174  return PLUS_SUCCESS;
1175 }
1176 //----------------------------------------------------------------------------
1178 {
1179  if (!this->UlteriusConnected)
1180  {
1181  // Connection has not been established yet. Parameter value will be set upon connection.
1182  acquisitionDataType = this->AcquisitionDataType;
1183  return PLUS_SUCCESS;
1184  }
1185  acquisitionDataType = this->Ult->getDataToAcquire();
1186  this->AcquisitionDataType = acquisitionDataType;
1187  return PLUS_SUCCESS;
1188 }
1189 
1190 //----------------------------------------------------------------------------
1192 {
1193  if (!this->UlteriusConnected)
1194  {
1195  // Connection has not been established yet. Parameter value will be set upon connection.
1196  this->ImagingMode = mode;
1197  return PLUS_SUCCESS;
1198  }
1199  if (!this->Ult->selectMode(mode))
1200  {
1201  LOG_ERROR("vtkPlusSonixVideoSource::SetImagingMode failed: couldn't select imaging mode " << mode << ", " << GetLastUlteriusError());
1202  return PLUS_FAIL;
1203  }
1204  this->ImagingMode = mode;
1205  return PLUS_SUCCESS;
1206 }
1207 
1208 //----------------------------------------------------------------------------
1210 {
1211  if (!this->UlteriusConnected)
1212  {
1213  // Connection has not been established yet. Parameter value will be set upon connection.
1214  mode = this->ImagingMode;
1215  return PLUS_SUCCESS;
1216  }
1217  mode = this->Ult->getActiveImagingMode();
1218  this->ImagingMode = mode;
1219  return PLUS_SUCCESS;
1220 }
1221 
1222 //----------------------------------------------------------------------------
1224 {
1225  if (!this->UlteriusConnected)
1226  {
1227  LOG_ERROR("vtkPlusSonixVideoSource::PrintListOfParameters failed: not connected");
1228  return PLUS_FAIL;
1229  }
1230  uParam prmDescriptor;
1231  LOG_INFO("Index; Id; Name; Source; Type; Unit");
1232  for (int paramId = 0; this->Ult->getParam(paramId, prmDescriptor); paramId++)
1233  {
1234  LOG_INFO(paramId << "; " << prmDescriptor.id << "; " << prmDescriptor.name << "; " << prmDescriptor.source
1235  << "; " << prmDescriptor.type << "; " << prmDescriptor.unit);
1236  }
1237  return PLUS_SUCCESS;
1238 }
1239 
1240 //----------------------------------------------------------------------------
1242 {
1243  if (!this->UlteriusConnected)
1244  {
1245  LOG_ERROR("vtkPlusSonixVideoSource::GetDisplayedFrameRate failed: not connected");
1246  return PLUS_FAIL;
1247  }
1248 
1249  if (!this->Ult->getParamValue("frame rate", aFrameRate))
1250  {
1251  LOG_ERROR("vtkPlusSonixVideoSource::GetDisplayedFrameRate failed: cannot retrieve displayed frame rate.");
1252  return PLUS_FAIL;
1253  }
1254 
1255  return PLUS_SUCCESS;
1256 }
1257 //----------------------------------------------------------------------------
1259 {
1260  if (!this->UlteriusConnected)
1261  {
1262  LOG_ERROR("vtkPlusSonixVideoSource::SetRFDecimation failed: not connected");
1263  return PLUS_FAIL;
1264  }
1265  if (!this->Ult->setParamValue("rf-rf decimation", decimation))
1266  {
1267  LOG_ERROR("vtkPlusSonixVideoSource::SetRFDecimation failed: cannot set decimation value.");
1268  return PLUS_FAIL;
1269  }
1270 
1271  return PLUS_SUCCESS;
1272 }
1273 //----------------------------------------------------------------------------
1275 {
1276  if (!this->UlteriusConnected)
1277  {
1278  LOG_ERROR("vtkPlusSonixVideoSource::SetPPFilter failed: not connected");
1279  return PLUS_FAIL;
1280  }
1281  if (!this->Ult->setParamValue("b-filter type", filterIndex))
1282  {
1283  LOG_ERROR("vtkPlusSonixVideoSource::SetPPFilter failed: cannot set filter value.");
1284  return PLUS_FAIL;
1285  }
1286 
1287  return PLUS_SUCCESS;
1288 }
1289 //----------------------------------------------------------------------------
1291 {
1292  if (!this->UlteriusConnected)
1293  {
1294  LOG_ERROR("vtkPlusSonixVideoSource::SetFrameRateLimit failed: not connected");
1295  return PLUS_FAIL;
1296  }
1297  if (!this->Ult->setParamValue("max fr", frLimit))
1298  {
1299  LOG_ERROR("vtkPlusSonixVideoSource::SetFrameRateLimit failed: cannot set maximum frame rate limit value.");
1300  return PLUS_FAIL;
1301  }
1302 
1303  return PLUS_SUCCESS;
1304 }
1305 //----------------------------------------------------------------------------
1307 {
1308  if (!this->UlteriusConnected)
1309  {
1310  // Connection has not been established yet. Parameter value will be set upon connection.
1311  this->RfAcquisitionMode = mode;
1312  return PLUS_SUCCESS;
1313  }
1314  if (!this->Ult->setParamValue("rf-mode", mode))
1315  {
1316  LOG_ERROR("vtkPlusSonixVideoSource::SetRfAcquisitionMode failed (paramId=rf-mode, paramValue=" << mode << ") " << GetLastUlteriusError());
1317  return PLUS_FAIL;
1318  }
1319  this->RfAcquisitionMode = mode;
1320  return PLUS_SUCCESS;
1321 }
1322 //----------------------------------------------------------------------------
1324 {
1325  int iMode = this->RfAcquisitionMode;
1326  if (this->UlteriusConnected)
1327  {
1328  if (!this->Ult->getParamValue("rf-mode", iMode))
1329  {
1330  LOG_ERROR("vtkPlusSonixVideoSource::GetRfAcquisitionMode failed. " << GetLastUlteriusError());
1331  return PLUS_FAIL;
1332  }
1333  }
1334 
1335  switch (iMode)
1336  {
1337  case 0:
1338  mode = RF_ACQ_B_ONLY;
1339  break;
1340  case 1:
1341  mode = RF_ACQ_RF_ONLY;
1342  break;
1343  case 2:
1345  break;
1346  case 3:
1348  break;
1349  case 4:
1351  break;
1352  default:
1353  mode = RF_UNKNOWN;
1354  LOG_WARNING("Unknown RF acquisition mode type: " << iMode);
1355  return PLUS_FAIL;
1356  }
1357 
1358  return PLUS_SUCCESS;
1359 }
1360 
1361 //----------------------------------------------------------------------------
1363 {
1364  if (this->OutputChannels.size() > 2)
1365  {
1366  LOG_WARNING("vtkPlusSonixVideoSource is expecting at most two output channels and their are " << this->OutputChannels.size() << " channels. First output channel will be used.");
1367  }
1368 
1369  if (this->OutputChannels.size() == 0)
1370  {
1371  LOG_ERROR("No output channels defined for vtkPlusSonixVideoSource. Cannot proceed.");
1372  this->SetCorrectlyConfigured(false);
1373  return PLUS_FAIL;
1374  }
1375 
1377 }
1378 
1379 //----------------------------------------------------------------------------
1381 {
1382  uDataDesc someVal;
1383  bool success = this->Ult->getDataDescriptor(aValue, someVal);
1384  return success;
1385 }
1386 
1387 //----------------------------------------------------------------------------
1389 {
1390  return (this->AcquisitionDataType & aValue) > 0;
1391 }
1392 
1393 //----------------------------------------------------------------------------
1395 {
1396  vtkPlusDataSource* aSource(NULL);
1397  std::vector<vtkPlusDataSource*> sources;
1398  if ((aValue & udtBPost) > 0)
1399  {
1401  if (!sources.empty())
1402  {
1403  aSource = sources[0];
1404  }
1405  }
1406  else if ((aValue & udtRF) > 0)
1407  {
1409  if (!sources.empty())
1410  {
1411  aSource = sources[0];
1412  }
1413  }
1414  else
1415  {
1416  LOG_ERROR("Unsupported uData requested of Sonix video source.");
1417  return PLUS_FAIL;
1418  }
1419 
1420  if (aSource == NULL)
1421  {
1422  LOG_ERROR("Unable to locate the video source for uData: " << aValue);
1423  return PLUS_FAIL;
1424  }
1425 
1426  if (!this->Ult->isDataAvailable(aValue))
1427  {
1428  LOG_ERROR("Data type is not available. " << aValue);
1429  return PLUS_FAIL;
1430  }
1431 
1432  // Set frame size and pixel type
1433  uDataDesc aDataDescriptor;
1434  if (!this->Ult->getDataDescriptor(aValue, aDataDescriptor))
1435  {
1436  LOG_WARNING("Initialize: couldn't retrieve data descriptor (" << GetLastUlteriusError() << ")"); // error is reported at higher level, as it often happens that this call fails but after a few attempts it succeeds
1437  return PLUS_FAIL;
1438  }
1439 
1440  switch (aDataDescriptor.ss)
1441  {
1442  case 8:
1443  aSource->SetPixelType(VTK_UNSIGNED_CHAR);
1444  aSource->SetImageType(US_IMG_BRIGHTNESS);
1445  aSource->SetOutputImageOrientation(US_IMG_ORIENT_MF);
1446  break;
1447  case 16:
1448  aSource->SetPixelType(VTK_SHORT);
1449  aSource->SetImageType(US_IMG_RF_I_LINE_Q_LINE);
1450  // RF data is stored line-by-line, therefore set the storage buffer to FM orientation
1451  aSource->SetOutputImageOrientation(US_IMG_ORIENT_FM);
1452  // Swap w/h: in case of RF image acquisition the DataDescriptor.h is the width and the DataDescriptor.w is the height
1453  std::swap(aDataDescriptor.h, aDataDescriptor.w);
1454  std::swap(aDataDescriptor.roi.ulx, aDataDescriptor.roi.uly);
1455  std::swap(aDataDescriptor.roi.urx, aDataDescriptor.roi.ury);
1456  std::swap(aDataDescriptor.roi.blx, aDataDescriptor.roi.bly);
1457  std::swap(aDataDescriptor.roi.brx, aDataDescriptor.roi.bry);
1458  break;
1459  default:
1460  LOG_ERROR("Unsupported Ulterius bit depth: " << aDataDescriptor.ss);
1461  return PLUS_FAIL;
1462  }
1463 
1464  if (this->AutoClipEnabled)
1465  {
1466  std::array<int, 3> clipRectangleOrigin = {0, 0, 0};
1467  clipRectangleOrigin[0] = std::min(aDataDescriptor.roi.ulx, aDataDescriptor.roi.blx);
1468  clipRectangleOrigin[1] = std::min(aDataDescriptor.roi.uly, aDataDescriptor.roi.ury);
1469  std::array<int, 3> clipRectangleSize = {0, 0, 1};
1470  clipRectangleSize[0] = std::max(aDataDescriptor.roi.urx - aDataDescriptor.roi.ulx, aDataDescriptor.roi.brx - aDataDescriptor.roi.blx);
1471  clipRectangleSize[1] = std::max(aDataDescriptor.roi.bly - aDataDescriptor.roi.uly, aDataDescriptor.roi.bry - aDataDescriptor.roi.ury);
1472  aSource->SetClipRectangleOrigin(clipRectangleOrigin);
1473  aSource->SetClipRectangleSize(clipRectangleSize);
1474  }
1475 
1476  this->SetInputFrameSize(*aSource, aDataDescriptor.w, aDataDescriptor.h, 1);
1477 
1478  return PLUS_SUCCESS;
1479 }
1480 
1481 //----------------------------------------------------------------------------
1483 {
1484  requestedImagingDataType = 0;
1485  std::vector<vtkPlusDataSource*> sources;
1487  {
1488  return PLUS_FAIL;
1489  }
1490  if (!sources.empty())
1491  {
1492  requestedImagingDataType |= vtkPlusUsImagingParameters::DataTypeBPost;
1493  }
1495  {
1496  return PLUS_FAIL;
1497  }
1498  if (!sources.empty())
1499  {
1500  requestedImagingDataType |= vtkPlusUsImagingParameters::DataTypeRF;
1501  }
1502  return PLUS_SUCCESS;
1503 }
1504 
1505 //----------------------------------------------------------------------------
1506 std::vector<int> vtkPlusSonixVideoSource::Plus_uTGC::toVector()
1507 {
1508  std::vector<int> result;
1509  result.push_back(this->v1);
1510  result.push_back(this->v2);
1511  result.push_back(this->v3);
1512  result.push_back(this->v4);
1513  result.push_back(this->v5);
1514  result.push_back(this->v6);
1515  result.push_back(this->v7);
1516  result.push_back(this->v8);
1517  return result;
1518 }
1519 
1520 //----------------------------------------------------------------------------
1521 void vtkPlusSonixVideoSource::Plus_uTGC::fromVector(const std::vector<int> input)
1522 {
1523  if (input.size() != 8)
1524  {
1525  return;
1526  }
1527  this->v1 = input[0];
1528  this->v2 = input[1];
1529  this->v3 = input[2];
1530  this->v4 = input[3];
1531  this->v5 = input[4];
1532  this->v6 = input[5];
1533  this->v7 = input[6];
1534  this->v8 = input[7];
1535 }
1536 
1537 //----------------------------------------------------------------------------
1538 std::string vtkPlusSonixVideoSource::Plus_uTGC::toString(char separator/*=' '*/)
1539 {
1540  std::stringstream ss;
1541  ss << v1 << separator << v2 << separator << v3 << separator << v4 << separator << v5 << separator << v6 << separator << v7 << separator << v8;
1542  return ss.str();
1543 }
1544 
1545 //----------------------------------------------------------------------------
1546 void vtkPlusSonixVideoSource::Plus_uTGC::fromString(const std::string& input, char separator/*=' '*/)
1547 {
1548  std::vector<int> vect;
1549  std::stringstream ss(input);
1550 
1551  double i;
1552  while (ss >> i)
1553  {
1554  vect.push_back(i);
1555  if (ss.peek() == separator)
1556  {
1557  ss.ignore();
1558  }
1559  }
1560  this->fromVector(vect);
1561 }
1562 
1563 //----------------------------------------------------------------------------
1565 {
1566  PlusStatus status = PLUS_SUCCESS;
1567 
1570  {
1572  {
1573  LOG_ERROR("Failed to set frequency imaging parameter");
1574  status = PLUS_FAIL;
1575  }
1576  }
1579  {
1581  {
1582  LOG_ERROR("Failed to set depth imaging parameter");
1583  status = PLUS_FAIL;
1584  }
1585  }
1588  {
1590  {
1591  LOG_ERROR("Failed to set sector imaging parameter");
1592  status = PLUS_FAIL;
1593  }
1594  }
1597  {
1599  {
1600  LOG_ERROR("Failed to set gain imaging parameter");
1601  status = PLUS_FAIL;
1602  }
1603  }
1606  {
1608  {
1609  LOG_ERROR("Failed to set dynamic range imaging parameter");
1610  status = PLUS_FAIL;
1611  }
1612  }
1615  {
1617  {
1618  LOG_ERROR("Failed to set zoom imaging parameter");
1619  status = PLUS_FAIL;
1620  }
1621  }
1624  {
1626  {
1627  LOG_ERROR("Failed to set sound velocity imaging parameter");
1628  status = PLUS_FAIL;
1629  }
1630  }
1631 
1632  //TODO: Acknowledge parameter change
1633  // (if here then need to trust developer, or do it everywhere this function is called)
1634 
1635  return status;
1636 }
const uint32_t * data
Definition: phidget22.h:3971
virtual PlusStatus SetInputFrameSize(vtkPlusDataSource &aSource, unsigned int x, unsigned int y, unsigned int z)
PlusStatus GetDynRangeDevice(int &aDynRange)
vtkStandardNewMacro(vtkPlusSonixVideoSource)
static const std::string RFMODE_PORT_NAME
Definition: vtkPlusDevice.h:68
virtual const char * GetClassName()
PlusStatus GetSoundVelocityDevice(float &soundVelocity)
bool IsPending(const std::string &paramName) const
int CurrentTransducerOriginPixels[3]
Values used in calculation of image to transducer matrix.
virtual PlusStatus SetOutputImageOrientation(US_IMAGE_ORIENTATION imageOrientation)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
PlusStatus GetTimeGainCompensationDevice(int tgc[8])
PlusStatus SetDynRangeDevice(int aDynRange)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
PlusStatus SetFrameRateLimitDevice(int frLimit)
Phidget_MeshMode mode
Definition: phidget22.h:1332
int
Definition: phidget22.h:3069
igsioStatus PlusStatus
Definition: PlusCommon.h:40
static const std::string BMODE_PORT_NAME
Definition: vtkPlusDevice.h:67
PlusStatus GetDepthMm(double &aDepthMm) const
virtual PlusStatus GetRequestedImagingDataTypeFromSources(int &requestedImagingDataType)
PlusStatus GetSoundVelocity(float &aSoundVelocity) const
PlusStatus SetAcquisitionDataTypeDevice(int aAcquisitionDataType)
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
bool RequireImageOrientationInConfiguration
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
static const int CONNECT_RETRY_DELAY_SEC
for i
double AcquisitionRate
PlusStatus SetPending(const std::string &paramName, bool pending)
virtual PlusStatus AddVideoItemToVideoSources(const std::vector< vtkPlusDataSource * > &videoSources, const igsioVideoFrame &frame, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL) override
RfAcquisitionModeType
Defines RF acquisition mode types (0=B only, 1=RF only, 2=B and RF, 3=ChRF, 4=B and ChRF)
double CurrentPixelSpacingMm[3]
Values used in calculation of image to transducer matrix.
PlusStatus SetImagingModeDevice(int mode)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
#define PLUS_FAIL
Definition: PlusCommon.h:43
RfAcquisitionModeType RfAcquisitionMode
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
PlusStatus SetTimeGainCompensation(const std::vector< double > &tgc)
PlusStatus SetGainDevice(int aGain)
PlusStatus SetSectorDevice(int aSector)
std::array< int, 3 > GetClipRectangleOrigin() const
PlusStatus GetGainPercent(double aGainPercent) const
PlusStatus GetRfAcquisitionModeDevice(RfAcquisitionModeType &mode)
virtual PlusStatus InternalDisconnect()
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *)
std::map< std::string, bool > ChangedImagingParameters
PlusStatus SetRfAcquisitionModeDevice(RfAcquisitionModeType mode)
PlusStatus SetFrequencyDevice(double aFrequency)
virtual void SetCorrectlyConfigured(bool)
unsigned long FrameNumber
virtual PlusStatus InternalConnect()
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
PlusStatus GetSectorPercent(double &aSectorPercent) const
virtual std::string GetSdkVersion()
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus GetFrequencyDevice(double &aFrequency)
virtual PlusStatus InternalApplyImagingParameterChange()
vtkXMLDataElement * FindThisDeviceElement(vtkXMLDataElement *rootXMLElement)
PlusStatus GetAcquisitionDataTypeDevice(int &acquisitionDataType)
PlusStatus GetDisplayedFrameRateDevice(int &aFrameRate)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
PlusStatus GetGainDevice(int &aGain)
void SetClipRectangleOrigin(const std::array< int, 3 > _arg)
PlusStatus GetDynRangeDb(double &aDynRangeDb) const
PlusStatus SetGainPercent(double aGainPercent)
PlusStatus SetDynRangeDb(double aDynRangeDb)
VTK interface for video input from Ultrasonix machine.
PlusStatus SetSectorPercent(double aSectorPercent)
virtual PlusStatus InternalStartRecording()
PlusStatus GetCompressionStatus(int &aCompressionStatus)
PlusStatus SetPPFilterDevice(int filterIndex)
PlusStatus GetParamValueDevice(char *paramId, int &paramValue, int &validatedParamValue)
PlusStatus GetZoomFactor(double &aZoomFactor) const
virtual char * GetSonixIP()
PlusStatus GetDepthDevice(int &aDepth)
PlusStatus SetSoundVelocityDevice(float _arg)
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
PlusStatus AddFrameToBuffer(void *data, int type, int sz, bool cine, int frmnum)
PlusStatus SetRFDecimationDevice(int decimation)
virtual PlusStatus InternalStopRecording()
int VTKScalarPixelType
Definition: PlusCommon.h:55
bool StartThreadForInternalUpdates
PlusStatus GetZoomDevice(int &aZoom)
PlusStatus SetTimeGainCompensationDevice(int tgc[8])
void SetClipRectangleSize(const std::array< int, 3 > _arg)
PlusStatus GetImagingModeDevice(int &mode)
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
PlusStatus ConfigureVideoSource(uData aValue)
ChannelContainer OutputChannels
PlusStatus SetParamValueDevice(char *paramId, int paramValue, int &validatedParamValue)
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
PlusStatus SetZoomFactor(double aZoomFactor)
virtual PlusStatus NotifyConfigured()
PlusStatus SetZoomDevice(int aZoom)
PlusStatus SetDepthDevice(int aDepth)
bool IsSet(const std::string &paramName) const
PlusStatus SetTimeout(int aTimeout)
PlusStatus SetCompressionStatus(int aCompressionStatus)
virtual void SetSonixIP(const char *)
Abstract interface for ultrasound video devices.
FrameSizeType GetInputFrameSize() const
PlusStatus SetDepthMm(double aDepthMm)
PlusStatus SetSoundVelocity(float aSoundVelocity)
PlusStatus GetSectorDevice(int &aSector)
virtual PlusStatus NotifyConfigured()
static const int CONNECT_RETRY
Interface to a 3D positioning tool, video source, or generalized data stream.