8 #include "PlusConfigure.h" 14 #include "vtkPlusUSImagingParameters.h" 18 #include <vtkImageCast.h> 19 #include <vtkImageData.h> 20 #include <vtkImageImport.h> 21 #include <vtkObjectFactory.h> 24 #include <IntersonArrayCxxControlsHWControls.h> 25 #include <IntersonArrayCxxImagingContainer.h> 26 #include <IntersonArrayCxxIntersonClass.h> 38 struct BmodeCallbackClientData
42 struct RfCallbackClientData
48 void vtkPlusIntersonArraySDKCxxVideoSource::NewBmodeImageCallback(BmodePixelType* buffer,
void* clientData)
52 LOG_ERROR(
"No actual frame data received");
56 BmodeCallbackClientData* callbackClientData = static_cast<BmodeCallbackClientData*>(clientData);
59 if (activeIntersonArrayDevice != NULL)
61 activeIntersonArrayDevice->AddBmodeFrameToBuffer(buffer, clientData);
65 LOG_ERROR(
"vtkPlusIntersonArraySDKCxxVideoSource B-mode callback but the ActiveIntersonArrayDevice is NULL. Disconnect between the device and SDK.");
71 void vtkPlusIntersonArraySDKCxxVideoSource::NewRfImageCallback(RfPixelType* buffer,
void* clientData)
75 LOG_ERROR(
"No actual frame data received");
79 RfCallbackClientData* callbackClientData = static_cast<RfCallbackClientData*>(clientData);
82 if (activeIntersonArrayDevice != NULL)
84 activeIntersonArrayDevice->AddRfFrameToBuffer(buffer, clientData);
88 LOG_ERROR(
"vtkPlusIntersonArraySDKCxxVideoSource B-mode callback but the ActiveIntersonArrayDevice is NULL. Disconnect between the device and SDK.");
93 class vtkPlusIntersonArraySDKCxxVideoSource::vtkInternal
106 this->BmodeClientData.ActiveIntersonArrayDevice = this->External;
107 this->RfClientData.ActiveIntersonArrayDevice = this->External;
109 this->BModeBufferToVtkImage = vtkSmartPointer<vtkImageImport>::New();
110 this->BModeBufferToVtkImage->SetDataScalarType(VTK_UNSIGNED_SHORT);
111 this->BModeBufferToVtkImage->SetDataExtent(0, ContainerType::MAX_SAMPLES / 2 - 1, 0, ContainerType::NBOFLINES - 1, 0, 0);
112 this->BModeBufferToVtkImage->SetWholeExtent(0, ContainerType::MAX_SAMPLES / 2 - 1, 0, ContainerType::NBOFLINES - 1, 0, 0);
114 this->BModeImageCast = vtkSmartPointer<vtkImageCast>::New();
115 this->BModeImageCast->SetOutputScalarTypeToUnsignedChar();
116 this->BModeImageCast->SetInputConnection(this->BModeBufferToVtkImage->GetOutputPort());
118 this->RfBufferToVtkImage = vtkSmartPointer<vtkImageImport>::New();
119 this->RfBufferToVtkImage->SetDataScalarType(VTK_UNSIGNED_CHAR);
120 this->RfBufferToVtkImage->SetDataExtent(0, ContainerType::MAX_RFSAMPLES - 1, 0, ContainerType::NBOFLINES - 1, 0, 0);
121 this->RfBufferToVtkImage->SetWholeExtent(0, ContainerType::MAX_RFSAMPLES - 1, 0, ContainerType::NBOFLINES - 1, 0, 0);
125 vtkPlusIntersonArraySDKCxxVideoSource::vtkInternal::~vtkInternal()
127 this->External = NULL;
130 delete IntersonClass;
133 std::string GetSdkVersion()
135 return this->IntersonClass->Version();
140 return this->HWControls;
145 return this->Container;
148 vtkImageData* ConvertBModeBufferToVtkImage(
unsigned char* pixelData)
150 this->BModeBufferToVtkImage->SetImportVoidPointer(pixelData);
151 this->BModeBufferToVtkImage->Modified();
152 this->BModeImageCast->Update();
153 return this->BModeImageCast->GetOutput();
156 vtkImageData* ConvertRfBufferToVtkImage(
short* pixelData)
158 this->RfBufferToVtkImage->SetImportVoidPointer(pixelData);
159 this->RfBufferToVtkImage->Update();
160 return this->RfBufferToVtkImage->GetOutput();
163 void EnableBModeCallback()
165 this->Container->SetNewImageCallback(&vtkPlusIntersonArraySDKCxxVideoSource::NewBmodeImageCallback,
166 &(this->BmodeClientData));
169 void DisableBModeCallback()
171 this->Container->SetNewImageCallback(NULL, NULL);
174 void EnableRfCallback()
176 this->Container->SetNewRFImageCallback(&vtkPlusIntersonArraySDKCxxVideoSource::NewRfImageCallback,
177 &(this->RfClientData));
180 void DisableRfCallback()
182 this->Container->SetNewRFImageCallback(NULL, NULL);
194 if (!(*channelIt)->HasVideoSource())
196 LOG_ERROR(
"Output channel does not have VideoSource");
200 (*channelIt)->GetVideoSource(channelSource);
201 if (channelSource ==
source)
215 BmodeCallbackClientData BmodeClientData;
216 RfCallbackClientData RfClientData;
218 vtkSmartPointer<vtkImageImport> BModeBufferToVtkImage;
219 vtkSmartPointer<vtkImageCast> BModeImageCast;
220 vtkSmartPointer<vtkImageImport> RfBufferToVtkImage;
228 this->
Internal =
new vtkInternal(
this);
255 os << indent <<
"Pulse voltage: " << this->
PulseVoltage <<
"\n";
261 LOG_TRACE(
"vtkPlusIntersonArraySDKCxxVideoSource::InternalConnect");
265 typedef HWControlsType::FoundProbesType FoundProbesType;
266 FoundProbesType foundProbes;
267 hwControls->FindAllProbes(foundProbes);
268 if (foundProbes.empty())
270 LOG_ERROR(
"Interson SDK Cxx could not find the probe.");
273 if (foundProbes.size() > 1)
275 LOG_WARNING(
"Multiple Interson probes are attached, using the first one");
277 hwControls->FindMyProbe(0);
278 const unsigned int probeId = hwControls->GetProbeID();
279 LOG_DEBUG(
"Found probe ID: " << probeId);
282 LOG_ERROR(
"Interson Array SDK Cxx could not find the probe.");
293 if (!hwControls->SendHighVoltage(this->PulseVoltage, this->PulseVoltage))
295 LOG_ERROR(
"Could not set the pulse voltage.");
298 if (!hwControls->EnableHighVoltage())
300 LOG_ERROR(
"Could not enable high voltage.");
304 double dynamicRangeDb = -1;
312 hwControls->DisableHardButton();
315 container->SetHWControls(hwControls);
317 std::vector<vtkPlusDataSource*> rfSources;
322 if (!rfSources.empty())
324 container->SetRFData(
true);
325 width_samples = ContainerType::MAX_RFSAMPLES;
329 container->SetRFData(
false);
330 width_samples = ContainerType::MAX_SAMPLES / 2;
333 LOG_DEBUG(
"Interson Array SDK version " << this->
Internal->GetSdkVersion() <<
334 ", USB probe FPGA version " << hwControls->ReadFPGAVersion());
338 const int depth = 100;
339 const int heightLines = hwControls->GetLinesPerArray();
340 const int steering = 0;
341 const int compoundAngle = 0;
342 const int depthCfm = 0;
344 const bool doubler =
false;
345 const bool compound =
false;
347 if (hwControls->ValidDepth(depth) != depth)
349 LOG_ERROR(
"Invalid depth requested: " << depth);
353 auto converterErrorIdle = container->IdleInitScanConverter(depth, width_samples, heightLines, probeId,
354 steering, depthCfm, doubler, compound, compoundAngle, cfm);
355 if (converterErrorIdle != ContainerType::SUCCESS)
357 LOG_ERROR(
"Idle scan converter initialization error: " << converterErrorIdle);
361 auto converterErrorHard = container->HardInitScanConverter(depth, width_samples, heightLines, steering, depthCfm);
362 if (converterErrorHard != ContainerType::SUCCESS)
364 LOG_ERROR(
"Hard scan converter initialization error: " << converterErrorHard);
368 std::vector<vtkPlusDataSource*> bmodeSources;
371 if (!rfSources.empty())
374 this->
Internal->DisableBModeCallback();
376 source = rfSources[0];
383 LOG_ERROR(
"Could not find channel for source");
388 source->SetPixelType(VTK_UNSIGNED_CHAR);
389 source->SetImageType(US_IMG_RF_REAL);
390 source->SetOutputImageOrientation(US_IMG_ORIENT_FM);
391 source->SetInputFrameSize(ContainerType::MAX_RFSAMPLES,
392 hwControls->GetLinesPerArray(),
394 LOG_INFO(
"RF Pixel type: " << vtkImageScalarTypeNameMacro(
source->GetPixelType())
395 <<
", device image orientation: " 396 << igsioCommon::GetStringFromUsImageOrientation(
source->GetInputImageOrientation())
397 <<
", buffer image orientation: " 398 << igsioCommon::GetStringFromUsImageOrientation(
source->GetOutputImageOrientation()));
401 if (!bmodeSources.empty())
403 LOG_INFO(
"BMode souces are not empty!!");
408 LOG_ERROR(
"Could not find channel for source");
414 source->SetPixelType(VTK_UNSIGNED_CHAR);
415 source->SetImageType(US_IMG_BRIGHTNESS);
417 if (rfProcessor != NULL)
419 channel->SetSaveRfProcessingParameters(
true);
420 source->SetOutputImageOrientation(US_IMG_ORIENT_MF);
422 if (scanConverter != NULL)
426 if (outputExtent[1] - outputExtent[0] + 1 < 0 || outputExtent[3] - outputExtent[2] + 1 < 0)
428 LOG_ERROR(
"Invalid extents. Cannot set frame size.");
431 source->SetInputFrameSize(static_cast<unsigned int>(outputExtent[1] - outputExtent[0] + 1),
432 static_cast<unsigned int>(outputExtent[3] - outputExtent[2] + 1),
438 source->SetOutputImageOrientation(US_IMG_ORIENT_FM);
439 source->SetInputFrameSize(ContainerType::MAX_RFSAMPLES,
440 hwControls->GetLinesPerArray(),
443 LOG_INFO(
"Pixel type: " << vtkImageScalarTypeNameMacro(
source->GetPixelType())
444 <<
", device image orientation: " 445 << igsioCommon::GetStringFromUsImageOrientation(
source->GetInputImageOrientation())
446 <<
", buffer image orientation: " 447 << igsioCommon::GetStringFromUsImageOrientation(
source->GetOutputImageOrientation()));
450 else if (!bmodeSources.empty())
452 this->
Internal->EnableBModeCallback();
453 this->
Internal->DisableRfCallback();
455 source = bmodeSources[0];
458 source->SetPixelType(VTK_UNSIGNED_CHAR);
459 source->SetImageType(US_IMG_BRIGHTNESS);
464 LOG_ERROR(
"Could not find channel for source");
470 if (rfProcessor != NULL)
473 if (scanConverter != NULL)
475 channel->SetSaveRfProcessingParameters(
true);
476 source->SetOutputImageOrientation(US_IMG_ORIENT_MF);
479 if (outputExtent[1] - outputExtent[0] + 1 < 0 || outputExtent[3] - outputExtent[2] + 1 < 0)
481 LOG_ERROR(
"Invalid extents. Cannot set frame size.");
484 source->SetInputFrameSize(outputExtent[1] - outputExtent[0] + 1,
485 outputExtent[3] - outputExtent[2] + 1,
490 LOG_ERROR(
"Did not find expected scan converter parameters.");
496 source->SetOutputImageOrientation(US_IMG_ORIENT_MF);
497 source->SetInputFrameSize(ContainerType::MAX_SAMPLES / 2,
498 hwControls->GetLinesPerArray(),
503 LOG_INFO(
"BMode Pixel type: " << vtkImageScalarTypeNameMacro(
source->GetPixelType())
504 <<
", device image orientation: " 505 << igsioCommon::GetStringFromUsImageOrientation(
source->GetInputImageOrientation())
506 <<
", buffer image orientation: " 507 << igsioCommon::GetStringFromUsImageOrientation(
source->GetOutputImageOrientation()));
511 LOG_ERROR(
"Expected an RF or BMode port not found");
522 LOG_DEBUG(
"Disconnect from Interson");
525 hwControls->DisableHighVoltage();
540 std::vector<vtkPlusDataSource*> bmodeSources;
541 std::vector<vtkPlusDataSource*> rfSources;
545 if (!rfSources.empty())
547 container->StartRFReadScan();
549 else if (!bmodeSources.empty())
551 container->StartReadScan();
555 if (!rfSources.empty() && !hwControls->StartRFmode())
557 LOG_ERROR(
"Could not start RF collection.");
560 else if (!bmodeSources.empty() && !hwControls->StartBmode())
562 LOG_ERROR(
"Could not start B-mode collection.");
574 if (!hwControls->StopAcquisition())
576 LOG_ERROR(
"Could not stop acquisition.");
581 container->StopReadScan();
601 LOG_TRACE(
"vtkPlusIntersonArraySDKCxxVideoSource::ReadConfiguration");
604 LOG_ERROR(
"Unable to configure Interson Array video source! (XML data element is NULL)");
611 if (deviceConfig == NULL)
613 LOG_ERROR(
"Unable to find ImageAcquisition element in configuration XML structure!");
617 double dynRange = -1.0;
618 if (deviceConfig->GetScalarAttribute(
"DynRangeDb", dynRange))
624 if (deviceConfig->GetScalarAttribute(
"FrequencyMhz",
frequency))
629 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
int,
PulseVoltage, deviceConfig);
638 deviceConfig->SetIntAttribute(
"PulseVoltage", this->
GetPulseVoltage());
648 LOG_WARNING(
"vtkPlusIntersonArraySDKCxxVideoSource is expecting at most two output channels and there are " << this->
OutputChannels.size() <<
" channels.");
653 LOG_ERROR(
"No output channels defined for vtkPlusIntersonArraySDKCxxVideoSource. Cannot proceed.");
664 return this->
Internal->GetSdkVersion();
682 int frequency = static_cast<int>(freq * 1e6);
685 HWControlsType::FrequenciesType supportedFrequencies;
686 hwControls->GetFrequency(supportedFrequencies);
688 unsigned int frequencyIndex = 0;
689 if (
frequency <= supportedFrequencies[0])
693 const size_t numSupportedFrequencies = supportedFrequencies.size();
694 if (
frequency >= supportedFrequencies[numSupportedFrequencies - 1])
696 frequencyIndex = numSupportedFrequencies - 1;
698 for (
size_t ii = 1; ii < numSupportedFrequencies - 1; ++ii)
700 const int lower = supportedFrequencies[ii - 1] +
701 (supportedFrequencies[ii] - supportedFrequencies[ii - 1]) / 2;
704 frequencyIndex = ii - 1;
707 const int upper = supportedFrequencies[ii] +
708 (supportedFrequencies[ii + 1] - supportedFrequencies[ii]) / 2;
714 frequencyIndex = ii + 1;
716 frequency = supportedFrequencies[frequencyIndex];
717 LOG_DEBUG(
"Current frequency is " <<
frequency / 1.0e6);
719 const int focusIndex = 0;
720 const int steering = 0;
721 if (!hwControls->SetFrequencyAndFocus(frequencyIndex, focusIndex, steering))
723 LOG_ERROR(
"Could not set the frequency.");
735 unsigned char usedGain = 100;
736 if (dynRangeDb > 0.0)
738 usedGain = static_cast<unsigned char>(255 * dynRangeDb);
741 if (!hwControls->SendDynamic(usedGain))
743 LOG_ERROR(
"Could not set dynamic gain.");
750 PlusStatus vtkPlusIntersonArraySDKCxxVideoSource::AddBmodeFrameToBuffer(BmodePixelType* buffer,
void* clientData)
759 if (hwControls->ReadHardButton())
764 vtkImageData* bufferVtkImageData = NULL;
767 std::vector<vtkPlusDataSource*> sources;
770 if (!sources.empty())
776 LOG_ERROR(
"Expected Bmode port not found");
783 if (rfProcessor != NULL)
786 if (scanConverter != NULL)
789 scanConverter->Modified();
790 scanConverter->Update();
791 bufferVtkImageData = scanConverter->
GetOutput();
796 bufferVtkImageData = this->
Internal->ConvertBModeBufferToVtkImage(buffer);
800 source->GetInputImageOrientation(),
810 PlusStatus vtkPlusIntersonArraySDKCxxVideoSource::AddRfFrameToBuffer(RfPixelType* buffer,
void* clientData)
819 if (hwControls->ReadHardButton())
826 std::vector<vtkPlusDataSource*> rfSources;
829 if (!rfSources.empty())
835 LOG_ERROR(
"Expected RF port not found");
841 vtkImageData* rfBufferVtkImageData = this->
Internal->ConvertRfBufferToVtkImage(buffer);
842 if (
source->AddItem(rfBufferVtkImageData,
843 source->GetInputImageOrientation(),
847 LOG_ERROR(
"Failed to add RF frame to buffer");
851 std::vector<vtkPlusDataSource*> bmodeSources;
853 if (!bmodeSources.empty())
858 if (rfProcessor != NULL)
864 vtkImageData* bmodeBufferVtkImageData = NULL;
865 if (scanConverter != NULL)
873 if (
source->AddItem(bmodeBufferVtkImageData,
874 source->GetInputImageOrientation(),
878 LOG_ERROR(
"Failed to add BMode frame to buffer.");
884 LOG_ERROR(
"Expected RfProcessor not found.");
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
static const std::string RFMODE_PORT_NAME
virtual vtkPlusRfToBrightnessConvert * GetRfToBrightnessConverter()
virtual PlusStatus NotifyConfigured()
vtkPlusIntersonArraySDKCxxVideoSource()
PhidgetRCServo_Voltage voltage
vtkPlusUsImagingParameters * ImagingParameters
virtual PlusStatus InternalUpdate()
vtkStandardNewMacro(vtkPlusIntersonArraySDKCxxVideoSource)
IntersonArrayCxx::Controls::HWControls HWControlsType
virtual PlusStatus InternalConnect()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
static const std::string BMODE_PORT_NAME
virtual vtkPlusUsScanConvert * GetScanConverter()
bool RequirePortNameInDeviceSetConfiguration
bool RequireImageOrientationInConfiguration
Class for acquiring ultrasound images from Interson Array USB ultrasound systems with C++ Wrapped SDK...
virtual vtkImageData * GetBrightnessScanConvertedImage()
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
virtual PlusStatus SetRfFrame(vtkImageData *rfFrame, US_IMAGE_TYPE imageType)
~vtkPlusIntersonArraySDKCxxVideoSource()
virtual PlusStatus Disconnect()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *)
unsigned long FrameNumber
PlusStatus SetDynRangeDb(double dynRangeDb)
vtkXMLDataElement * FindThisDeviceElement(vtkXMLDataElement *rootXMLElement)
unsigned char PulseVoltage
ChannelContainer::const_iterator ChannelContainerConstIterator
virtual PlusStatus StopRecording()
IntersonArrayCxx::IntersonClass IntersonClassType
PlusStatus GetDynRangeDb(double &aDynRangeDb) const
static vtkPlusUsImagingParameters * New()
PlusStatus SetDynRangeDb(double aDynRangeDb)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
virtual int * GetOutputImageExtent()
virtual PlusStatus InternalStartRecording()
Convenience class to combine multiple algorithms to compute a displayable B-mode frame from RF data.
bool StartThreadForInternalUpdates
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
virtual unsigned char GetPulseVoltage()
virtual void SetInputData(vtkDataObject *input)
ChannelContainer OutputChannels
virtual PlusStatus InternalDisconnect()
PlusStatus GetFrequencyMhz(double &aFrequencyMhz) const
This is a base class for defining a common scan conversion algorithm interface for all kinds of probe...
virtual PlusStatus InternalStopRecording()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
virtual vtkImageData * GetOutput()=0
PlusStatus SetPulseVoltage(unsigned char voltage)
PlusStatus SetProbeFrequencyMhz(double aFreq)
virtual PlusStatus InternalUpdate()
IntersonArrayCxx::Imaging::Container ContainerType
virtual vtkImageData * GetBrightnessConvertedImage()
virtual std::string GetSdkVersion()
Interface to a 3D positioning tool, video source, or generalized data stream.