7 #include "PlusConfigure.h" 11 #include "vtkImageData.h" 12 #include "vtkImageImport.h" 20 #include "AcquisitionGrabberSapera.h" 21 #include "AcquisitionInjector.h" 22 #include "AcquisitionSettings.h" 23 #include "BmodeViewDataReceiver.h" 24 #include "CommandAndControl.h" 25 #include "ParamConnectionSettings.h" 26 #include "SaperaViewDataReceiver.h" 27 #include "TcpClient.h" 39 std::string rest = str;
42 int pos = rest.find(
",");
51 curItem = rest.substr(0, pos);
52 rest = rest.substr(pos + 1, rest.length());
66 if (result.length() > 2)
67 {
return result.substr(1, result.length() - 2); }
72 class vtkPlusBkProFocusCameraLinkVideoSource::vtkInternal
79 bool SubscribeScanPlane;
81 ParamConnectionSettings BKparamSettings;
83 AcquisitionInjector BKAcqInjector;
84 AcquisitionSettings BKAcqSettings;
85 AcquisitionGrabberSapera BKAcqSapera;
86 BmodeViewDataReceiver BKBModeView;
87 SaperaViewDataReceiver* pBKSaperaView;
90 CmdCtrlSettings BKcmdCtrlSettings;
91 CommandAndControl* pBKcmdCtrl;
98 , SubscribeScanPlane(false)
103 virtual vtkPlusBkProFocusCameraLinkVideoSource::vtkInternal::~vtkInternal()
106 this->Channel = NULL;
107 delete this->pBKSaperaView;
108 this->pBKSaperaView = NULL;
109 delete this->pBKcmdCtrl;
110 this->pBKcmdCtrl = NULL;
111 this->External = NULL;
114 PlusStatus vtkPlusBkProFocusCameraLinkVideoSource::vtkInternal::InitializeParametersFromOEM()
117 TcpClient* oemClient = (this->pBKcmdCtrl->GetOEMClient());
124 value = QueryParameter(oemClient,
"TRANSDUCER");
130 LOG_INFO(
"Transducer: " << transducer);
134 value = QueryParameter(oemClient,
"SCAN_PLANE");
140 LOG_INFO(
"Scan plane: " << scanPlane);
143 value = QueryParameter(oemClient,
"B_FRAMERATE");
149 LOG_INFO(
"Frame rate: " << frameRate);
151 LOG_INFO(
"Queried value: " <<
value);
159 value = QueryParameter(oemClient,
"B_GEOMETRY_SCANAREA");
166 float startAngleDeg =
178 value = QueryParameter(oemClient,
"B_SCANLINES_COUNT");
184 value = QueryParameter(oemClient,
"B_RF_LINE_LENGTH");
192 startAngleDeg = -(startAngleDeg - stopAngleDeg) / 2.;
193 stopAngleDeg = -startAngleDeg;
197 if (transducer ==
"8848")
199 if (scanPlane ==
"S")
201 LOG_DEBUG(
"Linear transducer");
205 vtkSmartPointer<vtkPlusUsScanConvertLinear> scanConverter = vtkSmartPointer<vtkPlusUsScanConvertLinear>::New();
209 else if (scanPlane ==
"T")
211 LOG_DEBUG(
"Curvilinear transducer");
215 vtkSmartPointer<vtkPlusUsScanConvertCurvilinear> scanConverter = vtkSmartPointer<vtkPlusUsScanConvertCurvilinear>::New();
221 LOG_WARNING(
"Unknown transducer scan plane (" << scanPlane <<
"). Cannot determine transducer geometry.");
226 LOG_WARNING(
"Unknown transducer model (" << transducer <<
"). Cannot determine transducer geometry.");
230 if (scanConverter != NULL)
234 if (scanConverterLinear != NULL)
239 else if (scanConverterCurvilinear != NULL)
255 scanConverter->
SetTransducerName((std::string(
"BK-") + transducer + scanPlane).c_str());
259 LOG_WARNING(
"Scan converter is not defined in either manually or through the OEM interface");
279 std::string vtkPlusBkProFocusCameraLinkVideoSource::vtkInternal::QueryParameter(TcpClient* oemClient,
const char* parameter)
284 query = std::string(
"QUERY:") + parameter +
":A;";
285 oemClient->Write(query.c_str(), strlen(query.c_str()));
288 oemClient->Read(&buffer[0], 1024);
290 catch (TcpClientWaitException exc)
292 LOG_WARNING(
"QueryParameter::" << exc.Message);
295 std::string
value = std::string(&buffer[0]);
296 std::string prefix = std::string(
"DATA:") + parameter +
":A ";
297 return value.substr(prefix.length(),
value.length() - prefix.length() - 1);
300 void vtkPlusBkProFocusCameraLinkVideoSource::vtkInternal::RegisterEventCallback(
void* owner,
void (*
func)(
void*,
char*,
size_t))
302 if (this->pBKcmdCtrl != NULL)
304 this->pBKcmdCtrl->RegisterEventCallback(owner,
func);
312 this->Internal =
new vtkInternal(
this);
332 delete this->Internal;
333 this->Internal = NULL;
359 igsioLockGuard<vtkIGSIORecursiveCriticalSection> critSectionGuard(self->UpdateMutex);
361 if (self->Internal->SubscribeScanPlane && !_strnicmp(
"SCAN_PLANE", &eventText[strlen(
"SDATA:")], strlen(
"SCAN_PLANE")))
363 char* probeId = &eventText[strlen(
"SDATA:SCAN_PLANE:")];
364 std::string eventStr(probeId);
365 std::string details = eventStr.substr(eventStr.find(
' '));
366 if (details.find(
'S') != std::string::npos)
368 self->Internal->CurrentPlane =
Sagittal;
370 if (details.find(
'T') != std::string::npos)
374 self->Internal->Channel =
self->FindChannelByPlane();
375 if (self->Internal->Channel == NULL)
377 LOG_ERROR(
"Unable to find a channel by plane. Check configuration.");
380 if (self->ChannelConfiguredMap.find(self->Internal->Channel) ==
self->ChannelConfiguredMap.end()
381 ||
self->ChannelConfiguredMap[
self->Internal->Channel] ==
false)
383 self->Internal->BKAcqSapera.StopGrabbing();
384 self->Internal->InitializeParametersFromOEM();
385 self->Internal->BKAcqSapera.StartGrabbing(&self->Internal->BKAcqInjector);
386 self->ChannelConfiguredMap[
self->Internal->Channel] =
true;
394 std::string iniFilePath;
396 if (!this->Internal->BKparamSettings.LoadSettingsFromIniFile(iniFilePath.c_str()))
398 LOG_ERROR(
"Could not load BK parameter settings from file: " << iniFilePath.c_str());
402 LOG_DEBUG(
"BK scanner address: " << this->Internal->BKparamSettings.GetScannerAddress());
403 LOG_DEBUG(
"BK scanner OEM port: " << this->Internal->BKparamSettings.GetOemPort());
404 LOG_DEBUG(
"BK scanner toolbox port: " << this->Internal->BKparamSettings.GetToolboxPort());
406 this->Internal->BKcmdCtrlSettings.LoadFromIniFile(iniFilePath.c_str());
408 if (!this->Internal->BKAcqSettings.LoadIni(iniFilePath.c_str()))
410 LOG_ERROR(
"Failed to load acquisition settings from file: " << iniFilePath.c_str());
414 this->Internal->BKcmdCtrlSettings.autoUpdate =
true;
415 this->Internal->pBKcmdCtrl =
new CommandAndControl(&this->Internal->BKparamSettings, &this->Internal->BKcmdCtrlSettings);
416 this->Internal->BKcmdCtrlSettings = this->Internal->pBKcmdCtrl->GetCmdCtrlSettings();
418 if (this->Internal->InitializeParametersFromOEM() !=
PLUS_SUCCESS)
420 LOG_ERROR(
"Unable to initialize BK parameters.");
426 if (!this->Internal->pBKcmdCtrl->CalcSaperaBufSize(&numSamples, &numLines))
428 LOG_ERROR(
"Failed to get Sapera framegrabber buffer size for RF data");
429 delete this->Internal->pBKcmdCtrl;
430 this->Internal->pBKcmdCtrl = NULL;
434 LOG_DEBUG(
"Sapera buffer size: numSamples=" << numSamples <<
", numLines=" << numLines);
436 this->Internal->BKAcqSettings.SetLinesPerFrame(numLines);
437 this->Internal->BKAcqSettings.SetRFLineLength(numSamples);
438 this->Internal->BKAcqSettings.SetFramesToGrab(0);
440 if (this->Internal->SubscribeScanPlane)
442 LOG_INFO(
"Subscribing to scan plane events.");
443 this->Internal->pBKcmdCtrl->SubscribeScanPlaneEvents();
444 this->Internal->RegisterEventCallback((
void*)
this,
EventCallback);
447 if (!this->Internal->BKAcqSapera.Init(this->Internal->BKAcqSettings))
449 LOG_ERROR(
"Failed to initialize framegrabber");
450 delete this->Internal->pBKcmdCtrl;
451 this->Internal->pBKcmdCtrl = NULL;
455 this->Internal->pBKSaperaView =
new SaperaViewDataReceiver(this->Internal->BKAcqSapera.GetBuffer());
459 this->Internal->BKAcqInjector.AddDataReceiver(this->Internal->pBKSaperaView);
465 this->Internal->BKAcqInjector.AddDataReceiver(&this->Internal->BKBModeView);
469 this->Internal->BKAcqInjector.AddDataReceiver(&this->Internal->PlusReceiver);
483 this->Internal->BKAcqSapera.Destroy();
485 this->Internal->BKAcqInjector.RemoveDataReceiver(&this->Internal->PlusReceiver);
489 this->Internal->BKAcqInjector.RemoveDataReceiver(&this->Internal->BKBModeView);
494 this->Internal->BKAcqInjector.RemoveDataReceiver(this->Internal->pBKSaperaView);
497 delete this->Internal->pBKSaperaView;
498 this->Internal->pBKSaperaView = NULL;
499 delete this->Internal->pBKcmdCtrl;
500 this->Internal->pBKcmdCtrl = NULL;
507 if (!this->Internal->BKAcqSapera.StartGrabbing(&this->Internal->BKAcqInjector))
509 LOG_ERROR(
"Failed to start grabbing");
532 igsioLockGuard<vtkIGSIORecursiveCriticalSection> critSectionGuard(this->
UpdateMutex);
535 FrameSizeType frameSizeInPix =
537 inputFrameSizeInPix[0],
538 inputFrameSizeInPix[1],
539 inputFrameSizeInPix[2]
542 LOG_TRACE(
"New frame received: " << frameSizeInPix[0] <<
"x" << frameSizeInPix[1]
543 <<
", pixel type: " << vtkImageScalarTypeNameMacro(pixelType)
544 <<
", image type: " << igsioCommon::GetStringFromUsImageType(imageType));
550 std::string type(
"Unknown");
551 if (this->Internal->CurrentPlane ==
Sagittal)
555 if (this->Internal->CurrentPlane ==
Transverse)
559 LOG_ERROR(
"No channel returned. Verify configuration. Requested plane: " << type);
567 if (imageType == US_IMG_RF_REAL || imageType == US_IMG_RF_IQ_LINE || imageType == US_IMG_RF_I_LINE_Q_LINE)
572 LOG_ERROR(
"The received frame is discarded, as it cannot be convert from " << igsioCommon::GetStringFromUsImageType(imageType) <<
" to RF");
577 if (imageType == US_IMG_BRIGHTNESS)
582 else if (imageType == US_IMG_RF_REAL || imageType == US_IMG_RF_IQ_LINE || imageType == US_IMG_RF_I_LINE_Q_LINE)
587 vtkSmartPointer<vtkImageImport> bufferToVtkImage = vtkSmartPointer<vtkImageImport>::New();
588 bufferToVtkImage->SetDataScalarType(pixelType);
589 bufferToVtkImage->SetImportVoidPointer((
unsigned char*)pixelDataPtr);
590 bufferToVtkImage->SetDataExtent(0, frameSizeInPix[0] - 1, 0, frameSizeInPix[1] - 1, 0, 0);
591 bufferToVtkImage->SetWholeExtent(0, frameSizeInPix[0] - 1, 0, frameSizeInPix[1] - 1, 0, 0);
592 bufferToVtkImage->Update();
594 channel->GetRfProcessor()->SetRfFrame(bufferToVtkImage->GetOutput(), imageType);
595 channel->SetSaveRfProcessingParameters(
true);
598 vtkImageData* convertedBmodeImage =
channel->GetRfProcessor()->GetBrightnessScanConvertedImage();
599 pixelDataPtr = convertedBmodeImage->GetScalarPointer();
600 int* resultExtent = convertedBmodeImage->GetExtent();
601 frameSizeInPix[0] = resultExtent[1] - resultExtent[0] + 1;
602 frameSizeInPix[1] = resultExtent[3] - resultExtent[2] + 1;
603 pixelType = convertedBmodeImage->GetScalarType();
604 imageType = US_IMG_BRIGHTNESS;
607 LOG_ERROR(
"The received frame is discarded, as it cannot be convert from " << igsioCommon::GetStringFromUsImageType(imageType) <<
" to Brightness");
611 LOG_ERROR(
"The received frame is discarded, as the requested imaging mode (" << igsioCommon::GetStringFromUsImageType(imageType) <<
") is not supported");
618 LOG_ERROR(
"Output channel does not have video source. Unable to record a new frame.");
624 LOG_DEBUG(
"Set up BK ProFocus image buffer");
628 if (imageType == US_IMG_BRIGHTNESS)
638 LOG_INFO(
"Frame size: " << frameSizeInPix[0] <<
"x" << frameSizeInPix[1]
639 <<
", pixel type: " << vtkImageScalarTypeNameMacro(pixelType)
640 <<
", image type: " << igsioCommon::GetStringFromUsImageType(imageType)
641 <<
", device image orientation: " << igsioCommon::GetStringFromUsImageOrientation(aSource->
GetInputImageOrientation())
642 <<
", buffer image orientation: " << igsioCommon::GetStringFromUsImageOrientation(aSource->
GetOutputImageOrientation()));
661 XML_READ_CSTRING_ATTRIBUTE_REQUIRED(
IniFileName, deviceConfig);
664 const char* subscribe = deviceConfig->GetAttribute(
"SubscribeScanPlane");
665 if (subscribe != NULL)
667 this->Internal->SubscribeScanPlane = (STRCASECMP(subscribe,
"TRUE") == 0);
670 if (this->Internal->SubscribeScanPlane && this->OutputChannels.size() != 2)
672 LOG_ERROR(
"Scan plane switching requested but there are not exactly two output channels.");
683 deviceElement->SetAttribute(
"IniFileName", this->
IniFileName);
692 LOG_ERROR(
"Ini file name has not been set");
710 if (!this->Internal->SubscribeScanPlane && this->OutputChannels.size() > 1)
712 LOG_WARNING(
"vtkPlusBkProFocusCameraLinkVideoSource is expecting one output channel and there are " << this->
OutputChannels.size() <<
" channels. First output channel will be used.");
717 LOG_ERROR(
"No output channels defined for vtkPlusBkProFocusCameraLinkVideoSource. Cannot proceed.");
722 if (!this->Internal->SubscribeScanPlane)
739 LOG_ERROR(
"vtkPlusBkProFocusCameraLinkVideoSource::FindChannelByPlane failed: expected two output channels");
743 std::string desiredPlane;
744 if (this->Internal->CurrentPlane ==
Transverse)
746 desiredPlane =
"Transverse";
750 desiredPlane =
"Sagittal";
756 if ((*it)->GetCustomAttribute(
"Plane", plane) !=
PLUS_SUCCESS)
758 LOG_ERROR(
"Plane switching requested but channel \"" << (*it)->GetChannelId() <<
"\" doesn't have attribute \"Plane\" defined. Please fix configuration.");
761 if (plane.compare(desiredPlane) == 0)
766 LOG_ERROR(desiredPlane <<
" requested but no channel with custom attribute Plane::" << desiredPlane <<
" detected.");
const char int const char * func
virtual vtkPlusRfProcessor * GetRfProcessor()
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
virtual PlusStatus SetOutputImageOrientation(US_IMAGE_ORIENTATION imageOrientation)
virtual void SetThetaStartDeg(double)
virtual PlusStatus InternalStartRecording()
virtual PlusStatus InternalStopRecording()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
std::string GetDeviceSetConfigurationDirectory()
virtual void SetScanConverter(vtkPlusUsScanConvert *scanConverter)
static vtkPlusUsScanConvertCurvilinear * SafeDownCast(vtkObject *o)
virtual void SetIniFileName(const char *)
virtual void SetImagingDepthMm(double)
virtual vtkPlusUsScanConvert * GetScanConverter()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
virtual void SetThetaStopDeg(double)
std::string ParseResponseQuoted(std::string str, int item)
bool RequireImageOrientationInConfiguration
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
virtual void SetRadiusStopMm(double)
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
virtual PlusStatus InternalConnect()
static vtkPlusConfig * GetInstance()
vtkStandardNewMacro(vtkPlusBkProFocusCameraLinkVideoSource)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
unsigned long FrameNumber
virtual void SetOutputImageStartDepthMm(double)
vtkPlusChannel * FindChannelByPlane()
static void EventCallback(void *, char *, size_t)
vtkIGSIORecursiveCriticalSection * UpdateMutex
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
void SetImagingMode(ImagingModeType imagingMode)
virtual void SetTransducerWidthMm(double)
virtual ~vtkPlusBkProFocusCameraLinkVideoSource()
virtual PlusStatus NotifyConfigured()
vtkPlusBkProFocusCameraLinkVideoSource()
const char const char * value
virtual US_IMAGE_ORIENTATION GetInputImageOrientation()
std::map< vtkPlusChannel *, bool > ChannelConfiguredMap
This class performs scan conversion from scan lines for curvilinear probes.
void NewFrameCallback(void *pixelDataPtr, const FrameSizeType &frameSizeInPix, igsioCommon::VTKScalarPixelType pixelType, US_IMAGE_TYPE imageType)
Class for acquiring ultrasound images from BK ProFocus scanners.
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
virtual const char * GetTransducerGeometry()=0
static void LogInfoMessageCallback(char *msg)
std::string ParseResponse(std::string str, int item)
ChannelContainer OutputChannels
virtual void SetTransducerName(const char *)
virtual PlusStatus InternalDisconnect()
This is a base class for defining a common scan conversion algorithm interface for all kinds of probe...
virtual US_IMAGE_ORIENTATION GetOutputImageOrientation()
This class performs scan conversion from scan lines for curvilinear probes.
PlusStatus GetFullIniFilePath(std::string &fullPath)
virtual void SetPlusVideoSource(vtkPlusBkProFocusCameraLinkVideoSource *videoSource)
static void LogDebugMessageCallback(char *msg)
Class for receiving images through the BK ProFocus SDK (Grabbie)
static vtkPlusUsScanConvertLinear * SafeDownCast(vtkObject *o)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *config)
ChannelContainer::iterator ChannelContainerIterator
ImagingModeType ImagingMode
virtual void SetRadiusStartMm(double)
virtual int GetNumberOfItems()
Interface to a 3D positioning tool, video source, or generalized data stream.