Created
May 7, 2014 03:55
-
-
Save thewtex/6f50c44b071fcbca152b to your computer and use it in GitHub Desktop.
Plus IntersonSDKCxx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: src/DataCollection/CMakeLists.txt | |
=================================================================== | |
--- src/DataCollection/CMakeLists.txt (revision 3305) | |
+++ src/DataCollection/CMakeLists.txt (working copy) | |
@@ -15,6 +15,7 @@ | |
OPTION (PLUS_USE_VFW_VIDEO "Provide support for the Video-for-Windows video digitizer" OFF) | |
OPTION (PLUS_USE_EPIPHAN "Provide support for the Epiphan" OFF) | |
OPTION (PLUS_USE_INTERSON_VIDEO "Provide support Interson USB ultrasound probes" OFF) | |
+OPTION (PLUS_USE_INTERSONSDKCXX_VIDEO "Provide support Interson SDK 1.X with C++ Wrapper USB ultrasound probes" OFF) | |
OPTION(PLUS_USE_STEALTHLINK "Provide support for the Medtronick StealthLink Server" OFF) | |
OPTION (PLUS_TEST_BKPROFOCUS "Enable testing of acquisition from BK ProFocus ultrasound systems. Enable this only if a BK ProFocus device is connected to this computer." OFF) | |
@@ -748,6 +749,36 @@ | |
ENDIF (PLUS_USE_INTERSON_VIDEO) | |
# -------------------------------------------------------------------------- | |
+# Interson SDK C++ support | |
+ | |
+IF (PLUS_USE_INTERSONSDKCXX_VIDEO) | |
+ FIND_PACKAGE( IntersonSDKCxx REQUIRED ) | |
+ SET (DataCollection_SRCS ${DataCollection_SRCS} | |
+ IntersonSDKCxx/vtkIntersonSDKCxxVideoSource.cxx | |
+ ) | |
+ if (WIN32) | |
+ SET (DataCollection_HDRS ${DataCollection_HDRS} | |
+ IntersonSDKCxx/vtkIntersonSDKCxxVideoSource.h | |
+ ) | |
+ endif (WIN32) | |
+ SET (DataCollection_LIBS ${DataCollection_LIBS} | |
+ ${IntersonSDKCxx_LIBRARIES} | |
+ ) | |
+ SET (DataCollection_INCLUDE_DIRS ${DataCollection_INCLUDE_DIRS} | |
+ ${IntersonSDKCxx_INCLUDE_DIRS} | |
+ ${CMAKE_CURRENT_SOURCE_DIR}/IntersonSDKCxx | |
+ ) | |
+ SET ( External_Libraries_Install ${External_Libraries_Install} | |
+ ${IntersonSDK_DIR}/Libraries/Interson${CMAKE_SHARED_LIBRARY_SUFFIX} | |
+ ${IntersonSDK_DIR}/Libraries/IntersonTools${CMAKE_SHARED_LIBRARY_SUFFIX} | |
+ ) | |
+ SET ( External_Libraries_Debug ${External_Libraries_Debug} | |
+ ${IntersonSDK_DIR}/Libraries/Interson${CMAKE_SHARED_LIBRARY_SUFFIX} | |
+ ${IntersonSDK_DIR}/Libraries/IntersonTools${CMAKE_SHARED_LIBRARY_SUFFIX} | |
+ ) | |
+ENDIF (PLUS_USE_INTERSONSDKCXX_VIDEO) | |
+ | |
+# -------------------------------------------------------------------------- | |
# Build the library | |
SET (DataCollection_LIBS ${DataCollection_LIBS} | |
Index: src/DataCollection/Testing/CMakeLists.txt | |
=================================================================== | |
--- src/DataCollection/Testing/CMakeLists.txt (revision 3305) | |
+++ src/DataCollection/Testing/CMakeLists.txt (working copy) | |
@@ -149,6 +149,17 @@ | |
SET_TESTS_PROPERTIES( vtkSonixVideoSourceTest1 PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR;WARNING" ) | |
ENDIF (PLUS_USE_ULTRASONIX_VIDEO AND PLUS_TEST_ULTRASONIX) | |
+#*************************** vtkIntersonSDKCxxVideoSourceTest.cxx *************************** | |
+IF (PLUS_USE_INTERSONSDKCXX_VIDEO) | |
+ ADD_EXECUTABLE(vtkIntersonSDKCxxVideoSourceTest vtkintersonSDKCxxVideoSourceTest.cxx) | |
+ TARGET_LINK_LIBRARIES(vtkIntersonSDKCxxVideoSourceTest vtkDataCollection vtkPlusCommon) | |
+ ADD_TEST(NAME vtkIntersonSDKCxxVideoSourceTest | |
+ COMMAND $<TARGET_FILE:vtkIntersonSDKCxxVideoSourceTest> | |
+ --rendering-off | |
+ --config-file=${ConfigFilesDir}/Testing/PlusDeviceSet_IntersonSDKCxxVideoSourceTest.xml | |
+ ) | |
+ SET_TESTS_PROPERTIES( vtkIntersonSDKCxxVideoSourceTest PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR;WARNING" ) | |
+ENDIF () | |
IF (PLUS_USE_BKPROFOCUS_VIDEO) | |
Index: src/DataCollection/vtkUsImagingParameters.h | |
=================================================================== | |
--- src/DataCollection/vtkUsImagingParameters.h (revision 3305) | |
+++ src/DataCollection/vtkUsImagingParameters.h (working copy) | |
@@ -161,4 +161,4 @@ | |
}; | |
-#endif | |
\ No newline at end of file | |
+#endif | |
Index: src/PlusConfigure.h.in | |
=================================================================== | |
--- src/PlusConfigure.h.in (revision 3305) | |
+++ src/PlusConfigure.h.in (working copy) | |
@@ -84,6 +84,7 @@ | |
#cmakedefine PLUS_USE_HEARTSIGNALBOX | |
#cmakedefine PLUS_USE_ICCAPTURING_VIDEO | |
#cmakedefine PLUS_USE_INTERSON_VIDEO | |
+#cmakedefine PLUS_USE_INTERSONSDKCXX_VIDEO | |
#cmakedefine PLUS_USE_MICRONTRACKER | |
#cmakedefine PLUS_USE_MMF_VIDEO | |
#cmakedefine PLUS_USE_PHIDGET_SPATIAL_TRACKER | |
@@ -135,4 +136,4 @@ | |
#include "vtkPlusLogger.h" | |
#include "vtkPlusConfig.h" | |
-#endif // __PlusConfigure_h | |
\ No newline at end of file | |
+#endif // __PlusConfigure_h | |
Index: src/PlusLibConfig.cmake.in | |
=================================================================== | |
--- src/PlusLibConfig.cmake.in (revision 3305) | |
+++ src/PlusLibConfig.cmake.in (working copy) | |
@@ -10,7 +10,12 @@ | |
# Tell the user project where to find Plus use file | |
SET(PlusLib_USE_FILE "@CMAKE_CURRENT_BINARY_DIR@/UsePlusLib.cmake" ) | |
+ | |
+# Get the location for IntersonCxx | |
+SET(PLUS_USE_INTERSONSDKCXX_VIDEO "@PLUS_USE_INTERSONSDKCXX_VIDEO@") | |
+IF(PLUS_USE_INTERSONSDKCXX_VIDEO) | |
+ find_package(IntersonSDKCxx REQUIRED) | |
+ENDIF() | |
# Our library dependencies (contains definitions for IMPORTED targets) | |
include("@CMAKE_CURRENT_BINARY_DIR@/PlusLibLibraryDepends.cmake") | |
- | |
Index: src/UsePlusLib.cmake.in | |
=================================================================== | |
--- src/UsePlusLib.cmake.in (revision 3305) | |
+++ src/UsePlusLib.cmake.in (working copy) | |
@@ -117,6 +117,7 @@ | |
SET(PLUS_USE_HEARTSIGNALBOX @PLUS_USE_HEARTSIGNALBOX@) | |
SET(PLUS_USE_ICCAPTURING_VIDEO @PLUS_USE_ICCAPTURING_VIDEO@) | |
SET(PLUS_USE_INTERSON_VIDEO @PLUS_USE_INTERSON_VIDEO@) | |
+ SET(PLUS_USE_INTERSONSDKCXX_VIDEO @PLUS_USE_INTERSONSDKCXX_VIDEO@) | |
SET(PLUS_USE_MICRONTRACKER @PLUS_USE_MICRONTRACKER@) | |
SET(PLUS_USE_MMF_VIDEO @PLUS_USE_MMF_VIDEO@) | |
SET(PLUS_USE_PHIDGET_SPATIAL_TRACKER @PLUS_USE_PHIDGET_SPATIAL_TRACKER@) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*=Plus=header=begin====================================================== | |
Program: Plus | |
Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved. | |
See License.txt for details. | |
=========================================================Plus=header=end*/ | |
#include "PlusConfigure.h" | |
#include "vtkIntersonSDKCxxVideoSource.h" | |
#include "vtkImageData.h" | |
#include "vtkObjectFactory.h" | |
#include "vtkPlusChannel.h" | |
#include "vtkPlusDataSource.h" | |
#include "vtkPlusBuffer.h" | |
#include "vtkUSImagingParameters.h" | |
#include "IntersonCxxImagingScan2DClass.h" | |
#include "IntersonCxxControlsHWControls.h" | |
#include "IntersonCxxIntersonClass.h" | |
#include "itkImage.h" | |
typedef IntersonCxx::Imaging::Scan2DClass Scan2DClassType; | |
typedef IntersonCxx::Controls::HWControls HWControlsType; | |
typedef IntersonCxx::IntersonClass IntersonClassType; | |
vtkCxxRevisionMacro(vtkIntersonSDKCxxVideoSource, "$Revision: 1.0$"); | |
vtkStandardNewMacro(vtkIntersonSDKCxxVideoSource); | |
const unsigned int Dimension = 3; | |
typedef Scan2DClassType::BmodePixelType BmodePixelType; | |
typedef itk::Image< BmodePixelType, Dimension > BmodeImageType; | |
struct BmodeCallbackClientData | |
{ | |
BmodeImageType * Image; | |
}; | |
//---------------------------------------------------------------------------- | |
void __stdcall pasteIntoBmodeImage( BmodePixelType * buffer, void * clientData ) | |
{ | |
BmodeCallbackClientData * callbackClientData = static_cast< BmodeCallbackClientData * >( clientData ); | |
BmodeImageType * image = callbackClientData->Image; | |
const BmodeImageType::RegionType & largestRegion = image->GetLargestPossibleRegion(); | |
const BmodeImageType::SizeType imageSize = largestRegion.GetSize(); | |
const int maxVectors = Scan2DClassType::MAX_VECTORS; | |
const int maxSamples = Scan2DClassType::MAX_SAMPLES; | |
const int framePixels = maxVectors * maxSamples; | |
BmodePixelType * imageBuffer = image->GetPixelContainer()->GetBufferPointer(); | |
std::memcpy( imageBuffer, buffer, framePixels * sizeof( BmodePixelType ) ); | |
} | |
class vtkIntersonSDKCxxVideoSource::vtkInternal | |
{ | |
public: | |
vtkIntersonSDKCxxVideoSource *External; | |
//---------------------------------------------------------------------------- | |
vtkIntersonSDKCxxVideoSource::vtkInternal::vtkInternal(vtkIntersonSDKCxxVideoSource* external) | |
: External(external) | |
{ | |
this->HWControls = new HWControlsType(); | |
this->Scan2DClass = new Scan2DClassType(); | |
this->IntersonClass = new IntersonClassType(); | |
const int maxVectors = Scan2DClassType::MAX_VECTORS; | |
const int maxSamples = Scan2DClassType::MAX_SAMPLES; | |
this->BmodeImage = BmodeImageType::New(); | |
typedef BmodeImageType::RegionType BmodeRegionType; | |
BmodeRegionType bmodeRegion; | |
BmodeRegionType::IndexType bmodeIndex; | |
bmodeIndex.Fill( 0 ); | |
bmodeRegion.SetIndex( bmodeIndex ); | |
BmodeRegionType::SizeType bmodeSize; | |
bmodeSize[0] = maxSamples; | |
bmodeSize[1] = maxVectors; | |
bmodeRegion.SetSize( bmodeSize ); | |
this->BmodeImage->SetRegions( bmodeRegion ); | |
this->BmodeImage->Allocate(); | |
this->BmodeClientData.Image = this->BmodeImage.GetPointer(); | |
this->Scan2DClass->SetNewBmodeImageCallback( &pasteIntoBmodeImage, | |
&(this->BmodeClientData) ); | |
} | |
//---------------------------------------------------------------------------- | |
vtkIntersonSDKCxxVideoSource::vtkInternal::~vtkInternal() | |
{ | |
this->External = NULL; | |
delete HWControls; | |
delete Scan2DClass; | |
delete IntersonClass; | |
} | |
std::string GetSdkVersion() | |
{ | |
return this->IntersonClass->Version(); | |
} | |
HWControlsType * GetHWControls() | |
{ | |
return this->HWControls; | |
} | |
Scan2DClassType * GetScan2DClass() | |
{ | |
return this->Scan2DClass; | |
} | |
void * GetBmodeBuffer() | |
{ | |
return this->BmodeImage->GetPixelContainer()->GetBufferPointer(); | |
} | |
private: | |
HWControlsType * HWControls; | |
Scan2DClassType * Scan2DClass; | |
IntersonClassType * IntersonClass; | |
BmodeImageType::Pointer BmodeImage; | |
BmodeCallbackClientData BmodeClientData; | |
}; | |
//---------------------------------------------------------------------------- | |
vtkIntersonSDKCxxVideoSource::vtkIntersonSDKCxxVideoSource() | |
{ | |
this->Internal = new vtkInternal(this); | |
this->RequireImageOrientationInConfiguration = true; | |
this->RequireFrameBufferSizeInDeviceSetConfiguration = true; | |
this->RequireAcquisitionRateInDeviceSetConfiguration = false; | |
this->RequireAveragedItemsForFilteringInDeviceSetConfiguration = false; | |
this->RequireLocalTimeOffsetSecInDeviceSetConfiguration = false; | |
this->RequireUsImageOrientationInDeviceSetConfiguration = true; | |
this->RequireRfElementInDeviceSetConfiguration = false; | |
this->ImagingParameters = new vtkUsImagingParameters(this); | |
this->PulseVoltage = 50; | |
} | |
//---------------------------------------------------------------------------- | |
vtkIntersonSDKCxxVideoSource::~vtkIntersonSDKCxxVideoSource() | |
{ | |
if( !this->Connected ) | |
{ | |
this->Disconnect(); | |
} | |
delete this->Internal; | |
this->Internal=NULL; | |
} | |
//---------------------------------------------------------------------------- | |
void vtkIntersonSDKCxxVideoSource::PrintSelf(ostream& os, vtkIndent indent) | |
{ | |
this->Superclass::PrintSelf(os,indent); | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::InternalConnect() | |
{ | |
LOG_TRACE( "vtkIntersonSDKCxxVideoSource::InternalConnect" ); | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
typedef HWControlsType::FoundProbesType FoundProbesType; | |
FoundProbesType foundProbes; | |
hwControls->FindAllProbes( foundProbes ); | |
if( foundProbes.empty() ) | |
{ | |
LOG_ERROR( "Interson SDK Cxx could not find the probe." ); | |
return PLUS_FAIL; | |
} | |
if( foundProbes.size() > 1 ) | |
{ | |
LOG_WARNING("Multiple Interson probes are attached, using the first one"); | |
} | |
hwControls->FindMyProbe( 0 ); | |
const unsigned int probeId = hwControls->GetProbeID(); | |
LOG_DEBUG( "Found probe ID: " << probeId ); | |
if( probeId == 0 ) | |
{ | |
LOG_ERROR( "Interson SDK Cxx could not find the probe." ); | |
return PLUS_FAIL; | |
} | |
double depth = -1; | |
this->ImagingParameters->GetDepthMm( depth ); | |
this->SetDepthMm( depth ); | |
double frequency = -1; | |
if( this->SetProbeFrequency( frequency ) == PLUS_FAIL ) | |
{ | |
return PLUS_FAIL; | |
} | |
if( !hwControls->SendHighVoltage( this->PulseVoltage ) ) | |
{ | |
LOG_ERROR( "Could not set the high voltage." ); | |
return PLUS_FAIL; | |
} | |
if( !hwControls->EnableHighVoltage() ) | |
{ | |
LOG_ERROR( "Could not enable high voltage." ); | |
return PLUS_FAIL; | |
} | |
vtkPlusDataSource* source = NULL; | |
if( this->GetFirstActiveOutputVideoSource( source ) != PLUS_SUCCESS ) | |
{ | |
LOG_ERROR("Unable to retrieve the video source in the IntersonVideo device."); | |
return PLUS_FAIL; | |
} | |
// Clear buffer on connect because the new frames that we will acquire might have a different size | |
vtkPlusBuffer * plusBuffer = source->GetBuffer(); | |
plusBuffer->Clear(); | |
plusBuffer->SetPixelType( VTK_UNSIGNED_CHAR ); | |
plusBuffer->SetFrameSize( Scan2DClassType::MAX_SAMPLES, Scan2DClassType::MAX_VECTORS ); | |
double dynamicRangeDb = -1; | |
this->ImagingParameters->GetDynRangeDb( dynamicRangeDb ); | |
if( this->SetDynRangeDb( dynamicRangeDb ) == PLUS_FAIL ) | |
{ | |
return PLUS_FAIL; | |
} | |
// TODO: use hardware button | |
hwControls->DisableHardButton(); | |
Scan2DClassType * scan2D = this->Internal->GetScan2DClass(); | |
scan2D->SetRFData( false ); | |
LOG_DEBUG( "Interson SDK version " << this->Internal->GetSdkVersion() << | |
", USB probe FPGA version " << hwControls->ReadFPGAVersion() ); | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::InternalDisconnect() | |
{ | |
LOG_DEBUG("Disconnect from Interson"); | |
this->StopRecording(); | |
Scan2DClassType * scan2D = this->Internal->GetScan2DClass(); | |
scan2D->AbortScan(); | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::InternalStartRecording() | |
{ | |
Scan2DClassType * scan2D = this->Internal->GetScan2DClass(); | |
scan2D->AbortScan(); | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
if( !hwControls->StartMotor() ) | |
{ | |
LOG_ERROR( "Could not start motor." ); | |
return PLUS_FAIL; | |
} | |
scan2D->StartReadScan(); | |
Sleep( 100 ); // "time to start" | |
if( !hwControls->StartBmode() ) | |
{ | |
LOG_ERROR( "Could not start B-mode collection." ); | |
return PLUS_FAIL; | |
}; | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::InternalStopRecording() | |
{ | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
if( !hwControls->StopAcquisition() ) | |
{ | |
LOG_ERROR( "Could not stop acquisition." ); | |
return PLUS_FAIL; | |
} | |
Scan2DClassType * scan2D = this->Internal->GetScan2DClass(); | |
scan2D->StopReadScan(); | |
Sleep( 100 ); // "time to stop" | |
scan2D->DisposeScan(); | |
if( !hwControls->StopMotor() ) | |
{ | |
LOG_ERROR( "Could not stop motor." ); | |
return PLUS_FAIL; | |
} | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::InternalUpdate() | |
{ | |
if( !this->Recording ) | |
{ | |
// drop the frame, we are not recording data now | |
return PLUS_SUCCESS; | |
} | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
if( hwControls->ReadHardButton() ) | |
{ | |
// TODO: add support for sending the button press info through OpenIGTLink | |
} | |
this->FrameNumber++; | |
vtkPlusDataSource* source = NULL; | |
if( this->GetFirstActiveOutputVideoSource( source ) != PLUS_SUCCESS ) | |
{ | |
LOG_ERROR("Unable to retrieve the video source in the ICCapturing device."); | |
return PLUS_FAIL; | |
} | |
int frameSizeInPx[2] = { Scan2DClassType::MAX_SAMPLES, | |
Scan2DClassType::MAX_VECTORS }; | |
vtkPlusBuffer * plusBuffer = source->GetBuffer(); | |
// If the buffer is empty, set the pixel type and frame size to the first received properties | |
if ( plusBuffer->GetNumberOfItems() == 0 ) | |
{ | |
LOG_DEBUG("Set up Plus image buffer"); | |
plusBuffer->SetPixelType( VTK_UNSIGNED_CHAR ); | |
plusBuffer->SetImageType( US_IMG_BRIGHTNESS ); | |
plusBuffer->SetFrameSize( frameSizeInPx ); | |
plusBuffer->SetImageOrientation( US_IMG_ORIENT_FU ); | |
LOG_INFO("Frame size: " << frameSizeInPx[0] << "x" << frameSizeInPx[1] | |
<< ", pixel type: " << vtkImageScalarTypeNameMacro( plusBuffer->GetPixelType() ) | |
<< ", device image orientation: " | |
<< PlusVideoFrame::GetStringFromUsImageOrientation( source->GetPortImageOrientation() ) | |
<< ", buffer image orientation: " | |
<< PlusVideoFrame::GetStringFromUsImageOrientation( plusBuffer->GetImageOrientation() )); | |
} | |
if( plusBuffer->AddItem( this->Internal->GetBmodeBuffer(), | |
source->GetPortImageOrientation(), | |
frameSizeInPx, | |
VTK_UNSIGNED_CHAR, | |
1, | |
US_IMG_BRIGHTNESS, | |
0, | |
this->FrameNumber ) != PLUS_SUCCESS ) | |
{ | |
LOG_ERROR( "Error adding item to video source " << source->GetSourceId() ); | |
return PLUS_FAIL; | |
} | |
this->Modified(); | |
return PLUS_SUCCESS; | |
} | |
//----------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::ReadConfiguration(vtkXMLDataElement* config) | |
{ | |
LOG_TRACE("vtkIntersonSDKCxxVideoSource::ReadConfiguration"); | |
if ( config == NULL ) | |
{ | |
LOG_ERROR("Unable to configure Interson video source! (XML data element is NULL)"); | |
return PLUS_FAIL; | |
} | |
Superclass::ReadConfiguration(config); | |
vtkXMLDataElement* deviceConfig = this->FindThisDeviceElement(config); | |
if (deviceConfig == NULL) | |
{ | |
LOG_ERROR("Unable to find ImageAcquisition element in configuration XML structure!"); | |
return PLUS_FAIL; | |
} | |
double dynRange = -1; | |
if ( deviceConfig->GetScalarAttribute("DynRangeDb", dynRange)) | |
{ | |
this->ImagingParameters->SetDynRangeDb(dynRange); | |
} | |
double frequency = -1; | |
if ( deviceConfig->GetScalarAttribute("FrequencyMhz", frequency)) | |
{ | |
this->ImagingParameters->SetFrequencyMhz(frequency); | |
} | |
double depthMm = -1; | |
if ( deviceConfig->GetScalarAttribute("DepthMm", depthMm)) | |
{ | |
this->ImagingParameters->SetDepthMm(depthMm); | |
} | |
return PLUS_SUCCESS; | |
} | |
//----------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::WriteConfiguration(vtkXMLDataElement* config) | |
{ | |
// Write superclass configuration | |
Superclass::WriteConfiguration(config); | |
if ( config == NULL ) | |
{ | |
LOG_ERROR("Config is invalid"); | |
return PLUS_FAIL; | |
} | |
vtkXMLDataElement* imageAcquisitionConfig = this->FindThisDeviceElement(config); | |
if (imageAcquisitionConfig == NULL) | |
{ | |
LOG_ERROR("Cannot find ImageAcquisition element in XML tree!"); | |
return PLUS_FAIL; | |
} | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::NotifyConfigured() | |
{ | |
if( this->OutputChannels.size() > 1 ) | |
{ | |
LOG_WARNING("vtkIntersonSDKCxxVideoSource is expecting one output channel and there are " << this->OutputChannels.size() << " channels. First output channel will be used."); | |
} | |
if( this->OutputChannels.empty() ) | |
{ | |
LOG_ERROR("No output channels defined for vtkIntersonSDKCxxVideoSource. Cannot proceed." ); | |
this->CorrectlyConfigured = false; | |
return PLUS_FAIL; | |
} | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
std::string vtkIntersonSDKCxxVideoSource::GetSdkVersion() | |
{ | |
return this->Internal->GetSdkVersion(); | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::SetProbeFrequency(double freq) | |
{ | |
int frequency = static_cast< int >( freq * 1e6 ); | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
HWControlsType::FrequenciesType supportedFrequencies; | |
hwControls->GetFrequency( supportedFrequencies ); | |
// Set to the closest frequency value. | |
unsigned int frequencyIndex = 0; | |
if( frequency <= supportedFrequencies[0] ) | |
{ | |
frequencyIndex = 0; | |
} | |
const size_t numSupportedFrequencies = supportedFrequencies.size(); | |
if( frequency >= supportedFrequencies[numSupportedFrequencies - 1] ) | |
{ | |
frequencyIndex = numSupportedFrequencies - 1; | |
} | |
for( size_t ii = 1; ii < numSupportedFrequencies - 1; ++ii ) | |
{ | |
const int lower = supportedFrequencies[ii - 1] + | |
( supportedFrequencies[ii] - supportedFrequencies[ii - 1] ) / 2; | |
if( frequency <= lower ) | |
{ | |
frequencyIndex = ii - 1; | |
break; | |
} | |
const int upper = supportedFrequencies[ii] + | |
( supportedFrequencies[ii + 1] - supportedFrequencies[ii] ) / 2; | |
if( frequency < upper ) | |
{ | |
frequencyIndex = ii; | |
break; | |
} | |
frequencyIndex = ii + 1; | |
} | |
frequency = supportedFrequencies[frequencyIndex]; | |
LOG_TRACE( "Current frequency is " << frequency / 1.0e6 ); | |
if( !hwControls->SetFrequency( frequency ) ) | |
{ | |
LOG_ERROR( "Could not set the frequency." ); | |
return PLUS_FAIL; | |
} | |
this->ImagingParameters->SetFrequencyMhz( static_cast< double >( frequency / 1.0e6 ) ); | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::SetDepthMm(double depthMm) | |
{ | |
int depth = static_cast< int >( depthMm ); | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
// Since we are not using their scan converter, this does not have much effect | |
// other than limiting to the maximum valid depth. | |
depth = hwControls->ValidDepth( depth ); | |
this->ImagingParameters->SetDepthMm( static_cast< double >( depth ) ); | |
return PLUS_SUCCESS; | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::SetFrequencyMhz(double freq) | |
{ | |
return this->SetProbeFrequency( freq ); | |
} | |
//---------------------------------------------------------------------------- | |
PlusStatus vtkIntersonSDKCxxVideoSource::SetDynRangeDb(double dynRangeDb) | |
{ | |
if( dynRangeDb > 0.0 ) | |
{ | |
const unsigned char usedGain = static_cast< unsigned char >( 255 * dynRangeDb ); | |
HWControlsType * hwControls = this->Internal->GetHWControls(); | |
if( !hwControls->SendDynamic( usedGain ) ) | |
{ | |
LOG_ERROR( "Could not set dynamic gain." ); | |
return PLUS_FAIL; | |
} | |
} | |
return PLUS_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*=Plus=header=begin====================================================== | |
Program: Plus | |
Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved. | |
See License.txt for details. | |
=========================================================Plus=header=end*/ | |
#ifndef __vtkIntersonSDKCxxVideoSource_h | |
#define __vtkIntersonSDKCxxVideoSource_h | |
#include "vtkPlusDevice.h" | |
#include "vtkUSImagingParameters.h" | |
using namespace std; | |
/*! | |
\class vtkIntersonSDKCxxVideoSource | |
\brief Class for acquiring ultrasound images from Interson USB ultrasound systems | |
with C++ Wrapped SDK. | |
Requires the PLUS_USE_INTERSONSDKCXX option in CMake. | |
Requires Interson SDK 1.X and the C++ Wrappers (SDK provided by Interson, | |
Wrappers provided by Kitware). | |
\ingroup PlusLibDataCollection | |
*/ | |
class VTK_EXPORT vtkIntersonSDKCxxVideoSource : public vtkPlusDevice | |
{ | |
public: | |
static vtkIntersonSDKCxxVideoSource *New(); | |
vtkTypeRevisionMacro(vtkIntersonSDKCxxVideoSource,vtkPlusDevice); | |
void PrintSelf(ostream& os, vtkIndent indent); | |
virtual bool IsTracker() const { return false; } | |
/*! Read configuration from xml data */ | |
virtual PlusStatus ReadConfiguration(vtkXMLDataElement* config); | |
/*! Write configuration to xml data */ | |
virtual PlusStatus WriteConfiguration(vtkXMLDataElement* config); | |
/*! Verify the device is correctly configured */ | |
virtual PlusStatus NotifyConfigured(); | |
virtual std::string GetSdkVersion(); | |
vtkUsImagingParameters* ImagingParameters; | |
protected: | |
/*! Constructor */ | |
vtkIntersonSDKCxxVideoSource(); | |
/*! Destructor */ | |
~vtkIntersonSDKCxxVideoSource(); | |
/*! Device-specific connect */ | |
virtual PlusStatus InternalConnect(); | |
/*! Device-specific disconnect */ | |
virtual PlusStatus InternalDisconnect(); | |
/*! Device-specific recording start */ | |
virtual PlusStatus InternalStartRecording(); | |
/*! Device-specific recording stop */ | |
virtual PlusStatus InternalStopRecording(); | |
/*! The internal function which actually does the grab. */ | |
virtual PlusStatus InternalUpdate(); | |
PlusStatus GetFullIniFilePath(std::string &fullPath); | |
/* Set the desired probe frequency in MHz. The resulting probe speed will be approximately the value specified */ | |
PlusStatus SetProbeFrequency(double aFreq); | |
PlusStatus GetProbeVelocity(double& aVel); | |
/* Set the probe depth in mm */ | |
PlusStatus SetDepthMm(double depthMm); | |
/* Set the frquency in Mhz */ | |
PlusStatus SetFrequencyMhz(double freq); | |
/* Set the gain in percent */ | |
PlusStatus SetDynRangeDb(double dynRangeDb); | |
// For internal storage of additional variables (to minimize the number of included headers) | |
class vtkInternal; | |
vtkInternal* Internal; | |
unsigned char PulseVoltage; | |
private: | |
vtkIntersonSDKCxxVideoSource(const vtkIntersonSDKCxxVideoSource&); // Not implemented. | |
void operator=(const vtkIntersonSDKCxxVideoSource&); // Not implemented. | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*=Plus=header=begin====================================================== | |
Program: Plus | |
Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved. | |
See License.txt for details. | |
=========================================================Plus=header=end*/ | |
/*! | |
\file vtkIntersonSDKCxxVideoSourceTest.cxx | |
\brief Test basic connection to the Interson SDKCxx USB ultrasound probe | |
If the --rendering-off switch is defined then the connection is established, images are | |
transferred for a few seconds, then the connection is closed (useful for automatic testing). | |
If the --rendering-off switch is not defined then the live ultrasound image is displayed | |
in a window (useful for quick interactive testing of the image transfer). | |
\todo This is a test todo | |
\ingroup PlusLibDataCollection | |
*/ | |
#include "PlusConfigure.h" | |
#include "vtkCallbackCommand.h" | |
#include "vtkChartXY.h" | |
#include "vtkCommand.h" | |
#include "vtkContextScene.h" | |
#include "vtkContextView.h" | |
#include "vtkFloatArray.h" | |
#include "vtkImageData.h" | |
#include "vtkImageViewer.h" | |
#include "vtkInformation.h" | |
#include "vtkInformationVector.h" | |
#include "vtkPlot.h" | |
#include "vtkPlusBuffer.h" | |
#include "vtkRenderWindow.h" | |
#include "vtkRenderWindowInteractor.h" | |
#include "vtkRenderer.h" | |
#include "vtkSmartPointer.h" | |
#include "vtkIntersonSDKCxxVideoSource.h" | |
#include "vtkTable.h" | |
#include "vtkTableAlgorithm.h" | |
#include "vtkXMLUtilities.h" | |
#include "vtksys/CommandLineArguments.hxx" | |
#include <stdlib.h> | |
//---------------------------------------------------------------------------- | |
enum DisplayMode | |
{ | |
SHOW_IMAGE, | |
SHOW_PLOT | |
}; | |
//---------------------------------------------------------------------------- | |
class vtkExtractImageRow : public vtkTableAlgorithm | |
{ | |
public: | |
static vtkExtractImageRow* New(); | |
vtkTypeMacro(vtkExtractImageRow,vtkTableAlgorithm); | |
void PrintSelf(ostream& os, vtkIndent indent) | |
{ | |
this->Superclass::PrintSelf(os, indent); | |
} | |
// Description: | |
// Specify the first vtkGraph input and the second vtkSelection input. | |
int FillInputPortInformation(int port, vtkInformation* info) | |
{ | |
if (port == 0) | |
{ | |
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); | |
return 1; | |
} | |
return 0; | |
} | |
protected: | |
vtkExtractImageRow() | |
{ | |
this->SetNumberOfInputPorts(1); | |
} | |
virtual ~vtkExtractImageRow() | |
{ | |
} | |
int RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) | |
{ | |
vtkImageData* inputImage = vtkImageData::GetData(inputVector[0]); | |
vtkInformation* outInfo = outputVector->GetInformationObject(0); | |
vtkTable* outputTable = vtkTable::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); | |
if(!inputImage) | |
{ | |
LOG_ERROR("No input image is available"); | |
return 0; | |
} | |
// Create the tables if they haven't been created yet | |
if (outputTable->GetColumnByName("time")==NULL) | |
{ | |
vtkSmartPointer<vtkFloatArray> arrXnew = vtkSmartPointer<vtkFloatArray>::New(); | |
arrXnew->SetName("time"); | |
outputTable->AddColumn(arrXnew); | |
} | |
if (outputTable->GetColumnByName("RF value")==NULL) | |
{ | |
vtkSmartPointer<vtkFloatArray> arrRfValNew = vtkSmartPointer<vtkFloatArray>::New(); | |
arrRfValNew->SetName("RF value"); | |
outputTable->AddColumn(arrRfValNew); | |
} | |
if (inputImage->GetScalarType()!=VTK_SHORT) | |
{ | |
LOG_ERROR("Plotting is only supported for signed short data"); | |
return 0; | |
} | |
int rowCount=inputImage->GetDimensions()[1]; // number of transducer crystals | |
int numPoints=inputImage->GetDimensions()[0]; // number of data points (RF data values) recorded for one crystal | |
int selectedRow=rowCount/2; // plot the center column of the image | |
short* pixelBuffer=reinterpret_cast<short*>(inputImage->GetScalarPointer())+selectedRow*numPoints; | |
outputTable->SetNumberOfRows(numPoints); | |
int timeIndex=numPoints-1; // the RF data set starts with the latest time | |
for (int i = 0; i < numPoints; ++i) | |
{ | |
outputTable->SetValue(i, 0, timeIndex); | |
short value=*pixelBuffer; | |
outputTable->SetValue(i, 1, value); | |
pixelBuffer++; | |
timeIndex--; | |
} | |
return 1; | |
} | |
private: | |
vtkExtractImageRow(const vtkExtractImageRow&); // Not implemented | |
void operator=(const vtkExtractImageRow&); // Not implemented | |
}; | |
vtkStandardNewMacro(vtkExtractImageRow); | |
//--------------------------------------------------------------------------------- | |
class vtkMyPlotCallback : public vtkCommand | |
{ | |
public: | |
static vtkMyPlotCallback *New() { return new vtkMyPlotCallback; } | |
virtual void Execute(vtkObject *caller, unsigned long eventId, void* callData) | |
{ | |
if (eventId==vtkCommand::KeyPressEvent) | |
{ | |
if (m_Interactor->GetKeyCode()=='q') | |
{ | |
m_Interactor->ExitCallback(); | |
} | |
return; | |
} | |
m_ImageToTableAdaptor->Update(); | |
m_Viewer->Render(); | |
//update the timer so it will trigger again | |
m_Interactor->CreateTimer(VTKI_TIMER_UPDATE); | |
} | |
vtkRenderWindowInteractor *m_Interactor; | |
vtkContextView *m_Viewer; | |
vtkExtractImageRow *m_ImageToTableAdaptor; | |
private: | |
vtkMyPlotCallback() | |
{ | |
m_Interactor=NULL; | |
m_Viewer=NULL; | |
m_ImageToTableAdaptor=NULL; | |
} | |
}; | |
//---------------------------------------------------------------------------- | |
void TestLinePlot(vtkIntersonSDKCxxVideoSource *intersonDevice) | |
{ | |
// Set up a 2D scene, add an XY chart to it | |
vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New(); | |
view->GetRenderer()->SetBackground(1.0, 1.0, 1.0); | |
view->GetRenderWindow()->SetSize(400, 300); | |
vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New(); | |
view->GetScene()->AddItem(chart); | |
vtkSmartPointer<vtkExtractImageRow> imageToTableAdaptor=vtkSmartPointer<vtkExtractImageRow>::New(); | |
imageToTableAdaptor->SetInputConnection(intersonDevice->GetOutputPort()); | |
imageToTableAdaptor->Update(); | |
// Add multiple line plots, setting the colors etc | |
vtkPlot *line = chart->AddPlot(vtkChart::LINE); | |
line->SetInput(imageToTableAdaptor->GetOutput(), 0, 1); | |
line->SetColor(0, 255, 0, 255); | |
line->SetWidth(1.0); | |
vtkSmartPointer<vtkMyPlotCallback> call = vtkSmartPointer<vtkMyPlotCallback>::New(); | |
call->m_Interactor=view->GetInteractor(); | |
call->m_Viewer=view; | |
call->m_ImageToTableAdaptor=imageToTableAdaptor; | |
view->GetInteractor()->Initialize(); | |
view->GetInteractor()->AddObserver(vtkCommand::TimerEvent, call); | |
view->GetInteractor()->CreateTimer(VTKI_TIMER_FIRST); | |
view->GetInteractor()->AddObserver(vtkCommand::KeyPressEvent, call); | |
view->GetInteractor()->Start(); | |
} | |
//--------------------------------------------------------------------------------- | |
class vtkMyCallback : public vtkCommand | |
{ | |
public: | |
static vtkMyCallback *New() { return new vtkMyCallback; } | |
virtual void Execute(vtkObject *caller, unsigned long, void*) | |
{ | |
m_Viewer->Render(); | |
//update the timer so it will trigger again | |
m_Interactor->CreateTimer(VTKI_TIMER_UPDATE); | |
} | |
vtkRenderWindowInteractor *m_Interactor; | |
vtkImageViewer *m_Viewer; | |
private: | |
vtkMyCallback() | |
{ | |
m_Interactor=NULL; | |
m_Viewer=NULL; | |
} | |
}; | |
//------------------------------------------------------------------------------------------- | |
int main(int argc, char* argv[]) | |
{ | |
bool printHelp(false); | |
bool renderingOff(false); | |
bool printParams(false); | |
std::string inputConfigFile; | |
double depthCm = -1; | |
double dynRangeDb = -1; | |
double frequencyMhz = -1; | |
std::string acqMode("B"); | |
vtksys::CommandLineArguments args; | |
args.Initialize(argc, argv); | |
int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED; | |
args.AddArgument("--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp, "Print this help."); | |
args.AddArgument("--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFile, "Config file containing the device configuration."); | |
args.AddArgument("--depth", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &depthCm, "Depth in cm."); | |
args.AddArgument("--frequencyMhz", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &frequencyMhz, "Frequency in MHz"); | |
args.AddArgument("--dynRangeDb", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &dynRangeDb, "BMode Dynamic Range. 1 corresponds to the maximum dynamic range."); | |
args.AddArgument("--rendering-off", vtksys::CommandLineArguments::NO_ARGUMENT, &renderingOff, "Run test without rendering."); | |
args.AddArgument("--print-params", vtksys::CommandLineArguments::NO_ARGUMENT, &printParams, "Print all the supported imaging parameters (for diagnostic purposes only)."); | |
args.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level 1=error only, 2=warning, 3=info, 4=debug, 5=trace)"); | |
if ( !args.Parse() ) | |
{ | |
std::cerr << "Problem parsing arguments" << std::endl; | |
std::cout << "\n\nvtkIntersonSDKCxxVideoSourceTest help:" << args.GetHelp() << std::endl; | |
exit(EXIT_FAILURE); | |
} | |
vtkPlusLogger::Instance()->SetLogLevel(verboseLevel); | |
if ( printHelp ) | |
{ | |
std::cout << "\n\nvtkIntersonSDKCxxVideoSourceTest help:" << args.GetHelp() << std::endl; | |
exit(EXIT_SUCCESS); | |
} | |
vtkSmartPointer<vtkIntersonSDKCxxVideoSource> intersonDevice = vtkSmartPointer<vtkIntersonSDKCxxVideoSource>::New(); | |
intersonDevice->SetDeviceId("VideoDevice"); | |
/* | |
// Read config file | |
if (STRCASECMP(inputConfigFile.c_str(), "")!=0) | |
{ | |
LOG_DEBUG("Reading config file..."); | |
vtkSmartPointer<vtkXMLDataElement> configRead = vtkSmartPointer<vtkXMLDataElement>::Take(::vtkXMLUtilities::ReadElementFromFile(inputConfigFile.c_str())); | |
LOG_DEBUG("Reading config file finished."); | |
if ( configRead != NULL ) | |
{ | |
intersonDevice->ReadConfiguration(configRead); | |
} | |
} | |
intersonDevice->CreateDefaultOutputChannel(); | |
DisplayMode displayMode=SHOW_IMAGE; | |
if (STRCASECMP(acqMode.c_str(), "B")==0) | |
{ | |
LOG_DEBUG("Acquisition mode: B"); | |
//intersonDevice->SetImagingMode(BMode); | |
//intersonDevice->SetAcquisitionDataType(udtBPost); | |
displayMode=SHOW_IMAGE; | |
} | |
else if (STRCASECMP(acqMode.c_str(), "RF")==0) | |
{ | |
LOG_DEBUG("Acquisition mode: RF"); | |
//intersonDevice->SetImagingMode(RfMode); | |
//intersonDevice->SetAcquisitionDataType(udtRF); | |
displayMode=SHOW_PLOT; | |
} | |
else | |
{ | |
LOG_ERROR("Unsupported AcquisitionDataType requested: "<<acqMode); | |
exit(EXIT_FAILURE); | |
} | |
//DisplayMode displayMode=SHOW_PLOT; | |
if ( intersonDevice->Connect()!=PLUS_SUCCESS ) | |
{ | |
//LOG_ERROR( "Unable to connect to Sonix RP machine at: " << intersonDevice->GetSonixIP() ); | |
exit(EXIT_FAILURE); | |
} | |
if (printParams) | |
{ | |
LOG_INFO("List of supported imaging parameters:"); | |
//intersonDevice->PrintListOfImagingParameters(); | |
} | |
intersonDevice->StartRecording(); //start recording frame from the video | |
if (renderingOff) | |
{ | |
// just run the recording for a few seconds then exit | |
LOG_DEBUG("Rendering disabled. Wait for just a few seconds to acquire data before exiting"); | |
Sleep(5000); // no need to use accurate timer, it's just an approximate delay | |
intersonDevice->StopRecording(); | |
intersonDevice->Disconnect(); | |
} | |
else | |
{ | |
if (displayMode==SHOW_PLOT) | |
{ | |
TestLinePlot(intersonDevice); | |
} | |
else | |
{ | |
// Show the live ultrasound image in a VTK renderer window | |
vtkSmartPointer<vtkImageViewer> viewer = vtkSmartPointer<vtkImageViewer>::New(); | |
viewer->SetInputConnection(intersonDevice->GetOutputPort()); //set image to the render and window | |
viewer->SetColorWindow(255); | |
viewer->SetColorLevel(127.5); | |
viewer->SetZSlice(0); | |
//Create the interactor that handles the event loop | |
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New(); | |
iren->SetRenderWindow(viewer->GetRenderWindow()); | |
viewer->SetupInteractor(iren); | |
viewer->Render(); //must be called after iren and viewer are linked or there will be problems | |
// Establish timer event and create timer to update the live image | |
vtkSmartPointer<vtkMyCallback> call = vtkSmartPointer<vtkMyCallback>::New(); | |
call->m_Interactor=iren; | |
call->m_Viewer=viewer; | |
iren->AddObserver(vtkCommand::TimerEvent, call); | |
iren->CreateTimer(VTKI_TIMER_FIRST); | |
//iren must be initialized so that it can handle events | |
iren->Initialize(); | |
iren->Start(); | |
} | |
} | |
*/ | |
intersonDevice->Disconnect(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment