diff --git a/Interson/IntersonArraySDKCxx/CMakeLists.txt b/Interson/IntersonArraySDKCxx/CMakeLists.txt new file mode 100644 index 0000000..c77915d --- /dev/null +++ b/Interson/IntersonArraySDKCxx/CMakeLists.txt @@ -0,0 +1,122 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## + +cmake_minimum_required( VERSION 3.5 ) + +project( IntersonArraySDKCxx ) + +# CMake modules +include( CMakePackageConfigHelpers ) +include( CTest ) + +# Options +option( BUILD_APPLICATIONS "Build applications" OFF ) +option( BUILD_SERVERS "Build OpenIGTLink Servers" OFF) + +# External dependencies +find_path( IntersonArraySDK_DIR + NAMES Libraries/IntersonArray.dll + PATHS C:/IntersonArraySDK + ) +if( NOT IntersonArraySDK_DIR ) + message( FATAL_ERROR "Please specify the path to the IntersonArraySDK" + " in IntersonArraySDK_DIR" ) +endif() +set( IntersonArraySDK_LIBRARY "${IntersonArraySDK_DIR}/IntersonArray.dll" ) +if( NOT EXISTS ${IntersonArraySDK_LIBRARY} ) + message( FATAL_ERROR "Interson library is missing [${IntersonArraySDK_LIBRARY}]" ) +endif() + +# Install relative directories +set( INSTALL_LIB_DIR lib ) +set( INSTALL_BIN_DIR bin ) +set( INSTALL_INCLUDE_DIR include ) +set( INSTALL_CMAKE_DIR cmake ) + +# Output directories +if( NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY ) + set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${IntersonArraySDKCxx_BINARY_DIR}/${INSTALL_BIN_DIR} ) +endif() +if( NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY ) + set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${IntersonArraySDKCxx_BINARY_DIR}/${INSTALL_LIB_DIR} ) +endif() +if( NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY ) + set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${IntersonArraySDKCxx_BINARY_DIR}/${INSTALL_LIB_DIR} ) +endif() + +# Add subdirectories +add_subdirectory( include ) +add_subdirectory( src ) +if( BUILD_TESTING ) + add_subdirectory( test ) +endif() +if( BUILD_APPLICATIONS ) + add_subdirectory( app ) +endif() + +if( BUILD_SERVERS ) + add_subdirectory( openigtlink ) +endif() + +# Install Interson libraries +install( FILES ${IntersonArraySDK_LIBRARY} + DESTINATION ${INSTALL_BIN_DIR} COMPONENT Runtime + ) + +# Configure 'IntersonArraySDKCxxConfig.cmake' for a build tree +set(CONFIG_DIR_CONFIG ${PROJECT_BINARY_DIR}) +set(intersonArraySDKCxx_config ${PROJECT_BINARY_DIR}/IntersonArraySDKCxxConfig.cmake) +configure_package_config_file( + IntersonArraySDKCxxConfig.cmake.in + ${intersonArraySDKCxx_config} + INSTALL_DESTINATION ${PROJECT_BINARY_DIR} + PATH_VARS CONFIG_DIR_CONFIG + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) + +# Configure 'IntersonArraySDKCxxConfig.cmake' for an install tree +set(CONFIG_DIR_CONFIG ${INSTALL_CMAKE_DIR}) +set( intersonArraySDKCxx_install_config ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/IntersonArraySDKCxxConfig.cmake ) +configure_package_config_file( + IntersonArraySDKCxxConfig.cmake.in + ${intersonArraySDKCxx_install_config} + INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR} + PATH_VARS CONFIG_DIR_CONFIG + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) +install( + FILES ${intersonArraySDKCxx_install_config} + DESTINATION ${INSTALL_CMAKE_DIR} COMPONENT Development + ) + +# Configure 'IntersonArraySDKCxxTargets.cmake' +export( TARGETS IntersonArrayCxx + FILE ${PROJECT_BINARY_DIR}/IntersonArraySDKCxxTargets.cmake + ) + +# Install 'IntersonArraySDKCxxTargets.cmake' and 'IntersonArraySDKCxxConfig.cmake' +install( EXPORT IntersonArraySDKCxxTargets + FILE IntersonArraySDKCxxTargets.cmake + DESTINATION ${INSTALL_CMAKE_DIR} + COMPONENT Development + ) diff --git a/Interson/IntersonArraySDKCxx/IntersonArraySDKCxxConfig.cmake.in b/Interson/IntersonArraySDKCxx/IntersonArraySDKCxxConfig.cmake.in new file mode 100644 index 0000000..7a5dad3 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/IntersonArraySDKCxxConfig.cmake.in @@ -0,0 +1,41 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## + +# Config file for the IntersonArraySDKCxx library wrapper. +# +# It defines the following variables: +# IntersonArraySDKCxx_LIBRARIES - libraries to link against +# IntersonArraySDK_DIR - Path to the IntersonArraySDK used to +# build this library. + +@PACKAGE_INIT@ + +set_and_check( IntersonArraySDKCxx_TARGETS "@PACKAGE_CONFIG_DIR_CONFIG@/IntersonArraySDKCxxTargets.cmake" ) + +if( NOT IntersonArraySDKCxx_TARGETS_IMPORTED ) + set( IntersonArraySDKCxx_TARGETS_IMPORTED 1 ) + include( ${IntersonArraySDKCxx_TARGETS} ) +endif() + +set( IntersonArraySDKCxx_LIBRARIES IntersonArrayCxx ) +set( IntersonArraySDK_DIR "@IntersonArraySDK_DIR@" ) diff --git a/Interson/README.md b/Interson/IntersonArraySDKCxx/README.md similarity index 100% rename from Interson/README.md rename to Interson/IntersonArraySDKCxx/README.md diff --git a/Interson/IntersonArraySDKCxx/README.rst b/Interson/IntersonArraySDKCxx/README.rst new file mode 100644 index 0000000..51e55fd --- /dev/null +++ b/Interson/IntersonArraySDKCxx/README.rst @@ -0,0 +1,12 @@ +IntersonArraySDKCxx +=================== + +C++ Wrapper for the C# SDK for Interson's Linear Array Probe +------------------------------------------------------------- + +Dependencies +------------ + +- CMake +- Interson Array SDK +- Visual Studio, VC x86 Compiler >= 2015 diff --git a/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.cxx b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.cxx new file mode 100644 index 0000000..d4bd7ad --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.cxx @@ -0,0 +1,233 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include // Sleep + +#include "itkImageFileWriter.h" + +#include "IntersonArrayCxxControlsHWControls.h" +#include "IntersonArrayCxxImagingContainer.h" + +#include "AcquireIntersonArrayBModeCLP.h" + +typedef IntersonArrayCxx::Imaging::Container ContainerType; + +const unsigned int Dimension = 3; +typedef ContainerType::PixelType PixelType; +typedef itk::Image< PixelType, Dimension > ImageType; + + +struct CallbackClientData +{ + ImageType * Image; + itk::SizeValueType FrameIndex; +}; + + +void __stdcall pasteIntoImage( PixelType * buffer, void * clientData ) +{ + CallbackClientData * callbackClientData = + static_cast< CallbackClientData * >( clientData ); + ImageType * image = callbackClientData->Image; + + const ImageType::RegionType & largestRegion = + image->GetLargestPossibleRegion(); + const ImageType::SizeType imageSize = largestRegion.GetSize(); + const itk::SizeValueType imageFrames = imageSize[2]; + if( callbackClientData->FrameIndex >= imageFrames ) + { + return; + } + + const int framePixels = imageSize[0] * imageSize[1]; + + PixelType * imageBuffer = image->GetPixelContainer()->GetBufferPointer(); + imageBuffer += framePixels * callbackClientData->FrameIndex; + std::memcpy( imageBuffer, buffer, framePixels * sizeof( PixelType ) ); + + std::cout << "Acquired frame: " << callbackClientData->FrameIndex + << std::endl; + ++(callbackClientData->FrameIndex); +} + + +int main( int argc, char * argv[] ) +{ + PARSE_ARGS; + + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + HWControlsType hwControls; + + const int steering = 0; + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + if( foundProbes.empty() ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + hwControls.FindMyProbe( 0 ); + const unsigned int probeId = hwControls.GetProbeID(); + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency( frequencies ); + if( !hwControls.SetFrequencyAndFocus( frequencyIndex, focusIndex, + steering ) ) + { + std::cerr << "Could not set the frequency." << std::endl; + return EXIT_FAILURE; + } + + if( !hwControls.SendHighVoltage( highVoltage, highVoltage ) ) + { + std::cerr << "Could not set the high voltage." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.EnableHighVoltage() ) + { + std::cerr << "Could not enable high voltage." << std::endl; + return EXIT_FAILURE; + } + + if( !hwControls.SendDynamic( gain ) ) + { + std::cerr << "Could not set dynamic gain." << std::endl; + } + + hwControls.DisableHardButton(); + + ContainerType container; + container.SetRFData( false ); + + const int height = hwControls.GetLinesPerArray(); + const int width = container.MAX_SAMPLES; + const int depth = 100; + const int depthCfm = 50; + if( hwControls.ValidDepth( depth ) == depth ) + { + ContainerType::ScanConverterError converterErrorIdle = + container.IdleInitScanConverter( depth, width, height, probeId, + steering, depthCfm, false, false, 0, false ); + ContainerType::ScanConverterError converterError = + container.HardInitScanConverter( depth, width, height, steering, + depthCfm ); + if( converterError != ContainerType::SUCCESS ) + { + std::cerr << "Error during hard scan converter initialization: " + << converterError << std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cerr << "Invalid requested depth for probe." << std::endl; + } + + const int scanWidth = container.GetWidthScan(); + const int scanHeight = container.GetHeightScan(); + std::cout << "Width = " << width << std::endl; + std::cout << "Height = " << height << std::endl; + std::cout << "ScanWidth = " << scanWidth << std::endl; + std::cout << "ScanHeight = " << scanHeight << std::endl; + std::cout << "MM per Pixel = " << container.GetMmPerPixel() << std::endl; + std::cout << "Depth: " << depth << "mm" << std::endl; + std::cout << std::endl; + + const itk::SizeValueType framesToCollect = frames; + + ImageType::Pointer image = ImageType::New(); + typedef ImageType::RegionType RegionType; + RegionType imageRegion; + ImageType::IndexType imageIndex; + imageIndex.Fill( 0 ); + imageRegion.SetIndex( imageIndex ); + ImageType::SizeType imageSize; + imageSize[0] = width; + imageSize[1] = height; + imageSize[2] = framesToCollect; + imageRegion.SetSize( imageSize ); + image->SetRegions( imageRegion ); + ImageType::SpacingType imageSpacing; + imageSpacing[ 0 ] = container.GetMmPerPixel() / 10.; + imageSpacing[ 1 ] = 38.0 / (height - 1); + const short frameRate = hwControls.GetProbeFrameRate(); + imageSpacing[ 2 ] = 1.0 / frameRate; + image->SetSpacing( imageSpacing ); + ImageType::DirectionType direction; + direction.SetIdentity(); + ImageType::DirectionType::InternalMatrixType & vnlDirection = direction.GetVnlMatrix(); + vnlDirection.put(0, 0, 0.0); + vnlDirection.put(0, 1, 1.0); + vnlDirection.put(1, 0, 1.0); + vnlDirection.put(1, 1, 0.0); + vnlDirection.put(2, 2, -1.0); + image->SetDirection( direction ); + image->Allocate(); + + CallbackClientData clientData; + clientData.Image = image.GetPointer(); + clientData.FrameIndex = 0; + + container.SetNewImageCallback( &pasteIntoImage, &clientData ); + container.StartReadScan(); + Sleep( 100 ); // "time to start" + if( !hwControls.StartBmode() ) + { + std::cerr << "Could not start B-mode collection." << std::endl; + return EXIT_FAILURE; + }; + + int c = 0; + while( clientData.FrameIndex < framesToCollect && c < 10000 ) + { + std::cout << "Frames to collect: " << clientData.FrameIndex << " of " << framesToCollect + << std::endl; + Sleep( 100 ); + ++c; + } + + hwControls.StopAcquisition(); + container.StopReadScan(); + Sleep( 100 ); // "time to stop" + + typedef itk::ImageFileWriter< ImageType > WriterType; + WriterType::Pointer writer = WriterType::New(); + writer->SetFileName( outputImage ); + writer->SetInput( image ); + try + { + writer->Update(); + } + catch( itk::ExceptionObject & error ) + { + std::cerr << "Error: " << error << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.xml b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.xml new file mode 100644 index 0000000..ba6e7f7 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayBMode.xml @@ -0,0 +1,63 @@ + + + Ultrasound + Acquire Interson B Mode + Acquire multiple B-Mode frames with the Interson USB probe. + 0.1.0 + Apache 2.0 + Matt McCormick (Kitware) + This work is funded in part by a grant with InnerOptic/Kitware + + + outputImage + + output + 0 + Output image filename. + + + frames + + Frames to collect. + frames + n + 1 + + + frequencyIndex + + Index of the frequency to examine. See the output of PrintIntersonProbeInfo. + frequencyIndex + f + 1 + + + focusIndex + + Index of the focus to examine. See the output of PrintIntersonProbeInfo. + focusIndex + F + 1 + + + highVoltage + + Percentage of the high voltage for transducer excitation. + highVoltage + z + 50 + 0 + 100 + + + gain + + Dynamic gain [dB]. + gain + g + 100 + 0 + 255 + + + diff --git a/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.cxx b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.cxx new file mode 100644 index 0000000..a99745a --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.cxx @@ -0,0 +1,218 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include // Sleep + +#include "itkImageFileWriter.h" + +#include "IntersonArrayCxxImagingContainer.h" +#include "IntersonArrayCxxControlsHWControls.h" + +#include "AcquireIntersonArrayRFCLP.h" + +typedef IntersonArrayCxx::Imaging::Container ContainerType; + +const unsigned int Dimension = 3; +typedef ContainerType::RFImagePixelType PixelType; +typedef itk::Image< PixelType, Dimension > ImageType; + + +struct CallbackClientData +{ + ImageType * Image; + itk::SizeValueType FrameIndex; +}; + +void __stdcall pasteIntoImage( PixelType * buffer, void * clientData ) +{ + CallbackClientData * callbackClientData = + static_cast< CallbackClientData * >( clientData ); + ImageType * image = + callbackClientData->Image; + + const ImageType::RegionType & largestRegion = + image->GetLargestPossibleRegion(); + const ImageType::SizeType imageSize = largestRegion.GetSize(); + const itk::SizeValueType imageFrames = largestRegion.GetSize()[2]; + if( callbackClientData->FrameIndex >= imageFrames ) + { + return; + } + + const int framePixels = imageSize[0] * imageSize[1]; + + PixelType * imageBuffer = image->GetPixelContainer()->GetBufferPointer(); + imageBuffer += framePixels * callbackClientData->FrameIndex; + std::memcpy( imageBuffer, buffer, framePixels * sizeof( PixelType ) ); + + std::cout << "Acquired frame RF: " << callbackClientData->FrameIndex + << std::endl; + ++(callbackClientData->FrameIndex); +} + +int main( int argc, char * argv[] ) +{ + PARSE_ARGS; + + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + IntersonArrayCxx::Controls::HWControls hwControls; + + int ret = EXIT_SUCCESS; + + int steering = 0; + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + if( foundProbes.empty() ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + hwControls.FindMyProbe( 0 ); + const unsigned int probeId = hwControls.GetProbeID(); + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency( frequencies ); + if( !hwControls.SetFrequencyAndFocus( frequencyIndex, focusIndex, + steering ) ) + { + std::cerr << "Could not set the frequency and focus." << std::endl; + return EXIT_FAILURE; + } + + if( !hwControls.SendHighVoltage( highVoltage, highVoltage ) ) + { + std::cerr << "Could not set the high voltage." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.EnableHighVoltage() ) + { + std::cerr << "Could not enable high voltage." << std::endl; + return EXIT_FAILURE; + } + + hwControls.DisableHardButton(); + + ContainerType container; + container.SetHWControls(&hwControls); + + const int height_lines = hwControls.GetLinesPerArray(); + std::cout << "Lines per array: " << height_lines << std::endl; + const int width_samples = ContainerType::MAX_RFSAMPLES; + std::cout << "Max RF samples: " << width_samples << std::endl; + const itk::SizeValueType framesToCollect = frames; + + const double ns = ContainerType::MAX_RFSAMPLES; // number of samples + const double fs = 30000; // [kHz]=[samples/ms] - sampling frequency + const double depth = sos * ( ns - 1 ) / ( 2 * fs ); + const double depthCfm = depth/2; + std::cout << "Depth: " << depth << "mm" << std::endl; + std::cout << std::endl; + + container.SetRFData( true ); + + container.IdleInitScanConverter( depth, width_samples, height_lines, probeId, + steering, depthCfm, false, false, 0, false ); + container.HardInitScanConverter( depth, width_samples, height_lines, steering, + depthCfm ); + + ImageType::Pointer image = ImageType::New(); + typedef ImageType::RegionType RegionType; + RegionType imageRegion; + ImageType::IndexType imageIndex; + imageIndex.Fill( 0 ); + imageRegion.SetIndex( imageIndex ); + ImageType::SizeType imageSize; + imageSize[0] = width_samples; + imageSize[1] = height_lines; + imageSize[2] = framesToCollect; + imageRegion.SetSize( imageSize ); + image->SetRegions( imageRegion ); + ImageType::SpacingType imageSpacing; + imageSpacing[ 0 ] = sos / ( 2 * fs ); + imageSpacing[ 1 ] = 38.0 / ( height_lines - 1 ); + const short frameRate = hwControls.GetProbeFrameRate(); + imageSpacing[ 2 ] = 1.0 / frameRate; + image->SetSpacing( imageSpacing ); + ImageType::DirectionType direction; + direction.SetIdentity(); + ImageType::DirectionType::InternalMatrixType & vnlDirection = direction.GetVnlMatrix(); + vnlDirection.put(0, 0, 0.0); + vnlDirection.put(0, 1, 1.0); + vnlDirection.put(1, 0, 1.0); + vnlDirection.put(1, 1, 0.0); + vnlDirection.put(2, 2, -1.0); + image->SetDirection( direction ); + image->Allocate(); + + CallbackClientData clientData; + clientData.Image = image.GetPointer(); + clientData.FrameIndex = 0; + + container.SetNewRFImageCallback( &pasteIntoImage, &clientData ); + + std::cout << "StartRFReadScan" << std::endl; + container.StartRFReadScan(); + Sleep( 100 ); // "time to start" + std::cout << "StartRFmode" << std::endl; + if( !hwControls.StartRFmode() ) + { + std::cerr << "Could not start RF collection." << std::endl; + return EXIT_FAILURE; + } + + int c = 0; + while( clientData.FrameIndex < framesToCollect && c < 10000 ) + { + std::cout << "Frames to collect: " << clientData.FrameIndex << " of " << framesToCollect << std::endl; + std::cout << clientData.FrameIndex << " of " << framesToCollect + << std::endl; + Sleep( 100 ); + ++c; + } + + hwControls.StopAcquisition(); + container.StopReadScan(); + Sleep( 100 ); // "time to stop" + + typedef itk::ImageFileWriter< ImageType > WriterType; + WriterType::Pointer writer = WriterType::New(); + writer->SetFileName( outputImage ); + writer->SetInput( image ); + + try + { + writer->Update(); + } + catch( itk::ExceptionObject & error ) + { + std::cerr << "Error: " << error << std::endl; + return EXIT_FAILURE; + } + + return ret; +} diff --git a/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.xml b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.xml new file mode 100644 index 0000000..db90c5c --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/AcquireIntersonArrayRF.xml @@ -0,0 +1,60 @@ + + + Ultrasound + Acquire Interson RF + Acquire multiple RF frames with the Interson USB probe. + 0.1.0 + Apache 2.0 + Matt McCormick (Kitware) + This work is funded in part by a grant with InnerOptic/Kitware + + + outputImage + + output + 0 + Output image filename. + + + frames + + Frames to collect. + frames + n + 1 + + + frequencyIndex + + Index of the frequency to examine. See the output of PrintIntersonProbeInfo. + frequencyIndex + f + 1 + + + focusIndex + + Index of the focus to examine. See the output of PrintIntersonProbeInfo. + focusIndex + F + 1 + + + highVoltage + + Percentage of the high voltage for transducer excitation. + highVoltage + z + 50 + 0 + 100 + + + sos + + Assumed speed of sound in the crossed medium in mm/ms. + sos + 1540 + + + diff --git a/Interson/IntersonArraySDKCxx/app/CMakeLists.txt b/Interson/IntersonArraySDKCxx/app/CMakeLists.txt new file mode 100644 index 0000000..3c241e8 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/CMakeLists.txt @@ -0,0 +1,92 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## +find_package( SlicerExecutionModel REQUIRED ) +include( ${SlicerExecutionModel_USE_FILE} ) + +find_package( ITK REQUIRED ) +include( ${ITK_USE_FILE} ) + +SEMMacroBuildCLI( + NAME AcquireIntersonArrayBMode + TARGET_LIBRARIES ${ITK_LIBRARIES} + IntersonArrayCxx + INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ) + +SEMMacroBuildCLI( + NAME AcquireIntersonArrayRF + TARGET_LIBRARIES ${ITK_LIBRARIES} + IntersonArrayCxx + INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ) + +SEMMacroBuildCLI( + NAME PrintIntersonArrayProbeInfo + TARGET_LIBRARIES IntersonArrayCxx + INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ) + +if( BUILD_TESTING ) + set( TEMP ${PROJECT_BINARY_DIR}/Testing/Temporary ) + + add_test( NAME AcquireIntersonArrayBModeTest + COMMAND $ + ${TEMP}/AcquireIntersonArrayBModeTest.mha + ) + add_test( NAME AcquireIntersonArrayBModeTestFrames + COMMAND $ + --frames 5 + ${TEMP}/AcquireIntersonArrayBModeTestFrames.mha + ) + add_test( NAME AcquireIntersonArrayBModeTestVoltage + COMMAND $ + --highVoltage 30 + ${TEMP}/AcquireIntersonArrayBModeTestVoltage.mha + ) + add_test( NAME AcquireIntersonArrayBModeTestGain + COMMAND $ + --gain 50 + ${TEMP}/AcquireIntersonArrayBModeTestGain.mha + ) + + add_test( NAME AcquireIntersonArrayRFTest + COMMAND $ + ${TEMP}/AcquireIntersonArrayRFTest.mha + ) + add_test( NAME AcquireIntersonArrayRFTestFrames + COMMAND $ + --frames 5 + ${TEMP}/AcquireIntersonArrayRFTestFrames.mha + ) + add_test( NAME AcquireIntersonArrayRFTestVoltage + COMMAND $ + --highVoltage 30 + ${TEMP}/AcquireIntersonArrayRFTestVoltage.mha + ) + add_test( NAME PrintIntersonArrayProbeInfoTest + COMMAND $ + ) +endif() diff --git a/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.cxx b/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.cxx new file mode 100644 index 0000000..0ebc745 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.cxx @@ -0,0 +1,112 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include "IntersonArrayCxxControlsHWControls.h" + +#include +#include + +#include "PrintIntersonArrayProbeInfoCLP.h" + +int main( int argc, char * argv[] ) +{ + PARSE_ARGS; + + std::cout << "Start---" << std::endl; + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + + IntersonArrayCxx::Controls::HWControls hwControls; + + std::cout << "ProbeID: " << static_cast< int >( + hwControls.GetProbeID() ) << std::endl; + + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + if( foundProbes.empty() ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + std::cout << "Probes Found: " << std::endl; + for( size_t ii = 0; ii < foundProbes.size(); ++ii ) + { + std::cout << " " << ii << ": " << foundProbes[ii] << std::endl; + } + if( probeIndex < 0 || probeIndex >= foundProbes.size() ) + { + std::cerr << "Invalid probe index." << std::endl; + return EXIT_FAILURE; + } + hwControls.FindMyProbe( probeIndex ); + const unsigned int probeId = hwControls.GetProbeID(); + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency( frequencies ); + std::cout << "\nFrequencies: [Hz]" << std::endl; + for( size_t ii = 0; ii < frequencies.size(); ++ii ) + { + std::cout << " " << ii << ": " << frequencies[ii] << std::endl; + } + + HWControlsType::FocusType focus; + hwControls.GetFocus( focus ); + std::cout << "\nFocus: [mm]" << std::endl; + for( size_t ii = 0; ii < focus.size(); ++ii ) + { + std::cout << " " << ii << ": " << focus[ii] << std::endl; + } + + std::cout << "\nSupported Depth [mm]: FrameRate [fps]" << std::endl; + int depth = 20; + while( hwControls.ValidDepth( depth ) == depth ) + { + short frameRate = hwControls.GetProbeFrameRate(); + std::cout << " " << depth << ":\t" << frameRate << std::endl; + depth += 20; + } + + std::cout << "Lines per array = " << hwControls.GetLinesPerArray() + << std::endl; + std::cout << "Array CompoundAngle = " << hwControls.GetCompoundAngle() + << std::endl; + std::cout << "Array Radius = " << hwControls.GetArrayRadius() + << std::endl; + std::cout << "Array Angle = " << hwControls.GetArrayAngle() + << std::endl; + std::cout << "Array Width = " << hwControls.GetArrayWidth() + << std::endl; + + std::cout << "\nSerial number: " << hwControls.GetProbeSerialNumber() + << std::endl; + std::cout << "FPGA Version: " << hwControls.ReadFPGAVersion() + << std::endl; + std::cout << "OEM ID: " << hwControls.GetOEMId() << std::endl; + std::cout << "Filter ID: " << hwControls.GetFilterId() << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.xml b/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.xml new file mode 100644 index 0000000..5f8db7e --- /dev/null +++ b/Interson/IntersonArraySDKCxx/app/PrintIntersonArrayProbeInfo.xml @@ -0,0 +1,20 @@ + + + Ultrasound + Print Interson Probe Info + Print properties of the connected Interson USB probe. + 0.1.0 + Apache 2.0 + Matt McCormick (Kitware) + This work is funded in part by a grant with InnerOptic/Kitware + + + probeIndex + + Index of the probe to examine. + probeIndex + i + 0 + + + diff --git a/Interson/IntersonArraySDKCxx/doc/CMakeLists.StandardHeader.txt b/Interson/IntersonArraySDKCxx/doc/CMakeLists.StandardHeader.txt new file mode 100644 index 0000000..f0c11ce --- /dev/null +++ b/Interson/IntersonArraySDKCxx/doc/CMakeLists.StandardHeader.txt @@ -0,0 +1,22 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## diff --git a/Interson/IntersonArraySDKCxx/doc/IntersonArray.StandardHeader.txt b/Interson/IntersonArraySDKCxx/doc/IntersonArray.StandardHeader.txt new file mode 100644 index 0000000..0c5a20d --- /dev/null +++ b/Interson/IntersonArraySDKCxx/doc/IntersonArray.StandardHeader.txt @@ -0,0 +1,22 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ diff --git a/Interson/IntersonArraySDKCxx/include/CMakeLists.txt b/Interson/IntersonArraySDKCxx/include/CMakeLists.txt new file mode 100644 index 0000000..787faa5 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/include/CMakeLists.txt @@ -0,0 +1,31 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## +set( IntersonArrayCxx_HEADERS + IntersonArrayCxxControlsHWControls.h + IntersonArrayCxxImagingContainer.h + IntersonArrayCxxIntersonClass.h + ) +install( FILES + ${IntersonArrayCxx_HEADERS} + DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT Development + ) diff --git a/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxControlsHWControls.h b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxControlsHWControls.h new file mode 100644 index 0000000..5079e8a --- /dev/null +++ b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxControlsHWControls.h @@ -0,0 +1,191 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#ifndef _IntersonArrayCxxControlsHWControls_h +#define _IntersonArrayCxxControlsHWControls_h + +// Export library, autogenerated using Cmake +#include "IntersonArrayCxx_Export.h" + +#include +#include + +// Namespace similar to IntersonArray Namespace from SDK + +/* +The library is organized via namespaces; the root is IntersonArray, +then IntersonArray.Controls to get the methods which access to the +USB probe controls, IntersonArray.Imaging is the scan converter, to +build the 2D image B-Scan bitmap from the log-compressed A-Scan +vectors. +*/ +namespace IntersonArrayCxx +{ +// Namespace similar to IntersonArray.Controls Namespace from SDK +namespace Controls +{ +// Wrapper Class for IntersonArrayClass from SDK +class HWControlsImpl; + +// HWControls similar to IntersonArrayClass from SDK +class IntersonArrayCxx_EXPORT HWControls +{ +public: + typedef std::vector< std::string > FoundProbesType; + typedef std::vector< int > FrequenciesType; + typedef std::vector< int > FocusType; + + HWControls(); + ~HWControls(); + + static const int DIG_GAIN_MIN = -127; + static const int DIG_GAIN_INIT = 0; + static const int DIG_GAIN_MAX = 127; + + // Maximum number of frequencies + static const int MAX_FREQ = 3; + + // Maximum focus + static const int MAX_FOCUS = 3; + + // Maximum stgeering angle + static const int MAX_STERING_ANGLE = 30; + + // These are the valid Probe IDs. + static const int ID_A_7_5MHz = 256; + static const int ID_CA_5_0MHz = 512; + static const int ID_CA_OP_10MHz = 768; + static const int ID_A_OP_10MHz = 1024; + static const int ID_A_OP_12MHz = 1280; + + // Size of the OEM (Original equipment manufacturer) space in the Probe + // EEPROM number of frequencies. + // http://en.wikipedia.org/wiki/Original_equipment_manufacturer + static const unsigned short int EEOEMSpace = 6144; + + // Compound Angle Functions + int GetCompoundAngle() const; + bool EnableCompound(); + bool DisableCompound(); + + // Doubler Functions + bool EnableDoubler(); + bool DisableDoubler(); + + // To get the ID of the probe + short GetProbeID() const; + + // String Vector with all probe names connected + void FindAllProbes( FoundProbesType &foundProbes ) const; + + // Summary: To open a handle to the probe defined by the ProbeIndex. + // Parameters: " ProbeIndex ": Index in the mycolProbesName collection + void FindMyProbe( int probeIndex ); + + // Angle + float GetArrayAngle() const; + + // Radius + float GetArrayRadius() const; + + // Width + float GetArrayWidth() const; + + // Focus + void GetFocus( FocusType & focus ) const; + + // To check if the chosen Depth is valid for the probe. Returns the same + // depth if in the max range, otherwise returns the max depth + int ValidDepth( int depth ) const; + + // Get/Set the list of supported frequencies. Units: Hz. + void GetFrequency( FrequenciesType &frequencies ) const; + bool SetFrequencyAndFocus( unsigned char frequency, unsigned char focus, + int steering ); + + // Lines per array + unsigned int GetLinesPerArray() const; + + //" voltage ": percentage of the maximum of the High Voltage. Returns + //whether the command succeeded (true) or failed (false) + bool SendHighVoltage( unsigned char voltage, unsigned char voltageCfm ); + bool EnableHighVoltage(); + bool DisableHighVoltage(); + + // To set the value of the dynamic and to calculate the value sent to + // the control. " bytDynamic ": value of the Dynamic (db). + // Returns: Returns whether the command succeeded (true) or failed (false) + bool SendDynamic( unsigned char dynamic ); + + // To Start watching the Hardware Button to enable to raise the event + // HWButtonTickť + void EnableHardButton(); + void DisableHardButton(); + unsigned char ReadHardButton(); + + typedef void (__stdcall *NewHardButtonCallbackType)( void *clientData ); + void SetNewHardButtonCallback( NewHardButtonCallbackType callback, + void *clientData = NULL ); + + bool StartBmode(); + bool StartRFmode(); + bool StopAcquisition(); + + //To get the Frame Rate of that probe according to the depth + //" iDepth ": current depth. Returns: Return the current Frame Rate + short GetProbeFrameRate() const; + + // To get the Serial Number of the probe + std::string GetProbeSerialNumber() const; + + // To get the version of the software installed in the FPGA. + std::string ReadFPGAVersion() const; + + // To get the identification of the OEM + std::string GetOEMId() const; + + // To get the identification of 3D + std::string Get3DId() const; + + //To get the identification of the filter. + std::string GetFilterId() const; + + bool DoReadOEMEEPROM( unsigned char * bytDataStage, unsigned short addr, + unsigned short length ); + + bool DoWriteOEMEEPROM( unsigned char * bytDataStage, unsigned short addr, + unsigned short length ); + + +private: + HWControls( const HWControls &); + void operator=( const HWControls &); + + HWControlsImpl *Impl; +}; + +} // end namespace Controls + +} // end namespace IntersonArrayCxx + + +#endif // _IntersonArrayCxxControlsHWControls_h diff --git a/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxImagingContainer.h b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxImagingContainer.h new file mode 100644 index 0000000..905c530 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxImagingContainer.h @@ -0,0 +1,134 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#ifndef _IntersonArrayCxxImagingContainer_h +#define _IntersonArrayCxxImagingContainer_h + +#include "IntersonArrayCxx_Export.h" +#include "IntersonArrayCxxControlsHWControls.h" +#include +#include + +namespace IntersonArrayCxx +{ + +namespace Imaging +{ + +class ContainerImpl; + +class IntersonArrayCxx_EXPORT Container +{ +public: + Container(); + ~Container(); + + typedef unsigned char PixelType; + typedef unsigned short RFPixelType; + typedef short RFImagePixelType; + + static const int MAX_SAMPLES = 1024; + static const int MAX_RFSAMPLES = 2048; + static const int NBOFLINES = 127; + + bool GetCompound(); + + void SetCompound( bool value ); + + bool GetDoubler(); + + void SetDoubler( bool value ); + + int GetHeightScan() const; + + float GetMmPerPixel() const; + + double GetTrueDepth() const; + + int GetWidthScan() const; + + int GetZeroOfYScale() const; + + // Error code of HardInitScanConverter and SoftInitScanConverter + enum ScanConverterError + { + SUCCESS = 1, + PROBE_NOT_INITIALIZED, // FindMyProbe has not been called + UNKNOWN_PROBE, // Probe Identity not valid + UNDER_LIMITS, // Width * Height over 10 * 10 + OVER_LIMITS, // Width * Height over 800 * 1000 + WRONG_FORMAT, // other error + OTHER_ERROR + }; + + ScanConverterError HardInitScanConverter( int depth, int widthScan, + int heightScan, int steering, int depthCfm ); + + ScanConverterError IdleInitScanConverter( int depth, int width, + int height, short idleId, int idleSteering, int depthCfm, bool idleDoubler, + bool idleCompound, int idleCompoundAngle, bool idleCfm ); + + // + // Begin Capture Methods + // + bool GetRFData(); + + void SetRFData( bool value ); + + bool GetFrameAvg(); + + void SetFrameAvg( bool value ); + + bool GetScanOn() const; + + void StartReadScan(); + + void StartRFReadScan(); + + void StopReadScan(); + + typedef void (__stdcall *NewImageCallbackType)( PixelType *buffer, + void *clientData ); + void SetNewImageCallback( NewImageCallbackType callback, + void *clientData = NULL ); + + typedef void (__stdcall *NewRFImageCallbackType)( RFImagePixelType *buffer, + void *clientData ); + void SetNewRFImageCallback( NewRFImageCallbackType callback, + void *clientData = NULL ); + + void SetHWControls(IntersonArrayCxx::Controls::HWControls * controls); + +private: + + Container( const Container &); + void operator=( const Container &); + + ContainerImpl *Impl; +}; + +} // end namespace Imaging + +} // end namespace IntersonArrayCxx + + +#endif // _IntersonArrayCxxImagingContainer_h diff --git a/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxIntersonClass.h b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxIntersonClass.h new file mode 100644 index 0000000..b012438 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/include/IntersonArrayCxxIntersonClass.h @@ -0,0 +1,68 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#ifndef _IntersonArrayCxxIntersonClass_h +#define _IntersonArrayCxxIntersonClass_h + +// Export library, autogenerated using Cmake +#include "IntersonArrayCxx_Export.h" + +#include + +// Namespace similar to IntersonArray Namespace from SDK + +/* +The library is organized via namespaces; the root is “IntersonArray”, +then “IntersonArray.Controls” to get the methods which access to the +USB probe controls, “IntersonArray.Imaging” is the scan converter, to +build the 2D image B-Scan bitmap from the log-compressed A-Scan +vectors. +*/ +namespace IntersonArrayCxx +{ +// Wrapper Class for IntersonClass from SDK +class IntersonClassImpl; + +// IntersonClass similar to IntersonClass from SDK +class IntersonArrayCxx_EXPORT IntersonClass +{ +public: + IntersonClass(); + ~IntersonClass(); + + /* + Summary: To Get the version of IntersonArray.dll + Returns: Returns the String of the version. + */ + std::string Version() const; + +private: + IntersonClass( const IntersonClass &); + void operator=( const IntersonClass &); + + // Add the wrapper to the main class to use dll function in C# + IntersonClassImpl *Impl; +}; + +} // end namespace IntersonArrayCxx + +#endif // _IntersonArrayCxxIntersonClass_h diff --git a/Interson/IntersonArraySDKCxx/openigtlink/CMakeLists.txt b/Interson/IntersonArraySDKCxx/openigtlink/CMakeLists.txt new file mode 100644 index 0000000..b2ad8a5 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/openigtlink/CMakeLists.txt @@ -0,0 +1,49 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## +find_package( SlicerExecutionModel REQUIRED ) +include( ${SlicerExecutionModel_USE_FILE} ) + +find_package(OpenIGTLink REQUIRED) +include(${OpenIGTLink_USE_FILE}) + +find_package( ITK REQUIRED ) +include( ${ITK_USE_FILE} ) + +SEMMacroBuildCLI( + NAME IntersonArrayServerRF + TARGET_LIBRARIES ${ITK_LIBRARIES} + IntersonArrayCxx + OpenIGTLink + INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include + ) + +SEMMacroBuildCLI( + NAME IntersonArrayServerBMode + TARGET_LIBRARIES ${ITK_LIBRARIES} + IntersonArrayCxx + OpenIGTLink + INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/include + ${PROJECT_BINARY_DIR}/include +) + diff --git a/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.cxx b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.cxx new file mode 100644 index 0000000..4a5c97c --- /dev/null +++ b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.cxx @@ -0,0 +1,309 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include // Sleep + +#include "itkImageFileWriter.h" + +#include "IntersonArrayCxxControlsHWControls.h" +#include "IntersonArrayCxxImagingContainer.h" + +#include "igtlImageMessage.h" +#include "igtlServerSocket.h" + +#include "IntersonArrayServerBModeCLP.h" + +bool running; + +typedef IntersonArrayCxx::Imaging::Container ContainerType; + +const unsigned int Dimension = 3; +typedef ContainerType::PixelType PixelType; +typedef itk::Image< PixelType, Dimension > ImageType; + +BOOL WINAPI consoleHandler(DWORD signal) { + + if (signal == CTRL_C_EVENT) + { + running = false; + } + + return TRUE; +} + +struct CallbackClientData +{ + itk::SizeValueType FrameIndex; + igtl::Socket* socket; + igtl::ImageMessage* imgMsg; + igtl::TimeStamp* ts; + int width; + int height; +}; + + +void __stdcall pasteIntoImage(PixelType* buffer, void* clientData) +{ + CallbackClientData* callbackClientData = + static_cast(clientData); + + std::cout << "Acquired frame: " << callbackClientData->FrameIndex + << std::endl; + ++(callbackClientData->FrameIndex); + + // sending to openigtlink + igtl::ImageMessage* message = callbackClientData->imgMsg; + igtl::Socket* socket = callbackClientData->socket; + igtl::TimeStamp* ts = callbackClientData->ts; + + int framePixels = callbackClientData->width * callbackClientData->height; + + message->SetMessageID(callbackClientData->FrameIndex); + ts->GetTime(); + igtlUint32 sec; + igtlUint32 nsec; + ts->GetTimeStamp(&sec, &nsec); + message->SetTimeStamp(sec, nsec); + + std::memcpy(message->GetScalarPointer(), buffer, framePixels * sizeof(PixelType)); + + if (!socket) + { + return; + } + + message->Pack(); + socket->Send(message->GetPackPointer(), message->GetPackSize()); +} + + +int main(int argc, char* argv[]) +{ + PARSE_ARGS; + + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + HWControlsType hwControls; + + const int steering = 0; + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes(foundProbes); + if (foundProbes.empty()) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + hwControls.FindMyProbe(0); + const unsigned int probeId = hwControls.GetProbeID(); + if (probeId == 0) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency(frequencies); + + HWControlsType::FocusType focuses; + hwControls.GetFocus(focuses); + + if (!hwControls.SetFrequencyAndFocus(frequencyIndex, focusIndex, + steering)) + { + std::cerr << "Could not set the frequency." << std::endl; + return EXIT_FAILURE; + } + + if (!hwControls.SendHighVoltage(highVoltage, highVoltage)) + { + std::cerr << "Could not set the high voltage." << std::endl; + return EXIT_FAILURE; + } + if (!hwControls.EnableHighVoltage()) + { + std::cerr << "Could not enable high voltage." << std::endl; + return EXIT_FAILURE; + } + + if (!hwControls.SendDynamic(gain)) + { + std::cerr << "Could not set dynamic gain." << std::endl; + } + + hwControls.DisableHardButton(); + + ContainerType container; + container.SetRFData(false); + + const int height = hwControls.GetLinesPerArray(); + const int width = container.MAX_SAMPLES; + const int depth = 100; + const int depthCfm = 50; + if (hwControls.ValidDepth(depth) == depth) + { + ContainerType::ScanConverterError converterErrorIdle = + container.IdleInitScanConverter(depth, width, height, probeId, + steering, depthCfm, false, false, 0, false); + ContainerType::ScanConverterError converterError = + container.HardInitScanConverter(depth, width, height, steering, + depthCfm); + if (converterError != ContainerType::SUCCESS) + { + std::cerr << "Error during hard scan converter initialization: " + << converterError << std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cerr << "Invalid requested depth for probe." << std::endl; + } + + const int scanWidth = container.GetWidthScan(); + const int scanHeight = container.GetHeightScan(); + std::cout << "Width = " << width << std::endl; + std::cout << "Height = " << height << std::endl; + std::cout << "ScanWidth = " << scanWidth << std::endl; + std::cout << "ScanHeight = " << scanHeight << std::endl; + std::cout << "MM per Pixel = " << container.GetMmPerPixel() << std::endl; + std::cout << "Depth: " << depth << "mm" << std::endl; + std::cout << std::endl; + + int imageSize[3]; + imageSize[0] = width; + imageSize[1] = height; + imageSize[2] = 1; + + float imageSpacing[3]; + imageSpacing[0] = container.GetMmPerPixel() / 10.; + imageSpacing[1] = 38.0 / (height - 1); + const short frameRate = hwControls.GetProbeFrameRate(); + imageSpacing[2] = 1.0 / frameRate; + + //------------------------------------------------------------ + // Create a new IMAGE type message + igtl::ImageMessage::Pointer imgMsg = igtl::ImageMessage::New(); + imgMsg->SetDimensions(imageSize); + imgMsg->SetSpacing(imageSpacing); + imgMsg->SetScalarType(igtl::ImageMessage::TYPE_UINT8); + imgMsg->SetDeviceName("IntersonBMode"); + + int svsize[] = { imageSize[0], imageSize[1], 1 }; // sub-volume size + int svoffset[] = { 0, 0, 0 }; + + imgMsg->SetSubVolume(svsize, svoffset); + imgMsg->SetHeaderVersion(IGTL_HEADER_VERSION_2); + IANA_ENCODING_TYPE codingScheme = IANA_TYPE_US_ASCII; + + //Add meta data here + imgMsg->SetMetaDataElement("Frequency (MHz)", codingScheme, std::to_string(frequencies[frequencyIndex])); + imgMsg->SetMetaDataElement("Focus (mm)", codingScheme, std::to_string(focuses[focusIndex])); + imgMsg->SetMetaDataElement("High voltage", codingScheme, std::to_string(highVoltage)); + imgMsg->SetMetaDataElement("FPS", codingScheme, std::to_string(frameRate)); + imgMsg->SetMetaDataElement("Steering", codingScheme, std::to_string(steering)); + imgMsg->SetMetaDataElement("Image Type", codingScheme, "RF"); + imgMsg->SetMetaDataElement("Timestamp seconds", codingScheme, "0"); + imgMsg->SetMetaDataElement("Timestamp nseconds", codingScheme, "0"); + + imgMsg->AllocateScalars(); + imgMsg->SetEndian(igtl::ImageMessage::ENDIAN_LITTLE); + imgMsg->SetCoordinateSystem(igtl::ImageMessage::COORDINATE_LPS); // LPS + igtl::Matrix4x4 matrix; + matrix[0][0] = 0.0; matrix[1][0] = -1.0; matrix[2][0] = 0.0; matrix[3][0] = 0.0; + matrix[0][1] = 1.0; matrix[1][1] = 0.0; matrix[2][1] = 0.0; matrix[3][1] = 0.0; + matrix[0][2] = 0.0; matrix[1][2] = 0.0; matrix[2][2] = 1.0; matrix[3][2] = 0.0; + matrix[0][3] = 0.0; matrix[1][3] = 0.0; matrix[2][3] = 0.0; matrix[3][3] = 1.0; + /*igtl::Matrix4x4 matrix; + matrix[0][0] = 0.0; matrix[0][1] = 1.0; matrix[0][2] = 0.0; matrix[0][3] = 0.0; + matrix[1][2] = -1.0; matrix[1][2] = 0.0; matrix[1][2] = 0.0; matrix[1][3] = 0.0; + matrix[2][2] = 0.0; matrix[2][2] = 0.0; matrix[2][2] = 1.0; matrix[2][3] = 0.0; + matrix[3][2] = 0.0; matrix[3][2] = 0.0; matrix[3][2] = 0.0; matrix[3][3] = 1.0;*/ + + +// matrix[0][0] = -1.0; matrix[0][1] = 0.0; matrix[0][2] = 0.0; matrix[0][3] = 0.0; +// matrix[1][2] = 0.0; matrix[1][2] = 1.0; matrix[1][2] = 0.0; matrix[1][3] = 0.0; +// matrix[2][2] = 0.0; matrix[2][2] = 0.0; matrix[2][2] = 1.0; matrix[2][3] = 0.0; +// matrix[3][2] = 0.0; matrix[3][2] = 0.0; matrix[3][2] = 0.0; matrix[3][3] = 1.0; + imgMsg->SetMatrix(matrix); + igtl::TimeStamp::Pointer ts = igtl::TimeStamp::New(); + + CallbackClientData clientData; + clientData.ts = ts.GetPointer(); + clientData.imgMsg = imgMsg.GetPointer(); + clientData.FrameIndex = 0; + clientData.width = imageSize[0]; + clientData.height = imageSize[1]; + + //socket setup + igtl::ServerSocket::Pointer serverSocket; + serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + std::cerr << "Created Server socket." << std::endl; + igtl::Socket::Pointer socket; + clientData.socket = socket; + + container.SetNewImageCallback(&pasteIntoImage, &clientData); + container.StartReadScan(); + Sleep(100); // "time to start" + if (!hwControls.StartBmode()) + { + std::cerr << "Could not start B-mode collection." << std::endl; + return EXIT_FAILURE; + }; + + if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) + { + std::cout << "Could not set control handler" << std::endl; + return 1; + } + running = true; + std::cout << "Server is running, use Ctrl-C to stop" << std::endl; + while (running) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + clientData.socket = socket.GetPointer(); + if (socket.IsNotNull()) // if client connected + { + Sleep(10000); //chill for a bit + } + + } + + std::cout << "Shutting down" << std::endl; + hwControls.StopAcquisition(); + container.StopReadScan(); + if (socket) + { + socket->CloseSocket(); + } + + Sleep(100); // "time to stop" + return EXIT_SUCCESS; +} diff --git a/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.xml b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.xml new file mode 100644 index 0000000..f5aa15a --- /dev/null +++ b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerBMode.xml @@ -0,0 +1,64 @@ + + + Ultrasound + Acquire Interson B Mode + Acquire multiple B-Mode frames with the Interson USB probe. + 0.1.0 + Apache 2.0 + Brad T. Moore (Kitware) + This effort was sponsored by the U.S. Government under Other Transactions Number W81XWH-15-9-0001/W81XWH-19-9-0015 (MTEC 19-08-MuLTI-0079). + + + port + + Port for OpenIGTLink Server. + port + p + 18944 + + + frames + + Frames to collect. + frames + n + 1 + + + frequencyIndex + + Index of the frequency to examine. See the output of PrintIntersonProbeInfo. + frequencyIndex + f + 1 + + + focusIndex + + Index of the focus to examine. See the output of PrintIntersonProbeInfo. + focusIndex + F + 1 + + + highVoltage + + Percentage of the high voltage for transducer excitation. + highVoltage + z + 50 + 0 + 100 + + + gain + + Dynamic gain [dB]. + gain + g + 100 + 0 + 255 + + + diff --git a/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.cxx b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.cxx new file mode 100644 index 0000000..1c48679 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.cxx @@ -0,0 +1,258 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include // Sleep + +#include "IntersonArrayCxxImagingContainer.h" +#include "IntersonArrayCxxControlsHWControls.h" +#include "igtlImageMessage.h" +#include "igtlServerSocket.h" + +#include "IntersonArrayServerRFCLP.h" + +typedef IntersonArrayCxx::Imaging::Container ContainerType; +typedef ContainerType::RFImagePixelType PixelType; +bool running; + +BOOL WINAPI consoleHandler(DWORD signal) { + + if (signal == CTRL_C_EVENT) + { + running = false; + } + + return TRUE; +} + +struct CallbackClientData +{ + int FrameIndex; + igtl::Socket * socket; + igtl::ImageMessage * imgMsg; + igtl::TimeStamp * ts; +}; + +void __stdcall pasteIntoImage( PixelType * buffer, void * clientData ) +{ + CallbackClientData * callbackClientData = + static_cast< CallbackClientData * >( clientData ); + + igtl::ImageMessage * message = callbackClientData->imgMsg; + igtl::Socket * socket = callbackClientData->socket; + igtl::TimeStamp * ts = callbackClientData->ts; + + const int framePixels = ContainerType::MAX_RFSAMPLES * ContainerType::NBOFLINES; + ++(callbackClientData->FrameIndex); + + message->SetMessageID(callbackClientData->FrameIndex); + ts->GetTime(); + igtlUint32 sec; + igtlUint32 nsec; + ts->GetTimeStamp(&sec, &nsec); + message->SetTimeStamp(sec, nsec); + + std::memcpy(message->GetScalarPointer(), buffer, framePixels * sizeof(PixelType)); + + if (!socket) + { + return; + } + + message->Pack(); + socket->Send(message->GetPackPointer(), message->GetPackSize()); +} + +int main( int argc, char * argv[] ) +{ + PARSE_ARGS; + + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + IntersonArrayCxx::Controls::HWControls hwControls; + + int ret = EXIT_SUCCESS; + + int steering = 0; + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + if( foundProbes.empty() ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + hwControls.FindMyProbe( 0 ); + const unsigned int probeId = hwControls.GetProbeID(); + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency( frequencies ); + + HWControlsType::FocusType focuses; + hwControls.GetFocus(focuses); + + if( !hwControls.SetFrequencyAndFocus( frequencyIndex, focusIndex, + steering ) ) + { + std::cerr << "Could not set the frequency and focus." << std::endl; + return EXIT_FAILURE; + } + + if( !hwControls.SendHighVoltage( highVoltage, highVoltage ) ) + { + std::cerr << "Could not set the high voltage." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.EnableHighVoltage() ) + { + std::cerr << "Could not enable high voltage." << std::endl; + return EXIT_FAILURE; + } + + hwControls.DisableHardButton(); + ContainerType container; + container.SetHWControls(&hwControls); + + const int height_lines = hwControls.GetLinesPerArray(); + std::cout << "Lines per array: " << height_lines << std::endl; + const int width_samples = ContainerType::MAX_RFSAMPLES; + std::cout << "Max RF samples: " << width_samples << std::endl; + const double ns = ContainerType::MAX_RFSAMPLES; // number of samples + const double fs = 30000; // [kHz]=[samples/ms] - sampling frequency + const double depth = sos * ( ns - 1 ) / ( 2 * fs ); + const double depthCfm = depth/2; + std::cout << "Depth: " << depth << "mm" << std::endl; + std::cout << std::endl; + + container.SetRFData( true ); + container.IdleInitScanConverter( depth, width_samples, height_lines, probeId, + steering, depthCfm, false, false, 0, false ); + container.HardInitScanConverter( depth, width_samples, height_lines, steering, + depthCfm ); + + CallbackClientData clientData; + clientData.FrameIndex = 0; + + // size parameters + const short frameRate = hwControls.GetProbeFrameRate(); + int size[] = { ContainerType::MAX_RFSAMPLES, ContainerType::NBOFLINES, 1 }; // image dimension + float spacing[] = { sos / (2 * fs), 38.0 / (height_lines - 1), 1.0 / frameRate }; // spacing (mm/pixel) + int svsize[] = { ContainerType::MAX_RFSAMPLES, ContainerType::NBOFLINES, 1 }; // sub-volume size + int svoffset[] = { 0, 0, 0 }; // sub-volume offset + int scalarType = igtl::ImageMessage::TYPE_INT16;// scalar type + + //------------------------------------------------------------ + // Create a new IMAGE type message + igtl::ImageMessage::Pointer imgMsg = igtl::ImageMessage::New(); + imgMsg->SetDimensions(size); + imgMsg->SetSpacing(spacing); + imgMsg->SetScalarType(scalarType); + imgMsg->SetDeviceName("IntersonRF"); + imgMsg->SetSubVolume(svsize, svoffset); + imgMsg->SetHeaderVersion(IGTL_HEADER_VERSION_2); + IANA_ENCODING_TYPE codingScheme = IANA_TYPE_US_ASCII; + + //Add meta data here + imgMsg->SetMetaDataElement("Frequency (MHz)", codingScheme, std::to_string(frequencies[frequencyIndex])); + imgMsg->SetMetaDataElement("Focus (mm)", codingScheme, std::to_string(focuses[focusIndex])); + imgMsg->SetMetaDataElement("High voltage", codingScheme, std::to_string(highVoltage)); + imgMsg->SetMetaDataElement("SOS", codingScheme, std::to_string(sos)); + imgMsg->SetMetaDataElement("FPS", codingScheme, std::to_string(frameRate)); + imgMsg->SetMetaDataElement("Steering", codingScheme, std::to_string(steering)); + imgMsg->SetMetaDataElement("Image Type", codingScheme, "RF"); + imgMsg->SetMetaDataElement("Timestamp seconds", codingScheme, "0"); + imgMsg->SetMetaDataElement("Timestamp nseconds", codingScheme, "0"); + + imgMsg->AllocateScalars(); + imgMsg->SetEndian(igtl::ImageMessage::ENDIAN_LITTLE); + igtl::Matrix4x4 matrix; + matrix[0][0] = 0.0; matrix[1][0] = -1.0; matrix[2][0] = 0.0; matrix[3][0] = 0.0; + matrix[0][1] = 1.0; matrix[1][1] = 0.0; matrix[2][1] = 0.0; matrix[3][1] = 0.0; + matrix[0][2] = 0.0; matrix[1][2] = 0.0; matrix[2][2] = 1.0; matrix[3][2] = 0.0; + matrix[0][3] = 0.0; matrix[1][3] = 0.0; matrix[2][3] = 0.0; matrix[3][3] = 1.0; + imgMsg->SetMatrix(matrix); + igtl::TimeStamp::Pointer ts = igtl::TimeStamp::New(); + clientData.ts = ts.GetPointer(); + clientData.imgMsg = imgMsg.GetPointer(); + + //socket setup + igtl::ServerSocket::Pointer serverSocket; + serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + std::cerr << "Created Server socket." << std::endl; + + + igtl::Socket::Pointer socket; + clientData.socket = socket; + + container.SetNewRFImageCallback( &pasteIntoImage, &clientData ); + + std::cout << "StartRFReadScan" << std::endl; + container.StartRFReadScan(); + Sleep( 100 ); // "time to start" + std::cout << "StartRFmode" << std::endl; + if( !hwControls.StartRFmode() ) + { + std::cerr << "Could not start RF collection." << std::endl; + return EXIT_FAILURE; + } + + if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) + { + std::cout << "Could not set control handler" << std::endl; + return 1; + } + running = true; + std::cout << "Server is running, use Ctrl-C to stop" << std::endl; + while( running ) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + clientData.socket = socket.GetPointer(); + if (socket.IsNotNull()) // if client connected + { + Sleep(10000); //chill for a bit + } + + } + + std::cout << "Shutting down" << std::endl; + hwControls.StopAcquisition(); + container.StopReadScan(); + if (socket) + { + socket->CloseSocket(); + } + + Sleep( 100 ); // "time to stop" + return ret; +} diff --git a/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.xml b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.xml new file mode 100644 index 0000000..d987e0b --- /dev/null +++ b/Interson/IntersonArraySDKCxx/openigtlink/IntersonArrayServerRF.xml @@ -0,0 +1,53 @@ + + + Ultrasound + Interson RF OpenIGTLink Server + Broadcast RF images over OpenIGTLink. + 0.1.0 + Apache 2.0 + Sam Horvath (Kitware), Matt McCormick (Kitware) + This work is funded in part by a grant with InnerOptic/Kitware + + + port + + Port for OpenIGTLink Server. + port + p + 18944 + + + frequencyIndex + + Index of the frequency to examine. See the output of PrintIntersonProbeInfo. + frequencyIndex + f + 1 + + + focusIndex + + Index of the focus to examine. See the output of PrintIntersonProbeInfo. + focusIndex + F + 1 + + + highVoltage + + Percentage of the high voltage for transducer excitation. + highVoltage + z + 50 + 0 + 100 + + + sos + + Assumed speed of sound in the crossed medium in mm/ms. + sos + 1540 + + + diff --git a/Interson/IntersonArraySDKCxx/src/CMakeLists.txt b/Interson/IntersonArraySDKCxx/src/CMakeLists.txt new file mode 100644 index 0000000..2f379d7 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/src/CMakeLists.txt @@ -0,0 +1,110 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## + +# XXX (Maeliss, Jc) Ideally, these flags should probably be associated with the +# targets using target_compile_options command. +if(CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1") + string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") +endif() + +#if(CMAKE_CXX_FLAGS MATCHES "/EHsc") + #string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +#endif() +set( CMAKE_CXX_FLAGS "/clr /EHa /AI\"${IntersonArraySDK_DIR}\"" ) + +set( IntersonArrayCxx_SRCS + IntersonArrayCxxControlsHWControls.cxx + IntersonArrayCxxImagingContainer.cxx + IntersonArrayCxxIntersonClass.cxx + ) + +add_library( IntersonArrayCxx SHARED + ${IntersonArrayCxx_SRCS} ) + +target_include_directories( IntersonArrayCxx PUBLIC + $ + $ + $ + ) + +find_library(MSCOREE_LIBRARY + NAMES MSCOREE mscoree + PATHS "C:/Program Files (x86)/Common Files/Microsoft/Visual C++ for Python/9.0/WinSDK/Lib/" + ) +if(MSCOREE_LIBRARY) + target_link_libraries(IntersonArrayCxx ${MSCOREE_LIBRARY}) +endif() + +# Generate and install export header +include( GenerateExportHeader ) +set(export_header ${PROJECT_BINARY_DIR}/include/IntersonArrayCxx_Export.h) +generate_export_header( IntersonArrayCxx + BASE_NAME IntersonArrayCxx + EXPORT_MACRO_NAME IntersonArrayCxx_EXPORT + EXPORT_FILE_NAME ${export_header} + ) +install( + FILES ${export_header} + DESTINATION include COMPONENT Development + ) + +# Install library +install( + TARGETS IntersonArrayCxx + EXPORT IntersonArraySDKCxxTargets + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT Runtime + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT Development + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" COMPONENT Development + ) + +# Copy "IntersonArray.dll" and "IntersonArrayCxx.dll" to allow tests and applications to be executed from the build directory +if( BUILD_TESTING ) + add_custom_command( TARGET IntersonArrayCxx + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/bin" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/bin/" + ) +endif() +if( BUILD_APPLICATIONS ) + add_custom_command( TARGET IntersonArrayCxx + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/app/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/app/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/app/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/app/bin" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/app/bin" + ) +endif() + +if( BUILD_SERVERS ) + add_custom_command( TARGET IntersonArrayCxx + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/openigtlink/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/openigtlink/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/openigtlink/bin/$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${IntersonArraySDK_DIR}/IntersonArray.dll" "${PROJECT_BINARY_DIR}/openigtlink/bin" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "${PROJECT_BINARY_DIR}/openigtlink/bin" + ) +endif() diff --git a/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxControlsHWControls.cxx b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxControlsHWControls.cxx new file mode 100644 index 0000000..b75e97c --- /dev/null +++ b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxControlsHWControls.cxx @@ -0,0 +1,658 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +// C++ +#include "IntersonArrayCxxControlsHWControls.h" + +// C# + +#include +#include + +// Add library from SDK +#using "IntersonArray.dll" + +#pragma managed + +namespace IntersonArrayCxx +{ + +namespace Controls +{ + +ref class NewHardButtonHandler +{ +public: + typedef HWControls::NewHardButtonCallbackType NewHardButtonCallbackType; + + NewHardButtonHandler(): + NewHardButtonCallback( NULL ), + NewHardButtonCallbackClientData( NULL ) + { + } + + ~NewHardButtonHandler() + { + } + + void HandleNewHardButton( IntersonArray::Controls::HWControls ^controls, + System::EventArgs ^eventArgs ) + { + if ( this->NewHardButtonCallback != NULL ) + { + this->NewHardButtonCallback( this->NewHardButtonCallbackClientData ); + } + } + + void SetNewHardButtonCallback( NewHardButtonCallbackType callback, + void *clientData ) + { + this->NewHardButtonCallback = callback; + this->NewHardButtonCallbackClientData = clientData; + } + +private: + NewHardButtonCallbackType NewHardButtonCallback; + void *NewHardButtonCallbackClientData; +}; + +// Wrapper Class for IntersonArrayClass from SDK +class HWControlsImpl +{ +public: + // New defininions look header file + typedef HWControls::FoundProbesType FoundProbesType; + typedef HWControls::FrequenciesType FrequenciesType; + typedef HWControls::FocusType FocusType; + + + HWControlsImpl() + { + // New method for managed code. Wrapped is data member or this class + Wrapped = gcnew IntersonArray::Controls::HWControls(); + + HardButtonHandler = gcnew NewHardButtonHandler(); + HardButtonHandlerDelegate = gcnew + IntersonArray::Controls::HWControls::HWButtonHandlerReleased( + HardButtonHandler, &NewHardButtonHandler::HandleNewHardButton ); + Wrapped->HWButtonTickReleased += HardButtonHandlerDelegate; + } + + ~HWControlsImpl() + { + Wrapped->HWButtonTickReleased -= HardButtonHandlerDelegate; + } + + // Compound Angle Functions + int GetCompoundAngle() const + { + return Wrapped->CompoundAngle; + } + + bool EnableCompound() + { + return Wrapped->EnableCompound(); + } + + bool DisableCompound() + { + return Wrapped->DisableCompound(); + } + + // Doubler Functions + bool EnableDoubler() + { + return Wrapped->EnableDoubler(); + } + + bool DisableDoubler() + { + return Wrapped->DisableDoubler(); + } + + + // Probe ID Functions + short GetProbeID() const + { + return Wrapped->GetProbeID(); + } + + void FindAllProbes( FoundProbesType &foundProbes ) const + { + System::Collections::Specialized::StringCollection ^managedProbes = + gcnew System::Collections::Specialized::StringCollection(); + Wrapped->FindAllProbes( managedProbes );; + foundProbes.resize( managedProbes->Count ); + // Copy all available probes to the C++ class + for ( int ii = 0; ii < managedProbes->Count; ++ii ) + { + foundProbes[ii] = msclr::interop::marshal_as< std::string >( + managedProbes[ii] ); + } + } + + void FindMyProbe( int probeIndex ) const + { + Wrapped->FindMyProbe( probeIndex ); + } + + // Angle + float GetArrayAngle() const + { + return Wrapped->GetArrayAngle(); + } + + // Radius + float GetArrayRadius() const + { + return Wrapped->GetArrayRadius(); + } + + // Width + float GetArrayWidth() const + { + return Wrapped->GetArrayWidth(); + } + + // Focus + void GetFocus( FocusType & focus ) const + { + array< int > ^managedFocus = Wrapped->GetFocus(); + focus.resize( managedFocus->Length ); + for ( int ii = 0; ii < managedFocus->Length; ++ii ) + { + focus[ii] = managedFocus[ii]; + } + } + + // To check if the chosen Depth is valid for the probe. Returns the same + // depth if in the max range, otherwise returns the max depth + int ValidDepth( int depth ) const + { + return Wrapped->ValidDepth( depth ); + } + + // Get the list of supported frequencies. Units: Hz. + void GetFrequency( FrequenciesType &frequencies ) const + { + array< int > ^managedFrequencies = Wrapped->GetFrequency(); + frequencies.resize( managedFrequencies->Length ); + for ( int ii = 0; ii < managedFrequencies->Length; ++ii ) + { + frequencies[ii] = managedFrequencies[ii]; + } + } + + // Set the list of supported frequencies. Units: Hz. + bool SetFrequencyAndFocus( unsigned char frequency, unsigned char focus, + int steering ) + { + return Wrapped->SetFrequencyAndFocus( frequency, focus, steering ); + } + + // Lines Per Array + unsigned int GetLinesPerArray() const + { + return Wrapped->GetLinesPerArray(); + } + + //" voltage ": percentage of the maximum of the High Voltage. Returns + //whether the command succeeded (true) or failed (false) + bool SendHighVoltage( unsigned char voltage, unsigned char voltageCfm ) + { + return Wrapped->SendHighVoltage( voltage, voltageCfm ); + } + + bool EnableHighVoltage() + { + return Wrapped->EnableHighVoltage(); + } + + bool DisableHighVoltage() + { + return Wrapped->DisableHighVoltage(); + } + + // To set the value of the dynamic and to calculate the value sent to + // the control. " bytDynamic ": value of the Dynamic (db). + // Returns: Returns whether the command succeeded (true) or failed (false) + bool SendDynamic( unsigned char dynamic ) + { + return Wrapped->SendDynamic( dynamic ); + } + + // To Start watching the Hardware Button to enable to raise the event + // HWButtonTickť + void EnableHardButton() + { + Wrapped->EnableHardButton(); + } + + void DisableHardButton() + { + Wrapped->DisableHardButton(); + } + + unsigned char ReadHardButton() const + { + return Wrapped->ReadHardButton(); + } + + void SetNewHardButtonCallback( HWControls::NewHardButtonCallbackType + callback, void *clientData = 0 ) + { + this->HardButtonHandler->SetNewHardButtonCallback( callback, + clientData ); + } + + bool StartBmode() + { + return Wrapped->StartBmode(); + } + + bool StartRFmode() + { + return Wrapped->StartRFmode(); + } + + bool StopAcquisition() + { + return Wrapped->StopAcquisition(); + } + + short GetProbeFrameRate() const + { + return Wrapped->GetProbeFrameRate(); + } + + std::string GetProbeSerialNumber() const + { + return msclr::interop::marshal_as< std::string >( + Wrapped->GetProbeSerialNumber() ); + } + + std::string ReadFPGAVersion() const + { + return msclr::interop::marshal_as< std::string >( + Wrapped->ReadFPGAVersion() ); + } + + std::string GetOEMId() const + { + return msclr::interop::marshal_as< std::string >( + IntersonArray::Controls::HWControls::GetOEMId() ); + } + + std::string Get3DId() const + { + return msclr::interop::marshal_as< std::string >( + IntersonArray::Controls::HWControls::Get3DId() ); + } + + std::string GetFilterId() + { + return msclr::interop::marshal_as< std::string >( + IntersonArray::Controls::HWControls::GetFilterId() ); + } + + bool DoReadOEMEEPROM( unsigned char * bytDataStage, unsigned short addr, + unsigned short length ) + { + typedef cli::array< unsigned char, 1 > DataType; + DataType ^ managedData; + + if( Wrapped->DoReadOEMEEPROM( managedData, addr, length ) ) + { + bytDataStage = new unsigned char[ length ]; + for( unsigned int ii=0; ii DataType; + DataType ^ managedData; + + for( unsigned int ii=0; iiDoWriteOEMEEPROM( managedData, addr, length ); + } + + +private: + + gcroot< IntersonArray::Controls::HWControls ^ > Wrapped; + gcroot< NewHardButtonHandler ^ > HardButtonHandler; + gcroot< IntersonArray::Controls::HWControls::HWButtonHandlerReleased ^ > + HardButtonHandlerDelegate; + +}; + +// C++ +#pragma unmanaged + +HWControls +::HWControls(): + Impl( new HWControlsImpl() ) +{ +} + + +HWControls +::~HWControls() +{ + delete Impl; +} + + +int +HWControls +::GetCompoundAngle() const +{ + return Impl->GetCompoundAngle(); +} + + +bool +HWControls +::EnableCompound() +{ + return Impl->EnableCompound(); +} + + +bool +HWControls +::DisableCompound() +{ + return Impl->DisableCompound(); +} + + +bool +HWControls +::EnableDoubler() +{ + return Impl->EnableDoubler(); +} + + +bool +HWControls +::DisableDoubler() +{ + return Impl->DisableDoubler(); +} + + +short +HWControls +::GetProbeID() const +{ + return Impl->GetProbeID(); +} + + +void +HWControls +::FindAllProbes( FoundProbesType &foundProbes ) const +{ + Impl->FindAllProbes( foundProbes ); +} + + +void +HWControls +::FindMyProbe( int probeIndex ) +{ + Impl->FindMyProbe( probeIndex ); +} + + +float +HWControls +::GetArrayAngle() const +{ + return Impl->GetArrayAngle(); +} + + +float +HWControls +::GetArrayRadius() const +{ + return Impl->GetArrayRadius(); +} + + +float +HWControls +::GetArrayWidth() const +{ + return Impl->GetArrayWidth(); +} + + +void +HWControls +::GetFocus( FocusType &focus ) const +{ + Impl->GetFocus( focus ); +} + + +int +HWControls +::ValidDepth( int depth ) const +{ + return Impl->ValidDepth( depth ); +} + + +void +HWControls +::GetFrequency( FrequenciesType &frequencies ) const +{ + Impl->GetFrequency( frequencies ); +} + + +bool +HWControls +::SetFrequencyAndFocus( unsigned char frequency, unsigned char focus, + int steering ) +{ + return Impl->SetFrequencyAndFocus( frequency, focus, steering ); +} + + +unsigned int +HWControls +::GetLinesPerArray() const +{ + return Impl->GetLinesPerArray(); +} + + +bool +HWControls +::SendHighVoltage( unsigned char voltage, unsigned char voltageCfm ) +{ + return Impl->SendHighVoltage( voltage, voltageCfm ); +} + + +bool +HWControls +::EnableHighVoltage() +{ + return Impl->EnableHighVoltage(); +} + + +bool +HWControls +::DisableHighVoltage() +{ + return Impl->DisableHighVoltage(); +} + + +bool +HWControls +::SendDynamic( unsigned char dynamic ) +{ + return Impl->SendDynamic( dynamic ); +} + + +void +HWControls +::EnableHardButton() +{ + Impl->EnableHardButton(); +} + + +void +HWControls +::DisableHardButton() +{ + Impl->DisableHardButton(); +} + + +unsigned char +HWControls +::ReadHardButton() +{ + return Impl->ReadHardButton(); +} + +void +HWControls +::SetNewHardButtonCallback( HWControls::NewHardButtonCallbackType callback, + void * clientData ) +{ + Impl->SetNewHardButtonCallback( callback, clientData ); +} + +bool +HWControls +::StartBmode() +{ + return Impl->StartBmode(); +} + + +bool +HWControls +::StartRFmode() +{ + return Impl->StartRFmode(); +} + + +bool +HWControls +::StopAcquisition() +{ + return Impl->StopAcquisition(); +} + + +short +HWControls +::GetProbeFrameRate() const +{ + return Impl->GetProbeFrameRate(); +} + + +std::string +HWControls +::GetProbeSerialNumber() const +{ + return Impl->GetProbeSerialNumber(); +} + + +std::string +HWControls +::ReadFPGAVersion() const +{ + return Impl->ReadFPGAVersion(); +} + + +std::string +HWControls +::GetOEMId() const +{ + return Impl->GetOEMId(); +} + + +std::string +HWControls +::Get3DId() const +{ + return Impl->Get3DId(); +} + + +std::string +HWControls +::GetFilterId() const +{ + return Impl->GetFilterId(); +} + + +bool +HWControls +::DoReadOEMEEPROM( unsigned char * bytDataStage, unsigned short addr, + unsigned short length ) +{ + return Impl->DoReadOEMEEPROM( bytDataStage, addr, length ); +} + +bool +HWControls +::DoWriteOEMEEPROM( unsigned char * bytDataStage, unsigned short addr, + unsigned short length ) +{ + return Impl->DoWriteOEMEEPROM( bytDataStage, addr, length ); +} + +} // end namespace Controls + +} // end namespace IntersonArrayCxx diff --git a/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxImagingContainer.cxx b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxImagingContainer.cxx new file mode 100644 index 0000000..d313c3b --- /dev/null +++ b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxImagingContainer.cxx @@ -0,0 +1,562 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include "IntersonArrayCxxImagingContainer.h" +#include + +#include +#include +#include + +#using "IntersonArray.dll" + +#pragma managed + +namespace IntersonArrayCxx +{ + +namespace Imaging +{ + +// +// Begin Capture +// +ref class NewRFImageHandler +{ +public: + + typedef Container::NewRFImageCallbackType NewRFImageCallbackType; + + typedef IntersonArrayCxx::Imaging::Container::RFPixelType RFPixelType; + typedef IntersonArrayCxx::Imaging::Container::RFImagePixelType RFImagePixelType; + typedef cli::array< RFPixelType, 2 > RFArrayType; + + NewRFImageHandler( RFArrayType ^managedRFBuffer ): + NewRFImageCallback( NULL ), + NewRFImageCallbackClientData( NULL ), + bufferWidth( Container::MAX_RFSAMPLES ), + bufferHeight( Container::NBOFLINES ), + NativeRFBuffer(new RFImagePixelType[Container::MAX_RFSAMPLES + * Container::NBOFLINES] ), + ManagedRFBuffer( managedRFBuffer ) + { + } + + ~NewRFImageHandler() + { + delete [] NativeRFBuffer; + } + + void HandleNewRFImage( IntersonArray::Imaging::Capture ^scan2D, + System::EventArgs ^eventArgs ) + { + if ( this->NewRFImageCallback != NULL ) + { + for ( int ii = 0; ii < bufferHeight; ++ii ) + { + for ( int jj = 0; jj < bufferWidth; ++jj ) + { + this->NativeRFBuffer[bufferWidth * ii + jj] = (short) + this->ManagedRFBuffer[ii, jj]; + } + } + this->NewRFImageCallback( this->NativeRFBuffer, + this->NewRFImageCallbackClientData ); + } + } + + void SetNewRFImageCallback( NewRFImageCallbackType callback, + void *clientData ) + { + this->NewRFImageCallback = callback; + this->NewRFImageCallbackClientData = clientData; + } + +private: + NewRFImageCallbackType NewRFImageCallback; + void * NewRFImageCallbackClientData; + RFImagePixelType * NativeRFBuffer; + RFArrayType ^ ManagedRFBuffer; + int bufferWidth; + int bufferHeight; +}; + + +ref class NewImageHandler +{ +public: + typedef Container::NewImageCallbackType NewImageCallbackType; + + typedef IntersonArrayCxx::Imaging::Container::PixelType PixelType; + typedef cli::array< byte, 2 > ArrayType; + + NewImageHandler( ArrayType ^managedBuffer ): + NewImageCallback( NULL ), + NewImageCallbackClientData( NULL ), + bufferWidth( Container::MAX_SAMPLES ), + bufferHeight( Container::NBOFLINES ), + NativeBuffer( new PixelType[Container::MAX_SAMPLES * + Container::NBOFLINES ] ), + ManagedBuffer( managedBuffer ) + { + } + + ~NewImageHandler() + { + delete [] NativeBuffer; + } + + void HandleNewImage( IntersonArray::Imaging::Capture ^scan2D, + System::EventArgs ^eventArgs ) + { + if ( this->NewImageCallback != NULL ) + { + for ( int ii = 0; ii < bufferHeight; ++ii ) + { + for ( int jj = 0; jj < bufferWidth; ++jj ) + { + this->NativeBuffer[bufferWidth * ii + jj] = + this->ManagedBuffer[ii, jj]; + } + } + this->NewImageCallback( this->NativeBuffer, + this->NewImageCallbackClientData ); + } + } + + void SetNewImageCallback( NewImageCallbackType callback, + void *clientData ) + { + this->NewImageCallback = callback; + this->NewImageCallbackClientData = clientData; + } + +private: + NewImageCallbackType NewImageCallback; + void * NewImageCallbackClientData; + PixelType * NativeBuffer; + ArrayType ^ ManagedBuffer; + int bufferWidth; + int bufferHeight; +}; + +// End Capture + +class ContainerImpl +{ +public: + typedef cli::array< Container::PixelType, 2 > ArrayType; + typedef cli::array< Container::RFPixelType, 2 > RFArrayType; + + typedef Container::NewImageCallbackType NewImageCallbackType; + typedef Container::NewRFImageCallbackType NewRFImageCallbackType; + + ContainerImpl() + { + WrappedScanConverter = gcnew IntersonArray::Imaging::ScanConverter(); + WrappedImageBuilding = gcnew IntersonArray::Imaging::ImageBuilding(); + WrappedCapture = gcnew IntersonArray::Imaging::Capture(); + + Buffer = gcnew ArrayType( Container::NBOFLINES, Container::MAX_SAMPLES ); + Handler = gcnew NewImageHandler( Buffer ); + HandlerDelegate = gcnew + IntersonArray::Imaging::Capture::NewImageHandler( Handler, + & NewImageHandler::HandleNewImage ); + WrappedCapture->NewImageTick += HandlerDelegate; + + RFBuffer = gcnew RFArrayType( Container::NBOFLINES, + Container::MAX_RFSAMPLES ); + RFHandler = gcnew NewRFImageHandler( RFBuffer ); + RFHandlerDelegate = gcnew + IntersonArray::Imaging::Capture::NewImageHandler( RFHandler, + & NewRFImageHandler::HandleNewRFImage ); + } + + ~ContainerImpl() + { + WrappedCapture->NewImageTick -= RFHandlerDelegate; + WrappedCapture->NewImageTick -= HandlerDelegate; + } + + bool GetCompound() + { + return WrappedScanConverter->Compound; + } + + void SetCompound( bool value ) + { + WrappedScanConverter->Compound = value; + } + + bool GetDoubler() + { + return WrappedScanConverter->Doubler; + } + + void SetDoubler( bool value ) + { + WrappedScanConverter->Doubler = value; + } + + int GetHeightScan() const + { + return WrappedScanConverter->HeightScan; + } + + float GetMmPerPixel() const + { + return WrappedScanConverter->MmPerPixel; + } + + double GetTrueDepth() const + { + return WrappedScanConverter->TrueDepth; + } + + int GetWidthScan() const + { + return WrappedScanConverter->WidthScan; + } + + int GetZeroOfYScale() const + { + return WrappedScanConverter->ZeroOfYScale; + } + + Container::ScanConverterError HardInitScanConverter( int depth, + int widthScan, int heightScan, int steering, int depthCfm ) + { + + return static_cast< Container::ScanConverterError >( + WrappedScanConverter->HardInitScanConverter( depth, widthScan, + heightScan, steering, depthCfm, WrappedCapture.get(), + WrappedImageBuilding.get() ) ); + } + + Container::ScanConverterError IdleInitScanConverter( int depth, + int widthScan, int heightScan, short idleId, int idleSteering, int depthCfm, + bool idleDoubler, bool idleCompound, int idleCompoundAngle, bool idleCfm ) + { + return static_cast< Container::ScanConverterError >( + WrappedScanConverter->IdleInitScanConverter( depth, widthScan, + heightScan, idleId, idleSteering, depthCfm, idleDoubler, idleCompound, + idleCompoundAngle, idleCfm, WrappedImageBuilding.get() ) ); + } + + // + // Begin Capture + // + bool GetFrameAvg() + { + return WrappedCapture->FrameAvg; + } + + void SetFrameAvg( bool value) + { + WrappedCapture->FrameAvg = value; + } + + bool GetRFData() + { + return WrappedCapture->RFData; + } + + void SetRFData( bool value ) + { + if (value){ + this->hwControls->ReadFPGAVersion(); + } + WrappedCapture->RFData = value; + //Set correct image handler + if (value){ + WrappedCapture->NewImageTick -= HandlerDelegate; + WrappedCapture->NewImageTick += RFHandlerDelegate; + } + else{ + WrappedCapture->NewImageTick -= RFHandlerDelegate; + WrappedCapture->NewImageTick += HandlerDelegate; + } + } + + double GetScanOn() + { + return WrappedCapture->ScanOn; + } + + void StartReadScan() + { + WrappedCapture->StartReadScan( (ArrayType ^)Buffer ); + } + + void StartRFReadScan() + { + WrappedCapture->StartRFReadScan( (RFArrayType ^)RFBuffer ); + } + + void StopReadScan() + { + WrappedCapture->StopReadScan(); + } + + void SetNewImageCallback( NewImageCallbackType callback, + void *clientData = 0 ) + { + this->Handler->SetNewImageCallback( callback, clientData ); + } + + void SetNewRFImageCallback( NewRFImageCallbackType callback, + void *clientData = 0 ) + { + this->RFHandler->SetNewRFImageCallback( callback, clientData ); + } + void SetHWControls(IntersonArrayCxx::Controls::HWControls * controls) + { + this->hwControls = controls; + } + + // + // Begin Wrapped ImageBuilding + // + +private: + IntersonArrayCxx::Controls::HWControls * hwControls; + msclr::auto_gcroot< IntersonArray::Imaging::ScanConverter ^ > + WrappedScanConverter; + msclr::auto_gcroot< IntersonArray::Imaging::ImageBuilding ^ > + WrappedImageBuilding; + msclr::auto_gcroot< IntersonArray::Imaging::Capture ^ > + WrappedCapture; + + gcroot< ArrayType ^ > Buffer; + gcroot< RFArrayType ^ > RFBuffer; + gcroot< NewImageHandler ^ > Handler; + gcroot< NewRFImageHandler ^ > RFHandler; + + gcroot< IntersonArray::Imaging::Capture::NewImageHandler ^ > + HandlerDelegate; + gcroot< IntersonArray::Imaging::Capture::NewImageHandler ^ > + RFHandlerDelegate; + +}; + + +#pragma unmanaged + +Container +::Container(): + Impl( new ContainerImpl() ) +{ +} + + +Container +::~Container() +{ + delete Impl; +} + + +bool +Container +::GetCompound() +{ + return Impl->GetCompound(); +} + + +void +Container +::SetCompound( bool value ) +{ + Impl->SetCompound( value ); +} + + +bool +Container +::GetDoubler() +{ + return Impl->GetDoubler(); +} + + +void +Container +::SetDoubler( bool value ) +{ + Impl->SetDoubler( value ); +} + + +int +Container +::GetHeightScan() const +{ + return Impl->GetHeightScan(); +} + + +float +Container +::GetMmPerPixel() const +{ + return Impl->GetMmPerPixel(); +} + + +double +Container +::GetTrueDepth() const +{ + return Impl->GetTrueDepth(); +} + + +int +Container +::GetWidthScan() const +{ + return Impl->GetWidthScan(); +} + + +int +Container +::GetZeroOfYScale() const +{ + return Impl->GetZeroOfYScale(); +} + + +Container::ScanConverterError +Container +::HardInitScanConverter( int depth, int widthScan, int heightScan, + int steering, int depthCfm ) +{ + return Impl->HardInitScanConverter( depth, widthScan, heightScan, + steering, depthCfm ); +} + + +Container::ScanConverterError +Container +::IdleInitScanConverter( int depth, int width, int height, short idleId, + int idleSteering, int depthCfm, bool idleDoubler, bool idleCompound, + int idleCompoundAngle, bool idleCfm ) +{ + return Impl->IdleInitScanConverter( depth, width, height, idleId, + idleSteering, depthCfm, idleDoubler, idleCompound, idleCompoundAngle, + idleCfm ); +} + +// +// Begin Capture +// +bool +Container +::GetRFData() +{ + return Impl->GetRFData(); +} + +void +Container +::SetRFData( bool transferOn ) +{ + Impl->SetRFData( transferOn ); +} + + +bool +Container +::GetFrameAvg() +{ + return Impl->GetFrameAvg(); +} + +void +Container +::SetFrameAvg( bool doAveraging ) +{ + Impl->SetFrameAvg( doAveraging ); +} + + +bool +Container +::GetScanOn() const +{ + return Impl->GetScanOn(); +} + + +void +Container +::StartReadScan() +{ + Impl->StartReadScan(); +} + + +void +Container +::StartRFReadScan() +{ + Impl->StartRFReadScan(); +} + + +void +Container +::StopReadScan() +{ + Impl->StopReadScan(); +} + + +void +Container +::SetNewImageCallback( NewImageCallbackType callback, + void *clientData ) +{ + Impl->SetNewImageCallback( callback, clientData ); +} + + +void +Container +::SetNewRFImageCallback( NewRFImageCallbackType callback, + void *clientData ) +{ + Impl->SetNewRFImageCallback( callback, clientData ); +} + +void +Container +::SetHWControls(IntersonArrayCxx::Controls::HWControls * controls) +{ + Impl->SetHWControls(controls); +} + +} // end namespace Imaging + +} // end namespace IntersonArrayCxx diff --git a/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxIntersonClass.cxx b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxIntersonClass.cxx new file mode 100644 index 0000000..1f386ae --- /dev/null +++ b/Interson/IntersonArraySDKCxx/src/IntersonArrayCxxIntersonClass.cxx @@ -0,0 +1,78 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +// C++ +#include "IntersonArrayCxxIntersonClass.h" + +// C# + +#include +#include + +// Add library from SDK +#using "IntersonArray.dll" + +#pragma managed + +namespace IntersonArrayCxx +{ +// Wrapper Class for IntersonClass from SDK +class IntersonClassImpl +{ +public: + IntersonClassImpl() + { + } + + // Wrapped method for IntersonClass from SDK + std::string Version() + { + // This method converts data between native and managed environments. + // http://msdn.microsoft.com/en-us/library/bb384859.aspx + std::string marshalled = msclr::interop::marshal_as< std::string >( + IntersonArray::IntersonClass::Version ); + return marshalled; + } + +private: +}; + + +// C++ +#pragma unmanaged + +IntersonClass::IntersonClass(): + Impl( new IntersonClassImpl() ) +{ +} + +IntersonClass::~IntersonClass() +{ + delete Impl; +} + +std::string IntersonClass::Version() const +{ + return Impl->Version(); +} + +} // end namespace IntersonArrayCxx diff --git a/Interson/IntersonArraySDKCxx/test/CMakeLists.txt b/Interson/IntersonArraySDKCxx/test/CMakeLists.txt new file mode 100644 index 0000000..99db988 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/test/CMakeLists.txt @@ -0,0 +1,33 @@ +############################################################################## +# +# Library: IntersonArraySDK +# +# Copyright Kitware Inc. 28 Corporate Drive, +# Clifton Park, NY, 12065, USA. +# +# All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +############################################################################## +set( _tests + IntersonArrayCxxIntersonClassTest + IntersonArrayCxxControlsHWControlsTest + IntersonArrayCxxImagingContainerTest + ) + +foreach( test ${_tests} ) + add_executable( ${test} ${test}.cxx ) + target_link_libraries( ${test} IntersonArrayCxx ) + add_test( NAME ${test} COMMAND $ ) +endforeach() diff --git a/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxControlsHWControlsTest.cxx b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxControlsHWControlsTest.cxx new file mode 100644 index 0000000..dd04caa --- /dev/null +++ b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxControlsHWControlsTest.cxx @@ -0,0 +1,131 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include "IntersonArrayCxxControlsHWControls.h" + +#include +#include + +int main( int argc, char * argv[] ) +{ + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + + HWControlsType hwControls; + + std::cout << "ProbeID: " << static_cast< int >( + hwControls.GetProbeID() ) << std::endl; + + typedef IntersonArrayCxx::Controls::HWControls::FoundProbesType + FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + std::cout << "Number of probes = " << foundProbes.size() << std::endl; + if( foundProbes.empty() ) + { + std::cerr << "No probes found. Please connect a probe for tests." + << std::endl; + return EXIT_FAILURE; + } + std::cout << "Found Probes: " << std::endl; + for( size_t ii = 0; ii < foundProbes.size(); ++ii ) + { + std::cout << " " << foundProbes[ii] << std::endl; + } + + hwControls.FindMyProbe( 0 ); + const short probeId = hwControls.GetProbeID(); + std::cout << "ProbeID after FindMyProbe: " << probeId << std::endl; + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + int depth = hwControls.ValidDepth( 3 ); + std::cout << "\nValidDepth( 3 ): " << depth << std::endl; + depth = hwControls.ValidDepth( 1000 ); + std::cout << "ValidDepth( 1000 ): " << depth << std::endl; + + HWControlsType::FrequenciesType frequencies; + hwControls.GetFrequency( frequencies ); + std::cout << "\nFrequencies: " << std::endl; + for( size_t ii = 0; ii < frequencies.size(); ++ii ) + { + std::cout << " " << frequencies[ii] << std::endl; + } + HWControlsType::FocusType focus; + hwControls.GetFocus( focus ); + std::cout << "\nFocus: " << std::endl; + for( size_t ii = 0; ii < focus.size(); ++ii ) + { + std::cout << " " << focus[ii] << std::endl; + } + if( !hwControls.SetFrequencyAndFocus( 0, 0, 0 ) ) + { + std::cerr << "Could not set the frequency." << std::endl; + return EXIT_FAILURE; + } + + hwControls.SendHighVoltage( 50, 50 ); + hwControls.EnableHighVoltage(); + hwControls.DisableHighVoltage(); + + hwControls.SendDynamic( 50 ); + + hwControls.EnableHardButton(); + hwControls.DisableHardButton(); + const unsigned char button = hwControls.ReadHardButton(); + std::cout << "\nButton: " << static_cast< int >( button ) << std::endl; + + std::cout << "\nStarting acquisition...\n" << std::endl; + if( !hwControls.StartBmode() ) + { + std::cerr << "Could not start B mode acquision." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.StopAcquisition() ) + { + std::cerr << "Could not stop acquision." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.StartRFmode() ) + { + std::cerr << "Could not start RF acquision." << std::endl; + return EXIT_FAILURE; + } + if( !hwControls.StopAcquisition() ) + { + std::cerr << "Could not stop acquision." << std::endl; + return EXIT_FAILURE; + } + + const short frameRate = hwControls.GetProbeFrameRate(); + std::cout << "Frame rate: " << frameRate << std::endl; + std::cout << "Serial number: " << hwControls.GetProbeSerialNumber() + << std::endl; + std::cout << "FPGA Version: " << hwControls.ReadFPGAVersion() + << std::endl; + std::cout << "OEM ID: " << hwControls.GetOEMId() << std::endl; + std::cout << "Filter ID: " << hwControls.GetFilterId() << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxImagingContainerTest.cxx b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxImagingContainerTest.cxx new file mode 100644 index 0000000..3a33444 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxImagingContainerTest.cxx @@ -0,0 +1,104 @@ +/*========================================================================= + +Library: IntersonArrayArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include "IntersonArrayCxxImagingContainer.h" +#include "IntersonArrayCxxControlsHWControls.h" + +#include +#include +#include + +#include // Sleep + +int main( int argc, char * argv[] ) +{ + typedef IntersonArrayCxx::Controls::HWControls HWControlsType; + HWControlsType hwControls; + + typedef IntersonArrayCxx::Imaging::Container ContainerType; + ContainerType container; + + typedef HWControlsType::FoundProbesType FoundProbesType; + FoundProbesType foundProbes; + hwControls.FindAllProbes( foundProbes ); + if( foundProbes.empty() ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + hwControls.FindMyProbe( 0 ); + const unsigned int probeId = hwControls.GetProbeID(); + std::cout << "ProbeID after FindMyProbe: " << probeId << std::endl; + if( probeId == 0 ) + { + std::cerr << "Could not find the probe." << std::endl; + return EXIT_FAILURE; + } + + const int depth = 50; + if( hwControls.ValidDepth( depth ) != depth ) + { + std::cerr << "Did not request a valid depth" << std::endl; + return EXIT_SUCCESS; + } + const int width = 776; + const int height = 512; + + int steering = 0; + int depthCfm = 50; + ContainerType::ScanConverterError converterError = + container.IdleInitScanConverter( depth, width, height, probeId, + steering, depthCfm, false, false, 0, false ); + if( converterError != ContainerType::SUCCESS ) + { + std::cerr << "Error during idle scan converter initialization: " + << converterError << std::endl; + return EXIT_FAILURE; + } + converterError = container.HardInitScanConverter( depth, width, + height, steering, depthCfm ); + if( converterError != ContainerType::SUCCESS ) + { + std::cerr << "Error during hard scan converter initialization: " + << converterError << std::endl; + return EXIT_FAILURE; + } + + std::cout << "\nStarting BMode scanning..." << std::endl; + container.StartReadScan(); + Sleep( 100 ); // "time to start" + hwControls.StartBmode(); + + std::cout << "\nScan is on: " << container.GetScanOn() << std::endl; + std::cout << "\nTrueDepth: " << container.GetTrueDepth() << std::endl; + std::cout << "\nHeightScan: " << container.GetHeightScan() << std::endl; + std::cout << "WidthScan: " << container.GetWidthScan() << std::endl; + std::cout << "\nMmPerPixel: " << container.GetMmPerPixel() << std::endl; + std::cout << "\nZeroOfYScale: " << container.GetZeroOfYScale() << std::endl; + + hwControls.StopAcquisition(); + container.StopReadScan(); + Sleep( 100 ); // "time to stop" + + return EXIT_SUCCESS; +} diff --git a/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxIntersonClassTest.cxx b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxIntersonClassTest.cxx new file mode 100644 index 0000000..3040883 --- /dev/null +++ b/Interson/IntersonArraySDKCxx/test/IntersonArrayCxxIntersonClassTest.cxx @@ -0,0 +1,34 @@ +/*========================================================================= + +Library: IntersonArray + +Copyright Kitware Inc. 28 Corporate Drive, +Clifton Park, NY, 12065, USA. + +All rights reserved. + +Licensed under the Apache License, Version 2.0 ( the "License" ); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ +#include "IntersonArrayCxxIntersonClass.h" + +#include +#include + +int main( int argc, char * argv[] ) +{ + IntersonArrayCxx::IntersonClass intersonClass; + + std::cout << "Version: " << intersonClass.Version() << std::endl; + return EXIT_SUCCESS; +} diff --git a/LICENSE b/LICENSE index fb2782d..02b28c1 100644 --- a/LICENSE +++ b/LICENSE @@ -10,4 +10,5 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. +