PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusIntersonSDKCxxVideoSource.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 
10 #include "vtkImageData.h"
11 #include "vtkObjectFactory.h"
12 #include "vtkImageImport.h"
13 
14 #include "vtkPlusChannel.h"
15 #include "vtkPlusDataSource.h"
16 
17 #include "vtkPlusUSImagingParameters.h"
18 
19 #include "vtkPlusRfProcessor.h"
22 
23 #include "IntersonCxxImagingScan2DClass.h"
24 #include "IntersonCxxControlsHWControls.h"
25 #include "IntersonCxxIntersonClass.h"
26 #include "IntersonCxxImagingScanConverter.h"
27 
28 //----------------------------------------------------------------------------
29 typedef IntersonCxx::Imaging::Scan2DClass Scan2DClassType;
30 typedef IntersonCxx::Controls::HWControls HWControlsType;
31 typedef IntersonCxx::IntersonClass IntersonClassType;
32 
33 //----------------------------------------------------------------------------
35 
36 //----------------------------------------------------------------------------
37 struct BmodeCallbackClientData
38 {
39  vtkPlusIntersonSDKCxxVideoSource * ActiveIntersonDevice;
40 };
41 struct RfCallbackClientData
42 {
43  vtkPlusIntersonSDKCxxVideoSource * ActiveIntersonDevice;
44 };
45 
46 //----------------------------------------------------------------------------
47 void vtkPlusIntersonSDKCxxVideoSource::NewBmodeImageCallback( BmodePixelType * buffer, void * clientData )
48 {
49  if( buffer == NULL )
50  {
51  LOG_ERROR("No actual frame data received");
52  return;
53  }
54 
55  BmodeCallbackClientData * callbackClientData = static_cast< BmodeCallbackClientData * >( clientData );
56  vtkPlusIntersonSDKCxxVideoSource * activeIntersonDevice = callbackClientData->ActiveIntersonDevice;
57 
58  if( activeIntersonDevice != NULL )
59  {
60  activeIntersonDevice->AddBmodeFrameToBuffer( buffer, clientData );
61  }
62  else
63  {
64  LOG_ERROR("vtkPlusIntersonSDKCxxVideoSource B-mode callback but the ActiveIntersonDevice is NULL. Disconnect between the device and SDK.");
65  return;
66  }
67 }
68 
69 //----------------------------------------------------------------------------
70 void vtkPlusIntersonSDKCxxVideoSource::NewRfImageCallback( RfPixelType * buffer, void * clientData )
71 {
72  if( buffer == NULL )
73  {
74  LOG_ERROR("No actual frame data received");
75  return;
76  }
77 
78  RfCallbackClientData * callbackClientData = static_cast< RfCallbackClientData * >( clientData );
79  vtkPlusIntersonSDKCxxVideoSource * activeIntersonDevice = callbackClientData->ActiveIntersonDevice;
80 
81  if( activeIntersonDevice != NULL )
82  {
83  activeIntersonDevice->AddRfFrameToBuffer( buffer, clientData );
84  }
85  else
86  {
87  LOG_ERROR("vtkPlusIntersonSDKCxxVideoSource B-mode callback but the ActiveIntersonDevice is NULL. Disconnect between the device and SDK.");
88  return;
89  }
90 }
91 
92 class vtkPlusIntersonSDKCxxVideoSource::vtkInternal
93 {
94 public:
96 
97  //----------------------------------------------------------------------------
98  vtkPlusIntersonSDKCxxVideoSource::vtkInternal::vtkInternal(vtkPlusIntersonSDKCxxVideoSource* external)
99  : External(external)
100  {
101  this->HWControls = new HWControlsType();
102  this->Scan2DClass = new Scan2DClassType();
103  this->IntersonClass = new IntersonClassType();
104 
105  this->BmodeClientData.ActiveIntersonDevice = this->External;
106  this->RfClientData.ActiveIntersonDevice = this->External;
107 
108  this->BModeBufferToVtkImage = vtkImageImport::New();
109  this->BModeBufferToVtkImage->SetDataScalarType( VTK_UNSIGNED_CHAR );
110  this->BModeBufferToVtkImage->SetDataExtent( 0, Scan2DClassType::MAX_SAMPLES - 1, 0, Scan2DClassType::MAX_VECTORS - 1, 0, 0 );
111  this->BModeBufferToVtkImage->SetWholeExtent( 0, Scan2DClassType::MAX_SAMPLES - 1, 0, Scan2DClassType::MAX_VECTORS - 1, 0, 0 );
112 
113  this->RfBufferToVtkImage = vtkImageImport::New();
114  this->RfBufferToVtkImage->SetDataScalarType( VTK_SHORT );
115  this->RfBufferToVtkImage->SetDataExtent( 0, Scan2DClassType::MAX_RFSAMPLES - 1, 0, Scan2DClassType::MAX_VECTORS - 1, 0, 0 );
116  this->RfBufferToVtkImage->SetWholeExtent( 0, Scan2DClassType::MAX_RFSAMPLES - 1, 0, Scan2DClassType::MAX_VECTORS - 1, 0, 0 );
117  }
118 
119  //----------------------------------------------------------------------------
120  vtkPlusIntersonSDKCxxVideoSource::vtkInternal::~vtkInternal()
121  {
122  this->External = NULL;
123  delete HWControls;
124  delete Scan2DClass;
125  delete IntersonClass;
126 
127  this->BModeBufferToVtkImage->Delete();
128  this->RfBufferToVtkImage->Delete();
129  }
130 
131  std::string GetSdkVersion()
132  {
133  return this->IntersonClass->Version();
134  }
135 
136  HWControlsType * GetHWControls()
137  {
138  return this->HWControls;
139  }
140 
141  Scan2DClassType * GetScan2DClass()
142  {
143  return this->Scan2DClass;
144  }
145 
146  vtkImageData * ConvertBModeBufferToVtkImage( unsigned char * pixelData )
147  {
148  this->BModeBufferToVtkImage->SetImportVoidPointer( pixelData );
149  this->BModeBufferToVtkImage->Update();
150  return this->BModeBufferToVtkImage->GetOutput();
151  }
152 
153  vtkImageData * ConvertRfBufferToVtkImage( short * pixelData )
154  {
155  this->RfBufferToVtkImage->SetImportVoidPointer( pixelData );
156  this->RfBufferToVtkImage->Update();
157  return this->RfBufferToVtkImage->GetOutput();
158  }
159 
160  void EnableBModeCallback()
161  {
162  this->Scan2DClass->SetNewBmodeImageCallback( &vtkPlusIntersonSDKCxxVideoSource::NewBmodeImageCallback,
163  &(this->BmodeClientData) );
164  }
165 
166  void DisableBModeCallback()
167  {
168  this->Scan2DClass->SetNewBmodeImageCallback( NULL, NULL );
169  }
170 
171  void EnableRfCallback()
172  {
173  this->Scan2DClass->SetNewRFImageCallback( &vtkPlusIntersonSDKCxxVideoSource::NewRfImageCallback,
174  &(this->RfClientData) );
175  }
176 
177  void DisableRfCallback()
178  {
179  this->Scan2DClass->SetNewRFImageCallback( NULL, NULL );
180  }
181 
182 
183  // Find the channel that outputs the source.
184  vtkPlusChannel * GetSourceChannel( vtkPlusDataSource * source )
185  {
186  vtkPlusChannel * channel = NULL;
187  for( ChannelContainerConstIterator channelIt = this->External->OutputChannels.begin();
188  channelIt != this->External->OutputChannels.end();
189  ++channelIt )
190  {
191  if( !(*channelIt)->HasVideoSource() )
192  {
193  LOG_ERROR( "Output channel does not have VideoSource" );
194  return channel;
195  }
196  vtkPlusDataSource * channelSource = NULL;
197  (*channelIt)->GetVideoSource( channelSource );
198  if( channelSource == source )
199  {
200  channel = *channelIt;
201  break;
202  }
203  }
204  return channel;
205  }
206 
207 private:
208  HWControlsType * HWControls;
209  Scan2DClassType * Scan2DClass;
210  IntersonClassType * IntersonClass;
211 
212  BmodeCallbackClientData BmodeClientData;
213  RfCallbackClientData RfClientData;
214 
215  vtkImageImport * BModeBufferToVtkImage;
216  vtkImageImport * RfBufferToVtkImage;
217 };
218 
219 
220 //----------------------------------------------------------------------------
222  PulseVoltage( 30 ),
223  RfDecimation( 0 )
224 {
225  this->Internal = new vtkInternal(this);
226 
227  this->StartThreadForInternalUpdates = false;
228 
231 
233 }
234 
235 //----------------------------------------------------------------------------
237 {
238  if( !this->Connected )
239  {
240  this->Disconnect();
241  }
242 
243  delete this->Internal;
244  this->Internal = NULL;
245 }
246 
247 //----------------------------------------------------------------------------
248 void vtkPlusIntersonSDKCxxVideoSource::PrintSelf(ostream& os, vtkIndent indent)
249 {
250  this->Superclass::PrintSelf(os,indent);
251 
252  os << indent << "Pulse voltage: " << this->PulseVoltage << "\n";
253  os << indent << "RF decimation: " << this->RfDecimation << "\n";
254 }
255 
256 //----------------------------------------------------------------------------
258 {
259  LOG_TRACE( "vtkPlusIntersonSDKCxxVideoSource::InternalConnect" );
260 
261  HWControlsType * hwControls = this->Internal->GetHWControls();
262 
263  typedef HWControlsType::FoundProbesType FoundProbesType;
264  FoundProbesType foundProbes;
265  hwControls->FindAllProbes( foundProbes );
266  if( foundProbes.empty() )
267  {
268  LOG_ERROR( "Interson SDK Cxx could not find the probe." );
269  return PLUS_FAIL;
270  }
271  if( foundProbes.size() > 1 )
272  {
273  LOG_WARNING("Multiple Interson probes are attached, using the first one");
274  }
275  hwControls->FindMyProbe( 0 );
276  const unsigned int probeId = hwControls->GetProbeID();
277  LOG_DEBUG( "Found probe ID: " << probeId );
278  if( probeId == 0 )
279  {
280  LOG_ERROR( "Interson SDK Cxx could not find the probe." );
281  return PLUS_FAIL;
282  }
283 
284  double frequency = -1;
285  this->ImagingParameters->GetFrequencyMhz( frequency );
286  if( this->SetProbeFrequencyMhz( frequency ) == PLUS_FAIL )
287  {
288  return PLUS_FAIL;
289  }
290 
291  if( !hwControls->SendHighVoltage( this->PulseVoltage ) )
292  {
293  LOG_ERROR( "Could not set the pulse voltage." );
294  return PLUS_FAIL;
295  }
296  if( !hwControls->EnableHighVoltage() )
297  {
298  LOG_ERROR( "Could not enable high voltage." );
299  return PLUS_FAIL;
300  }
301 
302  double dynamicRangeDb = -1;
303  this->ImagingParameters->GetDynRangeDb( dynamicRangeDb );
304  if( this->SetDynRangeDb( dynamicRangeDb ) == PLUS_FAIL )
305  {
306  return PLUS_FAIL;
307  }
308 
309  // TODO: use hardware button
310  hwControls->DisableHardButton();
311 
312  Scan2DClassType * scan2D = this->Internal->GetScan2DClass();
313  std::vector<vtkPlusDataSource *> rfSources;
314  vtkPlusDataSource * source = NULL;
315 
317  if( !rfSources.empty() )
318  {
319  scan2D->SetRFData( true );
320  }
321  else
322  {
323  scan2D->SetRFData( false );
324  }
325 
326  LOG_DEBUG( "Interson SDK version " << this->Internal->GetSdkVersion() <<
327  ", USB probe FPGA version " << hwControls->ReadFPGAVersion() );
328 
329  // Even if we do not use their SDK scan converter, we have to initialize the
330  // scan converter to get the probe fully initialized.
331  const bool upDown = false;
332  const bool leftRight = false;
333  const int width = 1000;
334  const int height = 650;
335  const int scanConvertDepth = 10;
336  typedef IntersonCxx::Imaging::ScanConverter ScanConverterType;
337  ScanConverterType scanConverter;
338  ScanConverterType::ScanConverterError converterError =
339  scanConverter.HardInitScanConverter( scanConvertDepth,
340  upDown,
341  leftRight,
342  width,
343  height );
344 
345  std::vector<vtkPlusDataSource *> bmodeSources;
347 
348  if( !rfSources.empty() )
349  {
350  this->Internal->EnableRfCallback();
351  this->Internal->DisableBModeCallback();
352 
353  if( this->RfDecimation )
354  {
355  hwControls->EnableRFDecimator();
356  }
357  else
358  {
359  hwControls->DisableRFDecimator();
360  }
361 
362  source = rfSources[0];
363  // Clear buffer on connect because the new frames that we will acquire might have a different size
364  source->Clear();
365 
366  vtkPlusChannel * channel = this->Internal->GetSourceChannel( source );
367  if( channel == NULL )
368  {
369  LOG_ERROR( "Could not find channel for source" );
370  return PLUS_FAIL;
371  }
372  else
373  {
374  source->SetPixelType( VTK_SHORT );
375  source->SetImageType( US_IMG_RF_REAL );
376  source->SetOutputImageOrientation( US_IMG_ORIENT_FM );
377  source->SetInputFrameSize( Scan2DClassType::MAX_RFSAMPLES,
378  Scan2DClassType::MAX_VECTORS,
379  1 );
380  LOG_INFO("RF Pixel type: " << vtkImageScalarTypeNameMacro( source->GetPixelType() )
381  << ", device image orientation: "
382  << igsioCommon::GetStringFromUsImageOrientation( source->GetInputImageOrientation() )
383  << ", buffer image orientation: "
384  << igsioCommon::GetStringFromUsImageOrientation( source->GetOutputImageOrientation() ));
385  }
386 
387  if( !bmodeSources.empty() )
388  {
389  LOG_INFO("BMode souces are not empty!!");
390  source = bmodeSources[0];
391  channel = this->Internal->GetSourceChannel( source );
392  if( channel == NULL )
393  {
394  LOG_ERROR( "Could not find channel for source" );
395  return PLUS_FAIL;
396  }
397 
398  // Clear buffer on connect because the new frames that we will acquire might have a different size
399  source->Clear();
400  source->SetPixelType( VTK_UNSIGNED_CHAR );
401  source->SetImageType( US_IMG_BRIGHTNESS ) ;
402  vtkPlusRfProcessor * rfProcessor = channel->GetRfProcessor();
403  if( rfProcessor != NULL )
404  {
405  channel->SetSaveRfProcessingParameters(true); // RF processing parameters were used, make sure they will be saved into the config file
406  source->SetOutputImageOrientation( US_IMG_ORIENT_MF );
407  vtkPlusUsScanConvert * scanConverter = rfProcessor->GetScanConverter();
408  if( scanConverter != NULL )
409  {
410  int outputExtent[6];
411  scanConverter->GetOutputImageExtent( outputExtent );
412  source->SetInputFrameSize( outputExtent[1] - outputExtent[0] + 1,
413  outputExtent[3] - outputExtent[2] + 1,
414  1 );
415  }
416  }
417  else
418  {
419  source->SetOutputImageOrientation( US_IMG_ORIENT_FM );
420  source->SetInputFrameSize( Scan2DClassType::MAX_RFSAMPLES,
421  Scan2DClassType::MAX_VECTORS,
422  1 );
423  }
424  LOG_INFO("Pixel type: " << vtkImageScalarTypeNameMacro( source->GetPixelType() )
425  << ", device image orientation: "
426  << igsioCommon::GetStringFromUsImageOrientation( source->GetInputImageOrientation() )
427  << ", buffer image orientation: "
428  << igsioCommon::GetStringFromUsImageOrientation( source->GetOutputImageOrientation() ));
429  }
430  }
431  else if( !bmodeSources.empty() )
432  {
433  this->Internal->EnableBModeCallback();
434  this->Internal->DisableRfCallback();
435 
436  source = bmodeSources[0];
437  // Clear buffer on connect because the new frames that we will acquire might have a different size
438  source->Clear();
439  source->SetPixelType( VTK_UNSIGNED_CHAR );
440  source->SetImageType( US_IMG_BRIGHTNESS );
441 
442  vtkPlusChannel * channel = this->Internal->GetSourceChannel( source );
443  if( channel == NULL )
444  {
445  LOG_ERROR( "Could not find channel for source" );
446  return PLUS_FAIL;
447  }
448  else
449  {
450  vtkPlusRfProcessor * rfProcessor = channel->GetRfProcessor();
451  if( rfProcessor != NULL )
452  {
453  vtkPlusUsScanConvert * scanConverter = rfProcessor->GetScanConverter();
454  if( scanConverter != NULL )
455  {
456  channel->SetSaveRfProcessingParameters(true); // RF processing parameters were used, make sure they will be saved into the config file
457  source->SetOutputImageOrientation( US_IMG_ORIENT_MF );
458  int outputExtent[6];
459  scanConverter->GetOutputImageExtent( outputExtent );
460  source->SetInputFrameSize( outputExtent[1] - outputExtent[0] + 1,
461  outputExtent[3] - outputExtent[2] + 1,
462  1 );
463  }
464  else
465  {
466  LOG_ERROR( "Did not find expected scan converter parameters." );
467  return PLUS_FAIL;
468  }
469  }
470  else
471  {
472  source->SetOutputImageOrientation( US_IMG_ORIENT_MF );
473  source->SetInputFrameSize( Scan2DClassType::MAX_SAMPLES,
474  Scan2DClassType::MAX_VECTORS,
475  1 );
476  }
477  }
478 
479  LOG_INFO("BMode Pixel type: " << vtkImageScalarTypeNameMacro( source->GetPixelType() )
480  << ", device image orientation: "
481  << igsioCommon::GetStringFromUsImageOrientation( source->GetInputImageOrientation() )
482  << ", buffer image orientation: "
483  << igsioCommon::GetStringFromUsImageOrientation( source->GetOutputImageOrientation() ));
484  }
485  else
486  {
487  LOG_ERROR( "Expected an RF or BMode port not found" );
488  return PLUS_FAIL;
489  }
490 
491  return PLUS_SUCCESS;
492 }
493 
494 
495 //----------------------------------------------------------------------------
497 {
498  LOG_DEBUG("Disconnect from Interson");
499 
500  HWControlsType * hwControls = this->Internal->GetHWControls();
501  hwControls->DisableHighVoltage();
502 
503  this->StopRecording();
504  Scan2DClassType * scan2D = this->Internal->GetScan2DClass();
505  scan2D->AbortScan();
506 
507  return PLUS_SUCCESS;
508 }
509 
510 //----------------------------------------------------------------------------
512 {
513  Scan2DClassType * scan2D = this->Internal->GetScan2DClass();
514  scan2D->AbortScan();
515 
516  HWControlsType * hwControls = this->Internal->GetHWControls();
517  if( !hwControls->StartMotor() )
518  {
519  LOG_ERROR( "Could not start motor." );
520  return PLUS_FAIL;
521  }
522 
523  std::vector<vtkPlusDataSource *> bmodeSources;
524  std::vector<vtkPlusDataSource *> rfSources;
527 
528  if( !rfSources.empty() )
529  {
530  scan2D->StartRFReadScan();
531  }
532  else if( !bmodeSources.empty() )
533  {
534  scan2D->StartReadScan();
535  }
536  Sleep( 100 ); // "time to start"
537 
538  if( !rfSources.empty() && !hwControls->StartRFmode() )
539  {
540  LOG_ERROR( "Could not start RF collection." );
541  return PLUS_FAIL;
542  }
543  else if( !bmodeSources.empty() && !hwControls->StartBmode() )
544  {
545  LOG_ERROR( "Could not start B-mode collection." );
546  return PLUS_FAIL;
547  }
548  Sleep( 750 ); // "time to start"
549 
550  return PLUS_SUCCESS;
551 }
552 
553 //----------------------------------------------------------------------------
555 {
556  HWControlsType * hwControls = this->Internal->GetHWControls();
557  if( !hwControls->StopAcquisition() )
558  {
559  LOG_ERROR( "Could not stop acquisition." );
560  return PLUS_FAIL;
561  }
562 
563  Scan2DClassType * scan2D = this->Internal->GetScan2DClass();
564  scan2D->StopReadScan();
565  Sleep( 100 ); // "time to stop"
566  scan2D->DisposeScan();
567  if( !hwControls->StopMotor() )
568  {
569  LOG_ERROR( "Could not stop motor." );
570  return PLUS_FAIL;
571  }
572 
573  return PLUS_SUCCESS;
574 }
575 
576 //----------------------------------------------------------------------------
578 {
580  {
581  return PLUS_FAIL;
582  }
583 
584  return PLUS_SUCCESS;
585 }
586 
587 //-----------------------------------------------------------------------------
589 {
590  LOG_TRACE("vtkPlusIntersonSDKCxxVideoSource::ReadConfiguration");
591  if ( config == NULL )
592  {
593  LOG_ERROR("Unable to configure Interson video source! (XML data element is NULL)");
594  return PLUS_FAIL;
595  }
596 
598 
599  vtkXMLDataElement* deviceConfig = this->FindThisDeviceElement(config);
600  if (deviceConfig == NULL)
601  {
602  LOG_ERROR("Unable to find ImageAcquisition element in configuration XML structure!");
603  return PLUS_FAIL;
604  }
605 
606  double dynRange = -1;
607  if ( deviceConfig->GetScalarAttribute("DynRangeDb", dynRange))
608  {
609  this->ImagingParameters->SetDynRangeDb(dynRange);
610  }
611 
612  double frequency = -1;
613  if ( deviceConfig->GetScalarAttribute("FrequencyMhz", frequency))
614  {
615  this->ImagingParameters->SetFrequencyMhz(frequency);
616  }
617 
618  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, PulseVoltage, deviceConfig);
619  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, RfDecimation, deviceConfig);
620 
621  return PLUS_SUCCESS;
622 }
623 
624 //-----------------------------------------------------------------------------
626 {
627  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
628  deviceConfig->SetIntAttribute("PulseVoltage", this->GetPulseVoltage());
629  deviceConfig->SetIntAttribute("RfDecimation", this->RfDecimation);
630 
631  return PLUS_SUCCESS;
632 }
633 
634 
635 //----------------------------------------------------------------------------
637 {
638  if( this->OutputChannels.size() > 2 )
639  {
640  LOG_WARNING("vtkPlusIntersonSDKCxxVideoSource is expecting at most two output channels and there are " << this->OutputChannels.size() << " channels.");
641  }
642 
643  if( this->OutputChannels.empty() )
644  {
645  LOG_ERROR("No output channels defined for vtkPlusIntersonSDKCxxVideoSource. Cannot proceed." );
646  this->CorrectlyConfigured = false;
647  return PLUS_FAIL;
648  }
649 
650  return PLUS_SUCCESS;
651 }
652 
653 //----------------------------------------------------------------------------
655 {
656  return this->Internal->GetSdkVersion();
657 }
658 
659 //----------------------------------------------------------------------------
661 {
662  if( voltage != this->PulseVoltage )
663  {
664  this->PulseVoltage = voltage;
665  this->Modified();
666  }
667 
668  return PLUS_SUCCESS;
669 }
670 
671 //----------------------------------------------------------------------------
673 {
674  if( enableDecimation != this->RfDecimation )
675  {
676  this->RfDecimation = enableDecimation;
677  this->Modified();
678  }
679 
680  return PLUS_SUCCESS;
681 }
682 
683 //----------------------------------------------------------------------------
685 {
686  int frequency = static_cast< int >( freq * 1e6 );
687 
688  HWControlsType * hwControls = this->Internal->GetHWControls();
689  HWControlsType::FrequenciesType supportedFrequencies;
690  hwControls->GetFrequency( supportedFrequencies );
691  // Set to the closest frequency value.
692  unsigned int frequencyIndex = 0;
693  if( frequency <= supportedFrequencies[0] )
694  {
695  frequencyIndex = 0;
696  }
697  const size_t numSupportedFrequencies = supportedFrequencies.size();
698  if( frequency >= supportedFrequencies[numSupportedFrequencies - 1] )
699  {
700  frequencyIndex = numSupportedFrequencies - 1;
701  }
702  for( size_t ii = 1; ii < numSupportedFrequencies - 1; ++ii )
703  {
704  const int lower = supportedFrequencies[ii - 1] +
705  ( supportedFrequencies[ii] - supportedFrequencies[ii - 1] ) / 2;
706  if( frequency <= lower )
707  {
708  frequencyIndex = ii - 1;
709  break;
710  }
711  const int upper = supportedFrequencies[ii] +
712  ( supportedFrequencies[ii + 1] - supportedFrequencies[ii] ) / 2;
713  if( frequency < upper )
714  {
715  frequencyIndex = ii;
716  break;
717  }
718  frequencyIndex = ii + 1;
719  }
720  frequency = supportedFrequencies[frequencyIndex];
721  LOG_DEBUG( "Current frequency is " << frequency / 1.0e6 );
722 
723  if( !hwControls->SetFrequency( frequency ) )
724  {
725  LOG_ERROR( "Could not set the frequency." );
726  return PLUS_FAIL;
727  }
728 
729  this->ImagingParameters->SetFrequencyMhz( static_cast< double >( frequency / 1.0e6 ) );
730 
731  return PLUS_SUCCESS;
732 }
733 
734 //----------------------------------------------------------------------------
736 {
737  unsigned char usedGain = 100;
738  if( dynRangeDb > 0.0 )
739  {
740  usedGain = static_cast< unsigned char >( 255 * dynRangeDb );
741  }
742  HWControlsType * hwControls = this->Internal->GetHWControls();
743  if( !hwControls->SendDynamic( usedGain ) )
744  {
745  LOG_ERROR( "Could not set dynamic gain." );
746  return PLUS_FAIL;
747  }
748  return PLUS_SUCCESS;
749 }
750 
751 //----------------------------------------------------------------------------
752 PlusStatus vtkPlusIntersonSDKCxxVideoSource::AddBmodeFrameToBuffer( BmodePixelType * buffer, void * clientData )
753 {
754  if( !this->Recording )
755  {
756  // drop the frame, we are not recording data now
757  return PLUS_SUCCESS;
758  }
759 
760  HWControlsType * hwControls = this->Internal->GetHWControls();
761  if( hwControls->ReadHardButton() )
762  {
763  // TODO: add support for sending the button press info through OpenIGTLink
764  }
765 
766  vtkImageData * bufferVtkImageData = NULL;
767  ++this->FrameNumber;
768 
769  std::vector<vtkPlusDataSource *> sources;
770  vtkPlusDataSource * source = NULL;
772  if( !sources.empty() )
773  {
774  source = sources[0];
775  }
776  else
777  {
778  LOG_ERROR( "Expected Bmode port not found" );
779  return PLUS_FAIL;
780  }
781 
782  vtkPlusChannel * channel = this->Internal->GetSourceChannel( source );
783 
784  vtkPlusRfProcessor * rfProcessor = channel->GetRfProcessor();
785  if( rfProcessor != NULL )
786  {
787  /*
788  // currently does not work.
789  rfProcessor->SetRfFrame( this->Internal->ConvertBModeBufferToVtkImage(buffer),
790  US_IMG_BRIGHTNESS );
791  bufferVtkImageData = rfProcessor->GetBrightnessScanConvertedImage();
792  */
793  vtkPlusUsScanConvert * scanConverter = rfProcessor->GetScanConverter();
794  if( scanConverter != NULL )
795  {
796  scanConverter->SetInputData( this->Internal->ConvertBModeBufferToVtkImage( buffer ) );
797  scanConverter->Modified();
798  scanConverter->Update();
799  bufferVtkImageData = scanConverter->GetOutput();
800  }
801  }
802  else
803  {
804  bufferVtkImageData = this->Internal->ConvertBModeBufferToVtkImage( buffer );
805  }
806 
807  const PlusStatus status = source->AddItem( bufferVtkImageData,
808  source->GetInputImageOrientation(),
809  US_IMG_BRIGHTNESS,
810  this->FrameNumber );
811 
812  this->Modified();
813 
814  return status;
815 }
816 
817 //----------------------------------------------------------------------------
818 PlusStatus vtkPlusIntersonSDKCxxVideoSource::AddRfFrameToBuffer( RfPixelType * buffer, void * clientData )
819 {
820  if( !this->Recording )
821  {
822  // drop the frame, we are not recording data now
823  return PLUS_SUCCESS;
824  }
825 
826  HWControlsType * hwControls = this->Internal->GetHWControls();
827  if( hwControls->ReadHardButton() )
828  {
829  // TODO: add support for sending the button press info through OpenIGTLink
830  }
831 
832  ++this->FrameNumber;
833 
834  std::vector<vtkPlusDataSource *> rfSources;
835  vtkPlusDataSource * source = NULL;
837  if( !rfSources.empty() )
838  {
839  source = rfSources[0];
840  }
841  else
842  {
843  LOG_ERROR( "Expected RF port not found" );
844  return PLUS_FAIL;
845  }
846 
847  vtkPlusChannel * channel = this->Internal->GetSourceChannel( source );
848 
849  vtkImageData * rfBufferVtkImageData = this->Internal->ConvertRfBufferToVtkImage( buffer );
850  if( source->AddItem( rfBufferVtkImageData,
851  source->GetInputImageOrientation(),
852  US_IMG_RF_REAL,
853  this->FrameNumber ) == PLUS_FAIL )
854  {
855  LOG_ERROR( "Failed to add RF frame to buffer" );
856  return PLUS_FAIL;
857  }
858 
859  std::vector<vtkPlusDataSource *> bmodeSources;
861  if( !bmodeSources.empty() )
862  {
863  source = bmodeSources[0];
864  channel = this->Internal->GetSourceChannel( source );
865  vtkPlusRfProcessor * rfProcessor = channel->GetRfProcessor();
866  if( rfProcessor != NULL )
867  {
868  rfProcessor->SetRfFrame( rfBufferVtkImageData,
869  US_IMG_RF_REAL );
870  rfProcessor->GetRfToBrightnessConverter()->Modified();
871  vtkPlusUsScanConvert * scanConverter = rfProcessor->GetScanConverter();
872  vtkImageData * bmodeBufferVtkImageData = NULL;
873  if( scanConverter != NULL )
874  {
875  bmodeBufferVtkImageData = rfProcessor->GetBrightnessScanConvertedImage();
876  }
877  else
878  {
879  bmodeBufferVtkImageData = rfProcessor->GetBrightnessConvertedImage();
880  }
881  if( source->AddItem( bmodeBufferVtkImageData,
882  source->GetInputImageOrientation(),
883  US_IMG_BRIGHTNESS,
884  this->FrameNumber ) == PLUS_FAIL )
885  {
886  LOG_ERROR( "Failed to add BMode frame to buffer." );
887  return PLUS_FAIL;
888  }
889  }
890  else
891  {
892  LOG_ERROR( "Expected RfProcessor not found." );
893  return PLUS_FAIL;
894  }
895  }
896 
897  this->Modified();
898 
899  return PLUS_SUCCESS;
900 }
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
int * channel
Definition: phidget22.h:1303
static const std::string RFMODE_PORT_NAME
Definition: vtkPlusDevice.h:68
virtual vtkPlusRfToBrightnessConvert * GetRfToBrightnessConverter()
PhidgetRCServo_Voltage voltage
Definition: phidget22.h:3331
const char * source
Definition: phidget22.h:2461
IntersonArrayCxx::Controls::HWControls HWControlsType
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
static const std::string BMODE_PORT_NAME
Definition: vtkPlusDevice.h:67
virtual vtkPlusUsScanConvert * GetScanConverter()
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
bool RequirePortNameInDeviceSetConfiguration
bool RequireImageOrientationInConfiguration
virtual vtkImageData * GetBrightnessScanConvertedImage()
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
virtual PlusStatus SetRfFrame(vtkImageData *rfFrame, US_IMAGE_TYPE imageType)
Class for acquiring ultrasound images from Interson USB ultrasound systems with C++ Wrapped SDK.
vtkStandardNewMacro(vtkPlusIntersonSDKCxxVideoSource)
virtual PlusStatus Disconnect()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
unsigned long FrameNumber
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
IntersonCxx::Controls::HWControls HWControlsType
vtkXMLDataElement * FindThisDeviceElement(vtkXMLDataElement *rootXMLElement)
ChannelContainer::const_iterator ChannelContainerConstIterator
Definition: vtkPlusDevice.h:35
virtual PlusStatus StopRecording()
PlusStatus SetPulseVoltage(unsigned char voltage)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
IntersonArrayCxx::IntersonClass IntersonClassType
PlusStatus GetDynRangeDb(double &aDynRangeDb) const
static vtkPlusUsImagingParameters * New()
IntersonCxx::IntersonClass IntersonClassType
PhidgetLCD_Font int * width
Definition: phidget22.h:4275
PlusStatus SetDynRangeDb(double aDynRangeDb)
virtual int * GetOutputImageExtent()
IntersonCxx::Imaging::Scan2DClass Scan2DClassType
Convenience class to combine multiple algorithms to compute a displayable B-mode frame from RF data.
bool StartThreadForInternalUpdates
PhidgetLCD_Font int int * height
Definition: phidget22.h:4275
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
virtual void SetInputData(vtkDataObject *input)
ChannelContainer OutputChannels
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
This is a base class for defining a common scan conversion algorithm interface for all kinds of probe...
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
double frequency
Definition: phidget22.h:3246
virtual unsigned char GetPulseVoltage()
virtual vtkImageData * GetOutput()=0
PlusStatus SetRfDecimation(int enableDecimation)
virtual PlusStatus InternalUpdate()
virtual vtkImageData * GetBrightnessConvertedImage()
bool CorrectlyConfigured
Interface to a 3D positioning tool, video source, or generalized data stream.