diff --git a/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake b/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake new file mode 100644 index 0000000000..5b08ebc880 --- /dev/null +++ b/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake @@ -0,0 +1,26 @@ +message(STATUS "Configuring MITK Photoacoustics Setup Build") + +set(MITK_CONFIG_PACKAGES + ACVD + QT + BLUEBERRY +) + +# Enable open cv and open igt link, which is a necessary configuration +set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) +set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) +set(MITK_USE_US_DiPhAS_SDK ON CACHE BOOL "Use DiPhAS SDK" FORCE) +#set(MITK_USE_OPOTEK_HARDWARE ON CACHE BOOL "Use hardware build-in in OPOTEK Phocus Mobile" FORCE) +set(MITK_US_DiPhAS_SDK_PATH "C:/Users/dkfz/Source/Repos/UltrasoundResearchPlatform_SDK/UltrasoundResearchPlatformSDK_Cpp/x64/Release" CACHE PATH "DiPhAS SDK Path") + +# Enable default plugins and the navigation modules +set(MITK_CONFIG_PLUGINS + org.mitk.gui.qt.datamanager + org.mitk.gui.qt.stdmultiwidgeteditor + org.mitk.gui.qt.imagenavigator + org.mitk.gui.qt.properties + org.mitk.gui.qt.viewnavigator + org.mitk.gui.qt.ultrasound + org.mitk.gui.qt.lasercontrol +) + diff --git a/Modules/IGT/Common/mitkSerialCommunication.cpp b/Modules/IGT/Common/mitkSerialCommunication.cpp index 1c16873118..fb0332b9de 100644 --- a/Modules/IGT/Common/mitkSerialCommunication.cpp +++ b/Modules/IGT/Common/mitkSerialCommunication.cpp @@ -1,504 +1,509 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSerialCommunication.h" #ifdef WIN32 //#include #include #else // Posix #include #include #include #include #include #include #include #include #define INVALID_HANDLE_VALUE -1 #endif #define OK 1 #define ERROR_VALUE 0 mitk::SerialCommunication::SerialCommunication() : itk::Object(), m_DeviceName(""), m_PortNumber(COM1), m_BaudRate(BaudRate9600), m_DataBits(DataBits8), m_Parity(None), m_StopBits(StopBits1), m_HardwareHandshake(HardwareHandshakeOff), m_ReceiveTimeout(500), m_SendTimeout(500), m_Connected(false) { #ifdef WIN32 // Windows m_ComPortHandle = INVALID_HANDLE_VALUE; #else // Posix m_FileDescriptor = INVALID_HANDLE_VALUE; #endif } mitk::SerialCommunication::~SerialCommunication() { CloseConnection(); } +bool mitk::SerialCommunication::IsConnected() +{ + return m_Connected; +} + int mitk::SerialCommunication::OpenConnection() { if (m_Connected) return ERROR_VALUE; #ifdef WIN32 std::stringstream ss; if (m_DeviceName.empty()) ss << "\\\\.\\COM" << static_cast(m_PortNumber); // use m_PortNumber else ss << "\\\\.\\" << m_DeviceName; // use m_DeviceName m_ComPortHandle = CreateFile(ss.str().c_str(), GENERIC_READ | GENERIC_WRITE, NULL, /* no sharing */ NULL, /* no security flags */ OPEN_EXISTING, /* open com port, don't create it */ NULL, /* no flags */ NULL); /* no template */ if (m_ComPortHandle == INVALID_HANDLE_VALUE) return ERROR_VALUE; GetCommState(m_ComPortHandle, &m_PreviousDeviceControlBlock); GetCommTimeouts(m_ComPortHandle, &m_PreviousTimeout); GetCommMask(m_ComPortHandle, &m_PreviousMask); if (this->ApplyConfiguration() != OK) // set interface parameters { CloseHandle(m_ComPortHandle); m_ComPortHandle = INVALID_HANDLE_VALUE; return ERROR_VALUE; } m_Connected = true; return OK; #else // Posix std::stringstream ss; if (m_DeviceName.empty()) ss << "/dev/ttyS" << static_cast(m_PortNumber) - 1; // use m_PortNumber, COM1 = ttyS0 else ss << m_DeviceName; // use m_DeviceName //m_FileDescriptor = open(ss.str().c_str(), O_RDWR | O_NONBLOCK | O_NDELAY | O_NOCTTY | O_EXCL); // open device file m_FileDescriptor = open(ss.str().c_str(), O_RDWR|O_NONBLOCK|O_EXCL); // open device file if (m_FileDescriptor < 0) return ERROR_VALUE; fcntl(m_FileDescriptor, F_SETFL, 0); // change to blocking mode tcflush(m_FileDescriptor, TCIOFLUSH); // flush buffers if (this->ApplyConfiguration() != OK) // set interface parameters { close(m_FileDescriptor); m_FileDescriptor = INVALID_HANDLE_VALUE; return ERROR_VALUE; } m_Connected = true; return OK; #endif } void mitk::SerialCommunication::CloseConnection() { #ifdef WIN32 if (m_ComPortHandle == INVALID_HANDLE_VALUE) return; ClearReceiveBuffer(); ClearSendBuffer(); SetCommState(m_ComPortHandle, &m_PreviousDeviceControlBlock); // restore previous settings SetCommTimeouts(m_ComPortHandle, &m_PreviousTimeout); // restore previous timeout values SetCommMask(m_ComPortHandle, m_PreviousMask); // restore previous mask value PurgeComm(m_ComPortHandle, PURGE_TXCLEAR | PURGE_RXCLEAR); // empty buffers CloseHandle(m_ComPortHandle); // close handle m_ComPortHandle = INVALID_HANDLE_VALUE; m_Connected = false; return; #else // Posix if (m_FileDescriptor == INVALID_HANDLE_VALUE) return; ClearReceiveBuffer(); ClearSendBuffer(); close(m_FileDescriptor); m_FileDescriptor = INVALID_HANDLE_VALUE; m_Connected = false; return; #endif } int mitk::SerialCommunication::Receive(std::string& answer, unsigned int numberOfBytes, const char *eol) { if (numberOfBytes == 0) return OK; if (m_Connected == false) return ERROR_VALUE; #ifdef WIN32 if (m_ComPortHandle == INVALID_HANDLE_VALUE) return ERROR_VALUE; DWORD numberOfBytesRead = 0; char* buffer = new char[numberOfBytes]; if (ReadFile(m_ComPortHandle, buffer, numberOfBytes, &numberOfBytesRead, NULL) != 0) { if (numberOfBytesRead > 0) // data read { answer.assign(buffer, numberOfBytesRead); // copy buffer to answer delete buffer; if (numberOfBytesRead == numberOfBytes) { return OK; // everything was received } else { return ERROR_VALUE; // some data was received, but not as much as expected } } else // error { answer = ""; delete buffer; return ERROR_VALUE; } } delete buffer; return OK; #else // Posix if (m_FileDescriptor == INVALID_HANDLE_VALUE) return ERROR_VALUE; unsigned long bytesRead = 0; unsigned long bytesLeft = numberOfBytes; auto buffer = new char[numberOfBytes]; while ((bytesLeft > 0) && (bytesRead < numberOfBytes)) { int num = read(m_FileDescriptor, &buffer[bytesRead], 1); // read one byte if (num == -1) // ERROR_VALUE { if (errno == EAGAIN) // nonblocking, no byte there right now, but maybe next time continue; else break; // ERROR_VALUE, stop trying to read } if (num == 0) // timeout or eof(?) break; bytesLeft -= num; // n is number of chars left to read bytesRead += num; // i is the number of chars read if (eol && *eol == buffer[bytesRead-1]) // end of line char reached break; } if (bytesRead > 0) answer.assign(buffer, bytesRead); // copy buffer to answer delete buffer; if ( bytesRead == numberOfBytes || // everything was received (eol && answer.size() > 0 && *eol == answer.at(answer.size()-1)) ) // end of line char reached return OK; else return ERROR_VALUE; // some data was received, but not as much as expected #endif } int mitk::SerialCommunication::Send(const std::string& input, bool block) { //long retval = E2ERR_OPENFAILED; if (input.empty()) return OK; if (m_Connected == false) return ERROR_VALUE; #ifdef WIN32 if (m_ComPortHandle == INVALID_HANDLE_VALUE) return ERROR_VALUE; DWORD bytesWritten = 0; if (WriteFile(m_ComPortHandle, input.data(), static_cast(input.size()), &bytesWritten, NULL) == TRUE) return OK; else return GetLastError(); #else // Posix if (m_FileDescriptor == INVALID_HANDLE_VALUE) return ERROR_VALUE; long bytesWritten = 0; long bytesLeft = input.size(); while (bytesLeft > 0) { bytesWritten = write(m_FileDescriptor, input.data() + bytesWritten, bytesLeft); if (bytesWritten <= 0) return ERROR_VALUE; //return ERROR_VALUE bytesLeft -= bytesWritten; } if (block) { // wait for output to be physically sent if (tcdrain(m_FileDescriptor) == -1) return ERROR_VALUE; } return OK; #endif } int mitk::SerialCommunication::ApplyConfiguration() { #ifdef WIN32 // Windows implementation return ApplyConfigurationWin(); #else // Posix return ApplyConfigurationUnix(); #endif } /** * The Code for Baud rates is highly platform specific and divided into separate subroutines for readability. */ #ifdef WIN32 int mitk::SerialCommunication::ApplyConfigurationWin() { if (m_ComPortHandle == INVALID_HANDLE_VALUE) return ERROR_VALUE; DCB controlSettings; if (GetCommState(m_ComPortHandle, &controlSettings) == 0) { return ERROR_VALUE; } std::ostringstream o; o << "baud=" << m_BaudRate << " parity=" << static_cast(m_Parity) << " data=" << m_DataBits << " stop=" << m_StopBits; if (BuildCommDCBA(o.str().c_str(), &controlSettings) == 0) // Build device-control block return ERROR_VALUE; if (m_HardwareHandshake == HardwareHandshakeOn) // Modify hardware handshake values { controlSettings.fDtrControl = DTR_CONTROL_ENABLE; controlSettings.fRtsControl = RTS_CONTROL_ENABLE; controlSettings.fOutxCtsFlow = TRUE; controlSettings.fRtsControl = RTS_CONTROL_HANDSHAKE; } else { controlSettings.fDtrControl = DTR_CONTROL_DISABLE; controlSettings.fRtsControl = RTS_CONTROL_DISABLE; controlSettings.fOutxCtsFlow = FALSE; controlSettings.fRtsControl = RTS_CONTROL_DISABLE; } if (SetCommState(m_ComPortHandle, &controlSettings) == FALSE) // Configure com port return GetLastError(); COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = m_ReceiveTimeout; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = m_ReceiveTimeout; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = m_SendTimeout; if (SetCommTimeouts(m_ComPortHandle, &timeouts) == FALSE) // set timeout values return GetLastError(); PurgeComm(m_ComPortHandle, PURGE_TXCLEAR | PURGE_RXCLEAR); // clear read and write buffers return OK; } #else /** * \brief Applies the configuration for Linux */ int mitk::SerialCommunication::ApplyConfigurationUnix() { if ( m_FileDescriptor == INVALID_HANDLE_VALUE ) return ERROR_VALUE; struct termios termIOStructure; if ( tcgetattr(m_FileDescriptor, &termIOStructure) != 0 ) // retrieve parameters from com port return ERROR_VALUE; cfmakeraw(&termIOStructure); // set flags to raw mode termIOStructure.c_cflag |= CLOCAL; if (m_HardwareHandshake == HardwareHandshakeOn) { // enable termIOStructure.c_cflag |= CRTSCTS; termIOStructure.c_iflag &= ~(IXON|IXOFF); } else { // disable termIOStructure.c_cflag &= ~CRTSCTS; termIOStructure.c_iflag &= ~(IXON|IXOFF); } termIOStructure.c_cflag &= ~CSIZE; // set number of data bits switch (m_DataBits) { case DataBits7: termIOStructure.c_cflag |= CS7; break; case DataBits8: default: termIOStructure.c_cflag |= CS8; } switch (m_StopBits) // set number of stop bits { case StopBits2: termIOStructure.c_cflag |= CSTOPB; break; case StopBits1: default: termIOStructure.c_cflag &= ~CSTOPB; } switch (m_Parity) // set parity { case Odd: termIOStructure.c_cflag |= (PARENB|PARODD); break; case Even: termIOStructure.c_cflag |= PARENB; termIOStructure.c_cflag &= ~PARODD; case None: default: termIOStructure.c_cflag &= ~PARENB; break; } speed_t baudrate; // set baudrate switch (m_BaudRate) { case BaudRate9600: baudrate = B9600; break; case BaudRate14400: baudrate = B9600; //14400 is not defined for posix, use 9600 instead break; case BaudRate19200: baudrate = B19200; break; case BaudRate38400: baudrate = B38400; break; case BaudRate57600: baudrate = B57600; break; case BaudRate115200: baudrate = B115200; break; case BaudRate230400: baudrate = B230400; break; // the following baud rates do not work for apple #ifndef __APPLE__ case BaudRate460800: baudrate = B460800; break; case BaudRate500000: baudrate = B500000; break; case BaudRate576000: baudrate = B576000; break; case BaudRate921600: baudrate = B921600; break; case BaudRate1000000: baudrate = B1000000; break; case BaudRate1152000: baudrate = B1152000; break; //case BaudRate1228739: //baudrate = B1228739; //break; case BaudRate1500000: baudrate = B1500000; break; case BaudRate2000000: baudrate = B2000000; break; case BaudRate2500000: baudrate = B2500000; break; case BaudRate3000000: baudrate = B3000000; break; case BaudRate3500000: baudrate = B3500000; break; case BaudRate4000000: baudrate = B4000000; break; #endif default: MITK_WARN("mitk::SerialCommunication") << "Baud rate not recognized, using default of 9600 Baud."; baudrate = B9600; break; } cfsetispeed(&termIOStructure, baudrate); cfsetospeed(&termIOStructure, baudrate); termIOStructure.c_cc[VMIN] = 0; termIOStructure.c_cc[VTIME] = m_ReceiveTimeout / 100; // timeout in 1/10 sec, not in ms. Rounded down. if (tcsetattr(m_FileDescriptor, TCSANOW, &termIOStructure) == 0) return OK; else return ERROR_VALUE; } #endif void mitk::SerialCommunication::SendBreak(unsigned int ms) { #ifdef WIN32 if (m_ComPortHandle == INVALID_HANDLE_VALUE) return; SetCommBreak(m_ComPortHandle); itksys::SystemTools::Delay(ms); ClearCommBreak(m_ComPortHandle); return; #else // Posix if (m_FileDescriptor == INVALID_HANDLE_VALUE) return; tcsendbreak(m_FileDescriptor, ms); return; #endif } void mitk::SerialCommunication::ClearReceiveBuffer() { #ifdef WIN32 if (m_ComPortHandle != INVALID_HANDLE_VALUE) PurgeComm(m_ComPortHandle, PURGE_RXCLEAR); #else // Posix if (m_FileDescriptor != INVALID_HANDLE_VALUE) tcflush(m_FileDescriptor, TCIFLUSH); #endif } void mitk::SerialCommunication::ClearSendBuffer() { #ifdef WIN32 if ( m_ComPortHandle != INVALID_HANDLE_VALUE ) PurgeComm(m_ComPortHandle, PURGE_TXCLEAR); #else // Posix if ( m_FileDescriptor != INVALID_HANDLE_VALUE ) tcflush(m_FileDescriptor, TCOFLUSH); #endif } diff --git a/Modules/IGT/Common/mitkSerialCommunication.h b/Modules/IGT/Common/mitkSerialCommunication.h index 3f927107ac..4de53dfa3e 100644 --- a/Modules/IGT/Common/mitkSerialCommunication.h +++ b/Modules/IGT/Common/mitkSerialCommunication.h @@ -1,346 +1,351 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSERIALCOMMUNICATION_H_HEADER_INCLUDED_ #define MITKSERIALCOMMUNICATION_H_HEADER_INCLUDED_ #include #include "mitkCommon.h" #include #include #ifdef WIN32 #include #else // Posix #include #endif namespace mitk { /**Documentation * \brief serial communication interface * * This class allows to send and receive data over a serial communication interface (COM Port). * Define the serial interface that should be used either with SetPortNumber() or SetDeviceName() * Next, define communication parameters: baud rate, number of data bits, number of stop bits, * parity mode, usage of hardware handshake and timeout values (in ms). * Use OpenConnection() to establish a connection on the serial interface with the selected * parameters. While the connection is established, changes to the parameters will not take * effect. You have to close the connection using CloseConnection() and then reopen it with * the new parameters with OpenConnection(). * * \ingroup IGT */ class MITKIGT_EXPORT SerialCommunication : public itk::Object { public: mitkClassMacroItkParent(SerialCommunication, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) enum PortNumber { COM1 = 1, COM2 = 2, COM3 = 3, COM4 = 4, COM5 = 5, COM6 = 6, COM7 = 7, COM8 = 8, COM9 = 9, COM10 = 10, COM11 = 11, COM12 = 12, COM13 = 13 }; enum BaudRate { BaudRate9600 = 9600, BaudRate14400 = 14400, BaudRate19200 = 19200, BaudRate38400 = 38400, BaudRate57600 = 57600, BaudRate115200 = 115200, // Highest supported rate for NDI Aurora BaudRate230400 = 230400, BaudRate460800 = 460800, BaudRate500000 = 500000, BaudRate576000 = 576000, BaudRate921600 = 921600, BaudRate1000000 = 1000000, BaudRate1152000 = 1152000, // BaudRate1228739 = 1228739, // Highest supported rate for NDI Polaris According to handbook, unknown value to most compilers though BaudRate1500000 = 1500000, BaudRate2000000 = 2000000, BaudRate2500000 = 2500000, BaudRate3000000 = 3000000, BaudRate3500000 = 3500000, BaudRate4000000 = 4000000 }; enum DataBits { DataBits8 = 8, DataBits7 = 7 }; enum Parity { None = 'N', Odd = 'O', Even = 'E' }; enum StopBits { StopBits1 = 1, StopBits2 = 2 }; enum HardwareHandshake { HardwareHandshakeOn = 1, HardwareHandshakeOff = 0 }; + /** + * \brief Returns m_Connected + * + */ + bool IsConnected(); /** * \brief Opens connection to the COM port with port number m_PortNumber * or the device name m_DeviceName and all port settings. * */ int OpenConnection(); /** * \brief Closes the connection * */ void CloseConnection(); /** * \brief Read numberOfBytes characters from the serial interface * * This method tries to read numberOfBytes characters from the serial * interface or until an eol byte is received, whichever comes first. If * The ReceiveTimeout is set to 0, the Receive() method will wait * indefinetly until all characters are received or an eol character is * received. If the ReceiveTimeout is set to another value, it will return * after m_ReceiveTimeout milliseconds (or after all characters are read or * an eol character is received). * * \param[out] answer String that stores the received characters. Note * that this will overwrite the content of answer! * \param[in] numberOfBytes The number of bytes to read. When an eol * character is used this is interpretted as the * maximum number of bytes to read. * \param[in] eol Pointer to an End-of-Line character. If this is NULL * (the default) then no End-of-Line character is used. */ int Receive(std::string& answer, unsigned int numberOfBytes, const char *eol=nullptr); /** * \brief Send the string input * * \param[in] input The string to send to the serial interface. The string * termination character \\0 is not sent. * \param[in] block If false, the this method will return immediately. If * true, this method will block until all bytes have been * physically transmitted over the serial interface. */ int Send(const std::string& input, bool block = false); /** * \brief Send the break signal for ms milliseconds */ void SendBreak(unsigned int ms = 400); /** * \brief erase the receive buffer of the serial interface */ void ClearReceiveBuffer(); /** * \brief erase the send buffer of the serial interface */ void ClearSendBuffer(); /** * \brief Get the port number of the serial interface * * Returns the port number that will be used in the connection. * The port number is only used if the m_DeviceName is empty (""). */ itkGetConstMacro(PortNumber, PortNumber); /** * \brief Set the port number of the serial interface * * SerialCommunication can either use PortNumber to create serial interface device names * COM1 to COM9 for windows and /dev/ttyS0 to /dev/ttyS8 on linux * (SetPortNumber(COM1) is mapped to /dev/ttyS0 and so on). Alternatively, use SetDeviceName() * to set the device name directly (e.g. "CNCA0" for a com0com virtual com port or * "/dev/ttyUSB0" for a USB to serial adapter on linux. If a device name is set (m_DeviceName != "") * then OpenConnection() will try to open that device. Otherwise, it will build the device * name using the port number */ itkSetMacro(PortNumber, PortNumber); /** * \brief Get the device name * * SerialCommunication can either use m_PortNumber to create serial interface device names * or use m_DeviceName directly. This method allows to set an arbitrary device name * that will be used to connect to the device. Common names are COM1, CNCA0, CNCB9 * on windows and /dev/ttyS0 or /dev/ttyUSB0 on linux. */ itkGetStringMacro(DeviceName); /** * \brief Set the device name * * if the device name is set (!=""), OpenConnection() will try to open the * serial device on that device name. Normally, the serial interfaces are named COM1-COM9 * on windows and /dev/ttyS0 to /dev/ttyS9 on linux, but other names are possible too * (e.g. /dev/ttyUSB0). */ itkSetStringMacro(DeviceName); /** * \brief Get the baud rate of the serial interface */ itkGetConstMacro(BaudRate, BaudRate); /** * \brief Set the baud rate of the serial interface */ itkSetMacro(BaudRate, BaudRate); /** * \brief Get the number of data bits of the serial interface */ itkGetConstMacro(DataBits, DataBits); /** * \brief Set the number of data bits of the serial interface */ itkSetMacro(DataBits, DataBits); /** * \brief Get the parity mode of the serial interface */ itkGetConstMacro(Parity, Parity); /** * \brief Set the parity mode of the serial interface */ itkSetMacro(Parity, Parity); /** * \brief Get number of stop bits of the serial interface */ itkGetConstMacro(StopBits, StopBits); /** * \brief Set number of stop bits of the serial interface */ itkSetMacro(StopBits, StopBits); /** * \brief returns true if hardware handshake should is used */ itkGetConstMacro(HardwareHandshake, HardwareHandshake); /** * \brief Set if hardware handshake should be used */ itkSetMacro(HardwareHandshake, HardwareHandshake); /** * \brief returns the send timeout in milliseconds */ itkGetConstMacro(SendTimeout, unsigned int); /** * \brief set the send timeout in milliseconds * * Only applies to WIN32, not POSIX */ itkSetMacro(SendTimeout, unsigned int); /** * \brief returns the receive timeout in milliseconds */ itkGetConstMacro(ReceiveTimeout, unsigned int); /** * \brief set the send timeout in milliseconds * * Specify the receive timeout in milliseconds. * Setting this value to 0 will cause the Receive() * method to wait until all expected characters are received. */ itkSetMacro(ReceiveTimeout, unsigned int); protected: SerialCommunication(); virtual ~SerialCommunication(); /** * \brief configures the serial interface with all parameters * * This automatically reroutes the call to the hardware specific function */ int ApplyConfiguration(); #ifdef WIN32 /** * \brief Applies the configuration for Windows */ int ApplyConfigurationWin(); #else /** * \brief Applies the configuration for Linux */ int ApplyConfigurationUnix(); #endif std::string m_DeviceName; ///< device name that is used to connect to the serial interface (will be used if != "") PortNumber m_PortNumber; ///< port number of the device BaudRate m_BaudRate; ///< baud rate of the serial interface connection DataBits m_DataBits; ///< number of data bits per symbol Parity m_Parity; ///< parity mode StopBits m_StopBits; ///< number of stop bits per symbol HardwareHandshake m_HardwareHandshake; ///< whether to use hardware handshake for the connection unsigned int m_ReceiveTimeout; ///< timeout for receiving data from the serial interface in milliseconds unsigned int m_SendTimeout; ///< timeout for sending data to the serial interface in milliseconds bool m_Connected; ///< is set to true if a connection currently established #ifdef WIN32 HANDLE m_ComPortHandle; DWORD m_PreviousMask; COMMTIMEOUTS m_PreviousTimeout; DCB m_PreviousDeviceControlBlock; #else int m_FileDescriptor; #endif }; } // namespace mitk #endif /* MITKSERIALCOMMUNICATION_H_HEADER_INCLUDED_ */ diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index afa09b7371..b9b4006da0 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,81 +1,82 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction LegacyAdaptors SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QtWidgets QtWidgetsExt C3js QmlItems SegmentationUI DiffusionImaging GPGPU OpenIGTLink IGTBase IGT CameraCalibration RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI + PhotoacousticsHardware US USUI DicomUI Simulation Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI VtkShaders DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware Classification TumorInvasionAnalysis MatchPointRegistration MatchPointRegistrationUI BoundingShape ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/PhotoacousticsHardware/CMakeLists.txt b/Modules/PhotoacousticsHardware/CMakeLists.txt new file mode 100644 index 0000000000..e8a74022ed --- /dev/null +++ b/Modules/PhotoacousticsHardware/CMakeLists.txt @@ -0,0 +1,24 @@ +IF(WIN32) + +OPTION(MITK_USE_OPOTEK_HARDWARE "Enable support for OPOTEK Lasers" OFF) +OPTION(MITK_USE_OPHIR_PRYO_HARDWARE "Enable support for Ophir Pyroelectrical Sensors" OFF) + +IF(MITK_USE_OPHIR_PRYO_HARDWARE) +SET(MITK_OPHIR_API_PATH "" CACHE PATH "Path to Ophir API lib.") +ENDIF(MITK_USE_OPHIR_PRYO_HARDWARE) + +IF(MITK_USE_OPOTEK_HARDWARE) +SET(MITK_GALIL_API_PATH "" CACHE PATH "Path to Galil API header files.") + +MITK_CREATE_MODULE( + SUBPROJECTS + DEPENDS MitkIGT + INCLUDE_DIRS PUBLIC "${MITK_GALIL_API_PATH}/include" "${MITK_OPHIR_API_PATH}" + INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} + ADDITIONAL_LIBS "${MITK_GALIL_API_PATH}/lib/dynamic/x64/gclib.lib" "${MITK_GALIL_API_PATH}/lib/dynamic/x64/gclibo.lib" tinyxml "${MITK_OPHIR_API_PATH}/OphirPyroWrapper.lib" + PACKAGE_DEPENDS tinyxml +) + +ENDIF(MITK_USE_OPOTEK_HARDWARE) + +ENDIF(WIN32) \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/OphirCppWrapper/ConsoleExample.cpp b/Modules/PhotoacousticsHardware/OphirCppWrapper/ConsoleExample.cpp new file mode 100644 index 0000000000..8571245a98 --- /dev/null +++ b/Modules/PhotoacousticsHardware/OphirCppWrapper/ConsoleExample.cpp @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include "OphirPyroWrapper.h" +#include + +int main() +{ + OphirPyroWrapper pyro; + + char* sn = pyro.ScanUSB(); + if (sn != 0) + std::cout << "sn: " << sn << std::endl; + else + std::cout << "sn: NULL" << std::endl; + + int handle = pyro.OpenDevice(sn); + std::cout << "handle: " << handle << std::endl; + + char* wl = pyro.GetWavelengths(handle); + std::cout << "wl: " << wl << std::endl; + char* gr = pyro.GetRanges(handle); + std::cout << "gr: " << gr << std::endl; + + bool start = pyro.StartStream(handle); + std::cout << "start: " << start << std::endl; + + std::vector data; + std::vector timestamp; + std::vector status; + Sleep(100); + unsigned int gd = pyro.GetData(handle, &data, ×tamp, &status); + std::cout << "gd: " << gd << std::endl; + std::cout << "length: " << data.size() << std::endl; + for(int i = 0; i +#include +#include "OphirPyroWrapper.h" + +using namespace System::Runtime::InteropServices; // Marshal + +class OphirPyroWrapperPrivate +{ + public: msclr::auto_gcroot ophirAPI; +}; + +OphirPyroWrapper::OphirPyroWrapper() +{ + _private = new OphirPyroWrapperPrivate(); + _private->ophirAPI = gcnew OphirLMMeasurementLib::CoLMMeasurement(); +} + +OphirPyroWrapper::~OphirPyroWrapper() +{ + delete _private; +} + +char* OphirPyroWrapper::ScanUSB() +{ + char* foo; + System::Object^ managedObject; + _private->ophirAPI->ScanUSB(managedObject); + array^ managedCapi = dynamic_cast^>(managedObject); + if (managedCapi->Length != 0) + return (char*)Marshal::StringToHGlobalAnsi(managedCapi[0]).ToPointer(); + else + return 0; +} + +int OphirPyroWrapper::OpenDevice(char* serialNumber) +{ + int deviceHandle; + _private->ophirAPI->OpenUSBDevice(gcnew System::String(serialNumber), deviceHandle); + + return deviceHandle; +} + +char* OphirPyroWrapper::GetWavelengths(int deviceHandle) +{ + int index; + System::Object^ options; + // Show wavelengths of channel 0 + _private->ophirAPI->GetWavelengths(deviceHandle, 0, index, options); + array^ managedCapi = dynamic_cast^>(options); + if (managedCapi->Length != 0) + return (char*)Marshal::StringToHGlobalAnsi(managedCapi[index]).ToPointer(); + else + return 0; +} + +char* OphirPyroWrapper::GetRanges(int deviceHandle) +{ + int index; + System::Object^ options; + // Show ranges of channel 0 + _private->ophirAPI->GetRanges(deviceHandle, 0, index, options); + array^ managedCapi = dynamic_cast^>(options); + if (managedCapi->Length != 0) + return (char*)Marshal::StringToHGlobalAnsi(managedCapi[index]).ToPointer(); + else + return 0; +} + +bool OphirPyroWrapper::StartStream(int deviceHandle) +{ + _private->ophirAPI->StartStream(deviceHandle, 0); + return true; +} + +bool OphirPyroWrapper::StopStream(int deviceHandle) +{ + _private->ophirAPI->StopStream(deviceHandle, 0); + return true; +} + +bool OphirPyroWrapper::CloseDevice(int deviceHandle) +{ + _private->ophirAPI->Close(deviceHandle); + return true; +} + +unsigned int OphirPyroWrapper::GetData(int deviceHandle, std::vector* data, std::vector* timestamp, std::vector* status) +{ + System::Object^ dataArray; + System::Object^ timeStampArray; + System::Object^ statusArray; + array^ managedDataArray; + array^ managedTimeStampArray; + array^ managedStatusArray; + _private->ophirAPI->GetData(deviceHandle, 0, dataArray, timeStampArray, statusArray); + managedDataArray = (array^)dataArray; + managedTimeStampArray = (array^)timeStampArray; + managedStatusArray = (array^)statusArray; + if (managedDataArray->Length > 0) + { + data->resize(managedDataArray->Length); + timestamp->resize(managedDataArray->Length); + status->resize(managedDataArray->Length); + for(int i = 0; iLength; i++) + { + (*data)[i] = managedDataArray[i]; + (*timestamp)[i] = managedTimeStampArray[i]; + (*status)[i] = managedStatusArray[i]; + // DEBUG: std::cout << "managedDataArray " << i << ": " << managedDataArray[i] << " ts: " << managedTimeStampArray[i] << " status: " << managedStatusArray[i] << std::endl; + } + return managedDataArray->Length; + } + else + { + data->resize(1); + timestamp->resize(1); + status->resize(1); + (*data)[0] = -1; + (*timestamp)[0] = -1; + (*status)[0] = -1; + } + + return 0; +} \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/OphirCppWrapper/OphirPyroWrapper.h b/Modules/PhotoacousticsHardware/OphirCppWrapper/OphirPyroWrapper.h new file mode 100644 index 0000000000..1420071c1a --- /dev/null +++ b/Modules/PhotoacousticsHardware/OphirCppWrapper/OphirPyroWrapper.h @@ -0,0 +1,44 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +class OphirPyroWrapperPrivate; + +class __declspec(dllexport) OphirPyroWrapper +{ + private: OphirPyroWrapperPrivate* _private; + + public: OphirPyroWrapper(); + + public: ~OphirPyroWrapper(); + + public: char* ScanUSB(); + + public: int OpenDevice(char* serialNumber); + + public: char* GetWavelengths(int deviceHandle); + + public: char* GetRanges(int deviceHandle); + + public: bool StartStream(int deviceHandle); + + public: bool StopStream(int deviceHandle); + + public: bool CloseDevice(int deviceHandle); + + public: unsigned int GetData(int deviceHandle, std::vector* data, std::vector* timestamp, std::vector* status); +}; \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/OphirCppWrapper/readme.txt b/Modules/PhotoacousticsHardware/OphirCppWrapper/readme.txt new file mode 100644 index 0000000000..312e900b17 --- /dev/null +++ b/Modules/PhotoacousticsHardware/OphirCppWrapper/readme.txt @@ -0,0 +1,16 @@ +A C++/CLI Wrapper for Ophir Pyroelectrical Sensors + +compile release version of wapper via: cl /clr /LD OphirPyroWrapper.cpp +compile debug version of wapper via: cl /clr /LDd OphirPyroWrapper.cpp +you'll need: Interop.OphirLMMeasurementLib.dll + +compile shitty console example via: cl ConsoleExample.cpp OphirPyroWrapper.lib + +tested with: +VS2015, Windows 10 + 8, Starlab 3.20 + +todo: +- write documentation + +thanks to: +pragmateek for http://pragmateek.com/using-c-from-native-c-with-the-help-of-ccli-v2/ \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/FTUNE.dmc b/Modules/PhotoacousticsHardware/Resources/FTUNE.dmc new file mode 100644 index 0000000000..454e5dacab --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/FTUNE.dmc @@ -0,0 +1,57 @@ +#AUTO +#MAIN +WT 1 +'AMP SETTINGS +AU 0 +BR 1 +AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +MT -1 +CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 10 +JS#HOME +WT 10 +JS#RESETP +WT 10 +' +SP 3000000 +AC 60000000 +DC 60000000 +count=0 +idx=0 +#MOVE +II 1 +WT 5 +JP #MOVE +EN +#HOME +OE 0 +JG -10000;BG +#JOG;JP#JOG,@ABS[_TEX]<1000 +ST;AM +OE 1 +WT 10 +EN +#RESETP +PR 32561;BG;AM +DP*=0 +EN +#ININT +idx = count % points +PA pos[idx];BG;AM; +WT 10 +count = count + 1 +RI 1; diff --git a/Modules/PhotoacousticsHardware/Resources/GHOME.dmc b/Modules/PhotoacousticsHardware/Resources/GHOME.dmc new file mode 100644 index 0000000000..7900469823 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/GHOME.dmc @@ -0,0 +1,44 @@ +#AUTO +#MAIN +#GHOME +suc=99 +'AMP SETTINGS +AU 0 +BR 1 +AG 0 +TM 1000 +TL 3 +TK 9.998 +suc=98 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +MT -1 +CE 0 +CN-1 +suc=97 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +suc=96 +SHX +WT 10 +SP 3000000 +AC 60000000 +DC 60000000 +' +suc=95 +OE 0 +JG -10000;BG +#JOG;JP#JOG,@ABS[_TEX]<1000 +ST;AM +suc=94 +OE 1 +WT10 +PR 32561;BG;AM +suc=93 +DP*=0 +suc=1 +EN diff --git a/Modules/PhotoacousticsHardware/Resources/OpotekPhocusMobile.xml b/Modules/PhotoacousticsHardware/Resources/OpotekPhocusMobile.xml new file mode 100644 index 0000000000..37242e3275 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/OpotekPhocusMobile.xml @@ -0,0 +1,42 @@ + + + + -3.26731848e+07 + 2.35443306e+05 + -7.04376397e+02 + 1.12232174e+00 + -1.00519593e-03 + 4.79945765e-07 + -9.54424480e-11 + 32561 + + + 690.000 + 750.000 + 950.000 + + + 5 + 115200 + 8 + 0 + 10 + + + 690.0|695.2|700.4|705.6|710.8|716.0|721.2|726.4|731.6|736.8|742.0|747.2|752.4|757.6|762.8|768.0|773.2|778.4|783.6|788.8|794.0|799.2|804.4|809.6|814.8|820.0|825.2|830.4|835.6|840.8|846.0|851.2|856.4|861.6|866.8|872.0|877.2|882.4|887.6|892.8|898.0|903.2|908.4|913.6|918.8|924.0|929.2|934.4|939.6|944.8 + + 0.000727|0.000726|0.000764|0.000795|0.000824|0.000817|0.000832|0.000893|0.000898|0.000881|0.000870|0.000834|0.000849|0.000793|0.000778|0.000753|0.000755|0.000812|0.000843|0.000818|0.000843|0.000824|0.000829|0.000837|0.000832|0.000796|0.000808|0.000796|0.000774|0.000778|0.000760|0.000741|0.000724|0.000725|0.000703|0.000703|0.000695|0.000697|0.000671|0.000702|0.000679|0.000671|0.000676|0.000647|0.000660|0.000674|0.000686|0.000664|0.000658|0.000643 + + 0.042647|0.043251|0.045291|0.047462|0.048515|0.049305|0.049513|0.050434|0.049656|0.050895|0.048269|0.049129|0.050182|0.049334|0.046761|0.045675|0.045061|0.049129|0.050357|0.049206|0.050050|0.048745|0.048822|0.049041|0.048976|0.047813|0.047082|0.046980|0.046980|0.046442|0.045445|0.044063|0.043909|0.042451|0.041058|0.041760|0.042374|0.041683|0.040269|0.042374|0.041299|0.038996|0.041069|0.040736|0.039994|0.040839|0.040225|0.039994|0.038613|0.037692 + + + + + + 4 + 115200 + 8 + N + 1 + + \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/STUNE.dmc b/Modules/PhotoacousticsHardware/Resources/STUNE.dmc new file mode 100644 index 0000000000..edc14db0ae --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/STUNE.dmc @@ -0,0 +1,34 @@ +#AUTO +#STUNE +suc=-1 +'***************** +'AMP SETTINGS +AU 0 +BR 1 +AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +MT -1 +CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 10 +SP 3000000 +AC 60000000 +DC 60000000 +' +suc=-102 +WT 10 +PA pos;BG;AM +suc=1 +EN diff --git a/Modules/PhotoacousticsHardware/Resources/configFastTuneOPO.dmc b/Modules/PhotoacousticsHardware/Resources/configFastTuneOPO.dmc new file mode 100644 index 0000000000..e60875bc93 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/configFastTuneOPO.dmc @@ -0,0 +1,28 @@ +#AUTO +#MAIN +rt=-1 +II1 +'AMP SETTINGS +AU 0 +BR 1 +'AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +'MT -1 +'CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 250 +SP 3000000 +AC 120000000 +DC 120000000 \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/configSlowTuneOPO.dmc b/Modules/PhotoacousticsHardware/Resources/configSlowTuneOPO.dmc new file mode 100644 index 0000000000..91b36d58b1 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/configSlowTuneOPO.dmc @@ -0,0 +1,7 @@ +#AUTO +#MAIN +rt=0 +' +SP 150000 +AC 12000000 +DC 12000000 \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/executeFastTuneOPO.dmc b/Modules/PhotoacousticsHardware/Resources/executeFastTuneOPO.dmc new file mode 100644 index 0000000000..e616d85969 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/executeFastTuneOPO.dmc @@ -0,0 +1,14 @@ +points=pos[-1] +#MOVE +II 1 +WT 5 +rt=1 +JP #MOVE +EN +#ININT +idx = count % points +PA pos[idx];BG;AM; +BG;AM; +count = count + 1 +WT 1 +RI 1; \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/executeSlowTuneOPO.dmc b/Modules/PhotoacousticsHardware/Resources/executeSlowTuneOPO.dmc new file mode 100644 index 0000000000..741d78c64d --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/executeSlowTuneOPO.dmc @@ -0,0 +1,5 @@ +PA pos;BG;AM; +BG;AM; +WT 100 +rt = 1 +EN \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/fastTuneOPO.dmc b/Modules/PhotoacousticsHardware/Resources/fastTuneOPO.dmc new file mode 100644 index 0000000000..e2d7463d93 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/fastTuneOPO.dmc @@ -0,0 +1,55 @@ +#AUTO +#FTUNE +rt=-1 +II1 +'AMP SETTINGS +AU 0 +BR 1 +'AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +'MT -1 +'CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 250 +SP 3000000 +AC 120000000 +DC 120000000 +rt=-2 +count=0;idx=0;DM pos[2] +rt=-3 +pos[0]=36459 +pos[1]=24577 +rt=-4 +points=pos[-1] +rt=-5 +#MOVE +rt=-6 +II 1 +WT 5 +rt=1 +JP #MOVE +EN +#ININT +'MG "INSIDE INTERUPPT ROUTINE" +rt=-7 +idx = count % points +MG "idx = ", idx {F2.2} +PA pos[idx];BG;AM; +BG;AM; +rt=-8 +count = count + 1 +WT 1 +RI 1; 'Return to the main program +'and restore trip point \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/fastTuneOPO700to900.dmc b/Modules/PhotoacousticsHardware/Resources/fastTuneOPO700to900.dmc new file mode 100644 index 0000000000..10c65430d7 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/fastTuneOPO700to900.dmc @@ -0,0 +1,48 @@ +#AUTO +#MAIN +rt=-1 +II1 +'AMP SETTINGS +AU 0 +BR 1 +'AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +'MT -1 +'CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 250 +SP 3000000 +AC 120000000 +DC 120000000 +count=0;idx=0;DM pos[2] +pos[0]=36459 +pos[1]=24577 +points=pos[-1] +#MOVE +II 1 +WT 5 +rt=1 +JP #MOVE +EN +#ININT +'MG "INSIDE INTERUPPT ROUTINE" +idx = count % points +MG "idx = ", idx {F2.2} +PA pos[idx];BG;AM; +BG;AM; +count = count + 1 +WT 1 +RI 1; 'Return to the main program +'and restore trip point \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/homeOPO.dmc b/Modules/PhotoacousticsHardware/Resources/homeOPO.dmc new file mode 100644 index 0000000000..80ef2aaaba --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/homeOPO.dmc @@ -0,0 +1,35 @@ +#AUTO +#MAIN +rh=-1 +'***************** +'AMP SETTINGS +AU 0 +BR 1 +'AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +'MT -1 +'CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 250 +' +OE 0 +JG -10000;BG +#JOG;JP#JOG,@ABS[_TEX]<1000 +ST;AM +OE 1 +WT 100 +DP*=0 +rh=1 +EN diff --git a/Modules/PhotoacousticsHardware/Resources/opotekPhocusMobileDkfz160907.ini b/Modules/PhotoacousticsHardware/Resources/opotekPhocusMobileDkfz160907.ini new file mode 100644 index 0000000000..d2d84f4cfd --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/opotekPhocusMobileDkfz160907.ini @@ -0,0 +1,747 @@ +[Index] +Motor Config Size=6 +Current Config=0 +Show Spectrometer=FALSE + +[Software Version] +Software Version="1.3.2" + +[Motor Config 0] +Double BL=1 +Name="SIGNAL" +Default Wavelength=750.000000 +Motor 0 Equation=1 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=0 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Motor Config 1] +Double BL=1 +Name="IDLER" +Default Wavelength=1200.000000 +Motor 0 Equation=2 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=0 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Motor Config 2] +Double BL=1 +Name="UV-1" +Default Wavelength=230.000000 +Motor 0 Equation=4 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=3 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Motor Config 3] +Double BL=1 +Name="UV-2" +Default Wavelength=400.000000 +Motor 0 Equation=4 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=3 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Motor Config 4] +Double BL=1 +Name="UV-3" +Default Wavelength=365.000000 +Motor 0 Equation=5 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=3 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Motor Config 5] +Double BL=1 +Name="UV-X" +Default Wavelength=450.000000 +Motor 0 Equation=6 +Motor 0 Coeff="-10034351.9962601084000000000|66823.5712450537248000000|-182.2028426992165750000|0.2617740803347156640|-0.0002092387122824080|0.0000000881876090298|-0.0000000000152863918|146.4419507104903460000" +Motor 0 Speed=150.000000 +Motor 0 Acceleration=10.000000 +Motor 0 Current=0.600000 +Motor 0 Home=0 +Motor 0 BL Size=0 +Motor 0 BL Dir=1 +Motor 0 Max Step=50000 +Motor 0 Min Step=0 +Motor 0 Mix WL=1064.000000 +Motor 0 Name="OPO" +Motor 0 Park=0 +Motor 0 Ramp=150.000000 +Motor 0 Slope=10.000000 +Motor 0 First=0.600000 +Motor 1 Equation=3 +Motor 1 Coeff="" +Motor 1 Speed=150.000000 +Motor 1 Acceleration=10.000000 +Motor 1 Current=0.600000 +Motor 1 Home=0 +Motor 1 BL Size=650 +Motor 1 BL Dir=1 +Motor 1 Max Step=69000 +Motor 1 Min Step=-200 +Motor 1 Mix WL=1064.000000 +Motor 1 Name="UV" +Motor 1 Park=0 +Motor 1 Ramp=150.000000 +Motor 1 Slope=10.000000 +Motor 1 First=0.600000 +Motor 2 Equation=0 +Motor 2 Coeff="" +Motor 2 Speed=150.000000 +Motor 2 Acceleration=10.000000 +Motor 2 Current=0.600000 +Motor 2 Home=0 +Motor 2 BL Size=650 +Motor 2 BL Dir=1 +Motor 2 Max Step=200000 +Motor 2 Min Step=-20000 +Motor 2 Mix WL=1064.000000 +Motor 2 Name="Beamguide" +Motor 2 Park=0 +Motor 2 Ramp=150.000000 +Motor 2 Slope=10.000000 +Motor 2 First=0.600000 +Motor 3 Equation=0 +Motor 3 Coeff="" +Motor 3 Speed=150.000000 +Motor 3 Acceleration=10.000000 +Motor 3 Current=0.600000 +Motor 3 Home=0 +Motor 3 BL Size=650 +Motor 3 BL Dir=1 +Motor 3 Max Step=69000 +Motor 3 Min Step=-200 +Motor 3 Mix WL=1064.000000 +Motor 3 Name="UV L2" +Motor 3 Park=0 +Motor 3 Ramp=150.000000 +Motor 3 Slope=10.000000 +Motor 3 First=0.600000 + +[Port Config] +Port=7 +Baud=19200 +Data Bits=8 +Parity=0 +Stop BIts=10 +Flow=0 + +[Laser Serial Port] +Port=5 +Baud=115200 +Data Bits=8 +Parity=0 +Stop BIts=10 +Flow=0 + +[SSC Serial Port] +Port=0 +Baud=9600 +Data Bits=8 +Parity=0 +Stop BIts=10 +Flow=0 + +[Laser Config] +Laser Type=6 +Rep Rate=20 +MAX Power Param.=10.000000 +MIN Power Param.=100.000000 +Soft-Start=FALSE +SS Initial %=10.000000 +SS Steps=10 +Check Safety Interlocks=FALSE +Old Brilliant (no Q-switch control)=FALSE +Load Configuration=0 +Use External Timing=FALSE + +[Spectrometer] +Spectrometer=FALSE +Integration Time=8 +Trigger Mode=3 +Model=0 +Closed-Loop Tuning=FALSE +CL Resolution=0.500000 + +[Module Config] +Pump Wavelength=532.000000 +System Type=9 +Signal-lo=690.000000 +Signal-hi=950.000000 +Idler-lo=1200.000000 +Idler-hi=2400.000000 +UV-1=FALSE +UV-1-lo=0.000000 +UV-1-hi=0.000000 +UV-2=FALSE +UV-2-lo=0.000000 +UV-2-hi=0.000000 +UV-3=FALSE +UV-3-lo=0.000000 +UV-3-hi=0.000000 +UV-M=FALSE +UV-M-lo=0.000000 +UV-M-hi=0.000000 +UV-0=FALSE +UV-0-lo=0.000000 +UV-0-hi=0.000000 +Beamguide=FALSE + +[Miscellaneous] +OPO Recalibrate Max Step=1000 +UV Module Present=FALSE +Beamguide Present=FALSE +Period Decimal Notation=TRUE +OPO Cal. Limit Lo=0 +OPO Cal. Limit Hi=0 +Laser Control Mode=0 +Show User's LSODMM=FALSE +Hide System Configuration menu=TRUE +Closed-loop Tuning=FALSE +Digits of Precision=0 +Polarizer Present=FALSE +Attenuator Present=FALSE +LSODMM=FALSE +Show "Shutter (axis#1)"=FALSE +Shutter (axis#1).Label="" +Disable Tuning=FALSE +Suppress Polarizer Messages=FALSE + +[Automated Polarizer] +Automated Polarizer=FALSE +SIGNAL Position=293 +IDLER Position=438 +Stepper Current=0.600000 + +[Motorized Harmonics] +Motorized Harmonics=TRUE +SHG Min=-200000 +SHG Max=200000 +SHG Last=0 +THG Min=-200000 +THG Max=200000 +THG Last=0 +Fine Step=10 +Medium Step=20 +Coarse Step=50 +Stepper Current=0.600000 +Speed=100 +BL Size=200 +Steps per Revolution=96000 +Auto Optimization=TRUE +Feedback Device=2 +OPO Wavelength=760.000000 +OPO Threshold=0.000050 +Multi-Input Fiber=FALSE +532 Input=FALSE +532 Threshold=425.000000 +355 Input=FALSE +355 Threshold=425.000000 +Energy=90.000000 +Averaging=5 + +[DAQ Device] +DAQ Installed=FALSE +Model=1 +Device S/N=0 + +[Motorized Attenuator] +Motorized Attenuator=FALSE +Current Position=100.000000 +Attenuator Coeff="" +Stepper Current=0.600000 + +[Motor Controller] +Controller Type=1 +Auto Module Detection=FALSE +Motor Addresses="-1|4" +Wiring Scheme=1 + +[KAE Parameters] +Speed Mode=0 +Min Speed=10 +Run Current=20 +Hold Current=10 +Thermal Limit=0 +Output 1=FALSE +Output 2=TRUE +Output 3=TRUE +Output 4=TRUE +Output 5=FALSE +Ignore Limits=FALSE +Ignore E-Stop=TRUE +Off on E-Stop=TRUE + +[Scan Parameters] +Start WL=690.000000 +Period=50.000000 +End WL=950.000000 +Nr of shots/set=10 +Rep Rate=0 +Laser Energy=0.000000 + +[Advanced Scan Parameters] +Wavelengths="" +No. Cycles=0 + +[Burst Parameters] +Wavelength=690 +Nr of shots=10 +Rep Rate=0 +Laser Energy=0.000000 + +[Fast-Scan Parameters] +Start WL=0 +Period=50 +End WL=0 +Laser Energy=0.000000 + +[Shutter Parameters] +SSC32 Installed=FALSE +Shutter0_SSC32_Channel=0 +Shutter0_SIGNAL_Position=0 +Shutter0_IDLER_Position=0 +Shutter0_UV-1_Position=0 +Shutter0_UV-2_Position=0 +Shutter0_UV-3_Position=0 +Shutter0_UV-M_Position=0 +Shutter0_UV-0_Position=0 +Shutter1_SSC32_Channel=0 +Shutter1_SIGNAL_Position=0 +Shutter1_IDLER_Position=0 +Shutter1_UV-1_Position=0 +Shutter1_UV-2_Position=0 +Shutter1_UV-3_Position=0 +Shutter1_UV-M_Position=0 +Shutter1_UV-0_Position=0 +Shutter2_SSC32_Channel=0 +Shutter2_SIGNAL_Position=0 +Shutter2_IDLER_Position=0 +Shutter2_UV-1_Position=0 +Shutter2_UV-2_Position=0 +Shutter2_UV-3_Position=0 +Shutter2_UV-M_Position=0 +Shutter2_UV-0_Position=0 +Shutter3_SSC32_Channel=0 +Shutter3_SIGNAL_Position=0 +Shutter3_IDLER_Position=0 +Shutter3_UV-1_Position=0 +Shutter3_UV-2_Position=0 +Shutter3_UV-3_Position=0 +Shutter3_UV-M_Position=0 +Shutter3_UV-0_Position=0 +Shutter4_SSC32_Channel=0 +Shutter4_SIGNAL_Position=0 +Shutter4_IDLER_Position=0 +Shutter4_UV-1_Position=0 +Shutter4_UV-2_Position=0 +Shutter4_UV-3_Position=0 +Shutter4_UV-M_Position=0 +Shutter4_UV-0_Position=0 + +[Demo Parameters] +Motor Speed=80 +Start WL=0.000000 +End WL=0.000000 + +[Energy Metering] +Meter Installed=FALSE +Device=0 +Use Range #=0 +Device S/N="786441" +OPO S/N="781544" +OPO Channel=-1 +532nm S/N="" +532nm Scale Factor=0.000000 +532nm Channel=-1 +1064nm S/N="" +1064nm Scale Factor=0.000000 +1064nm Channel=-1 +355nm S/N="" +355nm Scale Factor=0.000000 +355nm Channel=-1 +Motor Config 0 Wavelengths="690.0|695.2|700.4|705.6|710.8|716.0|721.2|726.4|731.6|736.8|742.0|747.2|752.4|757.6|762.8|768.0|773.2|778.4|783.6|788.8|794.0|799.2|804.4|809.6|814.8|820.0|825.2|830.4|835.6|840.8|846.0|851.2|856.4|861.6|866.8|872.0|877.2|882.4|887.6|892.8|898.0|903.2|908.4|913.6|918.8|924.0|929.2|934.4|939.6|944.8" +Motor Config 0 Amplitudes="0.000727|0.000726|0.000764|0.000795|0.000824|0.000817|0.000832|0.000893|0.000898|0.000881|0.000870|0.000834|0.000849|0.000793|0.000778|0.000753|0.000755|0.000812|0.000843|0.000818|0.000843|0.000824|0.000829|0.000837|0.000832|0.000796|0.000808|0.000796|0.000774|0.000778|0.000760|0.000741|0.000724|0.000725|0.000703|0.000703|0.000695|0.000697|0.000671|0.000702|0.000679|0.000671|0.000676|0.000647|0.000660|0.000674|0.000686|0.000664|0.000658|0.000643" +Motor Config 0 Energies="0.042647|0.043251|0.045291|0.047462|0.048515|0.049305|0.049513|0.050434|0.049656|0.050895|0.048269|0.049129|0.050182|0.049334|0.046761|0.045675|0.045061|0.049129|0.050357|0.049206|0.050050|0.048745|0.048822|0.049041|0.048976|0.047813|0.047082|0.046980|0.046980|0.046442|0.045445|0.044063|0.043909|0.042451|0.041058|0.041760|0.042374|0.041683|0.040269|0.042374|0.041299|0.038996|0.041069|0.040736|0.039994|0.040839|0.040225|0.039994|0.038613|0.037692" +Motor Config 1 Wavelengths="" +Motor Config 1 Amplitudes="" +Motor Config 1 Energies="" +Motor Config 2 Wavelengths="" +Motor Config 2 Amplitudes="" +Motor Config 2 Energies="" +Motor Config 3 Wavelengths="" +Motor Config 3 Amplitudes="" +Motor Config 3 Energies="" +Motor Config 4 Wavelengths="" +Motor Config 4 Amplitudes="" +Motor Config 4 Energies="" +Motor Config 5 Wavelengths="" +Motor Config 5 Amplitudes="" +Motor Config 5 Energies="" + +[Ophir Sensor Settings] +Sensor1.Model Number="PE25-C" +Sensor1.Sensor Type="Pyroelectric" +Sensor1.Sensor S/N="781544" +Sensor1.Mode=1 +Sensor1.Wavelength=750 +Sensor1.Range=4 +Sensor1.Diffuser=FALSE +Sensor1.Pulsewidth=0 +Sensor1.Threshold=0 +Sensor1.Ext. Trigger=FALSE +Sensor2.Model Number="" +Sensor2.Sensor Type="" +Sensor2.Sensor S/N="" +Sensor2.Mode=0 +Sensor2.Wavelength=0 +Sensor2.Range=0 +Sensor2.Diffuser=FALSE +Sensor2.Pulsewidth=0 +Sensor2.Threshold=0 +Sensor2.Ext. Trigger=FALSE +Sensor3.Model Number="" +Sensor3.Sensor Type="" +Sensor3.Sensor S/N="" +Sensor3.Mode=0 +Sensor3.Wavelength=0 +Sensor3.Range=0 +Sensor3.Diffuser=FALSE +Sensor3.Pulsewidth=0 +Sensor3.Threshold=0 +Sensor3.Ext. Trigger=FALSE +Sensor4.Model Number="" +Sensor4.Sensor Type="" +Sensor4.Sensor S/N="" +Sensor4.Mode=0 +Sensor4.Wavelength=0 +Sensor4.Range=0 +Sensor4.Diffuser=FALSE +Sensor4.Pulsewidth=0 +Sensor4.Threshold=0 +Sensor4.Ext. Trigger=FALSE + +[UV Look-up Table] +UV-1 Use Lookup Table=FALSE +UV-1 Wavelengths="" +UV-1 Steps="" +UV-2 Use Lookup Table=FALSE +UV-2 Wavelengths="" +UV-2 Steps="" +UV-3 Use Lookup Table=FALSE +UV-3 Wavelengths="" +UV-3 Steps="" +UV-M Use Lookup Table=FALSE +UV-M Wavelengths="" +UV-M Steps="" +UV-0 Use Lookup Table=FALSE +UV-0 Wavelengths="" +UV-0 Steps="" + +[Fast Tuning] +Fast Tuning=TRUE +Kp=0.000000 +Ki=0.000000 +Kd=0.000000 \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/test.dmc b/Modules/PhotoacousticsHardware/Resources/test.dmc new file mode 100644 index 0000000000..af11477497 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/test.dmc @@ -0,0 +1,46 @@ +#FASTTUNE +rtf=-1 +II1 +'AMP SETTINGS +AU 0 +BR 1 +'AG 0 +TM 1000 +TL 3 +TK 9.998 +' +'GENERAL SETTINGS +ER 10000 +OE 1 +'MT -1 +'CE 0 +CN-1 +'PID PARAMETERS +KD 17.5 +KP 15 +KI 0 +' +SHX +WT 1000 +SP 1500000 +AC 120000000 +DC 120000000 +count=0;idx=0;DM pos[2] +pos[0]=27200 +pos[1]=30900 +points=pos[-1] +#MOVE; +II 1 +WT 10 +JP #MOVE; +EN +'SUBROUTINE +'************************************** +#ININT +rtf=count+10000000; +idx = count % points +'PA pos[idx];BG;AM; +'BG;AM; +count = count + 1 +WT 1 +RI 1; \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/Resources/tuneOPOto700.dmc b/Modules/PhotoacousticsHardware/Resources/tuneOPOto700.dmc new file mode 100644 index 0000000000..ac97c28bc2 --- /dev/null +++ b/Modules/PhotoacousticsHardware/Resources/tuneOPOto700.dmc @@ -0,0 +1,13 @@ +#AUTO +#MAIN +rt=0 +' +SP 150000 +AC 12000000 +DC 12000000 +pos=36459 +PA pos;BG;AM; +BG;AM; +WT 100 +rt=1 +EN \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/files.cmake b/Modules/PhotoacousticsHardware/files.cmake new file mode 100644 index 0000000000..d6d5d51880 --- /dev/null +++ b/Modules/PhotoacousticsHardware/files.cmake @@ -0,0 +1,23 @@ +set(CPP_FILES + mitkQuantelLaser.cpp + mitkGalilMotor.cpp + mitkOphirPyro.cpp +) + +set(RESOURCE_FILES + homeOPO.dmc + + GHOME.dmc + STUNE.dmc + FTUNE.dmc + + configSlowTuneOPO.dmc + executeSlowTuneOPO.dmc + + configFastTuneOPO.dmc + executeFastTuneOPO.dmc + + test.dmc + tuneOPOto700.dmc + OpotekPhocusMobile.xml +) \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/mitkGalilMotor.cpp b/Modules/PhotoacousticsHardware/mitkGalilMotor.cpp new file mode 100644 index 0000000000..583937ab5a --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkGalilMotor.cpp @@ -0,0 +1,281 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkGalilMotor.h" + +#include +#include + +#include + +#include "gclib.h" +#include "gclib_errors.h" + +#include "gclibo.h" + +mitk::GalilMotor::GalilMotor() : +m_ComPort(0), +m_BaudRate(0), +m_ErrorMessage("undefined"), +m_CurrentWavelength(0), +m_HomePosition(32561) +{ +} + +mitk::GalilMotor::~GalilMotor() +{ + this->CloseConnection(); + MITK_INFO << "[GalilMotor Debug] destroyed that motor"; +} + +void mitk::GalilMotor::LoadResorceFile(std::string filename, std::string* lines) +{ + us::ModuleResource resorceFile = us::GetModuleContext()->GetModule()->GetResource(filename); + std::string line; + if (resorceFile.IsValid() && resorceFile.IsFile()) + { + us::ModuleResourceStream stream(resorceFile); + while (std::getline(stream, line)) + { + *lines = *lines + line + "\n"; + } + } + else + { + MITK_ERROR << "Resource file was not valid"; + } +} + +bool mitk::GalilMotor::OpenConnection(std::string configuration) +{ + m_GalilSystem = 0; + m_ReturnCode = G_NO_ERROR; + LoadResorceFile(configuration + ".xml", &m_XmlOpoConfiguration); + TiXmlDocument xmlDoc; + + if (xmlDoc.Parse(m_XmlOpoConfiguration.c_str(), 0, TIXML_ENCODING_UTF8)) + { + TiXmlElement* root = xmlDoc.FirstChildElement("Motor"); + if (root) + { + TiXmlElement* elementNode = root->FirstChildElement("Coefficients"); + TiXmlElement* element = elementNode->FirstChildElement("lambda0"); + m_WavelengthToStepCalibration[0] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda1"); + m_WavelengthToStepCalibration[1] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda2"); + m_WavelengthToStepCalibration[2] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda3"); + m_WavelengthToStepCalibration[3] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda4"); + m_WavelengthToStepCalibration[4] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda5"); + m_WavelengthToStepCalibration[5] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("lambda6"); + m_WavelengthToStepCalibration[6] = std::stod(element->GetText()); + element = elementNode->FirstChildElement("home"); + m_HomePosition = std::stod(element->GetText()); + elementNode = root->FirstChildElement("Signal"); + element = elementNode->FirstChildElement("Signal-low"); + m_MinWavelength = std::stod(element->GetText()); + element = elementNode->FirstChildElement("Signal-default"); + m_CurrentWavelength = std::stod(element->GetText()); + element = elementNode->FirstChildElement("Signal-high"); + m_MaxWavelength = std::stod(element->GetText()); + elementNode = root->FirstChildElement("Seriell"); + element = elementNode->FirstChildElement("PortNumber"); + m_ComPort = std::stoi(element->GetText()); + element = elementNode->FirstChildElement("Baud"); + m_BaudRate = std::stoi(element->GetText()); + } + } + else + { + MITK_ERROR << "[GalilMotor Debug] Could not load configuration xml "; + } + std::string openCommand("COM" + std::to_string(m_ComPort) + " --baud " + std::to_string(m_BaudRate) + " --subscribe ALL --direct"); + MITK_INFO << "[Galil Debug] before GOpen(" << openCommand << ") = " << m_ReturnCode << "; m_GalilSystem = " << m_GalilSystem; + m_ReturnCode = GOpen(openCommand.c_str(), &m_GalilSystem); + MITK_INFO << "[Galil Debug] after GOpen = " << m_ReturnCode << "; m_GalilSystem = " << m_GalilSystem; + this->Home(); + return true; +} + +bool mitk::GalilMotor::CloseConnection() +{ + if (m_GalilSystem) + { + this->Home(); + m_ReturnCode = GClose(m_GalilSystem); + m_GalilSystem = 0; + return true; + } + else + return false; +} + +int mitk::GalilMotor::GetPositionFromWavelength(double wavelength) +{ + double posDouble = 0; + posDouble = m_WavelengthToStepCalibration[0] - m_HomePosition; + posDouble += (m_WavelengthToStepCalibration[1] * wavelength); + posDouble += (m_WavelengthToStepCalibration[2] * std::pow(wavelength, 2)); + posDouble += (m_WavelengthToStepCalibration[3] * std::pow(wavelength, 3)); + posDouble += (m_WavelengthToStepCalibration[4] * std::pow(wavelength, 4)); + posDouble += (m_WavelengthToStepCalibration[5] * std::pow(wavelength, 5)); + posDouble += (m_WavelengthToStepCalibration[6] * std::pow(wavelength, 6)); + int pos = posDouble; + return pos; +} + +bool mitk::GalilMotor::TuneToWavelength(double wavelength, bool isRecalibrating) +{ + std::string positionCommand; + if (!isRecalibrating) + { + positionCommand = "pos=" + std::to_string(this->GetPositionFromWavelength(wavelength)); + } + else + { + int posAbs = wavelength - m_HomePosition; + positionCommand = "pos=" + std::to_string(posAbs); + } + + m_ReturnCode = GCmd(m_GalilSystem, "AB"); // Abort any running programs + MITK_INFO << "[Galil Debug] after AB: " << m_ReturnCode << ""; + m_ReturnCode = GCmd(m_GalilSystem, "BV"); // Burn all variables + MITK_INFO << "[Galil Debug] after BV: " << m_ReturnCode << ""; + m_ReturnCode = GProgramDownload(m_GalilSystem, "", 0); // Erase the program on the system + MITK_INFO << "[Galil Debug] after empty GProgramDownload: " << m_ReturnCode << ""; + + m_ReturnCode = GCmd(m_GalilSystem, positionCommand.c_str()); + MITK_INFO << "[Galil Debug] after sending tune position(" << positionCommand << "): " << m_ReturnCode << ""; + + std::string galilProgramSTUNE; + this->LoadResorceFile("STUNE.dmc", &galilProgramSTUNE); + m_ReturnCode = GProgramDownload(m_GalilSystem, galilProgramSTUNE.c_str(), 0); + MITK_INFO << "[Galil Debug] after STUNE progam: " << m_ReturnCode << galilProgramSTUNE; + + GSleep(10); + m_ReturnCode = GCmd(m_GalilSystem, "XQ#STUNE"); + MITK_INFO << "[Galil Debug] after sending XQ#STUNE = " << m_ReturnCode; + GSleep(10000); + int success, pos = -1; + m_ReturnCode = GCmdI(m_GalilSystem, "suc=?", &success); + MITK_INFO << "[Galil Debug] after asking suc=? = " << m_ReturnCode << "; successfulTune = " << success; + m_ReturnCode = GCmdI(m_GalilSystem, "pos=?", &pos); + MITK_INFO << "[Galil Debug] after asking pos=? = " << m_ReturnCode << "; pos = " << pos; + if (success == 1) + { + m_CurrentWavelength = wavelength; + return true; + } + else + return false; +} + +bool mitk::GalilMotor::FastTuneWavelengths(std::vector wavelengthList) +{ + m_ReturnCode = GCmd(m_GalilSystem, "AB"); // Abort any running programs + GSleep(1000); + MITK_INFO << "[Galil Debug] after AB: " << m_ReturnCode << ""; + m_ReturnCode = GCmd(m_GalilSystem, "BV"); // Burn all variables + GSleep(2000); + MITK_INFO << "[Galil Debug] after BV: " << m_ReturnCode << ""; + + m_ReturnCode = GProgramDownload(m_GalilSystem, "", 0); // Erase the program on the system + MITK_INFO << "[Galil Debug] after empty GProgramDownload: " << m_ReturnCode << ""; + GSleep(1000); + std::string positionsCommand("#AUTO\n#PARA\nDA pos[0]\npoints = "+std::to_string(wavelengthList.size())+"\nDM pos[" + std::to_string(wavelengthList.size()) + "];\n"); + + for (int wavelengthIterator = 0; wavelengthIterator < wavelengthList.size(); wavelengthIterator++) + { + positionsCommand += "pos[" + std::to_string(wavelengthIterator) + "]=" + std::to_string(this->GetPositionFromWavelength(wavelengthList[wavelengthIterator])) + "\n"; + } + positionsCommand += "EN\n"; + + m_ReturnCode = GProgramDownload(m_GalilSystem, positionsCommand.c_str(), 0); + MITK_INFO << "[Galil Debug] after sending positions command(" << positionsCommand << "): " << m_ReturnCode << ""; + GSleep(1000); + m_ReturnCode = GCmd(m_GalilSystem, "XQ"); // FTUNE + MITK_INFO << "[Galil Debug] after asking XQ#PARA = " << m_ReturnCode; + m_ReturnCode = GProgramDownload(m_GalilSystem, "", 0); // Erase the program on the system + MITK_INFO << "[Galil Debug] after empty GProgramDownload: " << m_ReturnCode << ""; + GSleep(1000); + std::string galilProgramFTUNE; + this->LoadResorceFile("FTUNE.dmc", &galilProgramFTUNE); + m_ReturnCode = GProgramDownload(m_GalilSystem, galilProgramFTUNE.c_str(), 0); + MITK_INFO << "[Galil Debug] after FTUNE progam upload: " << m_ReturnCode << ""; + + GSleep(1000); + m_ReturnCode = GCmd(m_GalilSystem, "XQ"); // FTUNE + MITK_INFO << "[Galil Debug] after asking XQ#FTUNE = " << m_ReturnCode; + GSleep(10000); + int count = -1; + m_ReturnCode = GCmdI(m_GalilSystem, "count=?", &count); + MITK_INFO << "[Galil Debug] cycles = " << count; + m_ReturnCode = GCmdI(m_GalilSystem, "pos=?", &count); + MITK_INFO << "[Galil Debug] pos = " << count; + m_ReturnCode = GCmdI(m_GalilSystem, "points=?", &count); + MITK_INFO << "[Galil Debug] points = " << count; + + if (count > 0) + return true; + else + return false; +} + +bool mitk::GalilMotor::Home() +{ + m_ReturnCode = GCmd(m_GalilSystem, "AB"); // Abort any running programs + MITK_INFO << "[Galil Debug] after AB: " << m_ReturnCode << ""; + GSleep(1000); + m_ReturnCode = GCmd(m_GalilSystem, "BV"); // Burn all variables + MITK_INFO << "[Galil Debug] after BV: " << m_ReturnCode << ""; + GSleep(1000); + m_ReturnCode = GProgramDownload(m_GalilSystem, "", 0); // Erase the program on the system + MITK_INFO << "[Galil Debug] after empty GProgramDownload: " << m_ReturnCode << ""; + + std::string galilProgram; + this->LoadResorceFile("GHOME.dmc", &galilProgram); + + m_ReturnCode = GProgramDownload(m_GalilSystem, galilProgram.c_str(), 0); + MITK_INFO << "[Galil Debug] after home GProgramDownloadFile = " << m_ReturnCode << "; m_GalilSystem = " << m_GalilSystem; + + m_ReturnCode = GCmd(m_GalilSystem, "XQ"); // HOME + GSleep(15000); + int val = -2; + m_ReturnCode = GCmdI(m_GalilSystem, "suc=?", &val); + + MITK_INFO << "[Galil Debug] after home execution = " << m_ReturnCode << "; m_GalilSystem = " << m_GalilSystem << " homed = " << val; + + return true; +} + +double mitk::GalilMotor::GetMinWavelength() +{ + return m_MinWavelength; +} + +double mitk::GalilMotor::GetMaxWavelength() +{ + return m_MaxWavelength; +} + +double mitk::GalilMotor::GetCurrentWavelength() +{ + return m_CurrentWavelength; +} \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/mitkGalilMotor.h b/Modules/PhotoacousticsHardware/mitkGalilMotor.h new file mode 100644 index 0000000000..c73e07d512 --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkGalilMotor.h @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKGalilAPI_H_HEADER_INCLUDED +#define MITKGalilAPI_H_HEADER_INCLUDED + +#include "itkObject.h" +#include "mitkCommon.h" + +#include "vector" +#include "MitkPhotoacousticsHardwareExports.h" + +#include "gclib.h" +#include "gclibo.h" + +#include +#include +#include +#include +#include + +#include + +namespace mitk { + + class MITKPHOTOACOUSTICSHARDWARE_EXPORT GalilMotor : public itk::Object + { + public: + mitkClassMacroItkParent(mitk::GalilMotor, itk::Object); + itkFactorylessNewMacro(Self); + + virtual bool OpenConnection(std::string configuration); + virtual bool CloseConnection(); + + double GetMinWavelength(); + double GetMaxWavelength(); + double GetCurrentWavelength(); + + bool TuneToWavelength(double wavelength, bool isRecalibrating); + + bool FastTuneWavelengths(std::vector wavelengthList); + + protected: + virtual bool Home(); + void LoadResorceFile(std::string filename, std::string* lines); + int GetPositionFromWavelength(double wavelength); + GalilMotor(); + virtual ~GalilMotor(); + + int m_ComPort; + int m_BaudRate; + std::string m_ErrorMessage; + GCon m_GalilSystem; + GReturn m_ReturnCode; + + std::string m_XmlOpoConfiguration; + double m_MinWavelength; + double m_MaxWavelength; + double m_CurrentWavelength; + double m_WavelengthToStepCalibration[7]; + double m_HomePosition; + + }; +} // namespace mitk + +#endif /* MITKGalilAPI_H_HEADER_INCLUDED */ diff --git a/Modules/PhotoacousticsHardware/mitkOphirPyro.cpp b/Modules/PhotoacousticsHardware/mitkOphirPyro.cpp new file mode 100644 index 0000000000..1d5280b178 --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkOphirPyro.cpp @@ -0,0 +1,316 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkOphirPyro.h" + +#include +#include +#include +#include + +mitk::OphirPyro::OphirPyro() : +m_CurrentWavelength(0), +m_DeviceHandle(0), +m_Connected(false), +m_Streaming(false), +m_SerialNumber(nullptr), +m_GetDataThread(), +m_ImagePyroDelay(0), +m_EnergyMultiplicator(60000) +{ + m_PulseEnergy.clear(); + m_PulseTime.clear(); + m_PulseStatus.clear(); + m_TimeStamps.clear(); +} + +mitk::OphirPyro::~OphirPyro() +{ + if (m_Connected) + { + this->CloseConnection(); + if (m_GetDataThread.joinable()) + { + m_GetDataThread.join(); + MITK_INFO << "[OphirPyro Debug] joined data thread"; + } + } + MITK_INFO << "[OphirPyro Debug] destroying that Pyro"; + /* cleanup thread */ +} + +bool mitk::OphirPyro::StartDataAcquisition() +{ + if (ophirAPI.StartStream(m_DeviceHandle)) + { + m_Streaming = true; + m_GetDataThread = std::thread(&mitk::OphirPyro::GetDataFromSensorThread, this); + } + return m_Streaming; +} + +// this is just a little function to set the filenames below right +inline void replaceAll(std::string& str, const std::string& from, const std::string& to) { + if (from.empty()) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } +} + +void mitk::OphirPyro::SaveCsvData() +{ + // get the time and date, put them into a nice string and create a folder for the images + time_t time = std::time(nullptr); + time_t* timeptr = &time; + std::string currentDate = std::ctime(timeptr); + replaceAll(currentDate, ":", "-"); + currentDate.pop_back(); + std::string MakeFolder = "mkdir \"c:/DiPhASTimeStamps/" + currentDate + "\""; + system(MakeFolder.c_str()); + + std::string pathTS = "c:\\DiPhASTimeStamps\\" + currentDate + " Timestamps" + ".csv"; + + std::ofstream timestampFile; + timestampFile.open(pathTS); + + timestampFile << ",timestamp,PulseEnergy,PulseTime"; + + int currentSize = m_TimeStamps.size(); + + for (int index = 0; index < currentSize; ++index) + { + timestampFile << "\n" << index << "," << m_TimeStamps.at(index) << ","<< m_PulseEnergySaved.at(index) << "," << (long)m_PulseTimeSaved.at(index); + } + timestampFile.close(); +} + +void mitk::OphirPyro::SaveData() +{ + SaveCsvData(); +} + +bool mitk::OphirPyro::StopDataAcquisition() +{ + if (ophirAPI.StopStream(m_DeviceHandle)) + m_Streaming = false; + + SaveCsvData(); + MITK_INFO << "[OphirPyro Debug] m_Streaming = "<< m_Streaming; + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + if (m_GetDataThread.joinable()) + { + m_GetDataThread.join(); + } + return !m_Streaming; +} + +unsigned int mitk::OphirPyro::GetDataFromSensor() +{ + if (m_Streaming) + { + std::vector newEnergy; + std::vector newTimestamp; + std::vector newStatus; + unsigned int noPackages = 0; + try + { + noPackages = ophirAPI.GetData(m_DeviceHandle, &newEnergy, &newTimestamp, &newStatus); + if (noPackages > 0) + { + m_PulseEnergy.insert(m_PulseEnergy.end(), newEnergy.begin(), newEnergy.end()); + for (int i=0; iGetDataFromSensor(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + return; +} + +double mitk::OphirPyro::LookupCurrentPulseEnergy() +{ + if (m_Connected && !m_PulseEnergy.empty()) + { + MITK_INFO << m_PulseEnergy.size(); + return m_PulseEnergy.back(); + } + return 0; +} + +double mitk::OphirPyro::GetClosestEnergyInmJ(long long ImageTimeStamp, double interval) +{ + if (m_PulseTime.size() == 0) + return 0; + + long long searchTime = (ImageTimeStamp/1000000) - m_ImagePyroDelay; // conversion from ns to ms + + //MITK_INFO << "searchTime = " << searchTime; + int foundIndex = -1; + long long shortestDifference = 250*interval; + + // search the list for a fitting energy value time + for (int index = 0; index < m_PulseTime.size();++index) + { + long long newDifference = abs(((int)m_PulseTime[index]) - searchTime); + //MITK_INFO << "newDifference[" << index << "] = " << newDifference; + if (newDifference < shortestDifference) + { + shortestDifference = newDifference; + foundIndex = index; + //MITK_INFO << "foundIndex = " << foundIndex; + } + } + + if (abs(shortestDifference) < interval) + { + // delete all elements before the one found + m_PulseEnergy.erase(m_PulseEnergy.begin(), m_PulseEnergy.begin() + foundIndex); + m_PulseTime.erase(m_PulseTime.begin(), m_PulseTime.begin() + foundIndex); + m_PulseStatus.erase(m_PulseStatus.begin(), m_PulseStatus.begin() + foundIndex); + + // multipy with m_EnergyMultiplicator, because the Pyro gives just a fraction of the actual Laser Energy + return (GetNextPulseEnergy()*m_EnergyMultiplicator); + } + + //MITK_INFO << "No matching energy value for image found in interval of " << interval << "ms. sd: " << shortestDifference; + return -1; +} + +double mitk::OphirPyro::GetNextEnergyInmJ(long long ImageTimeStamp, double interval) +{ + if (m_Connected && !(m_PulseTime.size() > 0)) + return 0; + + long long searchTime = (ImageTimeStamp / 1000000) - m_ImagePyroDelay; // conversion from ns to ms + + if (abs(searchTime - m_PulseTime.front()) < interval) + { + return (GetNextPulseEnergy()*m_EnergyMultiplicator); // multipy with m_EnergyMultiplicator, because the Pyro gives just a fraction of the actual Laser Energy + } + + MITK_INFO << "Image aquisition and energy measurement ran out of sync"; + return -1; +} + +void mitk::OphirPyro::SetSyncDelay(long long FirstImageTimeStamp) +{ + while (!m_PulseTime.size()) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + m_ImagePyroDelay = (FirstImageTimeStamp / 1000000) - m_PulseTime.at(0); + + MITK_INFO << "m_ImagePyroDelay = " << m_ImagePyroDelay; + return; +} + +bool mitk::OphirPyro::IsSyncDelaySet() +{ + return (m_ImagePyroDelay != 0); +} + +double mitk::OphirPyro::GetNextPulseEnergy() +{ + if (m_Connected && m_PulseEnergy.size()>=1) + { + double out = m_PulseEnergy.front(); + m_PulseEnergy.erase(m_PulseEnergy.begin()); + m_PulseTime.erase(m_PulseTime.begin()); + m_PulseStatus.erase(m_PulseStatus.begin()); + return out; + } + return 0; +} + +double mitk::OphirPyro::LookupCurrentPulseEnergy(double* timestamp, int* status) +{ + if (m_Connected) + { + *timestamp = m_PulseTime.back(); + *status = m_PulseStatus.back(); + return m_PulseEnergy.back(); + } + return 0; +} + +double mitk::OphirPyro::GetNextPulseEnergy(double* timestamp, int* status) +{ + if (m_Connected) + { + double out = m_PulseEnergy.front(); + *timestamp = m_PulseTime.front(); + *status = m_PulseStatus.front(); + m_PulseEnergy.erase(m_PulseEnergy.begin()); + m_PulseTime.erase(m_PulseTime.begin()); + m_PulseStatus.erase(m_PulseStatus.begin()); + return out; + } + return 0; +} + +bool mitk::OphirPyro::OpenConnection() +{ + if (!m_Connected) + { + char* m_SerialNumber = ophirAPI.ScanUSB(); + if (m_SerialNumber != 0) + { + m_DeviceHandle = ophirAPI.OpenDevice(m_SerialNumber); + if (m_DeviceHandle != 0) + { + m_Connected = true; + return true; + } + } + } + return false; +} + +bool mitk::OphirPyro::CloseConnection() +{ + if (m_Connected) + { + bool closed = ophirAPI.CloseDevice(m_DeviceHandle); + if (closed) m_DeviceHandle = 0; + m_Connected = !closed; + return closed; + } + return false; +} \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/mitkOphirPyro.h b/Modules/PhotoacousticsHardware/mitkOphirPyro.h new file mode 100644 index 0000000000..b1d9f886d6 --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkOphirPyro.h @@ -0,0 +1,94 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKOPHIRPYRO_H_HEADER_INCLUDED +#define MITKOPHIRPYRO_H_HEADER_INCLUDED + +#include "itkObject.h" +#include "mitkCommon.h" + +#include "vector" +#include "MitkPhotoacousticsHardwareExports.h" + +#include "OphirPyroWrapper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mitk { + + class MITKPHOTOACOUSTICSHARDWARE_EXPORT OphirPyro : public itk::Object + { + public: + mitkClassMacroItkParent(mitk::OphirPyro, itk::Object); + itkFactorylessNewMacro(Self); + + virtual bool OpenConnection(); + virtual bool CloseConnection(); + virtual bool StartDataAcquisition(); + virtual bool StopDataAcquisition(); + unsigned int GetDataFromSensor(); + void GetDataFromSensorThread(); + void SaveData(); + + virtual double LookupCurrentPulseEnergy(); + virtual double GetNextPulseEnergy(); + virtual double LookupCurrentPulseEnergy(double* timestamp, int* status); + virtual double GetNextPulseEnergy(double* timestamp, int* status); + + virtual double GetClosestEnergyInmJ(long long ImageTimeStamp, double interval=20); + virtual double GetNextEnergyInmJ(long long ImageTimeStamp, double interval = 20); + virtual void SetSyncDelay(long long FirstImageTimeStamp); + virtual bool IsSyncDelaySet(); + + + protected: + OphirPyro(); + virtual ~OphirPyro(); + void SaveCsvData(); + OphirPyroWrapper ophirAPI; + char* m_SerialNumber; + int m_DeviceHandle; + bool m_Connected; + bool m_Streaming; + std::vector m_PulseEnergy; + std::vector m_PulseTime; + std::vector m_PulseStatus; + std::vector m_TimeStamps; + + std::vector m_PulseEnergySaved; + std::vector m_PulseTimeSaved; + std::vector m_PulseStatusSaved; + std::vector m_TimeStampsSaved; + + double m_CurrentWavelength; + double m_CurrentEnergyRange; + long long m_ImagePyroDelay; + float m_EnergyMultiplicator; + + std::thread m_GetDataThread; + }; +} // namespace mitk + +#endif /* MITKOPHIRPYRO_H_HEADER_INCLUDED */ diff --git a/Modules/PhotoacousticsHardware/mitkQuantelLaser.cpp b/Modules/PhotoacousticsHardware/mitkQuantelLaser.cpp new file mode 100644 index 0000000000..2f8c8a0093 --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkQuantelLaser.cpp @@ -0,0 +1,409 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkQuantelLaser.h" + +#include +#include +#include + +#include + +#include +#include + +const unsigned char CR = 0xD; // == '\r' - carriage return +const unsigned char LF = 0xA; // == '\n' - line feed + +mitk::QuantelLaser::QuantelLaser() : + m_State(mitk::QuantelLaser::UNCONNECTED), + m_FlashlampRunning(false), + m_ShutterOpen(false), + m_LaserEmission(false), + m_DeviceName(), + m_PortNumber(mitk::SerialCommunication::COM6), + m_BaudRate(mitk::SerialCommunication::BaudRate115200), + m_DataBits(mitk::SerialCommunication::DataBits8), + m_Parity(mitk::SerialCommunication::None), + m_StopBits(mitk::SerialCommunication::StopBits1), + m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), + m_SerialCommunication(nullptr), + m_StayAliveMessageThread(), + m_SerialCommunicationMutex() +{ +} + +mitk::QuantelLaser::~QuantelLaser() +{ + /* stop tracking and disconnect from tracking device */ + if ((GetState() == STATE3) || (GetState() == STATE4) || (GetState() == STATE5) || (GetState() == STATE6)) + { + this->StopQswitching(); + this->StopFlashing(); + } + if (GetState() == STATE2) + { + this->CloseConnection(); + } + /* cleanup stay alive thread */ + if (m_StayAliveMessageThread.joinable()) + m_StayAliveMessageThread.join(); + + /* free serial communication interface */ + if (m_SerialCommunication.IsNotNull()) + { + m_SerialCommunication->ClearReceiveBuffer(); + m_SerialCommunication->ClearSendBuffer(); + m_SerialCommunication->CloseConnection(); + m_SerialCommunication = nullptr; + } +} + +std::string mitk::QuantelLaser::SendAndReceiveLine(const std::string* input, std::string* answer) +{ + MITK_INFO << "[Quantel Laser Debug] sending: " << input->c_str(); + if (input == nullptr) + return "SERIALSENDERROR"; + + std::string message; + + message = *input + '\n'; + + // Clear send buffer + m_SerialCommunication->ClearSendBuffer(); + m_SerialCommunication->Send(message); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::string m; + do + { + long returnvalue = m_SerialCommunication->Receive(m, 1); + if ((returnvalue == 0) || (m.size() != 1)) + return "SERIALRECEIVEERROR"; + *answer += m; + } while (m.at(0) != LF); + m_SerialCommunication->ClearReceiveBuffer(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + m_SerialCommunication->ClearReceiveBuffer(); + MITK_INFO << "[Quantel Laser Debug] received: " << answer->c_str(); + return "OK"; +} + +void mitk::QuantelLaser::LoadResorceFile(std::string filename, std::string* lines) +{ + us::ModuleResource resorceFile = us::GetModuleContext()->GetModule()->GetResource(filename); + std::string line; + if (resorceFile.IsValid() && resorceFile.IsFile()) + { + us::ModuleResourceStream stream(resorceFile); + while (std::getline(stream, line)) + { + *lines = *lines + line + "\n"; + } + } + else + { + MITK_ERROR << "[Quantel Laser Debug] Resource file was not valid"; + } +} + +bool mitk::QuantelLaser::OpenConnection(std::string configurationFile) +{ + LoadResorceFile(configurationFile + ".xml", &m_XmlPumpLaserConfiguration); + TiXmlDocument xmlDoc; + + if (xmlDoc.Parse(m_XmlPumpLaserConfiguration.c_str(), 0, TIXML_ENCODING_UTF8)) + { + TiXmlElement* root = xmlDoc.FirstChildElement("PumpLaser"); + if (root) + { + TiXmlElement* elementNode = root->FirstChildElement("Seriell"); + TiXmlElement* element = elementNode->FirstChildElement("PortNumber"); + m_PortNumber = mitk::SerialCommunication::PortNumber(std::stoi(element->GetText())); + element = elementNode->FirstChildElement("Baud"); + m_BaudRate = mitk::SerialCommunication::BaudRate(std::stoi(element->GetText())); + + MITK_INFO << m_PortNumber << m_BaudRate; + } + } + else + { + MITK_ERROR << "[Quantel Laser Debug] Could not load configuration xml "; + return false; + } + + m_SerialCommunication = mitk::SerialCommunication::New(); + + if (m_DeviceName.empty()) + m_SerialCommunication->SetPortNumber(m_PortNumber); + else + m_SerialCommunication->SetDeviceName(m_DeviceName); + + m_SerialCommunication->SetBaudRate(m_BaudRate); + m_SerialCommunication->SetDataBits(m_DataBits); + m_SerialCommunication->SetParity(m_Parity); + m_SerialCommunication->SetStopBits(m_StopBits); + m_SerialCommunication->SetSendTimeout(1000); + m_SerialCommunication->SetReceiveTimeout(1000); + if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE + { + m_SerialCommunication->CloseConnection(); + m_SerialCommunication = nullptr; + MITK_ERROR << "[Quantel Laser Debug] " << "Can not open serial port"; + return false; + } + + if (this->GetState() != UNCONNECTED) + { + std::string *command = new std::string; + std::string answer(""); + command->assign("STOP"); + this->SendAndReceiveLine(command, &answer); + return true; + } + else + return false; +} + +bool mitk::QuantelLaser::CloseConnection() +{ + if (this->GetState() != UNCONNECTED) + { + this->StopQswitching(); + this->StopFlashing(); + + // close the serial connection + m_SerialCommunication->CloseConnection(); + m_SerialCommunication = nullptr; + this->GetState(); + } + return true; +} + +mitk::QuantelLaser::LaserState mitk::QuantelLaser::GetState() +{ + if (m_SerialCommunication == nullptr) + { + m_State = UNCONNECTED; + return m_State; + } + + if (!m_SerialCommunication->IsConnected()) + { + m_State = UNCONNECTED; + return m_State; + } + + std::string *command = new std::string; + std::string answer(""); + command->assign("STATE"); + this->SendAndReceiveLine(command, &answer); + MITK_INFO << "[Quantel Laser Debug] get state:" << answer; + if (answer == "STATE = 0\n") + m_State = STATE0; + else if(answer == "STATE = 1\n") + { + m_State = STATE1; + m_FlashlampRunning = false; + m_ShutterOpen = false; + m_LaserEmission = false; + } + else if(answer == "STATE = 2\n") // laser ready for RUN + { + m_State = STATE2; + m_FlashlampRunning = false; + m_ShutterOpen = false; + m_LaserEmission = false; + } + else if(answer == "STATE = 3\n") + { + m_State = STATE3; + m_FlashlampRunning = true; + m_ShutterOpen = false; + m_LaserEmission = false; + } + else if(answer == "STATE = 4\n") + { + m_State = STATE4; + m_FlashlampRunning = true; + m_ShutterOpen = false; + m_LaserEmission = false; + } + else if (answer == "STATE = 5\n") + { + m_State = STATE5; + m_FlashlampRunning = true; + m_ShutterOpen = true; + m_LaserEmission = false; + } + else if (answer == "STATE = 6\n") + { + m_State = STATE6; + m_FlashlampRunning = true; + m_ShutterOpen = true; + m_LaserEmission = true; + } + else if (answer == "STATE = 7\n") + { + m_State = STATE7; + m_FlashlampRunning = true; + m_ShutterOpen = true; + m_LaserEmission = true; + } + else + { + m_State = UNCONNECTED; + m_FlashlampRunning = false; + m_ShutterOpen = false; + m_LaserEmission = false; + } + + return m_State; +} + + +void mitk::QuantelLaser::StayAlive() +{ + do{ + std::this_thread::sleep_for(std::chrono::seconds(2)); + std::string *command = new std::string; + std::string answer(""); + command->assign("STATE"); + this->SendAndReceiveLine(command, &answer); + } while (m_KeepAlive); +} + +bool mitk::QuantelLaser::StartFlashing() +{ + this->GetState(); + if (!m_FlashlampRunning) + { + if (m_LaserEmission) + this->StopQswitching(); + + std::string *command = new std::string; + std::string answer(""); + command->assign("RUN"); + this->SendAndReceiveLine(command, &answer); + MITK_INFO << answer; + if (answer.at(0) == 'O' && answer.at(1) == 'K') + { + m_FlashlampRunning = true; + m_ShutterOpen = false; + m_KeepAlive = true; + //m_StayAliveMessageThread = std::thread(&mitk::QuantelLaser::StayAlive, this); + } + else + { + MITK_ERROR << "[Quantel Laser Debug] " << "Cannot start flashlamps." << " Laser is telling me: " << answer; + return false; + } + } + else + MITK_INFO << "[Quantel Laser Debug] " << "Flashlamps are already running"; + + return true; +} + +bool mitk::QuantelLaser::StopFlashing() +{ + this->GetState(); + if (m_FlashlampRunning) + { + if (m_LaserEmission) + this->StopQswitching(); + + std::string *command = new std::string; + std::string answer(""); + command->assign("STOP"); + this->SendAndReceiveLine(command, &answer); + MITK_INFO << answer; + if (answer.at(0) == 'O' && answer.at(1) == 'K') + { + m_FlashlampRunning = false; + m_ShutterOpen = false; + m_KeepAlive = false; + } + else + { + MITK_ERROR << "[Quantel Laser Debug] " << "Cannot Stop flashlamps." << " Laser is telling me: " << answer; + return false; + } + + } + else + MITK_INFO << "[Quantel Laser Debug] " << "Flashlamps are not running"; + + return true; +} + +bool mitk::QuantelLaser::StartQswitching() +{ + this->GetState(); + if (!m_LaserEmission) + { + std::string *command = new std::string; + std::string answer(""); + command->assign("QSW 1"); + this->SendAndReceiveLine(command, &answer); + MITK_INFO << answer; + if (answer.at(0) == 'O' && answer.at(1) == 'K') + { + m_FlashlampRunning = true; + m_ShutterOpen = true; + return true; + } + else + { + MITK_ERROR << "[Quantel Laser Debug] " << "Cannot start Qswitch." << " Laser is telling me: " << answer; + return false; + } + } + else + { + MITK_INFO << "[Quantel Laser Debug] " << "Laser is already emitting"; + return true; + } +} + +bool mitk::QuantelLaser::StopQswitching() +{ + this->GetState(); + if (m_FlashlampRunning && m_LaserEmission) + { + std::string *command = new std::string; + std::string answer(""); + command->assign("QSW 0"); + this->SendAndReceiveLine(command, &answer); + MITK_INFO << answer; + if (answer.at(0) == 'O' && answer.at(1) == 'K') + { + m_LaserEmission = false; + } + else + MITK_ERROR << "[Quantel Laser Debug] " << "Cannot stop Q-switch."; + + } + return true; +} + +bool mitk::QuantelLaser::IsEmitting() +{ + return m_LaserEmission; +} +bool mitk::QuantelLaser::IsFlashing() +{ + return m_FlashlampRunning; +} \ No newline at end of file diff --git a/Modules/PhotoacousticsHardware/mitkQuantelLaser.h b/Modules/PhotoacousticsHardware/mitkQuantelLaser.h new file mode 100644 index 0000000000..fda48f9b15 --- /dev/null +++ b/Modules/PhotoacousticsHardware/mitkQuantelLaser.h @@ -0,0 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKQUANTELLASER_H_HEADER_INCLUDED +#define MITKQUANTELLASER_H_HEADER_INCLUDED + +#include "itkObject.h" +#include "mitkCommon.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mitkSerialCommunication.h" +#include "MitkPhotoacousticsHardwareExports.h" + +namespace mitk { + + class MITKPHOTOACOUSTICSHARDWARE_EXPORT QuantelLaser : public itk::LightObject + { + public: + mitkClassMacroItkParent(QuantelLaser, itk::LightObject); + itkFactorylessNewMacro(Self); + + enum LaserState { UNCONNECTED, STATE0, STATE1, STATE2, STATE3, STATE4, STATE5, STATE6, STATE7 }; ///< Type for STATE variable. The LaserDevice is always in one of these states + /** + * \brief Opens a connection to the device + * + * This may only be called if there is currently no connection to the device. + * If OpenConnection() is successful, the object will change from UNCONNECTED state to a STATE state + */ + virtual bool OpenConnection(std::string configurationFile); + + /** + * \brief Closes the connection to the device + * + * This may only be called if there is currently a connection to the device. (e.g. object is in a STATE state) + */ + virtual bool CloseConnection(); ///< Closes the connection with the device + + virtual std::string SendAndReceiveLine(const std::string* input, std::string* answer); + + virtual void StayAlive(); + virtual bool StartFlashing(); + virtual bool StopFlashing(); + + virtual bool StartQswitching(); + virtual bool StopQswitching(); + virtual bool IsEmitting(); + virtual bool IsFlashing(); + + virtual LaserState GetState(); + + typedef mitk::SerialCommunication::PortNumber PortNumber; ///< Port number of the serial connection + typedef mitk::SerialCommunication::BaudRate BaudRate; ///< Baud rate of the serial connection + typedef mitk::SerialCommunication::DataBits DataBits; ///< Number of data bits used in the serial connection + typedef mitk::SerialCommunication::Parity Parity; ///< Parity mode used in the serial connection + typedef mitk::SerialCommunication::StopBits StopBits; ///< Number of stop bits used in the serial connection + typedef mitk::SerialCommunication::HardwareHandshake HardwareHandshake; ///< Hardware handshake mode of the serial connection + + private: + LaserState m_State; ///< current Laser state + protected: + + QuantelLaser(); + virtual ~QuantelLaser(); + + bool m_KeepAlive = false; + bool m_FlashlampRunning = false; + bool m_ShutterOpen = false; + bool m_LaserEmission = false; + void LoadResorceFile(std::string filename, std::string* lines); + + std::string m_DeviceName;///< Device Name + PortNumber m_PortNumber; ///< COM Port Number + BaudRate m_BaudRate; ///< COM Port Baud Rate + DataBits m_DataBits; ///< Number of Data Bits per token + Parity m_Parity; ///< Parity mode for communication + StopBits m_StopBits; ///< number of stop bits per token + HardwareHandshake m_HardwareHandshake; ///< use hardware handshake for serial port connection + + std::string m_XmlPumpLaserConfiguration; + mitk::SerialCommunication::Pointer m_SerialCommunication; ///< serial communication interface + std::thread m_StayAliveMessageThread; + std::mutex m_SerialCommunicationMutex; ///< mutex for coordinated access of serial communication interface + }; +} // namespace mitk + +#endif /* MITKQUANTELLASER_H_HEADER_INCLUDED */ diff --git a/Modules/US/CMakeLists.txt b/Modules/US/CMakeLists.txt index b4459daf79..ae141db32f 100644 --- a/Modules/US/CMakeLists.txt +++ b/Modules/US/CMakeLists.txt @@ -1,16 +1,17 @@ MITK_CREATE_MODULE( SUBPROJECTS INCLUDE_DIRS USControlInterfaces USFilters USModel INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} PACKAGE_DEPENDS Poco DEPENDS MitkOpenCVVideoSupport MitkQtWidgetsExt MitkIGTBase MitkOpenIGTLink WARNINGS_AS_ERRORS ) ## create US config #CONFIGURE_FILE(mitkUSConfig.h.in ${PROJECT_BINARY_DIR}/mitkUSConfig.h @ONLY) ADD_SUBDIRECTORY(USHardwareTelemed) +ADD_SUBDIRECTORY(USHardwareDiPhAS) ADD_SUBDIRECTORY(USNavigation) ADD_SUBDIRECTORY(Testing) diff --git a/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp new file mode 100644 index 0000000000..f6ffd5ca7f --- /dev/null +++ b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp @@ -0,0 +1,205 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkUSDiPhASDeviceCustomControls.h" + +mitk::USDiPhASDeviceCustomControls::USDiPhASDeviceCustomControls(itk::SmartPointer device) + : mitk::USAbstractControlInterface(device.GetPointer()), m_IsActive(false), silentUpdate(false) +{ +} + +mitk::USDiPhASDeviceCustomControls::~USDiPhASDeviceCustomControls() +{ +} + +void mitk::USDiPhASDeviceCustomControls::SetIsActive(bool isActive) +{ + m_IsActive = isActive; +} + +bool mitk::USDiPhASDeviceCustomControls::GetIsActive() +{ + return m_IsActive; +} + +void mitk::USDiPhASDeviceCustomControls::passGUIOut(std::function callback) {} + +void mitk::USDiPhASDeviceCustomControls::SetSilentUpdate(bool silent) +{ + silentUpdate = silent; +} + +bool mitk::USDiPhASDeviceCustomControls::GetSilentUpdate() +{ + return silentUpdate; +} + +//Set Functions + +void mitk::USDiPhASDeviceCustomControls::SetCompensateEnergy(bool compensate) +{ + this->OnSetCompensateEnergy(compensate); +} + +void mitk::USDiPhASDeviceCustomControls::SetUseBModeFilter(bool isSet) +{ + this->OnSetUseBModeFilter(isSet); +} + +void mitk::USDiPhASDeviceCustomControls::SetRecord(bool record) +{ + this->OnSetRecord(record); +} + +void mitk::USDiPhASDeviceCustomControls::SetVerticalSpacing(float mm) +{ + this->OnSetVerticalSpacing(mm); +} + +void mitk::USDiPhASDeviceCustomControls::SetScatteringCoefficient(float coeff) +{ + this->OnSetScatteringCoefficient(coeff); +} +void mitk::USDiPhASDeviceCustomControls::SetCompensateScattering(bool compensate) +{ + this->OnSetCompensateScattering(compensate); +} + +void mitk::USDiPhASDeviceCustomControls::SetSavingSettings(SavingSettings settings) +{ + this->OnSetSavingSettings(settings); +} + +//Transmit +void mitk::USDiPhASDeviceCustomControls::SetTransmitPhaseLength(double us) +{ + this->OnSetTransmitPhaseLength(us); +} + +void mitk::USDiPhASDeviceCustomControls::SetExcitationFrequency(double MHz) +{ + this->OnSetExcitationFrequency(MHz); +} + +void mitk::USDiPhASDeviceCustomControls::SetTransmitEvents(int events) +{ + this->OnSetTransmitEvents(events); +} + +void mitk::USDiPhASDeviceCustomControls::SetVoltage(int voltage) +{ + this->OnSetVoltage(voltage); +} + +void mitk::USDiPhASDeviceCustomControls::SetMode(bool interleaved) +{ + this->OnSetMode(interleaved); +} + +//Receive +void mitk::USDiPhASDeviceCustomControls::SetScanDepth(double mm) +{ + this->OnSetScanDepth(mm); +} + +void mitk::USDiPhASDeviceCustomControls::SetAveragingCount(int count) +{ + this->OnSetAveragingCount(count); +} + +void mitk::USDiPhASDeviceCustomControls::SetTGCMin(int min) +{ + this->OnSetTGCMin(min); +} + +void mitk::USDiPhASDeviceCustomControls::SetTGCMax(int max) +{ + this->OnSetTGCMax(max); +} + +void mitk::USDiPhASDeviceCustomControls::SetDataType(DataType type) +{ + this->OnSetDataType(type); +} + +//Beamforming +void mitk::USDiPhASDeviceCustomControls::SetPitch(double mm) +{ + this->OnSetPitch(mm); +} + +void mitk::USDiPhASDeviceCustomControls::SetReconstructedSamples(int samples) +{ + this->OnSetReconstructedSamples(samples); +} + +void mitk::USDiPhASDeviceCustomControls::SetReconstructedLines(int lines) +{ + this->OnSetReconstructedLines(lines); +} + +void mitk::USDiPhASDeviceCustomControls::SetSpeedOfSound(int mps) +{ + this->OnSetSpeedOfSound(mps); +} + +//Bandpass +void mitk::USDiPhASDeviceCustomControls::SetBandpassEnabled(bool bandpass) +{ + this->OnSetBandpassEnabled(bandpass); +} + +void mitk::USDiPhASDeviceCustomControls::SetLowCut(double MHz) +{ + this->OnSetLowCut(MHz); +} + +void mitk::USDiPhASDeviceCustomControls::SetHighCut(double MHz) +{ + this->OnSetHighCut(MHz); +} + + +//OnSetDummies + +void mitk::USDiPhASDeviceCustomControls::OnSetCompensateEnergy(bool compensate) {} +void mitk::USDiPhASDeviceCustomControls::OnSetUseBModeFilter(bool isSet) {} +void mitk::USDiPhASDeviceCustomControls::OnSetRecord(bool record) {} +void mitk::USDiPhASDeviceCustomControls::OnSetVerticalSpacing(float mm) {} +void mitk::USDiPhASDeviceCustomControls::OnSetScatteringCoefficient(float coeff) {} +void mitk::USDiPhASDeviceCustomControls::OnSetCompensateScattering(bool compensate) {} +void mitk::USDiPhASDeviceCustomControls::OnSetSavingSettings(SavingSettings settings) {} +//Transmit +void mitk::USDiPhASDeviceCustomControls::OnSetTransmitPhaseLength(double ms) {} +void mitk::USDiPhASDeviceCustomControls::OnSetExcitationFrequency(double MHz) {} +void mitk::USDiPhASDeviceCustomControls::OnSetTransmitEvents(int events) {} +void mitk::USDiPhASDeviceCustomControls::OnSetVoltage(int voltage) {} +void mitk::USDiPhASDeviceCustomControls::OnSetMode(bool interleaved) {} +//Receive +void mitk::USDiPhASDeviceCustomControls::OnSetScanDepth(double mm) {} +void mitk::USDiPhASDeviceCustomControls::OnSetAveragingCount(int count) {} +void mitk::USDiPhASDeviceCustomControls::OnSetTGCMin(int min) {} +void mitk::USDiPhASDeviceCustomControls::OnSetTGCMax(int max) {} +void mitk::USDiPhASDeviceCustomControls::OnSetDataType(DataType type) {} +//Beamforming +void mitk::USDiPhASDeviceCustomControls::OnSetPitch(double mm) {} +void mitk::USDiPhASDeviceCustomControls::OnSetReconstructedSamples(int samples) {} +void mitk::USDiPhASDeviceCustomControls::OnSetReconstructedLines(int lines) {} +void mitk::USDiPhASDeviceCustomControls::OnSetSpeedOfSound(int mps) {} +//Bandpass +void mitk::USDiPhASDeviceCustomControls::OnSetBandpassEnabled(bool bandpass) {} +void mitk::USDiPhASDeviceCustomControls::OnSetLowCut(double MHz) {} +void mitk::USDiPhASDeviceCustomControls::OnSetHighCut(double MHz) {} diff --git a/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.h b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.h new file mode 100644 index 0000000000..06df8278c5 --- /dev/null +++ b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.h @@ -0,0 +1,144 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASDeviceCustomControls_H_HEADER_INCLUDED_ +#define MITKUSDiPhASDeviceCustomControls_H_HEADER_INCLUDED_ + +#include "mitkUSAbstractControlInterface.h" +#include "mitkUSImageVideoSource.h" +#include "mitkUSDevice.h" + +#include + +#include +#include + +namespace mitk { +/** + * \brief Custom controls for mitk::USDiPhASDevice. + */ +class MITKUS_EXPORT USDiPhASDeviceCustomControls : public USAbstractControlInterface +{ +public: + mitkClassMacro(USDiPhASDeviceCustomControls, USAbstractControlInterface); + mitkNewMacro1Param(Self, itk::SmartPointer); + + /** + * Activate or deactivate the custom controls. This is just for handling + * widget visibility in a GUI for example. + */ + virtual void SetIsActive( bool isActive ) override; + + enum DataType { Image_uChar, Beamformed_Short }; + + struct SavingSettings + { + bool saveRaw; + bool saveBeamformed; + }; + /** + * \return if this custom controls are currently activated + */ + virtual bool GetIsActive( ) override; + + virtual void SetCompensateEnergy(bool compensate); + virtual void SetUseBModeFilter(bool isSet); + virtual void SetVerticalSpacing(float mm); + virtual void SetRecord(bool record); + virtual void SetScatteringCoefficient(float coeff); + virtual void SetCompensateScattering(bool compensate); + virtual void SetSavingSettings(SavingSettings settings); + + //Transmit + virtual void SetTransmitPhaseLength(double us); + virtual void SetExcitationFrequency(double MHz); + virtual void SetTransmitEvents(int events); + virtual void SetVoltage(int voltage); + virtual void SetMode(bool interleaved); + + //Receive + virtual void SetScanDepth(double mm); + virtual void SetAveragingCount(int count); + virtual void SetTGCMin(int min); + virtual void SetTGCMax(int max); + virtual void SetDataType(DataType type); + + //Beamforming + virtual void SetPitch(double mm); + virtual void SetReconstructedSamples(int samples); + virtual void SetReconstructedLines(int lines); + virtual void SetSpeedOfSound(int mps); + + //Bandpass + virtual void SetBandpassEnabled(bool bandpass); + virtual void SetLowCut(double MHz); + virtual void SetHighCut(double MHz); + + virtual void passGUIOut(std::function callback); + virtual void SetSilentUpdate(bool silent); + virtual bool GetSilentUpdate(); + + + +protected: + /** + * Class needs an mitk::USDevice object for beeing constructed. + */ + USDiPhASDeviceCustomControls( itk::SmartPointer device ); + virtual ~USDiPhASDeviceCustomControls( ); + + bool m_IsActive; + USImageVideoSource::Pointer m_ImageSource; + bool silentUpdate; + + /** virtual handlers implemented in Device Controls + */ + virtual void OnSetCompensateEnergy(bool compensate); + virtual void OnSetSavingSettings(SavingSettings settings); + virtual void OnSetUseBModeFilter(bool isSet); + virtual void OnSetRecord(bool record); + virtual void OnSetVerticalSpacing(float mm); + virtual void OnSetScatteringCoefficient(float coeff); + virtual void OnSetCompensateScattering(bool compensate); + //Transmit + virtual void OnSetTransmitPhaseLength(double us); + virtual void OnSetExcitationFrequency(double MHz); + virtual void OnSetTransmitEvents(int events); + virtual void OnSetVoltage(int voltage); + virtual void OnSetMode(bool interleaved); + + //Receive + virtual void OnSetScanDepth(double mm); + virtual void OnSetAveragingCount(int count); + virtual void OnSetTGCMin(int min); + virtual void OnSetTGCMax(int max); + virtual void OnSetDataType(DataType type); + + //Beamforming + virtual void OnSetPitch(double mm); + virtual void OnSetReconstructedSamples(int samples); + virtual void OnSetReconstructedLines(int lines); + virtual void OnSetSpeedOfSound(int mps); + + //Bandpass + virtual void OnSetBandpassEnabled(bool bandpass); + virtual void OnSetLowCut(double MHz); + virtual void OnSetHighCut(double MHz); + +}; +} // namespace mitk + +#endif // MITKUSDiPhASDeviceCustomControls_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/CMakeLists.txt b/Modules/US/USHardwareDiPhAS/CMakeLists.txt new file mode 100644 index 0000000000..00c5ff6690 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/CMakeLists.txt @@ -0,0 +1,20 @@ +IF(WIN32) + +OPTION(MITK_USE_US_DiPhAS_SDK "Enable support for DiPhAS API devices" OFF) + +IF(MITK_USE_US_DiPhAS_SDK) + +SET(MITK_US_DiPhAS_SDK_PATH "" CACHE PATH "Path to DiPhAS SDK header files.") + +MITK_CREATE_MODULE( + SUBPROJECTS + DEPENDS MitkUS MitkPhotoacousticsHardware + INCLUDE_DIRS PUBLIC "${MITK_US_DiPhAS_SDK_PATH}/Debug" "${MITK_US_DiPhAS_SDK_PATH}/Release" + INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} + ADDITIONAL_LIBS "${MITK_US_DiPhAS_SDK_PATH}/Debug/Framework.IBMT.US.CWrapper.lib" "${MITK_US_DiPhAS_SDK_PATH}/Release/Framework.IBMT.US.CWrapper.lib" + AUTOLOAD_WITH MitkUS +) + +ENDIF(MITK_USE_US_DiPhAS_SDK) + +ENDIF(WIN32) diff --git a/Modules/US/USHardwareDiPhAS/FranzTissue.nrrd b/Modules/US/USHardwareDiPhAS/FranzTissue.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/FranzTissue.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.h new file mode 100644 index 0000000000..bebba4955b --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.h @@ -0,0 +1,143 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkAnalyticSignalImageFilter_h +#define itkAnalyticSignalImageFilter_h + +#include + +#include "itkFFT1DComplexToComplexImageFilter.h" +#include "itkFFT1DRealToComplexConjugateImageFilter.h" +#include "itkImageRegionSplitterDirection.h" + +namespace itk +{ +/** \class AnalyticSignalImageFilter + * \brief Generates the analytic signal from one direction of an image. + * + * This filter generates the complex valued analytic signal along one direction + * of an image. This input is a real valued image, and the output is a complex + * image. + * + * The analytic signal is given by + * + * f_a(x) = f(x) - i f_H(x) + * + * Where i is the square root of one and f_H(x) is the Hibert transform of f(x). + * + * Since the Hilbert transform in the Fourier domain is + * + * F_H(k) = F(k) i sign(k), + * + * f_a(x) is calculated by + * + * f_a(x) = F^{-1}( F(k) 2 U(k) ) + * + * where U(k) is the unit step function. + * + * \ingroup FourierTransform + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage > +class AnalyticSignalImageFilter: + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension); + + typedef AnalyticSignalImageFilter Self; + typedef ImageToImageFilter< InputImageType, OutputImageType > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + itkTypeMacro( AnalyticSignalImageFilter, ImageToImageFilter ); + itkNewMacro( Self ); + + /** Get the direction in which the filter is to be applied. */ + virtual unsigned int GetDirection() const + { + return this->m_FFTRealToComplexFilter->GetDirection(); + } + + /** Set the direction in which the filter is to be applied. */ + virtual void SetDirection( const unsigned int direction ) + { + if( this->m_FFTRealToComplexFilter->GetDirection() != direction ) + { + this->m_FFTRealToComplexFilter->SetDirection( direction ); + this->m_FFTComplexToComplexFilter->SetDirection( direction ); + this->Modified(); + } + } + +protected: + AnalyticSignalImageFilter(); + virtual ~AnalyticSignalImageFilter() {} + + void PrintSelf(std::ostream& os, Indent indent) const ITK_OVERRIDE; + + // These behave like their analogs in FFT1DRealToComplexConjugateImageFilter. + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + virtual void EnlargeOutputRequestedRegion(DataObject *output) ITK_OVERRIDE; + + virtual void BeforeThreadedGenerateData() ITK_OVERRIDE; + virtual void ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType threadId ) ITK_OVERRIDE; + virtual void AfterThreadedGenerateData() ITK_OVERRIDE; + + typedef FFT1DRealToComplexConjugateImageFilter< InputImageType, OutputImageType > FFTRealToComplexType; + typedef FFT1DComplexToComplexImageFilter< OutputImageType, OutputImageType > FFTComplexToComplexType; + + typename FFTRealToComplexType::Pointer m_FFTRealToComplexFilter; + typename FFTComplexToComplexType::Pointer m_FFTComplexToComplexFilter; + + /** Override to return a splitter that does not split along the direction we + * are performing the transform. */ + virtual const ImageRegionSplitterBase* GetImageRegionSplitter() const ITK_OVERRIDE; + +private: + AnalyticSignalImageFilter( const Self& ); // purposely not implemented + void operator=( const Self& ); // purposely not implemented + + ImageRegionSplitterDirection::Pointer m_ImageRegionSplitter; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAnalyticSignalImageFilter.hxx" +#endif + +#endif // itkAnalyticSignalImageFilter_h diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.hxx new file mode 100644 index 0000000000..a48bcba4cb --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkAnalyticSignalImageFilter.hxx @@ -0,0 +1,271 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkAnalyticSignalImageFilter_hxx +#define itkAnalyticSignalImageFilter_hxx + +#include "itkAnalyticSignalImageFilter.h" + +#include "itkVnlFFT1DRealToComplexConjugateImageFilter.h" +#include "itkVnlFFT1DComplexToComplexImageFilter.h" + +#if defined(ITK_USE_FFTWD) || defined(ITK_USE_FFTWF) +#include "itkFFTW1DRealToComplexConjugateImageFilter.h" +#include "itkFFTW1DComplexToComplexImageFilter.h" +#endif + +#include "itkImageLinearConstIteratorWithIndex.h" +#include "itkImageLinearIteratorWithIndex.h" +#include "itkMetaDataObject.h" + +namespace itk +{ + +template< typename TInputImage, typename TOutputImage > +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::AnalyticSignalImageFilter() +{ + m_FFTRealToComplexFilter = FFTRealToComplexType::New(); + m_FFTComplexToComplexFilter = FFTComplexToComplexType::New(); + + m_FFTComplexToComplexFilter->SetTransformDirection( FFTComplexToComplexType::INVERSE ); + + this->SetDirection( 0 ); + + this->m_ImageRegionSplitter = ImageRegionSplitterDirection::New(); +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + typename InputImageType::Pointer inputPtr = + const_cast (this->GetInput()); + typename OutputImageType::Pointer outputPtr = this->GetOutput(); + + if ( !inputPtr || !outputPtr ) + { + return; + } + + // we need to compute the input requested region (size and start index) + typedef const typename OutputImageType::SizeType& OutputSizeType; + OutputSizeType outputRequestedRegionSize = + outputPtr->GetRequestedRegion().GetSize(); + typedef const typename OutputImageType::IndexType& OutputIndexType; + OutputIndexType outputRequestedRegionStartIndex = + outputPtr->GetRequestedRegion().GetIndex(); + + //// the regions other than the fft direction are fine + typename InputImageType::SizeType inputRequestedRegionSize = outputRequestedRegionSize; + typename InputImageType::IndexType inputRequestedRegionStartIndex = outputRequestedRegionStartIndex; + + // we but need all of the input in the fft direction + const unsigned int direction = this->GetDirection(); + const typename InputImageType::SizeType& inputLargeSize = + inputPtr->GetLargestPossibleRegion().GetSize(); + inputRequestedRegionSize[direction] = inputLargeSize[direction]; + const typename InputImageType::IndexType& inputLargeIndex = + inputPtr->GetLargestPossibleRegion().GetIndex(); + inputRequestedRegionStartIndex[direction] = inputLargeIndex[direction]; + + typename InputImageType::RegionType inputRequestedRegion; + inputRequestedRegion.SetSize( inputRequestedRegionSize ); + inputRequestedRegion.SetIndex( inputRequestedRegionStartIndex ); + + inputPtr->SetRequestedRegion( inputRequestedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::EnlargeOutputRequestedRegion(DataObject *output) +{ + OutputImageType* outputPtr = dynamic_cast< OutputImageType* >( output ); + + // we need to enlarge the region in the fft direction to the + // largest possible in that direction + typedef const typename OutputImageType::SizeType& ConstOutputSizeType; + ConstOutputSizeType requestedSize = + outputPtr->GetRequestedRegion().GetSize(); + ConstOutputSizeType outputLargeSize = + outputPtr->GetLargestPossibleRegion().GetSize(); + typedef const typename OutputImageType::IndexType& ConstOutputIndexType; + ConstOutputIndexType requestedIndex = + outputPtr->GetRequestedRegion().GetIndex(); + ConstOutputIndexType outputLargeIndex = + outputPtr->GetLargestPossibleRegion().GetIndex(); + + typename OutputImageType::SizeType enlargedSize = requestedSize; + typename OutputImageType::IndexType enlargedIndex = requestedIndex; + const unsigned int direction = this->GetDirection (); + enlargedSize[direction] = outputLargeSize[direction]; + enlargedIndex[direction] = outputLargeIndex[direction]; + + typename OutputImageType::RegionType enlargedRegion; + enlargedRegion.SetSize( enlargedSize ); + enlargedRegion.SetIndex( enlargedIndex ); + outputPtr->SetRequestedRegion( enlargedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::PrintSelf( std::ostream& os, Indent indent ) const +{ + Superclass::PrintSelf( os, indent ); + + const unsigned int direction = this->GetDirection(); + os << indent << "Direction: " << direction << std::endl; + + os << indent << "FFTRealToComplexFilter: " << std::endl; + m_FFTRealToComplexFilter->Print( os, indent ); + os << indent << "FFTComplexToComplexFilter: " << std::endl; + m_FFTComplexToComplexFilter->Print( os, indent ); +} + + +template< typename TInputImage, typename TOutputImage > +const ImageRegionSplitterBase * +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::GetImageRegionSplitter() const +{ + return this->m_ImageRegionSplitter.GetPointer(); +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::BeforeThreadedGenerateData() +{ + this->m_ImageRegionSplitter->SetDirection( this->GetDirection() ); + + m_FFTRealToComplexFilter->SetInput( this->GetInput() ); + m_FFTRealToComplexFilter->GetOutput()->SetRequestedRegion( this->GetOutput()->GetRequestedRegion() ); + m_FFTRealToComplexFilter->GetOutput()->SetLargestPossibleRegion( this->GetOutput()->GetLargestPossibleRegion() ); + m_FFTRealToComplexFilter->SetNumberOfThreads( this->GetNumberOfThreads() ); + m_FFTRealToComplexFilter->Update (); +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType itkNotUsed( threadId ) ) +{ + // get pointers to the input and output + const typename FFTRealToComplexType::OutputImageType * inputPtr = m_FFTRealToComplexFilter->GetOutput(); + OutputImageType * outputPtr = this->GetOutput(); + + const typename FFTRealToComplexType::OutputImageType::SizeType & inputSize = inputPtr->GetRequestedRegion().GetSize(); + const unsigned int direction = this->GetDirection (); + const unsigned int size = inputSize[direction]; + unsigned int dub_size; + bool even; + if( size % 2 == 0 ) + { + even = true; + dub_size = size / 2 - 1; + } + else + { + even = false; + dub_size = (size + 1) / 2 - 1; + } + + typedef ImageLinearConstIteratorWithIndex< typename FFTRealToComplexType::OutputImageType > InputIteratorType; + typedef ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType; + InputIteratorType inputIt( inputPtr, outputRegionForThread ); + OutputIteratorType outputIt( outputPtr, outputRegionForThread ); + inputIt.SetDirection( direction ); + outputIt.SetDirection( direction ); + + unsigned int i; + // for every fft line + for( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); + outputIt.NextLine(), inputIt.NextLine() ) + { + inputIt.GoToBeginOfLine(); + outputIt.GoToBeginOfLine(); + + // DC + outputIt.Set( inputIt.Get() ); + ++inputIt; + ++outputIt; + + for( i = 0; i < dub_size; i++ ) + { + outputIt.Set( inputIt.Get() * static_cast< typename TInputImage::PixelType >( 2 ) ); + ++outputIt; + ++inputIt; + } + if( even ) + { + outputIt.Set( inputIt.Get() ); + ++inputIt; + ++outputIt; + } + while( !outputIt.IsAtEndOfLine() ) + { + outputIt.Set( static_cast< typename TInputImage::PixelType >( 0 ) ); + ++outputIt; + } + } +} + + +template< typename TInputImage, typename TOutputImage > +void +AnalyticSignalImageFilter< TInputImage, TOutputImage > +::AfterThreadedGenerateData() +{ + // Trippy, eh? + m_FFTComplexToComplexFilter->SetInput( this->GetOutput() ); + m_FFTComplexToComplexFilter->GetOutput()->SetRequestedRegion( this->GetOutput()->GetRequestedRegion() ); + m_FFTComplexToComplexFilter->GetOutput()->SetLargestPossibleRegion( this->GetOutput()->GetLargestPossibleRegion() ); + m_FFTComplexToComplexFilter->SetNumberOfThreads( this->GetNumberOfThreads() ); + m_FFTComplexToComplexFilter->Update (); + this->GraftOutput( m_FFTComplexToComplexFilter->GetOutput() ); +} + +} // end namespace itk + +#endif // itkAnalyticSignalImageFilter_hxx diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.h new file mode 100644 index 0000000000..54bd15b325 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.h @@ -0,0 +1,156 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkBModeImageFilter_h +#define itkBModeImageFilter_h + +#include "itkAddImageFilter.h" +#include "itkComplexToModulusImageFilter.h" +#include "itkConstantPadImageFilter.h" +#include "itkRegionFromReferenceImageFilter.h" +#include "itkImageToImageFilter.h" +#include "itkImage.h" +#include "itkLog10ImageFilter.h" + +#include "itkAnalyticSignalImageFilter.h" + +namespace itk +{ + +/** + * \class BModeImageFilter + * + * \brief Create an ultrasound B-Mode (Brightness-Mode) image from raw + * "RF" data. The RF's envelope is calculated from the analytic signal and + * logarithmic intensity transform is applied. + * + * Use SetDirection() to define the axis of propagation. + * + * \ingroup Ultrasound + * + * \sa AnalyticSignalImageFilter + * + */ +template < typename TInputImage, typename TOutputImage=TInputImage, typename TComplexImage=Image< std::complex< typename TInputImage::PixelType >, TInputImage::ImageDimension > > +class BModeImageFilter : + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef BModeImageFilter Self; + typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** The type of input image. */ + typedef TInputImage InputImageType; + + /** Dimension of the input and output images. */ + itkStaticConstMacro (ImageDimension, unsigned int, + TInputImage::ImageDimension); + + /** Typedef support for the input image scalar value type. */ + typedef typename InputImageType::PixelType InputPixelType; + + /** The type of output image. */ + typedef TOutputImage OutputImageType; + + /** Typedef support for the output image scalar value type. */ + typedef typename OutputImageType::PixelType OutputPixelType; + + /** Typedef of the image used for internal computations that has + * std::complex pixels. */ + typedef TComplexImage ComplexImageType; + + /** Other convenient typedefs */ + typedef typename InputImageType::RegionType InputRegionType; + typedef typename InputImageType::SizeType InputSizeType; + typedef typename InputImageType::IndexType InputIndexType; + + /** Run-time type information (and related methods) */ + itkTypeMacro( BModeImageFilter, ImageToImageFilter ); + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + + /** Set the direction in which the envelope is to be calculated. */ + virtual void SetDirection( unsigned int direction ) + { + this->m_AnalyticFilter->SetDirection( direction ); + this->Modified(); + } + + /** Get the direction in which the envelope is to be calculated. */ + virtual unsigned int GetDirection() const + { + return m_AnalyticFilter->GetDirection(); + } + +protected: + BModeImageFilter(); + ~BModeImageFilter() {} + + virtual void PrintSelf( std::ostream& os, Indent indent ) const ITK_OVERRIDE; + + virtual void GenerateData() ITK_OVERRIDE; + + // These behave like their analogs in FFT1DRealToComplexConjugateImageFilter. + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + virtual void EnlargeOutputRequestedRegion(DataObject *output) ITK_OVERRIDE; + + /** Component filters. */ + typedef AnalyticSignalImageFilter< InputImageType, ComplexImageType > AnalyticType; + typedef ComplexToModulusImageFilter< typename AnalyticType::OutputImageType, OutputImageType > ComplexToModulusType; + typedef ConstantPadImageFilter< InputImageType, InputImageType > PadType; + typedef AddImageFilter< InputImageType, InputImageType > AddConstantType; + typedef Log10ImageFilter< InputImageType, OutputImageType > LogType; + typedef RegionFromReferenceImageFilter< OutputImageType, OutputImageType > ROIType; + +private: + BModeImageFilter( const Self& ); // purposely not implemented + void operator=( const Self& ); // purposely not implemented + + typename AnalyticType::Pointer m_AnalyticFilter; + typename ComplexToModulusType::Pointer m_ComplexToModulusFilter; + typename PadType::Pointer m_PadFilter; + typename AddConstantType::Pointer m_AddConstantFilter; + typename LogType::Pointer m_LogFilter; + typename ROIType::Pointer m_ROIFilter; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBModeImageFilter.hxx" +#endif + +#endif // itkBModeImageFilter_h \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.hxx new file mode 100644 index 0000000000..aa511e03b2 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkBModeImageFilter.hxx @@ -0,0 +1,212 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkBModeImageFilter_hxx +#define itkBModeImageFilter_hxx + +#include "itkBModeImageFilter.h" + +#include "itkMetaDataDictionary.h" + +#include +#include +#include + +namespace itk +{ + +template < typename TInputImage, typename TOutputImage, typename TComplexImage > +BModeImageFilter< TInputImage, TOutputImage, TComplexImage > +::BModeImageFilter() +{ + m_AnalyticFilter = AnalyticType::New(); + m_ComplexToModulusFilter = ComplexToModulusType::New(); + m_PadFilter = PadType::New(); + m_AddConstantFilter = AddConstantType::New(); + m_LogFilter = LogType::New(); + m_ROIFilter = ROIType::New(); + + // Avoid taking the log of zero. Assuming that the original input is coming + // from a digitizer that outputs integer types, so 1 is small. + m_AddConstantFilter->SetConstant2( 1 ); + m_PadFilter->SetConstant( 0. ); + + m_ComplexToModulusFilter->SetInput( m_AnalyticFilter->GetOutput() ); + m_ROIFilter->SetInput( m_ComplexToModulusFilter->GetOutput() ); + m_LogFilter->SetInput( m_AddConstantFilter->GetOutput() ); +} + + +template < typename TInputImage, typename TOutputImage, typename TComplexImage > +void +BModeImageFilter< TInputImage, TOutputImage, TComplexImage > +::PrintSelf( std::ostream& os, Indent indent ) const +{ + Superclass::PrintSelf( os, indent ); +} + + +template < typename TInputImage, typename TOutputImage, typename TComplexImage > +void +BModeImageFilter< TInputImage, TOutputImage, TComplexImage > +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + InputImageType * inputPtr = const_cast (this->GetInput()); + OutputImageType * outputPtr = this->GetOutput(); + + // we need to compute the input requested region (size and start index) + typedef const typename OutputImageType::SizeType& OutputSizeType; + OutputSizeType outputRequestedRegionSize = + outputPtr->GetRequestedRegion().GetSize(); + typedef const typename OutputImageType::IndexType& OutputIndexType; + OutputIndexType outputRequestedRegionStartIndex = + outputPtr->GetRequestedRegion().GetIndex(); + + //// the regions other than the fft direction are fine + typename InputImageType::SizeType inputRequestedRegionSize = outputRequestedRegionSize; + typename InputImageType::IndexType inputRequestedRegionStartIndex = outputRequestedRegionStartIndex; + + // we but need all of the input in the fft direction + const unsigned int direction = this->GetDirection(); + const typename InputImageType::SizeType& inputLargeSize = + inputPtr->GetLargestPossibleRegion().GetSize(); + inputRequestedRegionSize[direction] = inputLargeSize[direction]; + const typename InputImageType::IndexType& inputLargeIndex = + inputPtr->GetLargestPossibleRegion().GetIndex(); + inputRequestedRegionStartIndex[direction] = inputLargeIndex[direction]; + + typename InputImageType::RegionType inputRequestedRegion; + inputRequestedRegion.SetSize( inputRequestedRegionSize ); + inputRequestedRegion.SetIndex( inputRequestedRegionStartIndex ); + + inputPtr->SetRequestedRegion( inputRequestedRegion ); +} + + +template < typename TInputImage, typename TOutputImage, typename TComplexImage > +void +BModeImageFilter< TInputImage, TOutputImage, TComplexImage > +::EnlargeOutputRequestedRegion(DataObject *output) +{ + OutputImageType* outputPtr = dynamic_cast< OutputImageType* >( output ); + + // we need to enlarge the region in the fft direction to the + // largest possible in that direction + typedef const typename OutputImageType::SizeType& ConstOutputSizeType; + ConstOutputSizeType requestedSize = + outputPtr->GetRequestedRegion().GetSize(); + ConstOutputSizeType outputLargeSize = + outputPtr->GetLargestPossibleRegion().GetSize(); + typedef const typename OutputImageType::IndexType& ConstOutputIndexType; + ConstOutputIndexType requestedIndex = + outputPtr->GetRequestedRegion().GetIndex(); + ConstOutputIndexType outputLargeIndex = + outputPtr->GetLargestPossibleRegion().GetIndex(); + + typename OutputImageType::SizeType enlargedSize = requestedSize; + typename OutputImageType::IndexType enlargedIndex = requestedIndex; + const unsigned int direction = this->GetDirection (); + enlargedSize[direction] = outputLargeSize[direction]; + enlargedIndex[direction] = outputLargeIndex[direction]; + + typename OutputImageType::RegionType enlargedRegion; + enlargedRegion.SetSize( enlargedSize ); + enlargedRegion.SetIndex( enlargedIndex ); + outputPtr->SetRequestedRegion( enlargedRegion ); +} + + +template < typename TInputImage, typename TOutputImage, typename TComplexImage > +void +BModeImageFilter< TInputImage, TOutputImage, TComplexImage > +::GenerateData() +{ + this->AllocateOutputs(); + + const InputImageType * inputPtr = this->GetInput(); + OutputImageType * outputPtr = this->GetOutput(); + + const unsigned int direction = m_AnalyticFilter->GetDirection(); + typename InputImageType::SizeType size = inputPtr->GetLargestPossibleRegion().GetSize(); + + // Zero padding. FFT direction should be factorable by 2 for all FFT + // implementations to work. + unsigned int n = size[direction]; + while( n % 2 == 0 ) + { + n /= 2; + } + bool doPadding; + if( n == 1 ) + { + doPadding = false; + } + else + { + doPadding = true; + } + if( doPadding ) + { + n = size[direction]; + unsigned int newSizeDirection = 1; + while( newSizeDirection < n ) + { + newSizeDirection *= 2; + } + typename InputImageType::SizeType padSize; + padSize.Fill( 0 ); + padSize[direction] = newSizeDirection - size[direction]; + size[direction] = newSizeDirection; + m_PadFilter->SetPadUpperBound( padSize ); + m_PadFilter->SetInput( inputPtr ); + m_AnalyticFilter->SetInput( m_PadFilter->GetOutput() ); + m_ROIFilter->SetReferenceImage( inputPtr ); + m_ROIFilter->SetInput( m_ComplexToModulusFilter->GetOutput() ); + m_AddConstantFilter->SetInput( m_ROIFilter->GetOutput() ); + } + else // padding is not required + { + m_AnalyticFilter->SetInput( inputPtr ); + m_AddConstantFilter->SetInput( m_ComplexToModulusFilter->GetOutput() ); + } + m_LogFilter->GraftOutput( outputPtr ); + m_LogFilter->Update(); + this->GraftOutput( m_LogFilter->GetOutput() ); +} + +} // end namespace itk + +#endif \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.h new file mode 100644 index 0000000000..ed9b8b90f6 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.h @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkFFT1DComplexToComplexImageFilter_h +#define itkFFT1DComplexToComplexImageFilter_h + +#include + +#include "itkImage.h" +#include "itkImageToImageFilter.h" +#include "itkImageRegionSplitterDirection.h" + +namespace itk +{ +/** \class FFT1DComplexToComplexImageFilter + * \brief Perform the Fast Fourier Transform, complex input to complex output, + * but only along one dimension. + * + * The direction of the transform, 'Forward' or 'Inverse', can be set with + * SetTransformDirection() and GetTransformDirection(). + * + * The dimension along which to apply to filter can be specified with + * SetDirection() and GetDirection(). + * + * \ingroup FourierTransform + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage=TInputImage > +class FFT1DComplexToComplexImageFilter: + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + typedef FFT1DComplexToComplexImageFilter Self; + typedef ImageToImageFilter< InputImageType, OutputImageType > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension ); + + itkTypeMacro( FFT1DComplexToComplexImageFilter, ImageToImageFilter ); + + /** Customized object creation methods that support configuration-based + * selection of FFT implementation. + * + * Default implementation is VnlFFT1D. + */ + static Pointer New(); + + /** Transform direction. */ + typedef enum { DIRECT = 1, INVERSE } TransformDirectionType; + + /** Set/Get the direction in which the transform will be applied. + * By selecting DIRECT, this filter will perform a direct (forward) Fourier + * Transform. + * By selecting INVERSE, this filter will perform an inverse Fourier + * Transform. */ + itkSetMacro( TransformDirection, TransformDirectionType ); + itkGetConstMacro( TransformDirection, TransformDirectionType ); + + /** Get the direction in which the filter is to be applied. */ + itkGetMacro(Direction, unsigned int); + + /** Set the direction in which the filter is to be applied. */ + itkSetClampMacro(Direction, unsigned int, 0, ImageDimension - 1); + +protected: + FFT1DComplexToComplexImageFilter(); + virtual ~FFT1DComplexToComplexImageFilter() {} + + void PrintSelf(std::ostream& os, Indent indent) const ITK_OVERRIDE; + + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + virtual void EnlargeOutputRequestedRegion(DataObject *output) ITK_OVERRIDE; + + virtual void BeforeThreadedGenerateData() ITK_OVERRIDE; + + /** Override to return a splitter that does not split along the direction we + * are performing the transform. */ + virtual const ImageRegionSplitterBase* GetImageRegionSplitter() const ITK_OVERRIDE; + + /** Direction in which the filter is to be applied + * this should be in the range [0,ImageDimension-1]. */ + unsigned int m_Direction; + + /** Direction to apply the transform (forward/inverse). */ + TransformDirectionType m_TransformDirection; + +private: + FFT1DComplexToComplexImageFilter( const Self& ); + void operator=( const Self& ); + + ImageRegionSplitterDirection::Pointer m_ImageRegionSplitter; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#ifndef itkVnlFFT1DComplexToComplexImageFilter_h +#ifndef itkVnlFFT1DComplexToComplexImageFilter_hxx +#ifndef itkFFTW1DComplexToComplexImageFilter_h +#ifndef itkFFTW1DComplexToComplexImageFilter_hxx +#include "itkFFT1DComplexToComplexImageFilter.hxx" +#endif +#endif +#endif +#endif +#endif + +#endif // itkFFT1DComplexToComplexImageFilter_h diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.hxx new file mode 100644 index 0000000000..f287799e1c --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DComplexToComplexImageFilter.hxx @@ -0,0 +1,210 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkFFT1DComplexToComplexImageFilter_hxx +#define itkFFT1DComplexToComplexImageFilter_hxx + +#include "itkFFT1DComplexToComplexImageFilter.h" + +#include "itkVnlFFT1DComplexToComplexImageFilter.h" + +#if defined(ITK_USE_FFTWD) || defined(ITK_USE_FFTWF) +#include "itkFFTW1DComplexToComplexImageFilter.h" +#endif + +#include "itkMetaDataDictionary.h" +#include "itkMetaDataObject.h" + +namespace itk +{ + +template < typename TInputImage, typename TOutputImage > +typename FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage >::Pointer +FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::New() +{ + Pointer smartPtr = ::itk::ObjectFactory< Self >::Create(); + +#ifdef ITK_USE_FFTWD + if( smartPtr.IsNull() ) + { + if( typeid( TPixel ) == typeid( double ) ) + { + smartPtr = dynamic_cast< Self* >( + FFTW1DComplexToComplexImageFilter< double, VDimension > + ::New().GetPointer() ); + } + } +#endif +#ifdef ITK_USE_FFTWF + if( smartPtr.IsNull() ) + { + if( typeid( TPixel ) == typeid( float ) ) + { + smartPtr = dynamic_cast( + FFTW1DComplexToComplexImageFilter< float, VDimension > + ::New().GetPointer() ); + } + } +#endif + + if( smartPtr.IsNull() ) + { + smartPtr = VnlFFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > + ::New().GetPointer(); + } + + return smartPtr; +} + + +template< typename TInputImage, typename TOutputImage > +FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::FFT1DComplexToComplexImageFilter(): + m_Direction(0), m_TransformDirection( DIRECT ) +{ + this->m_ImageRegionSplitter = ImageRegionSplitterDirection::New(); +} + + +template +const ImageRegionSplitterBase* +FFT1DComplexToComplexImageFilter < TInputImage, TOutputImage > +::GetImageRegionSplitter(void) const +{ + return this->m_ImageRegionSplitter.GetPointer(); +} + + +template +void +FFT1DComplexToComplexImageFilter < TInputImage, TOutputImage > +::BeforeThreadedGenerateData() +{ + this->m_ImageRegionSplitter->SetDirection( this->GetDirection() ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + typename InputImageType::Pointer inputPtr = + const_cast (this->GetInput()); + typename OutputImageType::Pointer outputPtr = this->GetOutput(); + + if ( !inputPtr || !outputPtr ) + { + return; + } + + // we need to compute the input requested region (size and start index) + typedef const typename OutputImageType::SizeType& OutputSizeType; + OutputSizeType outputRequestedRegionSize = + outputPtr->GetRequestedRegion().GetSize(); + typedef const typename OutputImageType::IndexType& OutputIndexType; + OutputIndexType outputRequestedRegionStartIndex = + outputPtr->GetRequestedRegion().GetIndex(); + + //// the regions other than the fft direction are fine + typename InputImageType::SizeType inputRequestedRegionSize = outputRequestedRegionSize; + typename InputImageType::IndexType inputRequestedRegionStartIndex = outputRequestedRegionStartIndex; + + // we but need all of the input in the fft direction + const unsigned int direction = this->m_Direction; + const typename InputImageType::SizeType& inputLargeSize = + inputPtr->GetLargestPossibleRegion().GetSize(); + inputRequestedRegionSize[direction] = inputLargeSize[direction]; + const typename InputImageType::IndexType& inputLargeIndex = + inputPtr->GetLargestPossibleRegion().GetIndex(); + inputRequestedRegionStartIndex[direction] = inputLargeIndex[direction]; + + typename InputImageType::RegionType inputRequestedRegion; + inputRequestedRegion.SetSize( inputRequestedRegionSize ); + inputRequestedRegion.SetIndex( inputRequestedRegionStartIndex ); + + inputPtr->SetRequestedRegion( inputRequestedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::EnlargeOutputRequestedRegion(DataObject *output) +{ + OutputImageType* outputPtr = dynamic_cast( output ); + + // we need to enlarge the region in the fft direction to the + // largest possible in that direction + typedef const typename OutputImageType::SizeType& ConstOutputSizeType; + ConstOutputSizeType requestedSize = + outputPtr->GetRequestedRegion().GetSize(); + ConstOutputSizeType outputLargeSize = + outputPtr->GetLargestPossibleRegion().GetSize(); + typedef const typename OutputImageType::IndexType& ConstOutputIndexType; + ConstOutputIndexType requestedIndex = + outputPtr->GetRequestedRegion().GetIndex(); + ConstOutputIndexType outputLargeIndex = + outputPtr->GetLargestPossibleRegion().GetIndex(); + + typename OutputImageType::SizeType enlargedSize = requestedSize; + typename OutputImageType::IndexType enlargedIndex = requestedIndex; + enlargedSize[this->m_Direction] = outputLargeSize[this->m_Direction]; + enlargedIndex[this->m_Direction] = outputLargeIndex[this->m_Direction]; + + typename OutputImageType::RegionType enlargedRegion; + enlargedRegion.SetSize( enlargedSize ); + enlargedRegion.SetIndex( enlargedIndex ); + outputPtr->SetRequestedRegion( enlargedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::PrintSelf( std::ostream& os, Indent indent ) const +{ + Superclass::PrintSelf( os, indent ); + + os << indent << "Direction: " << m_Direction << std::endl; + os << indent << "TransformDirection: " << m_TransformDirection << std::endl; +} + + +} // end namespace itk + +#endif // itkFFT1DComplexToComplexImageFilter_hxx diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.h new file mode 100644 index 0000000000..9ff85ad00c --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.h @@ -0,0 +1,123 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkFFT1DRealToComplexConjugateImageFilter_h +#define itkFFT1DRealToComplexConjugateImageFilter_h + +#include + +#include "itkImageToImageFilter.h" +#include "itkImageRegionSplitterDirection.h" + +namespace itk +{ +/** \class FFT1DRealToComplexConjugateImageFilter + * \brief Perform the Fast Fourier Transform, in the forward direction, with + * real inputs, but only along one dimension. + * + * \ingroup FourierTransform + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage=Image< std::complex< typename TInputImage::PixelType >, TInputImage::ImageDimension > > +class FFT1DRealToComplexConjugateImageFilter: + public ImageToImageFilter< TInputImage, TOutputImage > +{ +public: + + /** Standard class typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + typedef FFT1DRealToComplexConjugateImageFilter Self; + typedef ImageToImageFilter< InputImageType, OutputImageType > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + itkStaticConstMacro( ImageDimension, unsigned int, InputImageType::ImageDimension ); + + itkTypeMacro( FFT1DRealToComplexConjugateImageFilter, ImageToImageFilter ); + + /** Customized object creation methods that support configuration-based + * selection of FFT implementation. + * + * Default implementation is VnlFFT1D. + */ + static Pointer New(); + + /** Get the direction in which the filter is to be applied. */ + itkGetMacro(Direction, unsigned int); + + /** Set the direction in which the filter is to be applied. */ + itkSetClampMacro(Direction, unsigned int, 0, ImageDimension - 1); + +protected: + FFT1DRealToComplexConjugateImageFilter(); + virtual ~FFT1DRealToComplexConjugateImageFilter() {} + + void PrintSelf(std::ostream& os, Indent indent) const ITK_OVERRIDE; + + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + virtual void EnlargeOutputRequestedRegion(DataObject *output) ITK_OVERRIDE; + + virtual void BeforeThreadedGenerateData() ITK_OVERRIDE; + + /** Override to return a splitter that does not split along the direction we + * are performing the transform. */ + virtual const ImageRegionSplitterBase* GetImageRegionSplitter() const ITK_OVERRIDE; + +private: + FFT1DRealToComplexConjugateImageFilter( const Self& ); + void operator=( const Self& ); + + ImageRegionSplitterDirection::Pointer m_ImageRegionSplitter; + + /** Direction in which the filter is to be applied + * this should be in the range [0,ImageDimension-1]. */ + unsigned int m_Direction; + +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#ifndef itkVnlFFT1DRealToComplexConjugateImageFilter_h +#ifndef itkVnlFFT1DRealToComplexConjugateImageFilter_hxx +#ifndef itkFFTW1DRealToComplexConjugateImageFilter_h +#ifndef itkFFTW1DRealToComplexConjugateImageFilter_hxx +#include "itkFFT1DRealToComplexConjugateImageFilter.hxx" +#endif +#endif +#endif +#endif +#endif + +#endif // itkFFT1DRealToComplexConjugateImageFilter_h diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.hxx new file mode 100644 index 0000000000..16c10f5477 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkFFT1DRealToComplexConjugateImageFilter.hxx @@ -0,0 +1,207 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkFFT1DRealToComplexConjugateImageFilter_hxx +#define itkFFT1DRealToComplexConjugateImageFilter_hxx + +#include "itkFFT1DRealToComplexConjugateImageFilter.h" + +#include "itkVnlFFT1DRealToComplexConjugateImageFilter.h" + +#if defined(ITK_USE_FFTWD) || defined(ITK_USE_FFTWF) +#include "itkFFTW1DRealToComplexConjugateImageFilter.h" +#endif + +#include "itkMetaDataObject.h" + +namespace itk +{ + +template < typename TInputImage, typename TOutputImage > +typename FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage >::Pointer +FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::New() +{ + Pointer smartPtr = ::itk::ObjectFactory< Self >::Create(); + +#ifdef ITK_USE_FFTWD + if( smartPtr.IsNull() ) + { + if( typeid( TPixel ) == typeid( double ) ) + { + smartPtr = dynamic_cast< Self* >( + FFTW1DRealToComplexConjugateImageFilter< double, VDimension > + ::New().GetPointer() ); + } + } +#endif +#ifdef ITK_USE_FFTWF + if( smartPtr.IsNull() ) + { + if( typeid( TPixel ) == typeid( float ) ) + { + smartPtr = dynamic_cast( + FFTW1DRealToComplexConjugateImageFilter< float, VDimension > + ::New().GetPointer() ); + } + } +#endif + + if( smartPtr.IsNull() ) + { + smartPtr = VnlFFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > + ::New().GetPointer(); + } + + return smartPtr; +} + + +template< typename TInputImage, typename TOutputImage > +FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::FFT1DRealToComplexConjugateImageFilter(): + m_Direction( 0 ) +{ + this->m_ImageRegionSplitter = ImageRegionSplitterDirection::New(); +} + + +template< typename TInputImage, typename TOutputImage > +const ImageRegionSplitterBase* +FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::GetImageRegionSplitter() const +{ + return this->m_ImageRegionSplitter.GetPointer(); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::BeforeThreadedGenerateData() +{ + this->m_ImageRegionSplitter->SetDirection( this->GetDirection() ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + typename InputImageType::Pointer inputPtr = + const_cast (this->GetInput()); + typename OutputImageType::Pointer outputPtr = this->GetOutput(); + + if ( !inputPtr || !outputPtr ) + { + return; + } + + // we need to compute the input requested region (size and start index) + typedef const typename OutputImageType::SizeType& OutputSizeType; + OutputSizeType outputRequestedRegionSize = + outputPtr->GetRequestedRegion().GetSize(); + typedef const typename OutputImageType::IndexType& OutputIndexType; + OutputIndexType outputRequestedRegionStartIndex = + outputPtr->GetRequestedRegion().GetIndex(); + + //// the regions other than the fft direction are fine + typename InputImageType::SizeType inputRequestedRegionSize = outputRequestedRegionSize; + typename InputImageType::IndexType inputRequestedRegionStartIndex = outputRequestedRegionStartIndex; + + // we but need all of the input in the fft direction + const unsigned int direction = this->m_Direction; + const typename InputImageType::SizeType& inputLargeSize = + inputPtr->GetLargestPossibleRegion().GetSize(); + inputRequestedRegionSize[direction] = inputLargeSize[direction]; + const typename InputImageType::IndexType& inputLargeIndex = + inputPtr->GetLargestPossibleRegion().GetIndex(); + inputRequestedRegionStartIndex[direction] = inputLargeIndex[direction]; + + typename InputImageType::RegionType inputRequestedRegion; + inputRequestedRegion.SetSize( inputRequestedRegionSize ); + inputRequestedRegion.SetIndex( inputRequestedRegionStartIndex ); + + inputPtr->SetRequestedRegion( inputRequestedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DRealToComplexConjugateImageFilter < TInputImage, TOutputImage > +::EnlargeOutputRequestedRegion(DataObject *output) +{ + OutputImageType* outputPtr = dynamic_cast< OutputImageType * >( output ); + + // we need to enlarge the region in the fft direction to the + // largest possible in that direction + typedef const typename OutputImageType::SizeType& ConstOutputSizeType; + ConstOutputSizeType requestedSize = + outputPtr->GetRequestedRegion().GetSize(); + ConstOutputSizeType outputLargeSize = + outputPtr->GetLargestPossibleRegion().GetSize(); + typedef const typename OutputImageType::IndexType& ConstOutputIndexType; + ConstOutputIndexType requestedIndex = + outputPtr->GetRequestedRegion().GetIndex(); + ConstOutputIndexType outputLargeIndex = + outputPtr->GetLargestPossibleRegion().GetIndex(); + + typename OutputImageType::SizeType enlargedSize = requestedSize; + typename OutputImageType::IndexType enlargedIndex = requestedIndex; + enlargedSize[this->m_Direction] = outputLargeSize[this->m_Direction]; + enlargedIndex[this->m_Direction] = outputLargeIndex[this->m_Direction]; + + typename OutputImageType::RegionType enlargedRegion; + enlargedRegion.SetSize( enlargedSize ); + enlargedRegion.SetIndex( enlargedIndex ); + outputPtr->SetRequestedRegion( enlargedRegion ); +} + + +template< typename TInputImage, typename TOutputImage > +void +FFT1DRealToComplexConjugateImageFilter < TInputImage, TOutputImage > +::PrintSelf( std::ostream& os, Indent indent ) const +{ + Superclass::PrintSelf( os, indent ); + + os << indent << "Direction: " << m_Direction << std::endl; +} + +} // end namespace itk + +#endif // itkFFT1DRealToComplexConjugateImageFilter_hxx diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.h new file mode 100644 index 0000000000..5a15e24723 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.h @@ -0,0 +1,143 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkRegionFromReferenceImageFilter_h +#define itkRegionFromReferenceImageFilter_h + +#include "itkExtractImageFilter.h" + +namespace itk +{ + +/** \class RegionFromReferenceImageFilter + * \brief Decrease the image size by cropping the image by an itk::Size at + * both the upper and lower bounds of the largest possible region. + * + * RegionFromReferenceImageFilter changes the image boundary of an image by removing + * pixels outside the target region. The target region is not specified in + * advance, but calculated in BeforeThreadedGenerateData(). + * + * This filter uses ExtractImageFilter to perform the cropping. + * + * \ingroup GeometricTransforms + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage=TInputImage > +class RegionFromReferenceImageFilter: + public ExtractImageFilter +{ +public: + /** Standard class typedefs. */ + typedef RegionFromReferenceImageFilter Self; + typedef ExtractImageFilter Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(RegionFromReferenceImageFilter, ExtractImageFilter); + + /** Typedef to describe the output and input image region types. */ + typedef typename Superclass::OutputImageRegionType OutputImageRegionType; + typedef typename Superclass::InputImageRegionType InputImageRegionType; + + /** Typedef to describe the type of pixel. */ + typedef typename Superclass::OutputImagePixelType OutputImagePixelType; + typedef typename Superclass::InputImagePixelType InputImagePixelType; + + /** Typedef to describe the output and input image index and size types. */ + typedef typename Superclass::OutputImageIndexType OutputImageIndexType; + typedef typename Superclass::InputImageIndexType InputImageIndexType; + typedef typename Superclass::OutputImageSizeType OutputImageSizeType; + typedef typename Superclass::InputImageSizeType InputImageSizeType; + typedef InputImageSizeType SizeType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + Superclass::InputImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + Superclass::OutputImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + Superclass::OutputImageDimension); + + typedef ImageBase< itkGetStaticConstMacro( ImageDimension ) > ReferenceImageType; + + /** Copy the output information from another Image. */ + void SetReferenceImage ( const ReferenceImageType *image ); + + const ReferenceImageType * GetReferenceImage() const; + + /** Set the input image */ + void SetInput1(const TInputImage *input) + { + this->SetInput( input ); + } + + /** Set the reference image */ + void SetInput2(const ReferenceImageType *input) + { + this->SetReferenceImage( input ); + } + + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputConvertibleToOutputCheck, + (Concept::Convertible)); + itkConceptMacro(SameDimensionCheck, + (Concept::SameDimension)); + /** End concept checking */ +#endif + +protected: + RegionFromReferenceImageFilter() + { + this->SetNumberOfRequiredInputs(2); + } + ~RegionFromReferenceImageFilter() {} + + virtual void GenerateOutputInformation() ITK_OVERRIDE; + +private: + RegionFromReferenceImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkRegionFromReferenceImageFilter.hxx" +#endif + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.hxx new file mode 100644 index 0000000000..463ef984eb --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkRegionFromReferenceImageFilter.hxx @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkRegionFromReferenceImageFilter_hxx +#define itkRegionFromReferenceImageFilter_hxx + +#include "itkRegionFromReferenceImageFilter.h" + +namespace itk +{ + +template +void +RegionFromReferenceImageFilter +::GenerateOutputInformation() +{ + if( !this->GetInput() || !this->GetReferenceImage() ) + { + return; + } + + // Superclass::Superclass::GenerateOutputInformation(); + this->SetExtractionRegion( this->GetReferenceImage()->GetLargestPossibleRegion() ); + Superclass::GenerateOutputInformation(); +} + + +template +void +RegionFromReferenceImageFilter +::SetReferenceImage ( const ReferenceImageType *image ) +{ + itkDebugMacro("setting input ReferenceImage to " << image); + if( image != static_cast(this->GetInput( 1 )) ) + { + this->ProcessObject::SetNthInput(1, const_cast< ReferenceImageType *>( image ) ); + this->Modified(); + } +} + + +template +const typename RegionFromReferenceImageFilter::ReferenceImageType * +RegionFromReferenceImageFilter +::GetReferenceImage() const +{ + Self * surrogate = const_cast< Self * >( this ); + + const DataObject * input = surrogate->ProcessObject::GetInput(1); + + const ReferenceImageType * referenceImage = static_cast( input ); + + return referenceImage; +} + +} // end namespace itk + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.h new file mode 100644 index 0000000000..91b2db0240 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DComplexConjugateToRealImageFilter_h +#define itkVnlFFT1DComplexConjugateToRealImageFilter_h + +#include "itkFFT1DComplexConjugateToRealImageFilter.h" +#include + +namespace itk +{ + +/** \class VnlFFT1DComplexConjugateToRealImageFilter + * + * \brief Perform the FFT along one dimension of an image using Vnl as a + * backend. + * + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage=Image< typename NumericTraits< typename TInputImage::PixelType >::ValueType, TInputImage::ImageDimension > > +class VnlFFT1DComplexConjugateToRealImageFilter: + public FFT1DComplexConjugateToRealImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef VnlFFT1DComplexConjugateToRealImageFilter Self; + typedef FFT1DComplexConjugateToRealImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::OutputImageType OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + + /** Run-time type information (and related methods). */ + itkTypeMacro( VnlFFT1DComplexConjugateToRealImageFilter, FFT1DComplexConjugateToRealImageFilter ); + +protected: + virtual void ThreadedGenerateData( const OutputImageRegionType&, ThreadIdType threadID ); // generates output from input + + VnlFFT1DComplexConjugateToRealImageFilter() { } + virtual ~VnlFFT1DComplexConjugateToRealImageFilter() { } + +private: + VnlFFT1DComplexConjugateToRealImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVnlFFT1DComplexConjugateToRealImageFilter.hxx" +#endif + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.hxx new file mode 100644 index 0000000000..6a628451d3 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexConjugateToRealImageFilter.hxx @@ -0,0 +1,114 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DComplexConjugateToRealImageFilter_hxx +#define itkVnlFFT1DComplexConjugateToRealImageFilter_hxx + +#include "itkVnlFFT1DComplexConjugateToRealImageFilter.h" + +#include "itkFFT1DComplexConjugateToRealImageFilter.hxx" +#include "itkImageLinearConstIteratorWithIndex.h" +#include "itkImageLinearIteratorWithIndex.h" +#include "itkIndent.h" +#include "itkMetaDataObject.h" +#include "itkExceptionObject.h" +#include "vnl/algo/vnl_fft_base.h" +#include "vnl/algo/vnl_fft_1d.h" + +namespace itk +{ + +template< typename TInputImage, typename TOutputImage > +void +VnlFFT1DComplexConjugateToRealImageFilter< TInputImage, TOutputImage > +::ThreadedGenerateData( const OutputImageRegionType& outputRegion, ThreadIdType itkNotUsed( threadID ) ) +{ + // get pointers to the input and output + const typename Superclass::InputImageType * inputPtr = this->GetInput(); + typename Superclass::OutputImageType * outputPtr = this->GetOutput(); + + if ( !inputPtr || !outputPtr ) + { + return; + } + + const typename Superclass::InputImageType::SizeType & inputSize = inputPtr->GetRequestedRegion().GetSize(); + + unsigned int vec_size = inputSize[this->m_Direction]; + + typedef itk::ImageLinearConstIteratorWithIndex< InputImageType > InputIteratorType; + typedef itk::ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType; + InputIteratorType inputIt( inputPtr, outputRegion ); + OutputIteratorType outputIt( outputPtr, outputRegion ); + + inputIt.SetDirection(this->m_Direction); + outputIt.SetDirection(this->m_Direction); + + typedef typename TOutputImage::PixelType OutputPixelType; + vnl_vector< vcl_complex< OutputPixelType > > inputBuffer( vec_size ); + typename vnl_vector< vcl_complex< OutputPixelType > >::iterator inputBufferIt = inputBuffer.begin(); + // fft is done in-place + typename vnl_vector< vcl_complex< OutputPixelType > >::iterator outputBufferIt = inputBuffer.begin(); + vnl_fft_1d< OutputPixelType > v1d(vec_size); + + // for every fft line + for( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); + outputIt.NextLine(), inputIt.NextLine() ) + { + // copy the input line into our buffer + inputIt.GoToBeginOfLine(); + inputBufferIt = inputBuffer.begin(); + while( !inputIt.IsAtEndOfLine() ) + { + *inputBufferIt = inputIt.Get(); + ++inputIt; + ++inputBufferIt; + } + + // do the transform + v1d.fwd_transform(inputBuffer); + + // copy the output from the buffer into our line + outputBufferIt = inputBuffer.begin(); + outputIt.GoToBeginOfLine(); + while( !outputIt.IsAtEndOfLine() ) + { + outputIt.Set( (*outputBufferIt).real() / vec_size ); + ++outputIt; + ++outputBufferIt; + } + } +} + +} // end namespace itk + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.h new file mode 100644 index 0000000000..f2a80377ca --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.h @@ -0,0 +1,89 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DComplexToComplexImageFilter_h +#define itkVnlFFT1DComplexToComplexImageFilter_h + +#include "itkFFT1DComplexToComplexImageFilter.h" +#include + +namespace itk +{ + +/** \class VnlFFT1DComplexToComplexImageFilter + * + * \brief Perform the FFT along one dimension of an image using Vnl as a + * backend. + * + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage > +class VnlFFT1DComplexToComplexImageFilter: + public FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef VnlFFT1DComplexToComplexImageFilter Self; + typedef FFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::OutputImageType OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + typedef typename Superclass::TransformDirectionType TransformDirectionType; + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + + /** Run-time type information (and related methods). */ + itkTypeMacro( VnlFFT1DComplexToComplexImageFilter, FFT1DComplexToComplexImageFilter ); + +protected: + VnlFFT1DComplexToComplexImageFilter() {} + virtual ~VnlFFT1DComplexToComplexImageFilter() {} + + virtual void ThreadedGenerateData( const OutputImageRegionType&, ThreadIdType threadID ) ITK_OVERRIDE; + +private: + VnlFFT1DComplexToComplexImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVnlFFT1DComplexToComplexImageFilter.hxx" +#endif + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.hxx new file mode 100644 index 0000000000..31639f9780 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DComplexToComplexImageFilter.hxx @@ -0,0 +1,131 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DComplexToComplexImageFilter_hxx +#define itkVnlFFT1DComplexToComplexImageFilter_hxx + +#include "itkVnlFFT1DComplexToComplexImageFilter.h" + +#include "itkFFT1DComplexToComplexImageFilter.hxx" +#include "itkImageLinearConstIteratorWithIndex.h" +#include "itkImageLinearIteratorWithIndex.h" +#include "itkIndent.h" +#include "itkMetaDataObject.h" +#include "itkExceptionObject.h" +#include "vnl/algo/vnl_fft_base.h" +#include "vnl/algo/vnl_fft_1d.h" + +namespace itk +{ + +template< typename TInputImage, typename TOutputImage > +void +VnlFFT1DComplexToComplexImageFilter< TInputImage, TOutputImage > +::ThreadedGenerateData( const OutputImageRegionType& outputRegion, ThreadIdType itkNotUsed( threadID ) ) +{ + // get pointers to the input and output + const typename Superclass::InputImageType * inputPtr = this->GetInput(); + typename Superclass::OutputImageType * outputPtr = this->GetOutput(); + + if ( !inputPtr || !outputPtr ) + { + return; + } + + const typename Superclass::InputImageType::SizeType & inputSize = inputPtr->GetRequestedRegion().GetSize(); + + const unsigned int direction = this->GetDirection(); + const unsigned int vectorSize = inputSize[direction]; + + typedef itk::ImageLinearConstIteratorWithIndex< InputImageType > InputIteratorType; + typedef itk::ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType; + InputIteratorType inputIt( inputPtr, outputRegion ); + OutputIteratorType outputIt( outputPtr, outputRegion ); + + inputIt.SetDirection( direction ); + outputIt.SetDirection( direction ); + + typedef typename TInputImage::PixelType PixelType; + typedef vnl_vector< PixelType > VNLVectorType; + VNLVectorType inputBuffer( vectorSize ); + typename VNLVectorType::iterator inputBufferIt = inputBuffer.begin(); + // fft is done in-place + typename VNLVectorType::iterator outputBufferIt = inputBuffer.begin(); + vnl_fft_1d< typename NumericTraits< PixelType >::ValueType > v1d(vectorSize); + + // for every fft line + for( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); + outputIt.NextLine(), inputIt.NextLine() ) + { + // copy the input line into our buffer + inputIt.GoToBeginOfLine(); + inputBufferIt = inputBuffer.begin(); + while( !inputIt.IsAtEndOfLine() ) + { + *inputBufferIt = inputIt.Get(); + ++inputIt; + ++inputBufferIt; + } + + // do the transform + if( this->m_TransformDirection == Superclass::DIRECT ) + { + v1d.bwd_transform(inputBuffer); + // copy the output from the buffer into our line + outputBufferIt = inputBuffer.begin(); + outputIt.GoToBeginOfLine(); + while( !outputIt.IsAtEndOfLine() ) + { + outputIt.Set( *outputBufferIt ); + ++outputIt; + ++outputBufferIt; + } + } + else // m_TransformDirection == INVERSE + { + v1d.fwd_transform(inputBuffer); + // copy the output from the buffer into our line + outputBufferIt = inputBuffer.begin(); + outputIt.GoToBeginOfLine(); + while( !outputIt.IsAtEndOfLine() ) + { + outputIt.Set( (*outputBufferIt) / static_cast< PixelType >( vectorSize )); + ++outputIt; + ++outputBufferIt; + } + } + } +} + +} // end namespace itk + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.h b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.h new file mode 100644 index 0000000000..e0e99f70f8 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DRealToComplexConjugateImageFilter_h +#define itkVnlFFT1DRealToComplexConjugateImageFilter_h + +#include "itkFFT1DRealToComplexConjugateImageFilter.h" +#include + +namespace itk +{ + +/** \class VnlFFT1DRealToComplexConjugateImageFilter + * + * \brief Perform the FFT along one dimension of an image using Vnl as a + * backend. + * + * \ingroup Ultrasound + */ +template< typename TInputImage, typename TOutputImage=Image< std::complex< typename TInputImage::PixelType >, TInputImage::ImageDimension > > +class VnlFFT1DRealToComplexConjugateImageFilter : + public FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef VnlFFT1DRealToComplexConjugateImageFilter Self; + typedef FFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::OutputImageType OutputImageType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + + /** Run-time type information (and related methods). */ + itkTypeMacro( VnlFFT1DRealToComplexConjugateImageFilter, FFT1DRealToComplexConjugateImageFilter ); + +protected: + virtual void ThreadedGenerateData( const OutputImageRegionType&, ThreadIdType threadID ) ITK_OVERRIDE; + + VnlFFT1DRealToComplexConjugateImageFilter() { } + ~VnlFFT1DRealToComplexConjugateImageFilter() { } + +private: + VnlFFT1DRealToComplexConjugateImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVnlFFT1DRealToComplexConjugateImageFilter.hxx" +#endif + +#endif diff --git a/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.hxx b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.hxx new file mode 100644 index 0000000000..57d3532734 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/ITKUltrasound/itkVnlFFT1DRealToComplexConjugateImageFilter.hxx @@ -0,0 +1,119 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * 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.txt + * + * 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 itkVnlFFT1DRealToComplexConjugateImageFilter_hxx +#define itkVnlFFT1DRealToComplexConjugateImageFilter_hxx + +#include "itkVnlFFT1DRealToComplexConjugateImageFilter.h" + +#include "itkFFT1DRealToComplexConjugateImageFilter.hxx" +#include "itkImageLinearConstIteratorWithIndex.h" +#include "itkImageLinearIteratorWithIndex.h" +#include "itkIndent.h" +#include "itkMetaDataObject.h" +#include "itkExceptionObject.h" +#include "itkVnlFFTCommon.h" +#include "vnl/algo/vnl_fft_base.h" +#include "vnl/algo/vnl_fft_1d.h" + +namespace itk +{ + +template< typename TInputImage, typename TOutputImage > +void +VnlFFT1DRealToComplexConjugateImageFilter< TInputImage, TOutputImage > +::ThreadedGenerateData( const OutputImageRegionType& outputRegion, ThreadIdType itkNotUsed( threadID ) ) +{ + // get pointers to the input and output + const typename Superclass::InputImageType * inputPtr = this->GetInput(); + typename Superclass::OutputImageType * outputPtr = this->GetOutput(); + + const typename Superclass::InputImageType::SizeType & inputSize = inputPtr->GetRequestedRegion().GetSize(); + + const unsigned int direction = this->GetDirection(); + unsigned int vectorSize = inputSize[direction]; + if( ! VnlFFTCommon::IsDimensionSizeLegal(vectorSize) ) + { + itkExceptionMacro("Illegal Array DIM for FFT"); + } + + + typedef ImageLinearConstIteratorWithIndex< InputImageType > InputIteratorType; + typedef ImageLinearIteratorWithIndex< OutputImageType > OutputIteratorType; + InputIteratorType inputIt( inputPtr, outputRegion ); + OutputIteratorType outputIt( outputPtr, outputRegion ); + + inputIt.SetDirection( direction ); + outputIt.SetDirection( direction ); + + typedef typename TInputImage::PixelType PixelType; + typedef vcl_complex< PixelType > ComplexType; + typedef vnl_vector< ComplexType > ComplexVectorType; + ComplexVectorType inputBuffer( vectorSize ); + typename ComplexVectorType::iterator inputBufferIt = inputBuffer.begin(); + // fft is done in-place + typename ComplexVectorType::iterator outputBufferIt = inputBuffer.begin(); + vnl_fft_1d< PixelType > v1d( vectorSize ); + + // for every fft line + for( inputIt.GoToBegin(), outputIt.GoToBegin(); + !inputIt.IsAtEnd(); + outputIt.NextLine(), inputIt.NextLine() ) + { + // copy the input line into our buffer + inputIt.GoToBeginOfLine(); + inputBufferIt = inputBuffer.begin(); + while( !inputIt.IsAtEndOfLine() ) + { + *inputBufferIt = inputIt.Value(); + ++inputIt; + ++inputBufferIt; + } + + // do the transform + v1d.bwd_transform( inputBuffer ); + + // copy the output from the buffer into our line + outputBufferIt = inputBuffer.begin(); + outputIt.GoToBeginOfLine(); + while( !outputIt.IsAtEndOfLine() ) + { + outputIt.Set( *outputBufferIt ); + ++outputIt; + ++outputBufferIt; + } + } +} + +} // end namespace itk + +#endif diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence05.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence05.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence05.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence06.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence06.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence06.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence07.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence07.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence07.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence08.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence08.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence08.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence09.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence09.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence09.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence10.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence10.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence10.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence11.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence11.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence11.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence12.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence12.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence12.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence13.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence13.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence13.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence14.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence14.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence14.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence15.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence15.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence15.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence16.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence16.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence16.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence17.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence17.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence17.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence18.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence18.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence18.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence19.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence19.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence19.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence20.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence20.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence20.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence21.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence21.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence21.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence22.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence22.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence22.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence23.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence23.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence23.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence24.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence24.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence24.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/Resources/Fluence25.nrrd b/Modules/US/USHardwareDiPhAS/Resources/Fluence25.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/Resources/Fluence25.nrrd differ diff --git a/Modules/US/USHardwareDiPhAS/files.cmake b/Modules/US/USHardwareDiPhAS/files.cmake new file mode 100644 index 0000000000..84d6550ddb --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/files.cmake @@ -0,0 +1,34 @@ +SET(CPP_FILES +mitkUSDiPhASActivator.cpp +mitkUSDiPhASDevice.cpp +mitkUSDiPhASImageSource.cpp +mitkUSDiPhASProbe.cpp +mitkUSDiPhASProbesControls.cpp +mitkUSDiPhASCustomControls.cpp +mitkUSDiPhASBModeImageFilter.hxx +mitkUSDiPhASBModeImageFilter.h +) + +set(RESOURCE_FILES + Fluence05.nrrd + Fluence06.nrrd + Fluence07.nrrd + Fluence08.nrrd + Fluence09.nrrd + Fluence10.nrrd + Fluence11.nrrd + Fluence12.nrrd + Fluence13.nrrd + Fluence14.nrrd + Fluence15.nrrd + Fluence16.nrrd + Fluence17.nrrd + Fluence18.nrrd + Fluence19.nrrd + Fluence20.nrrd + Fluence21.nrrd + Fluence22.nrrd + Fluence23.nrrd + Fluence24.nrrd + Fluence25.nrrd + ) \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.cpp new file mode 100644 index 0000000000..db7d7549ed --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.cpp @@ -0,0 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkUSDiPhASActivator.h" + +mitk::USDiPhASActivator::USDiPhASActivator() +{ + MITK_INFO << "USDiPhASActivator created"; +} + +mitk::USDiPhASActivator::~USDiPhASActivator() +{ +} + +void mitk::USDiPhASActivator::Load(us::ModuleContext* context) +{ + // create a new device + m_Device = mitk::USDiPhASDevice::New("DiPhAS", "Ultrasound System"); + m_Device->Initialize(); +} + +void mitk::USDiPhASActivator::Unload(us::ModuleContext* context) +{ + // set smart pointer to null (device will be unregistered from + // micro service in it's destrcutor) + m_Device = 0; +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.h new file mode 100644 index 0000000000..f8f4fc617a --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASActivator.h @@ -0,0 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __mitkUSDiPhASActivator_h +#define __mitkUSDiPhASActivator_h + +#include "mitkUSDiPhASDevice.h" + +// Microservices +#include +#include + +namespace mitk +{ + class USDiPhASActivator : public us::ModuleActivator { + public: + + USDiPhASActivator(); + virtual ~USDiPhASActivator(); + + /** + * \brief DiPhAS device is created and initialized on module load. + * Service registration is done during the initialization process. + */ + void Load(us::ModuleContext* context); + + /** + * \brief Device pointer is removed on module unload. + * Service deregistration is done in the device destructor. + */ + void Unload(us::ModuleContext* context); + + protected: + USDiPhASDevice::Pointer m_Device; + }; +} // namespace mitk + +US_EXPORT_MODULE_ACTIVATOR(mitk::USDiPhASActivator) + +#endif // __mitkUSDiPhASActivator_h \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.h new file mode 100644 index 0000000000..d71dc6f838 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.h @@ -0,0 +1,147 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= +* +* Copyright Insight Software Consortium +* +* 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.txt +* +* 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 itkPhotoacousticBModeImageFilter_h +#define itkPhotoacousticBModeImageFilter_h + +#include "itkComplexToModulusImageFilter.h" +#include "itkConstantPadImageFilter.h" +#include "itkImageToImageFilter.h" +#include "itkImage.h" + +#include "ITKUltrasound/itkRegionFromReferenceImageFilter.h" +#include "ITKUltrasound/itkAnalyticSignalImageFilter.h" + +namespace itk +{ + + /** + * \class PhotoacousticBModeImageFilter + * + * \brief Create an Photoacoustic B-Mode (Brightness-Mode) image from raw + * "RF" data. The RF's envelope is calculated from the analytic signal and + * logarithmic intensity transform is NOT applied. This is for now the only + * difference to the "normal" BModeImageFilter. + * + * Use SetDirection() to define the axis of propagation. + * + */ + template < typename TInputImage, typename TOutputImage = TInputImage, typename TComplexImage = Image< std::complex< typename TInputImage::PixelType >, TInputImage::ImageDimension > > + class PhotoacousticBModeImageFilter : + public ImageToImageFilter< TInputImage, TOutputImage > + { + public: + /** Standard class typedefs. */ + typedef PhotoacousticBModeImageFilter Self; + typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** The type of input image. */ + typedef TInputImage InputImageType; + + /** Dimension of the input and output images. */ + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + /** Typedef support for the input image scalar value type. */ + typedef typename InputImageType::PixelType InputPixelType; + + /** The type of output image. */ + typedef TOutputImage OutputImageType; + + /** Typedef support for the output image scalar value type. */ + typedef typename OutputImageType::PixelType OutputPixelType; + + /** Typedef of the image used for internal computations that has + * std::complex pixels. */ + typedef TComplexImage ComplexImageType; + + /** Other convenient typedefs */ + typedef typename InputImageType::RegionType InputRegionType; + typedef typename InputImageType::SizeType InputSizeType; + typedef typename InputImageType::IndexType InputIndexType; + + /** Run-time type information (and related methods) */ + itkTypeMacro(PhotoacousticBModeImageFilter, ImageToImageFilter); + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Set the direction in which the envelope is to be calculated. */ + virtual void SetDirection(unsigned int direction) + { + this->m_AnalyticFilter->SetDirection(direction); + this->Modified(); + } + + /** Get the direction in which the envelope is to be calculated. */ + virtual unsigned int GetDirection() const + { + return m_AnalyticFilter->GetDirection(); + } + + protected: + PhotoacousticBModeImageFilter(); + ~PhotoacousticBModeImageFilter() {} + + virtual void PrintSelf(std::ostream& os, Indent indent) const ITK_OVERRIDE; + + virtual void GenerateData() ITK_OVERRIDE; + + // These behave like their analogs in FFT1DRealToComplexConjugateImageFilter. + virtual void GenerateInputRequestedRegion() ITK_OVERRIDE; + virtual void EnlargeOutputRequestedRegion(DataObject *output) ITK_OVERRIDE; + + /** Component filters. */ + typedef AnalyticSignalImageFilter< InputImageType, ComplexImageType > AnalyticType; + typedef ComplexToModulusImageFilter< typename AnalyticType::OutputImageType, OutputImageType > ComplexToModulusType; + typedef ConstantPadImageFilter< InputImageType, InputImageType > PadType; + typedef RegionFromReferenceImageFilter< OutputImageType, OutputImageType > ROIType; + + private: + PhotoacousticBModeImageFilter(const Self&); // purposely not implemented + void operator=(const Self&); // purposely not implemented + + typename AnalyticType::Pointer m_AnalyticFilter; + typename ComplexToModulusType::Pointer m_ComplexToModulusFilter; + typename PadType::Pointer m_PadFilter; + typename ROIType::Pointer m_ROIFilter; + }; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "mitkUSDiPhASBModeImageFilter.hxx" +#endif + +#endif // itkPhotoacousticBModeImageFilter_h diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.hxx b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.hxx new file mode 100644 index 0000000000..d7ccf510b1 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASBModeImageFilter.hxx @@ -0,0 +1,207 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +/*========================================================================= +* +* Copyright Insight Software Consortium +* +* 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.txt +* +* 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 itkPhotoacousticBModeImageFilter_hxx +#define itkPhotoacousticBModeImageFilter_hxx + +#include "mitkUSDiPhASBModeImageFilter.h" + +#include "itkMetaDataDictionary.h" + +#include +#include +#include + +namespace itk +{ + + template < typename TInputImage, typename TOutputImage, typename TComplexImage > + PhotoacousticBModeImageFilter< TInputImage, TOutputImage, TComplexImage > + ::PhotoacousticBModeImageFilter() + { + m_AnalyticFilter = AnalyticType::New(); + m_ComplexToModulusFilter = ComplexToModulusType::New(); + m_PadFilter = PadType::New(); + m_ROIFilter = ROIType::New(); + + m_PadFilter->SetConstant(0.); + m_ComplexToModulusFilter->SetInput(m_AnalyticFilter->GetOutput()); + m_ROIFilter->SetInput(m_ComplexToModulusFilter->GetOutput()); + } + + + template < typename TInputImage, typename TOutputImage, typename TComplexImage > + void + PhotoacousticBModeImageFilter< TInputImage, TOutputImage, TComplexImage > + ::PrintSelf(std::ostream& os, Indent indent) const + { + Superclass::PrintSelf(os, indent); + } + + + template < typename TInputImage, typename TOutputImage, typename TComplexImage > + void + PhotoacousticBModeImageFilter< TInputImage, TOutputImage, TComplexImage > + ::GenerateInputRequestedRegion() + { + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the inputs + InputImageType * inputPtr = const_cast (this->GetInput()); + OutputImageType * outputPtr = this->GetOutput(); + + // we need to compute the input requested region (size and start index) + typedef const typename OutputImageType::SizeType& OutputSizeType; + OutputSizeType outputRequestedRegionSize = + outputPtr->GetRequestedRegion().GetSize(); + typedef const typename OutputImageType::IndexType& OutputIndexType; + OutputIndexType outputRequestedRegionStartIndex = + outputPtr->GetRequestedRegion().GetIndex(); + + //// the regions other than the fft direction are fine + typename InputImageType::SizeType inputRequestedRegionSize = outputRequestedRegionSize; + typename InputImageType::IndexType inputRequestedRegionStartIndex = outputRequestedRegionStartIndex; + + // we but need all of the input in the fft direction + const unsigned int direction = this->GetDirection(); + const typename InputImageType::SizeType& inputLargeSize = + inputPtr->GetLargestPossibleRegion().GetSize(); + inputRequestedRegionSize[direction] = inputLargeSize[direction]; + const typename InputImageType::IndexType& inputLargeIndex = + inputPtr->GetLargestPossibleRegion().GetIndex(); + inputRequestedRegionStartIndex[direction] = inputLargeIndex[direction]; + + typename InputImageType::RegionType inputRequestedRegion; + inputRequestedRegion.SetSize(inputRequestedRegionSize); + inputRequestedRegion.SetIndex(inputRequestedRegionStartIndex); + + inputPtr->SetRequestedRegion(inputRequestedRegion); + } + + + template < typename TInputImage, typename TOutputImage, typename TComplexImage > + void + PhotoacousticBModeImageFilter< TInputImage, TOutputImage, TComplexImage > + ::EnlargeOutputRequestedRegion(DataObject *output) + { + OutputImageType* outputPtr = dynamic_cast< OutputImageType* >(output); + + // we need to enlarge the region in the fft direction to the + // largest possible in that direction + typedef const typename OutputImageType::SizeType& ConstOutputSizeType; + ConstOutputSizeType requestedSize = + outputPtr->GetRequestedRegion().GetSize(); + ConstOutputSizeType outputLargeSize = + outputPtr->GetLargestPossibleRegion().GetSize(); + typedef const typename OutputImageType::IndexType& ConstOutputIndexType; + ConstOutputIndexType requestedIndex = + outputPtr->GetRequestedRegion().GetIndex(); + ConstOutputIndexType outputLargeIndex = + outputPtr->GetLargestPossibleRegion().GetIndex(); + + typename OutputImageType::SizeType enlargedSize = requestedSize; + typename OutputImageType::IndexType enlargedIndex = requestedIndex; + const unsigned int direction = this->GetDirection(); + enlargedSize[direction] = outputLargeSize[direction]; + enlargedIndex[direction] = outputLargeIndex[direction]; + + typename OutputImageType::RegionType enlargedRegion; + enlargedRegion.SetSize(enlargedSize); + enlargedRegion.SetIndex(enlargedIndex); + outputPtr->SetRequestedRegion(enlargedRegion); + } + + + template < typename TInputImage, typename TOutputImage, typename TComplexImage > + void + PhotoacousticBModeImageFilter< TInputImage, TOutputImage, TComplexImage > + ::GenerateData() + { + this->AllocateOutputs(); + + const InputImageType * inputPtr = this->GetInput(); + OutputImageType * outputPtr = this->GetOutput(); + + const unsigned int direction = m_AnalyticFilter->GetDirection(); + typename InputImageType::SizeType size = inputPtr->GetLargestPossibleRegion().GetSize(); + + // Zero padding. FFT direction should be factorable by 2 for all FFT + // implementations to work. + unsigned int n = size[direction]; + while (n % 2 == 0) + { + n /= 2; + } + bool doPadding; + if (n == 1) + { + doPadding = false; + } + else + { + doPadding = true; + } + if (doPadding) + { + n = size[direction]; + unsigned int newSizeDirection = 1; + while (newSizeDirection < n) + { + newSizeDirection *= 2; + } + typename InputImageType::SizeType padSize; + padSize.Fill(0); + padSize[direction] = newSizeDirection - size[direction]; + size[direction] = newSizeDirection; + m_PadFilter->SetPadUpperBound(padSize); + m_PadFilter->SetInput(inputPtr); + m_AnalyticFilter->SetInput(m_PadFilter->GetOutput()); + m_ROIFilter->SetReferenceImage(inputPtr); + m_ROIFilter->SetInput(m_ComplexToModulusFilter->GetOutput()); + m_ROIFilter->GraftOutput(outputPtr); + m_ROIFilter->Update(); + this->GraftOutput(m_ROIFilter->GetOutput()); + } + else // padding is not required + { + m_AnalyticFilter->SetInput(inputPtr); + m_ComplexToModulusFilter->GraftOutput(outputPtr); + m_ComplexToModulusFilter->Update(); + this->GraftOutput(m_ComplexToModulusFilter->GetOutput()); + } + + } + +} // end namespace itk + +#endif \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp new file mode 100644 index 0000000000..c0e0563ab2 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp @@ -0,0 +1,225 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkUSDiPhASCustomControls.h" +#include + +mitk::USDiPhASCustomControls::USDiPhASCustomControls(USDiPhASDevice* device) + : mitk::USDiPhASDeviceCustomControls(device), m_IsActive(false), m_device(device), currentBeamformingAlgorithm((int)Beamforming::PlaneWaveCompound) +{ +} + +mitk::USDiPhASCustomControls::~USDiPhASCustomControls() +{ +} + +void mitk::USDiPhASCustomControls::SetIsActive(bool isActive) +{ + m_IsActive = isActive; +} + +bool mitk::USDiPhASCustomControls::GetIsActive() +{ + return m_IsActive; +} + +void mitk::USDiPhASCustomControls::passGUIOut(std::function callback) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + callback("initializing"); + imageSource->SetGUIOutput(callback); +} + +// OnSet methods + +void mitk::USDiPhASCustomControls::OnSetCompensateEnergy(bool compensate) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->ModifyEnergyCompensation(compensate); +} + +void mitk::USDiPhASCustomControls::OnSetUseBModeFilter(bool isSet) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->ModifyUseBModeFilter(isSet); +} + +void mitk::USDiPhASCustomControls::OnSetRecord(bool record) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->SetRecordingStatus(record); +} + +void mitk::USDiPhASCustomControls::OnSetVerticalSpacing(float mm) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->SetVerticalSpacing(mm); +} + +void mitk::USDiPhASCustomControls::OnSetScatteringCoefficient(float coeff) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->ModifyScatteringCoefficient(coeff); +} +void mitk::USDiPhASCustomControls::OnSetCompensateScattering(bool compensate) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->ModifyCompensateForScattering(compensate); +} + +void mitk::USDiPhASCustomControls::OnSetSavingSettings(SavingSettings settings) +{ + mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + imageSource->SetSavingSettings(settings); +} + +//Transmit +void mitk::USDiPhASCustomControls::OnSetTransmitPhaseLength(double us) +{ + m_device->GetScanMode().transmitPhaseLengthSeconds = us/1000000; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetExcitationFrequency(double MHz) +{ + m_device->SetBursts(round(((120 / MHz) - 2) / 2)); + m_device->UpdateScanmode(); + // b = (c/f - 2) * 1/2, where c is the internal clock, f the wanted frequency, b the burst count +} + +void mitk::USDiPhASCustomControls::OnSetTransmitEvents(int events) +{ + m_device->GetScanMode().transmitEventsCount = events; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetVoltage(int voltage) +{ + m_device->GetScanMode().voltageV = voltage; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetMode(bool interleaved) +{ + m_device->SetInterleaved(interleaved); + m_device->UpdateScanmode(); +} + +//Receive +void mitk::USDiPhASCustomControls::OnSetScanDepth(double mm) +{ + auto& scanMode = m_device->GetScanMode(); + float time = 2 * (0.001 * mm) / scanMode.averageSpeedOfSound; + m_device->GetScanMode().receivePhaseLengthSeconds = time; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetAveragingCount(int count) +{ + m_device->GetScanMode().averagingCount = count; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetTGCMin(int min) +{ + auto& scanMode = m_device->GetScanMode(); + char range = scanMode.tgcdB[7] - min; + for (int tgc = 0; tgc < 7; ++tgc) + scanMode.tgcdB[tgc] = round(tgc*range / 7 + min); + + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetTGCMax(int max) +{ + auto& scanMode = m_device->GetScanMode(); + char range = max - scanMode.tgcdB[0]; + for (int tgc = 1; tgc < 8; ++tgc) + scanMode.tgcdB[tgc] = round(tgc*range / 7 + scanMode.tgcdB[0]); + + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetDataType(DataType type) +{ + auto& scanMode = m_device->GetScanMode(); + auto imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); + switch (type) { + case DataType::Image_uChar : { + scanMode.transferBeamformedData = false; + scanMode.transferImageData = true; + m_device->UpdateScanmode(); + imageSource->ModifyDataType(DataType::Image_uChar); + break; + } + case DataType::Beamformed_Short : { + scanMode.transferBeamformedData = true; + scanMode.transferImageData = false; + m_device->UpdateScanmode(); + imageSource->ModifyDataType(DataType::Beamformed_Short); + break; + } + + default: + MITK_INFO << "Unknown Data Type requested"; + break; + } +} +// 0= image; 1= beamformed + +//Beamforming +void mitk::USDiPhASCustomControls::OnSetPitch(double mm) +{ + m_device->GetScanMode().reconstructedLinePitchMmOrAngleDegree = mm; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetReconstructedSamples(int samples) +{ + m_device->GetScanMode().reconstructionSamplesPerLine = samples; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetReconstructedLines(int lines) +{ + m_device->GetScanMode().reconstructionLines = lines; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetSpeedOfSound(int mps) +{ + m_device->GetScanMode().averageSpeedOfSound = mps; + m_device->UpdateScanmode(); +} + +//Bandpass +void mitk::USDiPhASCustomControls::OnSetBandpassEnabled(bool bandpass) +{ + m_device->GetScanMode().bandpassApply = bandpass; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetLowCut(double MHz) +{ + m_device->GetScanMode().bandpassFrequencyLowHz = MHz*1000*1000; + m_device->UpdateScanmode(); +} + +void mitk::USDiPhASCustomControls::OnSetHighCut(double MHz) +{ + m_device->GetScanMode().bandpassFrequencyHighHz = MHz*1000*1000; + m_device->UpdateScanmode(); +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.h new file mode 100644 index 0000000000..5d3aea0c58 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.h @@ -0,0 +1,106 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASCustomControls_H_HEADER_INCLUDED_ +#define MITKUSDiPhASCustomControls_H_HEADER_INCLUDED_ + +#include "mitkUSDiPhASDeviceCustomControls.h" +#include "mitkUSDevice.h" +#include "mitkUSDiPhASDevice.h" +#include "Framework.IBMT.US.CWrapper.h" + +#include + +namespace mitk { +/** + * \brief Custom controls for mitk::USDiPhASDevice. + */ +class USDiPhASDevice; +class USDiPhASCustomControls : public USDiPhASDeviceCustomControls +{ +public: + mitkClassMacro(USDiPhASCustomControls, USAbstractControlInterface); + mitkNewMacro1Param(Self, mitk::USDiPhASDevice*); + + typedef USDiPhASDeviceCustomControls::DataType DataType; + typedef USDiPhASDeviceCustomControls::SavingSettings SavingSettings; + /** + * Activate or deactivate the custom controls. This is just for handling + * widget visibility in a GUI for example. + */ + virtual void SetIsActive( bool isActive ) override; + + /** + * \return if this custom controls are currently activated + */ + virtual bool GetIsActive( ) override; + + virtual void passGUIOut(std::function callback) override; + + BeamformingParametersPlaneWaveCompound parametersPW; + BeamformingParametersInterleaved_OA_US parametersOSUS; + +protected: + /** + * Class needs an mitk::USDiPhASDevice object for beeing constructed. + * This object's ScanMode will be manipulated by the custom controls methods. + */ + USDiPhASCustomControls(USDiPhASDevice* device); + virtual ~USDiPhASCustomControls( ); + + bool m_IsActive; + USImageVideoSource::Pointer m_ImageSource; + USDiPhASDevice* m_device; + int currentBeamformingAlgorithm; + + /** handlers for value changes + */ + virtual void OnSetCompensateEnergy(bool compensate) override; + virtual void OnSetUseBModeFilter(bool isSet) override; + virtual void OnSetRecord(bool record) override; + virtual void OnSetVerticalSpacing(float mm) override; + virtual void OnSetScatteringCoefficient(float coeff) override; + virtual void OnSetCompensateScattering(bool compensate) override; + virtual void OnSetSavingSettings(SavingSettings settings) override; + + //Transmit + virtual void OnSetTransmitPhaseLength(double us) override; + virtual void OnSetExcitationFrequency(double MHz) override; + virtual void OnSetTransmitEvents(int events) override; + virtual void OnSetVoltage(int voltage) override; + virtual void OnSetMode(bool interleaved) override; + + //Receive + virtual void OnSetScanDepth(double mm) override; + virtual void OnSetAveragingCount(int count) override; + virtual void OnSetTGCMin(int min) override; + virtual void OnSetTGCMax(int max) override; + virtual void OnSetDataType(DataType type) override; + + //Beamforming + virtual void OnSetPitch(double mm) override; + virtual void OnSetReconstructedSamples(int samples) override; + virtual void OnSetReconstructedLines(int lines) override; + virtual void OnSetSpeedOfSound(int mps) override; + + //Bandpass + virtual void OnSetBandpassEnabled(bool bandpass) override; + virtual void OnSetLowCut(double MHz) override; + virtual void OnSetHighCut(double MHz) override; +}; +} // namespace mitk + +#endif // MITKUSDiPhASCustomControls_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp new file mode 100644 index 0000000000..eb99f61ac7 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp @@ -0,0 +1,301 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkUSDiPhASDevice.h" +#include "mitkUSDiPhASCustomControls.h" + +mitk::USDiPhASDevice::USDiPhASDevice(std::string manufacturer, std::string model) + : mitk::USDevice(manufacturer, model), m_ControlsProbes(mitk::USDiPhASProbesControls::New(this)), + m_ImageSource(mitk::USDiPhASImageSource::New(this)), + m_ControlInterfaceCustom(mitk::USDiPhASCustomControls::New(this)), + m_IsRunning(false), + m_BurstHalfwaveClockCount(7), + m_Interleaved(true) +{ + SetNumberOfOutputs(1); + SetNthOutput(0, this->MakeOutput(0)); +} + +mitk::USDiPhASDevice::~USDiPhASDevice() +{ +} + +//Gets + +std::string mitk::USDiPhASDevice::GetDeviceClass() +{ + return "org.mitk.modules.us.USDiPhASDevice"; +} + +mitk::USControlInterfaceProbes::Pointer mitk::USDiPhASDevice::GetControlInterfaceProbes() +{ + return m_ControlsProbes.GetPointer(); +}; + +mitk::USAbstractControlInterface::Pointer mitk::USDiPhASDevice::GetControlInterfaceCustom() +{ + return m_ControlInterfaceCustom.GetPointer(); +} + +mitk::USImageSource::Pointer mitk::USDiPhASDevice::GetUSImageSource() +{ + return m_ImageSource.GetPointer(); +} + +ScanModeNative& mitk::USDiPhASDevice::GetScanMode() +{ + return m_ScanMode; +} + +// Setup and Cleanup + +bool mitk::USDiPhASDevice::OnInitialization() +{ + return true; +} + +//---------------------------------------------------------------------------------------------------------------------------- +/* ugly wrapper stuff - find better solution so it isn't necessary to create a global pointer to USDiPhASDevice... + * passing a lambda function would be nicer - sadly something goes wrong when passing the adress of a lambda function: + * the API produces access violations. Passing the Lambda function itself would be preferable, but that's not possible +*/ + +mitk::USDiPhASDevice* w_device; +mitk::USDiPhASImageSource* w_ISource; + +void WrapperMessageCallback(const char* message) +{ + w_device->MessageCallback(message); +} + +void WrapperImageDataCallback( + short* rfDataChannelData, int channelDatalinesPerDataset, int channelDataSamplesPerChannel, int channelDataTotalDatasets, + short* rfDataArrayBeamformed, int beamformedLines, int beamformedSamples, int beamformedTotalDatasets, + unsigned char* imageData, int imageWidth, int imageHeight, int imagePixelFormat, int imageSetsTotal, double timeStamp) +{ + w_ISource->ImageDataCallback( + rfDataChannelData, channelDatalinesPerDataset, channelDataSamplesPerChannel, channelDataTotalDatasets, + rfDataArrayBeamformed, beamformedLines, beamformedSamples, beamformedTotalDatasets, + imageData, imageWidth, imageHeight, imagePixelFormat, imageSetsTotal, timeStamp); +} + +//---------------------------------------------------------------------------------------------------------------------------- + +bool mitk::USDiPhASDevice::OnConnection() +{ + w_device = this; + w_ISource = m_ImageSource; + // Need those pointers for the forwarders to call member functions; createBeamformer expects non-member function pointers. + createBeamformer((StringMessageCallback)&WrapperMessageCallback, (NewDataCallback)&WrapperImageDataCallback); + + InitializeScanMode(); + initBeamformer(); //start the hardware connection + + m_ImageSource->UpdateImageGeometry(); //make sure the image geometry is initialized! + // pass the new scanmode to the device: + setupScan(this->m_ScanMode); + return true; +} + +bool mitk::USDiPhASDevice::OnDisconnection() +{ + //close the beamformer so hardware is disconnected + closeBeamformer(); + return true; +} + +bool mitk::USDiPhASDevice::OnActivation() +{ + // probe controls are available now + m_ControlsProbes->SetIsActive(true); + + if (m_ControlsProbes->GetProbesCount() < 1) + { + MITK_WARN("USDevice")("USDiPhASDevice") << "No probe found."; + return false; + } + + m_ControlsProbes->SelectProbe(0); + + // toggle the beamformer of the API + if(!m_IsRunning) + m_IsRunning=toggleFreeze(); + return true; +} + +bool mitk::USDiPhASDevice::OnDeactivation() +{ + if(m_IsRunning) + m_IsRunning=toggleFreeze(); + return true; +} + +void mitk::USDiPhASDevice::OnFreeze(bool freeze) +{ + if(m_IsRunning==freeze) + m_IsRunning=toggleFreeze(); // toggleFreeze() returns true if it starts running the beamformer, otherwise false +} + +void mitk::USDiPhASDevice::UpdateScanmode() +{ + OnFreeze(true); + SetInterleaved(m_Interleaved); // update the beamforming parameters... + UpdateTransmitEvents(); + + if (!(dynamic_cast(this->m_ControlInterfaceCustom.GetPointer())->GetSilentUpdate())) + { + setupScan(this->m_ScanMode); + m_ImageSource->UpdateImageGeometry(); + } + + OnFreeze(false); +} + +void mitk::USDiPhASDevice::UpdateTransmitEvents() +{ + int numChannels = m_ScanMode.reconstructionLines; + + // transmitEventsCount defines only the number of acoustic measurements (angles); there will be one event added to the start for OA measurement + m_ScanMode.TransmitEvents = new TransmitEventNative[m_ScanMode.transmitEventsCount]; + + for (int ev = 0; ev < m_ScanMode.transmitEventsCount; ++ev) + { + m_ScanMode.TransmitEvents[ev].transmitEventDelays = new float[numChannels]; + m_ScanMode.TransmitEvents[ev].BurstHalfwaveClockCountPerChannel = new int[numChannels]; + m_ScanMode.TransmitEvents[ev].BurstCountPerChannel = new int[numChannels]; + m_ScanMode.TransmitEvents[ev].BurstUseNegativePolarityPerChannel = new bool[numChannels]; + m_ScanMode.TransmitEvents[ev].ChannelMultiplexerSetups = nullptr; + + for (int i = 0; i < numChannels; ++i) + { + m_ScanMode.TransmitEvents[ev].BurstHalfwaveClockCountPerChannel[i] = m_BurstHalfwaveClockCount; // 120 MHz / (2 * (predefinedBurstHalfwaveClockCount + 1)) --> 7.5 MHz + m_ScanMode.TransmitEvents[ev].BurstCountPerChannel[i] = 1; // Burst with 1 cycle + m_ScanMode.TransmitEvents[ev].BurstUseNegativePolarityPerChannel[i] = true; + m_ScanMode.TransmitEvents[ev].transmitEventDelays[i] = 0; + } + } + + m_ScanMode.transmitSequenceCount = 1; + m_ScanMode.transmitSequences = new SequenceNative[m_ScanMode.transmitSequenceCount]; + m_ScanMode.transmitSequences[0].startEvent = 0; + m_ScanMode.transmitSequences[0].endEvent = m_ScanMode.transmitEventsCount; +} + +void mitk::USDiPhASDevice::InitializeScanMode() +{ + // create a scanmode to be used for measurements: + m_ScanMode.scanModeName = "InterleavedMode"; + + // configure a linear transducer + m_ScanMode.transducerName = "L5-10"; + m_ScanMode.transducerCurvedRadiusMeter = 0; + m_ScanMode.transducerElementCount = 128; + m_ScanMode.transducerFrequencyHz = 7500000; + m_ScanMode.transducerPitchMeter = 0.0003f; + m_ScanMode.transducerType = 1; + + // configure the receive paramters: + m_ScanMode.receivePhaseLengthSeconds = 65e-6f; // 5 cm imaging depth + m_ScanMode.tgcdB = new unsigned char[8]; + for (int tgc = 0; tgc < 8; ++tgc) + m_ScanMode.tgcdB[tgc] = tgc * 2 + 10; + m_ScanMode.accumulation = 1; + m_ScanMode.bandpassApply = false; + m_ScanMode.averagingCount = 1; + + // configure general processing: + m_ScanMode.transferChannelData = true; + + // configure reconstruction processing: + m_ScanMode.averageSpeedOfSound = 1540; + m_ScanMode.computeBeamforming = true; + + // setup beamforming parameters: + SetInterleaved(true); + + m_ScanMode.reconstructedLinePitchMmOrAngleDegree = 0.3f; + m_ScanMode.reconstructionLines = 128; + m_ScanMode.reconstructionSamplesPerLine = 2048; + m_ScanMode.transferBeamformedData = true; + + // configure the transmit sequence(s): + m_ScanMode.transmitEventsCount = 1; + m_ScanMode.transmitPhaseLengthSeconds = 1e-6f; + m_ScanMode.voltageV = 75; + UpdateTransmitEvents(); + + // configure bandpass: + m_ScanMode.bandpassApply = false; + m_ScanMode.bandpassFrequencyLowHz = 1e6f; + m_ScanMode.bandpassFrequencyHighHz = 20e6f; + + // configure image generation: + m_ScanMode.imageWidth = 512; + m_ScanMode.imageHeight = 512; + m_ScanMode.imageMultiplier = 1; + m_ScanMode.imageLeveling = 0; + m_ScanMode.transferImageData = false; + + // Trigger setup: + m_ScanMode.triggerSetup.enabled = true; + m_ScanMode.triggerSetup.constantPulseRepetitionRateHz = 20; + m_ScanMode.triggerSetup.triggerWidthMicroseconds = 15; + m_ScanMode.triggerSetup.delayTrigger2Microseconds = 300; +} + +// callback for the DiPhAS API + +void mitk::USDiPhASDevice::MessageCallback(const char* message) +{ + MITK_INFO << "DiPhAS API: " << message << '\n'; +} + +void mitk::USDiPhASDevice::SetBursts(int bursts) +{ + m_BurstHalfwaveClockCount = bursts; +} + +bool mitk::USDiPhASDevice::IsInterleaved() +{ + return m_Interleaved; +} + +void mitk::USDiPhASDevice::SetInterleaved(bool interleaved) +{ + m_Interleaved = interleaved; + if (interleaved) { + m_ScanMode.scanModeName = "Interleaved Beamforming Mode"; + m_CurrentBeamformingAlgorithm = Beamforming::Interleaved_OA_US; + + paramsInterleaved.SpeedOfSoundMeterPerSecond = m_ScanMode.averageSpeedOfSound; + paramsInterleaved.angleSkipFactor = 1; + paramsInterleaved.OptoacousticDelay = 0.0000003; // 300ns + paramsInterleaved.filter = Filter::None; + + m_ScanMode.beamformingAlgorithmParameters = ¶msInterleaved; + } + else { + m_ScanMode.scanModeName = "Plane Wave Beamforming Mode"; + m_CurrentBeamformingAlgorithm = Beamforming::PlaneWaveCompound; + + paramsPlaneWave.SpeedOfSoundMeterPerSecond = m_ScanMode.averageSpeedOfSound; + paramsPlaneWave.angleSkipFactor = 0; + paramsPlaneWave.usePhaseCoherence = 0; + + m_ScanMode.beamformingAlgorithmParameters = ¶msPlaneWave; + } + m_ScanMode.beamformingAlgorithm = m_CurrentBeamformingAlgorithm; +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.h new file mode 100644 index 0000000000..2732f4f7c8 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.h @@ -0,0 +1,173 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASDevice_H_HEADER_INCLUDED_ +#define MITKUSDiPhASDevice_H_HEADER_INCLUDED_ + +#include +#include "mitkUSDiPhASImageSource.h" +#include "mitkUSDevice.h" +#include "mitkUSDiPhASProbesControls.h" +#include "mitkUSDiPhASImageSource.h" +#include "mitkUSDiPhASCustomControls.h" + +#include "Framework.IBMT.US.CWrapper.h" + +#include +#include +#include +#include +#include + +#include + + +namespace mitk { + /** + * \brief Implementation of mitk::USDevice for DiPhAS API devices. + * Connects to a DiPhAS API device through its COM library interface. + * + * This class handles all API communications and creates interfaces for + * b mode, doppler and probes controls. + * Images given by the device are put into an object of + * mitk::USDiPhASImageSource. + */ + class USDiPhASImageSource; + + class USDiPhASDevice : public USDevice + { + public: + mitkClassMacro(USDiPhASDevice, mitk::USDevice); + mitkNewMacro2Param(Self, std::string, std::string); + + /** + * \brief Returns the class of the device. + */ + virtual std::string GetDeviceClass(); + + virtual USControlInterfaceProbes::Pointer GetControlInterfaceProbes(); + virtual itk::SmartPointer GetControlInterfaceCustom(); + + /** + * \brief Is called during the initialization process. + * There is nothing done on the initialization of a mik::USDiPhASDevive object. + * + * \return always true + */ + virtual bool OnInitialization(); + + /** + * \brief Is called during the connection process. + * Connect to the DiPhAS API. + * + * \return true if successfull, false if no device is connected to the pc + * \throws mitk::Exception if something goes wrong at the API calls + */ + virtual bool OnConnection(); + + /** + * \brief Is called during the disconnection process. + * Deactivate and remove all DiPhAS API controls. A disconnect from the + * DiPhAS API is not possible for which reason the hardware stays in connected + * state even after calling this method. + * + * \return always true + * \throws mitk::Exception if something goes wrong at the API calls + */ + virtual bool OnDisconnection(); + + /** + * \brief Is called during the activation process. + * After this method is finished, the device is generating images in b mode. + * Changing scanning mode is possible afterwards by using the appropriate + * control interfaces. + * + * \return always true + * \throws mitk::Exception if something goes wrong at the API calls + */ + virtual bool OnActivation(); + + /** + * \brief Is called during the deactivation process. + * After a call to this method the device is connected, but not producing images anymore. + * + * \return always true + * \throws mitk::Exception if something goes wrong at the API calls + */ + virtual bool OnDeactivation(); + + /** + * \brief Changes scan state of the device if freeze is toggeled in mitk::USDevice. + */ + virtual void OnFreeze(bool freeze); + + /** @return Returns the current image source of this device. */ + USImageSource::Pointer GetUSImageSource( ); + + /** @return Returns the currently used scanmode of this device*/ + ScanModeNative& GetScanMode(); + + /** Updates the Scanmode and feeds it to the hardware + */ + void UpdateScanmode(); + /** This method forwards messages from the API to the user*/ + void MessageCallback(const char* message); + void SetBursts(int bursts); + void SetInterleaved(bool interleaved); + bool IsInterleaved(); + + BeamformingParametersInterleaved_OA_US paramsInterleaved; + BeamformingParametersPlaneWaveCompound paramsPlaneWave; + + protected: + /** + * Constructs a mitk::USDiPhASDevice object by given manufacturer + * and model string. These strings are just for labeling the device + * in the micro service. + * + * Control interfaces and image source are available directly after + * construction. Registration at the micro service happens not before + * initialization method was called. + */ + USDiPhASDevice(std::string manufacturer, std::string model); + virtual ~USDiPhASDevice(); + + /** + * The DiPhAS API expects callback functions to pass + * both status messages and the processed images to the user. + * The message callback is here, the data itself is given directly to the image source. + */ + + /** + * This method sets up the scanmode at the begining + */ + void InitializeScanMode(); + void UpdateTransmitEvents(); + + USDiPhASProbesControls::Pointer m_ControlsProbes; + itk::SmartPointer m_ControlInterfaceCustom; + + mitk::USDiPhASImageSource::Pointer m_ImageSource; + + bool m_IsRunning; + ScanModeNative m_ScanMode; + int m_BurstHalfwaveClockCount; + Beamforming m_CurrentBeamformingAlgorithm; + bool m_Interleaved; + }; +} // namespace mitk + +#endif // MITKUSDiPhASDevice_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp new file mode 100644 index 0000000000..b4294741dd --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp @@ -0,0 +1,839 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std dependencies +#include +#include +#include + +// mitk dependencies +#include "mitkUSDiPhASDevice.h" +#include "mitkUSDiPhASImageSource.h" +#include +#include "mitkUSDiPhASBModeImageFilter.h" +#include "ITKUltrasound/itkBModeImageFilter.h" +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" + +// itk dependencies +#include "itkImage.h" +#include "itkResampleImageFilter.h" +#include "itkCastImageFilter.h" +#include "itkCropImageFilter.h" +#include "itkRescaleIntensityImageFilter.h" +#include "itkIntensityWindowingImageFilter.h" +#include +#include "itkMultiplyImageFilter.h" + + +mitk::USDiPhASImageSource::USDiPhASImageSource(mitk::USDiPhASDevice* device) + : m_Device(device), + m_StartTime(((float)std::clock()) / CLOCKS_PER_SEC), + m_UseGUIOutPut(false), + m_DataType(DataType::Image_uChar), + m_GUIOutput(nullptr), + m_UseBModeFilter(false), + m_CurrentlyRecording(false), + m_DataTypeModified(true), + m_DataTypeNext(DataType::Image_uChar), + m_CurrentImageTimestamp(0), + m_PyroConnected(false), + m_ImageTimestampBuffer(), + m_VerticalSpacing(0), + m_UseBModeFilterModified(false), + m_UseBModeFilterNext(false), + m_ScatteringCoefficientModified(false), + m_CompensateForScatteringModified(false), + m_VerticalSpacingModified(false), + m_ScatteringCoefficient(15), + m_CompensateForScattering(false), + m_CompensateEnergy(false), + m_CompensateEnergyNext(false), + m_CompensateEnergyModified(false) +{ + m_BufferSize = 100; + m_ImageTimestampBuffer.insert(m_ImageTimestampBuffer.begin(), m_BufferSize, 0); + m_LastWrittenImage = m_BufferSize - 1; + m_ImageBuffer.insert(m_ImageBuffer.begin(), m_BufferSize, nullptr); + + us::ModuleResource resourceFile; + std::string name; + m_FluenceCompOriginal.insert(m_FluenceCompOriginal.begin(), 5, Image::New()); + for (int i = 5; i <= 25; ++i) + { + name = "c:\\HomogeneousScatteringAssumptions\\Scattering" + std::to_string(i) + ".nrrd"; + + m_FluenceCompOriginal.push_back(mitk::IOUtil::LoadImage(name)); + } + + m_FluenceCompResized.insert(m_FluenceCompResized.begin(), 26, Image::New()); + m_FluenceCompResizedItk.insert(m_FluenceCompResizedItk.begin(), 26, itk::Image::New()); +} + +mitk::USDiPhASImageSource::~USDiPhASImageSource() +{ + // close the pyro + MITK_INFO("Pyro Debug") << "StopDataAcquisition: " << m_Pyro->StopDataAcquisition(); + MITK_INFO("Pyro Debug") << "CloseConnection: " << m_Pyro->CloseConnection(); + m_PyroConnected = false; + m_Pyro = nullptr; +} + +void mitk::USDiPhASImageSource::GetNextRawImage( mitk::Image::Pointer& image) +{ + // modify all settings that have been changed here, so we don't get multithreading issues + if (m_DataTypeModified) + { + SetDataType(m_DataTypeNext); + m_DataTypeModified = false; + UpdateImageGeometry(); + } + if (m_UseBModeFilterModified) + { + SetUseBModeFilter(m_UseBModeFilterNext); + m_UseBModeFilterModified = false; + } + if (m_VerticalSpacingModified) + { + m_VerticalSpacing = m_VerticalSpacingNext; + m_VerticalSpacingModified = false; + } + if (m_ScatteringCoefficientModified) + { + m_ScatteringCoefficient = m_ScatteringCoefficientNext; + m_ScatteringCoefficientModified = false; + } + if (m_CompensateForScatteringModified) + { + m_CompensateForScattering = m_CompensateForScatteringNext; + m_CompensateForScatteringModified = false; + } + if (m_CompensateEnergyModified) + { + m_CompensateEnergy = m_CompensateEnergyNext; + m_CompensateEnergyModified = false; + } + + // make sure image is nullptr + image = nullptr; + float ImageEnergyValue = 0; + + for (int i = 100; i > 90 && ImageEnergyValue <= 0; --i) + { + if (m_ImageTimestampBuffer[(m_LastWrittenImage + i) % 100] != 0) + { + ImageEnergyValue = m_Pyro->GetClosestEnergyInmJ(m_ImageTimestampBuffer[(m_LastWrittenImage + i) % 100]); + if (ImageEnergyValue > 0) { + image = &(*m_ImageBuffer[(m_LastWrittenImage + i) % 100]); + } + } + } + // if we did not get any usable Energy value, compensate using this default value + if (image == nullptr) + { + image = &(*m_ImageBuffer[m_LastWrittenImage]); + ImageEnergyValue = 40; + if (image == nullptr) + return; + } + + // do image processing before displaying it + if (image.IsNotNull()) + { + // now apply filters to the image, if the options have been selected. + if ((m_CompensateForScattering || m_UseBModeFilter) && m_DataType == DataType::Beamformed_Short) + { + if (m_Device->GetScanMode().beamformingAlgorithm == Beamforming::PlaneWaveCompound) + { + if(m_UseBModeFilter) + image = ApplyBmodeFilter(image, true, m_VerticalSpacing); + } // this is for ultrasound only mode + + else + { + Image::Pointer imagePA = Image::New(); + unsigned int dim[] = { image->GetDimension(0),image->GetDimension(1),1}; + imagePA->Initialize(image->GetPixelType(), 3, dim); + imagePA->SetGeometry(image->GetGeometry()); + + mitk::ImageReadAccessor inputReadAccessorCopy(image, image->GetSliceData(0)); + imagePA->SetSlice(inputReadAccessorCopy.GetData(), 0); + // first, seperate the PA image from the USImages + + // then, we compensate the PAImage using our ImageEnergyValue + if(m_CompensateEnergy) + imagePA = MultiplyImage(imagePA, 1/ImageEnergyValue); // TODO: add the correct prefactor here!!!! + + // now we apply the BModeFilter + if (m_UseBModeFilter) + { + image = ApplyBmodeFilter(image, true, m_VerticalSpacing); // the US Images get a logarithmic filter + imagePA = ApplyBmodeFilter(imagePA, false, m_VerticalSpacing); + } + + // and finally the scattering corrections + if (m_CompensateForScattering) + { + auto curResizeImage = m_FluenceCompResized.at(m_ScatteringCoefficient); // just for convenience + + // update the fluence reference images! + bool doResampling = image->GetDimension(0) != curResizeImage->GetDimension(0) || image->GetDimension(1) != curResizeImage->GetDimension(1) + || image->GetGeometry()->GetSpacing()[0] != curResizeImage->GetGeometry()->GetSpacing()[0] || image->GetGeometry()->GetSpacing()[1] != curResizeImage->GetGeometry()->GetSpacing()[1]; + if (doResampling) + { + curResizeImage = ApplyResampling(m_FluenceCompOriginal.at(m_ScatteringCoefficient), image->GetGeometry()->GetSpacing(), image->GetDimensions()); + + double* rawOutputData = new double[image->GetDimension(0)*image->GetDimension(1)]; + double* rawScatteringData = (double*)curResizeImage->GetData(); + int sizeRawScatteringData = curResizeImage->GetDimension(0) * curResizeImage->GetDimension(1); + int imageSize = image->GetDimension(0)*image->GetDimension(1); + + //everything above 1.5mm is still inside the transducer; therefore the fluence compensation image has to be positioned a little lower + float upperCutoffmm = 1.5; + int lowerBound = std::round(upperCutoffmm / image->GetGeometry()->GetSpacing()[1])*image->GetDimension(0); + int upperBound = lowerBound + sizeRawScatteringData; + + for (int i = 0; i < lowerBound && i < imageSize; ++i) + { + rawOutputData[i] = 0; // everything than cannot be compensated shall be treated as garbage, here the upper 0.15mm + } + for (int i = lowerBound; i < upperBound && i < imageSize; ++i) + { + rawOutputData[i] = 1 / rawScatteringData[i-lowerBound]; + } + for (int i = upperBound; i < imageSize; ++i) + { + rawOutputData[i] = 0; // everything than cannot be compensated shall be treated as garbage + } + + + unsigned int dim[] = { image->GetDimension(0), image->GetDimension(1), 1 }; + curResizeImage->Initialize(mitk::MakeScalarPixelType(), 3, dim); + curResizeImage->SetGeometry(image->GetGeometry()); + curResizeImage->SetSlice(rawOutputData,0); + + delete[] rawOutputData; + + mitk::CastToItkImage(curResizeImage, m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); + m_FluenceCompResized.at(m_ScatteringCoefficient) = mitk::GrabItkImageMemory(m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); + + MITK_INFO << "Resized a fluence image."; + } + // actually apply the scattering compensation + imagePA = ApplyScatteringCompensation(imagePA, m_ScatteringCoefficient); + } + mitk::ImageReadAccessor inputReadAccessor(imagePA, imagePA->GetSliceData(0)); + image->SetSlice(inputReadAccessor.GetData(), 0); + } + } + } +} + +mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyBmodeFilter(mitk::Image::Pointer inputImage, bool useLogFilter, float resampleSpacing) +{ + // we use this seperate ApplyBmodeFilter Method for processing of two-dimensional images + + // the image needs to be of floating point type for the envelope filter to work; the casting is done automatically by the CastToItkImage + typedef itk::Image< float, 3 > itkFloatImageType; + + typedef itk::BModeImageFilter < itkFloatImageType, itkFloatImageType > BModeFilterType; + BModeFilterType::Pointer bModeFilter = BModeFilterType::New(); // LogFilter + + typedef itk::PhotoacousticBModeImageFilter < itkFloatImageType, itkFloatImageType > PhotoacousticBModeImageFilter; + PhotoacousticBModeImageFilter::Pointer photoacousticBModeFilter = PhotoacousticBModeImageFilter::New(); // No LogFilter + + typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter; + ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New(); + + itkFloatImageType::Pointer itkImage; + + mitk::CastToItkImage(inputImage, itkImage); + + itkFloatImageType::Pointer bmode; + + if (useLogFilter) + { + bModeFilter->SetInput(itkImage); + bModeFilter->SetDirection(1); + bmode = bModeFilter->GetOutput(); + } + else + { + photoacousticBModeFilter->SetInput(itkImage); + photoacousticBModeFilter->SetDirection(1); + bmode = photoacousticBModeFilter->GetOutput(); + } + + // resampleSpacing == 0 means: do no resampling + if (resampleSpacing == 0) + { + return mitk::GrabItkImageMemory(bmode); + } + + itkFloatImageType::SpacingType outputSpacing; + itkFloatImageType::SizeType inputSize = itkImage->GetLargestPossibleRegion().GetSize(); + itkFloatImageType::SizeType outputSize = inputSize; + outputSize[0] = inputSize[0]; // don't do any resampling in x-direction! + + outputSpacing[0] = itkImage->GetSpacing()[0] * (static_cast(inputSize[0]) / static_cast(outputSize[0])); + outputSpacing[1] = resampleSpacing; + outputSpacing[2] = 0.6; + + outputSize[1] = inputSize[1] * itkImage->GetSpacing()[1] / outputSpacing[1]; + + typedef itk::IdentityTransform TransformType; + resampleImageFilter->SetInput(bmode); + resampleImageFilter->SetSize(outputSize); + resampleImageFilter->SetOutputSpacing(outputSpacing); + resampleImageFilter->SetTransform(TransformType::New()); + + resampleImageFilter->UpdateLargestPossibleRegion(); + return mitk::GrabItkImageMemory(resampleImageFilter->GetOutput()); +} + +mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyScatteringCompensation(mitk::Image::Pointer inputImage, int scattering) +{ + typedef itk::Image< float, 3 > itkFloatImageType; + typedef itk::MultiplyImageFilter MultiplyImageFilterType; + + itkFloatImageType::Pointer itkImage; + mitk::CastToItkImage(inputImage, itkImage); + + MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New(); + multiplyFilter->SetInput1(itkImage); + multiplyFilter->SetInput2(m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); + + return mitk::GrabItkImageMemory(multiplyFilter->GetOutput()); +} + +mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyResampling(mitk::Image::Pointer inputImage, mitk::Vector3D outputSpacing, unsigned int outputSize[3]) +{ + typedef itk::Image< double, 3 > itkFloatImageType; + + typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter; + ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New(); + + itkFloatImageType::Pointer itkImage; + + mitk::CastToItkImage(inputImage, itkImage); + + itkFloatImageType::SpacingType outputSpacingItk; + itkFloatImageType::SizeType inputSizeItk = itkImage->GetLargestPossibleRegion().GetSize(); + itkFloatImageType::SizeType outputSizeItk = inputSizeItk; + itkFloatImageType::SpacingType inputSpacing = itkImage->GetSpacing(); + + outputSizeItk[0] = outputSize[0]; + outputSizeItk[1] = 10*(inputSpacing[1] * inputSizeItk[1]) / (outputSpacing[1]); + + outputSizeItk[2] = 1; + + outputSpacingItk[0] = 0.996 * inputSpacing[0] * (static_cast(inputSizeItk[0]) / static_cast(outputSizeItk[0])); // TODO: find out why the spacing is not correct, so we need that factor; ?!?! + outputSpacingItk[1] = inputSpacing[1] * (static_cast(inputSizeItk[1]) / static_cast(outputSizeItk[1])); + outputSpacingItk[2] = outputSpacing[2]; + + typedef itk::IdentityTransform TransformType; + resampleImageFilter->SetInput(itkImage); + resampleImageFilter->SetSize(outputSizeItk); + resampleImageFilter->SetOutputSpacing(outputSpacingItk); + resampleImageFilter->SetTransform(TransformType::New()); + + resampleImageFilter->UpdateLargestPossibleRegion(); + return mitk::GrabItkImageMemory(resampleImageFilter->GetOutput()); +} + +mitk::Image::Pointer mitk::USDiPhASImageSource::MultiplyImage(mitk::Image::Pointer inputImage, double value) +{ + typedef itk::Image< float, 3 > itkFloatImageType; + typedef itk::MultiplyImageFilter MultiplyImageFilterType; + + itkFloatImageType::Pointer itkImage; + mitk::CastToItkImage(inputImage, itkImage); + + MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New(); + multiplyFilter->SetInput1(itkImage); + multiplyFilter->SetConstant(value); + + return mitk::GrabItkImageMemory(multiplyFilter->GetOutput()); +} + +void mitk::USDiPhASImageSource::ImageDataCallback( + short* rfDataChannelData, + int& channelDataChannelsPerDataset, + int& channelDataSamplesPerChannel, + int& channelDataTotalDatasets, + + short* rfDataArrayBeamformed, + int& beamformedLines, + int& beamformedSamples, + int& beamformedTotalDatasets, + + unsigned char* imageData, + int& imageWidth, + int& imageHeight, + int& imageBytesPerPixel, + int& imageSetsTotal, + + double& timeStamp) +{ + if (m_DataTypeModified) + return; + + if (!m_PyroConnected) + { + m_Pyro = mitk::OphirPyro::New(); + MITK_INFO << "[Pyro Debug] OpenConnection: " << m_Pyro->OpenConnection(); + MITK_INFO << "[Pyro Debug] StartDataAcquisition: " << m_Pyro->StartDataAcquisition(); + m_PyroConnected = true; + } + + bool writeImage = ((m_DataType == DataType::Image_uChar) && (imageData != nullptr)) || ((m_DataType == DataType::Beamformed_Short) && (rfDataArrayBeamformed != nullptr)); + if (writeImage) + { + //get the timestamp we might save later on + m_CurrentImageTimestamp = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + + // create a new image and initialize it + mitk::Image::Pointer image = mitk::Image::New(); + + switch (m_DataType) + { + case DataType::Image_uChar: { + m_ImageDimensions[0] = imageWidth; + m_ImageDimensions[1] = imageHeight; + m_ImageDimensions[2] = imageSetsTotal; + image->Initialize(mitk::MakeScalarPixelType(), 3, m_ImageDimensions); + break; + } + case DataType::Beamformed_Short: { + m_ImageDimensions[0] = beamformedLines; + m_ImageDimensions[1] = beamformedSamples; + m_ImageDimensions[2] = beamformedTotalDatasets; + image->Initialize(mitk::MakeScalarPixelType(), 3, m_ImageDimensions); + break; + } + } + image->GetGeometry()->SetSpacing(m_ImageSpacing); + image->GetGeometry()->Modified(); + + // write the given buffer into the image + switch (m_DataType) + { + case DataType::Image_uChar: { + for (unsigned char i = 0; i < imageSetsTotal; i++) { + image->SetSlice(&imageData[i*imageHeight*imageWidth], i); + } + break; + } + + case DataType::Beamformed_Short: { + short* flipme = new short[beamformedLines*beamformedSamples*beamformedTotalDatasets]; + int pixelsPerImage = beamformedLines*beamformedSamples; + + for (unsigned char currentSet = 0; currentSet < beamformedTotalDatasets; currentSet++) + { + for (unsigned short sample = 0; sample < beamformedSamples; sample++) + { + for (unsigned short line = 0; line < beamformedLines; line++) + { + flipme[sample*beamformedLines + line + pixelsPerImage*currentSet] + = rfDataArrayBeamformed[line*beamformedSamples + sample + pixelsPerImage*currentSet]; + } + } // the beamformed pa image is flipped by 90 degrees; we need to flip it manually + } + + for (unsigned char i = 0; i < beamformedTotalDatasets; i++) { + image->SetSlice(&flipme[i*beamformedLines*beamformedSamples], i); + // set every image to a different slice + } + + delete[] flipme; + break; + } + } + + if (m_SavingSettings.saveRaw && m_CurrentlyRecording && rfDataChannelData != nullptr) + { + unsigned int dim[3]; + dim[0] = channelDataChannelsPerDataset; + dim[1] = channelDataSamplesPerChannel; + dim[2] = 1; + short offset = m_Device->GetScanMode().accumulation * 2048; + + short* noOffset = new short[channelDataChannelsPerDataset*channelDataSamplesPerChannel*channelDataTotalDatasets]; + for (unsigned char set = 0; set < channelDataTotalDatasets; ++set) + { + for (unsigned short sam = 0; sam < channelDataSamplesPerChannel; ++sam) + { + for (unsigned short chan = 0; chan < channelDataChannelsPerDataset; ++chan) + { + noOffset[set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] = + rfDataChannelData[set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] - offset; // this offset in the raw Images is given by the API... + } + } + } + + // save the raw images when recording + for (unsigned char i = 0; i < channelDataTotalDatasets; ++i) + { + mitk::Image::Pointer rawImage = mitk::Image::New(); + rawImage->Initialize(mitk::MakeScalarPixelType(), 3, dim); + + rawImage->SetSlice(&noOffset[i*channelDataChannelsPerDataset*channelDataSamplesPerChannel]); + + float& recordTime = m_Device->GetScanMode().receivePhaseLengthSeconds; + int& speedOfSound = m_Device->GetScanMode().averageSpeedOfSound; + + mitk::Vector3D rawSpacing; + rawSpacing[0] = m_Device->GetScanMode().reconstructedLinePitchMmOrAngleDegree; + rawSpacing[1] = recordTime * speedOfSound / 2 * 1000 / channelDataSamplesPerChannel; + rawSpacing[2] = 0.6; + + rawImage->GetGeometry()->SetSpacing(rawSpacing); + rawImage->GetGeometry()->Modified(); + + m_RawRecordedImages.push_back(rawImage); + } + + delete[] noOffset; + } + + itk::Index<3> pixel = { { (image->GetDimension(0) / 2), 22.0/532.0*m_Device->GetScanMode().reconstructionSamplesPerLine, 0 } }; //22/532*2048 = 84 + if (!m_Pyro->IsSyncDelaySet() &&(image->GetPixelValueByIndex(pixel) < -30)) // #MagicNumber + { + MITK_INFO << "Setting SyncDelay now"; + m_Pyro->SetSyncDelay(m_CurrentImageTimestamp); + } + + m_ImageTimestampBuffer[(m_LastWrittenImage + 1) % m_BufferSize] = m_CurrentImageTimestamp; + m_ImageBuffer[(m_LastWrittenImage + 1) % m_BufferSize] = image; + m_LastWrittenImage = (m_LastWrittenImage + 1) % m_BufferSize; + + // if the user decides to start recording, we feed the vector the generated images + if (m_CurrentlyRecording) { + for (unsigned char index = 0; index < image->GetDimension(2); ++index) + { + if (image->IsSliceSet(index)) + { + m_RecordedImages.push_back(Image::New()); + unsigned int dim[] = { image ->GetDimension(0), image->GetDimension(1), 1}; + m_RecordedImages.back()->Initialize(image->GetPixelType(), 3, dim); + m_RecordedImages.back()->SetGeometry(image->GetGeometry()); + + mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(index)); + m_RecordedImages.back()->SetSlice(inputReadAccessor.GetData(),0); + } + } + m_ImageTimestampRecord.push_back(m_CurrentImageTimestamp); + // save timestamps for each laser image! + } + } +} + +void mitk::USDiPhASImageSource::UpdateImageGeometry() +{ + MITK_INFO << "Retreaving Image Geometry Information for Spacing..."; + float& recordTime = m_Device->GetScanMode().receivePhaseLengthSeconds; + int& speedOfSound = m_Device->GetScanMode().averageSpeedOfSound; + float& pitch = m_Device->GetScanMode().reconstructedLinePitchMmOrAngleDegree; + int& reconstructionLines = m_Device->GetScanMode().reconstructionLines; + + switch (m_DataType) + { + case DataType::Image_uChar : { + int& imageWidth = m_Device->GetScanMode().imageWidth; + int& imageHeight = m_Device->GetScanMode().imageHeight; + m_ImageSpacing[0] = pitch * reconstructionLines / imageWidth; + m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; + break; + } + case DataType::Beamformed_Short : { + int& imageWidth = reconstructionLines; + int& imageHeight = m_Device->GetScanMode().reconstructionSamplesPerLine; + m_ImageSpacing[0] = pitch; + m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; + break; + } + } + m_ImageSpacing[2] = 0.6; + + MITK_INFO << "Retreaving Image Geometry Information for Spacing " << m_ImageSpacing[0] << " ... " << m_ImageSpacing[1] << " ... " << m_ImageSpacing[2] << " ...[DONE]"; +} + +void mitk::USDiPhASImageSource::ModifyDataType(DataType dataT) +{ + m_DataTypeModified = true; + m_DataTypeNext = dataT; +} + +void mitk::USDiPhASImageSource::ModifyUseBModeFilter(bool isSet) +{ + m_UseBModeFilterModified = true; + m_UseBModeFilterNext = isSet; +} + +void mitk::USDiPhASImageSource::ModifyScatteringCoefficient(int coeff) +{ + m_ScatteringCoefficientNext = coeff; + m_ScatteringCoefficientModified = true; +} + +void mitk::USDiPhASImageSource::ModifyCompensateForScattering(bool useIt) +{ + m_CompensateForScatteringNext = useIt; + m_CompensateForScatteringModified = true; +} + +void mitk::USDiPhASImageSource::ModifyEnergyCompensation(bool compensate) +{ + m_CompensateEnergyNext = compensate; + m_CompensateEnergyModified = true; +} + +void mitk::USDiPhASImageSource::SetDataType(DataType dataT) +{ + if (dataT != m_DataType) + { + m_DataType = dataT; + MITK_INFO << "Setting new DataType..." << dataT; + switch (m_DataType) + { + case DataType::Image_uChar : + MITK_INFO << "height: " << m_Device->GetScanMode().imageHeight << " width: " << m_Device->GetScanMode().imageWidth; + break; + case DataType::Beamformed_Short : + MITK_INFO << "samples: " << m_Device->GetScanMode().reconstructionSamplesPerLine << " lines: " << m_Device->GetScanMode().reconstructionLines; + break; + } + } +} + +void mitk::USDiPhASImageSource::SetGUIOutput(std::function out) +{ + USDiPhASImageSource::m_GUIOutput = out; + m_StartTime = ((float)std::clock()) / CLOCKS_PER_SEC; //wait till the callback is available again + m_UseGUIOutPut = false; +} + +void mitk::USDiPhASImageSource::SetUseBModeFilter(bool isSet) +{ + m_UseBModeFilter = isSet; +} + +void mitk::USDiPhASImageSource::SetVerticalSpacing(float mm) +{ + m_VerticalSpacingNext = mm; + m_VerticalSpacingModified = true; +} + +void mitk::USDiPhASImageSource::SetSavingSettings(SavingSettings settings) +{ + m_SavingSettings = settings; +} + +// this is just a little function to set the filenames below right +inline void replaceAll(std::string& str, const std::string& from, const std::string& to) { + if (from.empty()) + return; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } +} + +void mitk::USDiPhASImageSource::SetRecordingStatus(bool record) +{ + // start the recording process + if (record) + { + m_RecordedImages.clear(); + m_RawRecordedImages.clear(); // we make sure there are no leftovers + m_ImageTimestampRecord.clear(); // also for the timestamps + m_PixelValues.clear(); // aaaand for the pixel values + + if (m_SavingSettings.saveRaw) + { + m_Device->GetScanMode().transferChannelData = true; + m_Device->UpdateScanmode(); + // set the raw Data to be transfered + } + + // tell the callback to start recording images + m_CurrentlyRecording = true; + } + // save images, end recording, and clean up + else + { + m_CurrentlyRecording = false; + + m_Device->GetScanMode().transferChannelData = false; // make sure raw Channel Data is not transferred anymore! + m_Device->UpdateScanmode(); + + // get the time and date, put them into a nice string and create a folder for the images + time_t time = std::time(nullptr); + time_t* timeptr = &time; + std::string currentDate = std::ctime(timeptr); + replaceAll(currentDate, ":", "-"); + currentDate.pop_back(); + std::string MakeFolder = "mkdir \"c:/DiPhASImageData/" + currentDate + "\""; + system(MakeFolder.c_str()); + + // initialize file paths and the images + Image::Pointer PAImage = Image::New(); + Image::Pointer USImage = Image::New(); + std::string pathPA = "c:\\DiPhASImageData\\" + currentDate + "\\" + "PAImages" + ".nrrd"; + std::string pathUS = "c:\\DiPhASImageData\\" + currentDate + "\\" + "USImages" + ".nrrd"; + std::string pathTS = "c:\\DiPhASImageData\\" + currentDate + "\\" + "TimestampsImages" + ".csv"; + + // idon't forget the raw Images (if chosen to be saved) + Image::Pointer PAImageRaw = Image::New(); + Image::Pointer USImageRaw = Image::New(); + std::string pathPARaw = "c:\\DiPhASImageData\\" + currentDate + "\\" + "PAImagesRaw" + ".nrrd"; + std::string pathUSRaw = "c:\\DiPhASImageData\\" + currentDate + "\\" + "USImagesRaw" + ".nrrd"; + + if (m_Device->GetScanMode().beamformingAlgorithm == (int)Beamforming::Interleaved_OA_US) // save a PAImage if we used interleaved mode + { + // first, save the data, so the pyro does not aquire more unneccessary timestamps + m_Pyro->SaveData(); + + // now order the images and save them + // the beamformed ones... + if (m_SavingSettings.saveBeamformed) + { + OrderImagesInterleaved(PAImage, USImage, m_RecordedImages, false); + mitk::IOUtil::Save(USImage, pathUS); + mitk::IOUtil::Save(PAImage, pathPA); + } + + // ...and the raw images + if (m_SavingSettings.saveRaw) + { + OrderImagesInterleaved(PAImageRaw, USImageRaw, m_RawRecordedImages, true); + mitk::IOUtil::Save(USImageRaw, pathUSRaw); + mitk::IOUtil::Save(PAImageRaw, pathPARaw); + } + + // read the pixelvalues of the enveloped images at this position + itk::Index<3> pixel = { { m_RecordedImages.at(1)->GetDimension(0) / 2, 22.0/532.0*m_Device->GetScanMode().reconstructionSamplesPerLine, 0 } }; //22/532*2048 = 84 + GetPixelValues(pixel); + + // save the timestamps! + ofstream timestampFile; + + timestampFile.open(pathTS); + timestampFile << ",timestamp,pixelvalue"; // write the header + + for (int index = 0; index < m_ImageTimestampRecord.size(); ++index) + { + timestampFile << "\n" << index << "," << m_ImageTimestampRecord.at(index) << "," << m_PixelValues.at(index); + } + timestampFile.close(); + } + else if (m_Device->GetScanMode().beamformingAlgorithm == (int)Beamforming::PlaneWaveCompound) // save no PAImage if we used US only mode + { + OrderImagesUltrasound(USImage, m_RecordedImages); + mitk::IOUtil::Save(USImage, pathUS); + } + + m_PixelValues.clear(); + m_RawRecordedImages.clear(); // clean up the pixel values + m_RecordedImages.clear(); // clean up the images + m_ImageTimestampRecord.clear(); // clean up the timestamps + } +} + +void mitk::USDiPhASImageSource::GetPixelValues(itk::Index<3> pixel) +{ + unsigned int events = m_Device->GetScanMode().transmitEventsCount + 1; // the PA event is not included in the transmitEvents, so we add 1 here + for (int index = 0; index < m_RecordedImages.size(); index += events) // omit sound images + { + Image::Pointer image = ApplyBmodeFilter(m_RecordedImages.at(index)); + m_PixelValues.push_back(image.GetPointer()->GetPixelValueByIndex(pixel)); + } +} + +void mitk::USDiPhASImageSource::OrderImagesInterleaved(Image::Pointer PAImage, Image::Pointer USImage, std::vector recordedList, bool raw) +{ + unsigned int width = 32; + unsigned int height = 32; + unsigned int events = m_Device->GetScanMode().transmitEventsCount + 1; // the PA event is not included in the transmitEvents, so we add 1 here + + if (raw) + { + width = recordedList.at(0)->GetDimension(0); + height = recordedList.at(0)->GetDimension(1); + } + else if (m_DataType == DataType::Beamformed_Short) + { + width = m_Device->GetScanMode().reconstructionLines; + height = m_Device->GetScanMode().reconstructionSamplesPerLine; + } + else if (m_DataType == DataType::Image_uChar) + { + width = m_Device->GetScanMode().imageWidth; + height = m_Device->GetScanMode().imageHeight; + } + + unsigned int dimLaser[] = { width, height, recordedList.size() / events}; + unsigned int dimSound[] = { width, height, recordedList.size() / events * (events-1)}; + + PAImage->Initialize(recordedList.back()->GetPixelType(), 3, dimLaser); + PAImage->SetGeometry(recordedList.back()->GetGeometry()); + USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound); + USImage->SetGeometry(recordedList.back()->GetGeometry()); + + for (int index = 0; index < recordedList.size(); ++index) + { + mitk::ImageReadAccessor inputReadAccessor(recordedList.at(index)); + if (index % events == 0) + { + PAImage->SetSlice(inputReadAccessor.GetData(), index / events); + } + else + { + USImage->SetSlice(inputReadAccessor.GetData(), ((index - (index % events)) / events) + (index % events)-1); + } + } +} + +void mitk::USDiPhASImageSource::OrderImagesUltrasound(Image::Pointer USImage, std::vector recordedList) +{ + unsigned int width = 32; + unsigned int height = 32; + unsigned int events = m_Device->GetScanMode().transmitEventsCount; + + if (m_DataType == DataType::Beamformed_Short) + { + width = m_Device->GetScanMode().reconstructionLines; + height = m_Device->GetScanMode().reconstructionSamplesPerLine; + } + else if (m_DataType == DataType::Image_uChar) + { + width = m_Device->GetScanMode().imageWidth; + height = m_Device->GetScanMode().imageHeight; + } + + unsigned int dimSound[] = { width, height, recordedList.size()}; + + USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound); + USImage->SetGeometry(recordedList.back()->GetGeometry()); + + for (int index = 0; index < recordedList.size(); ++index) + { + mitk::ImageReadAccessor inputReadAccessor(recordedList.at(index)); + USImage->SetSlice(inputReadAccessor.GetData(), index); + } +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h new file mode 100644 index 0000000000..5e0aba171b --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h @@ -0,0 +1,189 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASImageSource_H_HEADER_INCLUDED_ +#define MITKUSDiPhASImageSource_H_HEADER_INCLUDED_ + + +#include "mitkUSImageSource.h" +#include "mitkUSDiPhASCustomControls.h" + +#include "Framework.IBMT.US.CWrapper.h" + +#include "mitkImageReadAccessor.h" +#include "itkFastMutexLock.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace mitk { + +class USDiPhASDevice; +/** + * \brief Implementation of mitk::USImageSource for DiPhAS API devices. + * The method mitk::USImageSource::GetNextRawImage() is implemented for + * getting images from the DiPhAS API. + * + * The image data is given to this class from the DiPhAS API by calling + * a callback method that writes the image data to an mitk::image + */ +class USDiPhASImageSource : public USImageSource +{ + +public: + mitkClassMacro(USDiPhASImageSource, USImageSource); + mitkNewMacro1Param(Self, mitk::USDiPhASDevice*); + itkCloneMacro(Self); + + typedef mitk::USDiPhASDeviceCustomControls::DataType DataType; + typedef mitk::USDiPhASDeviceCustomControls::SavingSettings SavingSettings; + + /** + * Implementation of the superclass method. Returns the pointer + * to the mitk::Image filled by DiPhAS API callback. + */ + virtual void GetNextRawImage( mitk::Image::Pointer& ); + + /** + * The API calls this function to pass the image data to the + * user; here the m_Image is updated + */ + void mitk::USDiPhASImageSource::ImageDataCallback( + short* rfDataChannelData, + int& channelDataChannelsPerDataset, + int& channelDataSamplesPerChannel, + int& channelDataTotalDatasets, + + short* rfDataArrayBeamformed, + int& beamformedLines, + int& beamformedSamples, + int& beamformedTotalDatasets, + + unsigned char* imageData, + int& imageWidth, + int& imageHeight, + int& imagePixelFormat, + int& imageSetsTotal, + + double& timeStamp); + + void SetGUIOutput(std::function out); + + /** This starts or ends the recording session*/ + void SetRecordingStatus(bool record); + void SetSavingSettings(SavingSettings settings); + void SetVerticalSpacing(float mm); + + void ModifyDataType(DataType dataT); + void ModifyUseBModeFilter(bool isSet); + void ModifyScatteringCoefficient(int coeff); + void ModifyCompensateForScattering(bool useIt); + void ModifyEnergyCompensation(bool compensate); + + /** + * Sets the spacing used in the image based on the informations of the ScanMode in USDiPhAS Device + */ + void UpdateImageGeometry(); + +protected: + void SetDataType(DataType dataT); + void SetUseBModeFilter(bool isSet); + + USDiPhASImageSource(mitk::USDiPhASDevice* device); + virtual ~USDiPhASImageSource( ); + + /** This vector holds all the images we record, if recording is set to active. */ + std::vector m_RecordedImages; + std::vector m_RawRecordedImages; + std::vector m_ImageTimestampRecord; + std::vector m_ImageTimestampBuffer; + long long m_CurrentImageTimestamp; + bool m_CurrentlyRecording; + mitk::OphirPyro::Pointer m_Pyro; + bool m_PyroConnected; + + std::vector m_FluenceCompOriginal; + std::vector m_FluenceCompResized; + std::vector::Pointer> m_FluenceCompResizedItk; + + std::vector m_ImageBuffer; + int m_LastWrittenImage; + int m_BufferSize; + + unsigned int m_ImageDimensions[3]; + mitk::Vector3D m_ImageSpacing; + + mitk::Image::Pointer ApplyBmodeFilter(mitk::Image::Pointer inputImage, bool useLogFilter = false, float resampleSpacing = 0.15); + mitk::Image::Pointer ApplyScatteringCompensation(mitk::Image::Pointer inputImage, int scatteringCoefficient); + mitk::Image::Pointer ApplyResampling(mitk::Image::Pointer inputImage, mitk::Vector3D outputSpacing, unsigned int outputSize[3]); + mitk::Image::Pointer MultiplyImage(mitk::Image::Pointer inputImage, double value); + + void OrderImagesInterleaved(Image::Pointer PAImage, Image::Pointer USImage, std::vector recordedList, bool raw); + void OrderImagesUltrasound(Image::Pointer USImage, std::vector recordedList); + + void GetPixelValues(itk::Index<3> pixel); + float GetPixelValue(itk::Index<3> pixel); + std::vector m_PixelValues; + + mitk::USDiPhASDevice* m_Device; + + /** This is a callback to pass text data to the GUI. */ + std::function m_GUIOutput; + + /** + * Variables for management of current state. + */ + SavingSettings m_SavingSettings; + + float m_StartTime; + bool m_UseGUIOutPut; + + BeamformerStateInfoNative m_BeamformerInfos; + bool m_UseBModeFilter; + + bool m_DataTypeModified; + DataType m_DataTypeNext; + + bool m_UseBModeFilterModified; + bool m_UseBModeFilterNext; + + float m_VerticalSpacing; + float m_VerticalSpacingNext; + bool m_VerticalSpacingModified; + + int m_ScatteringCoefficient; + int m_ScatteringCoefficientNext; + bool m_ScatteringCoefficientModified; + + bool m_CompensateForScattering; + bool m_CompensateForScatteringNext; + bool m_CompensateForScatteringModified; + + bool m_CompensateEnergy; + bool m_CompensateEnergyNext; + bool m_CompensateEnergyModified; + + DataType m_DataType; +}; +} // namespace mitk + +#endif // MITKUSDiPhASImageSource_H diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.cpp new file mode 100644 index 0000000000..b51f585976 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.cpp @@ -0,0 +1,27 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkUSDiPhASProbe.h" +#include "Framework.IBMT.US.CWrapper.h" + +mitk::USDiPhASProbe::USDiPhASProbe(std::string ProbeName) +{ + SetName(ProbeName); +} + +mitk::USDiPhASProbe::~USDiPhASProbe() +{ +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.h new file mode 100644 index 0000000000..e89e3abf3b --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbe.h @@ -0,0 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASProbe_H_HEADER_INCLUDED_ +#define MITKUSDiPhASProbe_H_HEADER_INCLUDED_ + +#include "mitkUSProbe.h" + +namespace mitk +{ + /** + * \brief Specialized mitk::USProbe for handling DiPhAS API probe objects. + * It encapsulates a probe object from the DiPhAS API. + * + * This class should only be instantiated by mitk::USDiPhASProbesControls. + * Every other object can get instances of mitk::USDiPhASProbe from there. + */ + class USDiPhASProbe : public USProbe + { + public: + mitkClassMacro(USDiPhASProbe, USProbe); + mitkNewMacro1Param(Self, std::string); + + protected: + /** + * Constructs mitk::USDiPhASProbe object with given API objects. + * + * \param probe API probe object which should be represented by the constructed object + * \param dataView API data view object conected to this probe object + */ + USDiPhASProbe(std::string ProbeName); + virtual ~USDiPhASProbe(); + + }; +} // namespace mitk + +#endif // MITKUSDiPhASProbe_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.cpp new file mode 100644 index 0000000000..d40d09d4da --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.cpp @@ -0,0 +1,113 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkUSDiPhASProbesControls.h" +#include "mitkUSDiPhASDevice.h" +#include + +mitk::USDiPhASProbesControls::USDiPhASProbesControls(itk::SmartPointer device) + : mitk::USControlInterfaceProbes(device.GetPointer()), + m_IsActive(false), m_DiPhASDevice(device) +{ +} + +mitk::USDiPhASProbesControls::~USDiPhASProbesControls() +{ +} + + +void mitk::USDiPhASProbesControls::SetIsActive(bool isActive) +{ + this->CreateProbesSet(); + m_IsActive = isActive; +} + +bool mitk::USDiPhASProbesControls::GetIsActive() +{ + return m_IsActive; +} + +std::vector mitk::USDiPhASProbesControls::GetProbeSet() +{ + // create a new vector of base class (USProbe) objects, because + // interface wants a vector of this type + std::vector usProbes(m_ProbesSet.size(), 0); + for (unsigned int n = 0; n < m_ProbesSet.size(); ++n) + { + usProbes.at(n) = m_ProbesSet.at(n).GetPointer(); + } + return usProbes; +} + +void mitk::USDiPhASProbesControls::OnSelectProbe(unsigned int index) +{ + if (index >= m_ProbesSet.size()) + { + MITK_ERROR("USDiPhASProbesControls")("USControlInterfaceProbes") + << "Cannot select probe with index " << index << ". Maximum possible index is " << m_ProbesSet.size() - 1 << "."; + mitkThrow() << "Cannot select probe with index " << index << + ". Maximum possible index is " << m_ProbesSet.size() - 1 << "."; + } + + m_SelectedProbeIndex = index; +} + +void mitk::USDiPhASProbesControls::OnSelectProbe(mitk::USProbe::Pointer probe) +{ +} + +mitk::USProbe::Pointer mitk::USDiPhASProbesControls::GetSelectedProbe() +{ + if (m_SelectedProbeIndex >= m_ProbesSet.size()) + { + MITK_ERROR("USDiPhASProbesControls")("USControlInterfaceProbes") + << "Cannot get active probe as the current index is" << m_SelectedProbeIndex << + ". Maximum possible index is " << m_ProbesSet.size() - 1 << "."; + mitkThrow() << "Cannot get active probe as the current index is" << m_SelectedProbeIndex << + ". Maximum possible index is " << m_ProbesSet.size() - 1 << "."; + } + + return m_ProbesSet.at(m_SelectedProbeIndex).GetPointer(); +} + +unsigned int mitk::USDiPhASProbesControls::GetProbesCount() const +{ + return m_ProbesSet.size(); +} + + +void mitk::USDiPhASProbesControls::ProbeRemoved(unsigned int index) +{ + MITK_INFO << "Probe removed..."; + + if (m_ProbesSet.size() > index) + { + m_ProbesSet.erase(m_ProbesSet.begin() + index); + } +} + +void mitk::USDiPhASProbesControls::ProbeAdded(unsigned int index) +{ + MITK_INFO << "Probe arrived..."; + + this->CreateProbesSet(); +} + +void mitk::USDiPhASProbesControls::CreateProbesSet() +{ + m_ProbesSet.push_back(mitk::USDiPhASProbe::New( m_DiPhASDevice->GetScanMode().transducerName )); +} \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.h new file mode 100644 index 0000000000..daaa9c6466 --- /dev/null +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASProbesControls.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKUSDiPhASProbesControls_H_HEADER_INCLUDED_ +#define MITKUSDiPhASProbesControls_H_HEADER_INCLUDED_ + +#include "Framework.IBMT.US.CWrapper.h" +#include "mitkUSDiPhASProbe.h" +#include "mitkUSControlInterfaceProbes.h" + +#include + +namespace mitk { + class USDiPhASDevice; + + /** + * \brief Implementation of mitk::USControlInterfaceProbes for DiPhAS ultrasound devices. + * See documentation of mitk::USControlInterfaceProbes for a description of the interface methods. + * This class has to be implemented for the USDevice but the DiPhAS API does not support multiple devices. + * Therefore there will be just one probe at all times. + */ + class USDiPhASProbesControls : public USControlInterfaceProbes + { + public: + mitkClassMacro(USDiPhASProbesControls, USControlInterfaceProbes); + mitkNewMacro1Param(Self, itk::SmartPointer); + + /** + * Probe informations are fetched on activation. On deactivation there is nothing done. + */ + virtual void SetIsActive(bool); + + virtual bool GetIsActive(); + + virtual std::vector GetProbeSet(); + virtual void OnSelectProbe(unsigned int index); + virtual void OnSelectProbe(USProbe::Pointer probe); + virtual USProbe::Pointer GetSelectedProbe(); + virtual unsigned int GetProbesCount() const; + + void ProbeRemoved(unsigned int index); + void ProbeAdded(unsigned int index); + + protected: + /** + * Constructs an empty object. + * DiPhAS device has to be set after constructing by calling + * mitk::USDiPhASProbesControls::SetDiPhASDevice before the + * object can be used. + */ + USDiPhASProbesControls(itk::SmartPointer device); + virtual ~USDiPhASProbesControls(); + + /** + * Create collection object (DiPhAS API) for the API device. + */ + bool CreateProbesCollection(); + + /** + * Create vector of mitk::USDiPhASProbe objects from the + * DiPhAS API probe collection. Hence + * mitk::USDiPhASProbesControls::CreateProbesCollection has to + * be called before. + */ + void CreateProbesSet(); + + bool m_IsActive; + unsigned int m_SelectedProbeIndex; + std::vector m_ProbesSet; + itk::SmartPointer m_DiPhASDevice; + }; +} + +#endif // MITKUSDiPhASProbesControls_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/US/USModel/mitkUSDevice.cpp b/Modules/US/USModel/mitkUSDevice.cpp index b5eff69e42..433c4bf20c 100644 --- a/Modules/US/USModel/mitkUSDevice.cpp +++ b/Modules/US/USModel/mitkUSDevice.cpp @@ -1,664 +1,671 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSDevice.h" #include "mitkImageReadAccessor.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" // Microservices #include #include #include #include mitk::USDevice::PropertyKeys mitk::USDevice::GetPropertyKeys() { static mitk::USDevice::PropertyKeys propertyKeys; return propertyKeys; } mitk::USDevice::USImageCropArea mitk::USDevice::GetCropArea() { MITK_INFO << "Return Crop Area L:" << m_CropArea.cropLeft << " R:" << m_CropArea.cropRight << " T:" << m_CropArea.cropTop << " B:" << m_CropArea.cropBottom; return m_CropArea; } mitk::USDevice::USDevice(std::string manufacturer, std::string model) : mitk::ImageSource(), m_IsFreezed(false), m_DeviceState(State_NoState), m_Manufacturer(manufacturer), m_Name(model), m_SpawnAcquireThread(true), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_UnregisteringStarted(false) { USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(1); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::USDevice(mitk::USImageMetadata::Pointer metadata) : mitk::ImageSource(), m_IsFreezed(false), m_DeviceState(State_NoState), m_SpawnAcquireThread(true), m_MultiThreader(itk::MultiThreader::New()), m_ImageMutex(itk::FastMutexLock::New()), m_ThreadID(-1), m_UnregisteringStarted(false) { m_Manufacturer = metadata->GetDeviceManufacturer(); m_Name = metadata->GetDeviceModel(); m_Comment = metadata->GetDeviceComment(); USImageCropArea empty; empty.cropBottom = 0; empty.cropTop = 0; empty.cropLeft = 0; empty.cropRight = 0; this->m_CropArea = empty; // set number of outputs this->SetNumberOfIndexedOutputs(1); // create a new output mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); } mitk::USDevice::~USDevice() { if (m_ThreadID >= 0) { m_MultiThreader->TerminateThread(m_ThreadID); } // make sure that the us device is not registered at the micro service // anymore after it is destructed this->UnregisterOnService(); } mitk::USAbstractControlInterface::Pointer mitk::USDevice::GetControlInterfaceCustom() { MITK_INFO << "Custom control interface does not exist for this object."; return 0; } mitk::USControlInterfaceBMode::Pointer mitk::USDevice::GetControlInterfaceBMode() { MITK_INFO << "Control interface BMode does not exist for this object."; return 0; } mitk::USControlInterfaceProbes::Pointer mitk::USDevice::GetControlInterfaceProbes() { MITK_INFO << "Control interface Probes does not exist for this object."; return 0; } mitk::USControlInterfaceDoppler::Pointer mitk::USDevice::GetControlInterfaceDoppler() { MITK_INFO << "Control interface Doppler does not exist for this object."; return 0; } void mitk::USDevice::SetManufacturer(std::string manufacturer) { m_Manufacturer = manufacturer; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER, manufacturer); } } void mitk::USDevice::SetName(std::string name) { m_Name = name; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME, name); } } void mitk::USDevice::SetComment(std::string comment) { m_Comment = comment; if (m_DeviceState >= State_Initialized) { this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_COMMENT, comment); } } us::ServiceProperties mitk::USDevice::ConstructServiceProperties() { mitk::USDevice::PropertyKeys propertyKeys = mitk::USDevice::GetPropertyKeys(); us::ServiceProperties props; props[propertyKeys.US_PROPKEY_ISCONNECTED] = this->GetIsConnected() ? "true" : "false"; props[propertyKeys.US_PROPKEY_ISACTIVE] = this->GetIsActive() ? "true" : "false"; props[propertyKeys.US_PROPKEY_LABEL] = this->GetServicePropertyLabel(); // get identifier of selected probe if there is one selected mitk::USControlInterfaceProbes::Pointer probesControls = this->GetControlInterfaceProbes(); if (probesControls.IsNotNull() && probesControls->GetIsActive()) { mitk::USProbe::Pointer probe = probesControls->GetSelectedProbe(); if (probe.IsNotNull()) { props[propertyKeys.US_PROPKEY_PROBES_SELECTED] = probe->GetName(); } } props[propertyKeys.US_PROPKEY_CLASS] = GetDeviceClass(); props[propertyKeys.US_PROPKEY_MANUFACTURER] = m_Manufacturer; props[propertyKeys.US_PROPKEY_NAME] = m_Name; props[propertyKeys.US_PROPKEY_COMMENT] = m_Comment; m_ServiceProperties = props; return props; } void mitk::USDevice::UnregisterOnService() { // unregister on micro service if (m_ServiceRegistration && !m_UnregisteringStarted) { // make sure that unregister is not started a second // time due to a callback during unregister for example m_UnregisteringStarted = true; m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } } bool mitk::USDevice::Initialize() { if (!this->OnInitialization()) { return false; } m_DeviceState = State_Initialized; // Get Context and Module us::ModuleContext* context = us::GetModuleContext(); us::ServiceProperties props = this->ConstructServiceProperties(); m_ServiceRegistration = context->RegisterService(this, props); return true; } bool mitk::USDevice::Connect() { MITK_DEBUG << "mitk::USDevice::Connect() called"; if (this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Tried to connect an ultrasound device that " "was already connected. Ignoring call..."; return true; } if (!this->GetIsInitialized()) { MITK_ERROR("mitkUSDevice") << "Cannot connect device if it is not in initialized state."; return false; } // Prepare connection, fail if this fails. if (!this->OnConnection()) { return false; } // Update state m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, true); return true; } void mitk::USDevice::ConnectAsynchron() { this->m_MultiThreader->SpawnThread(this->ConnectThread, this); } bool mitk::USDevice::Disconnect() { if (!GetIsConnected()) { MITK_WARN << "Tried to disconnect an ultrasound device that was not " "connected. Ignoring call..."; return false; } // Prepare connection, fail if this fails. if (!this->OnDisconnection()) return false; // Update state m_DeviceState = State_Initialized; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISCONNECTED, false); return true; } bool mitk::USDevice::Activate() { if (!this->GetIsConnected()) { MITK_INFO("mitkUSDevice") << "Cannot activate device if it is not in connected state."; return true; } if (OnActivation()) { m_DeviceState = State_Activated; m_FreezeBarrier = itk::ConditionVariable::New(); // spawn thread for aquire images if us device is active if (m_SpawnAcquireThread) { this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); } this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, true); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); // initialize the b mode control properties of the micro service mitk::USControlInterfaceBMode::Pointer bmodeControls = this->GetControlInterfaceBMode(); if (bmodeControls.IsNotNull()) { bmodeControls->Initialize(); } } this->ProvideViaOIGTL(); return m_DeviceState == State_Activated; } void mitk::USDevice::ProvideViaOIGTL() { // create a new OpenIGTLink Server if (m_IGTLServer.IsNull()) m_IGTLServer = mitk::IGTLServer::New(true); m_IGTLServer->SetName(this->GetName()); // create a new OpenIGTLink Device source if (m_IGTLMessageProvider.IsNull()) m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); // set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); // register the provider so that it can be configured with the IGTL manager // plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); m_ImageToIGTLMsgFilter = mitk::ImageToIGTLMessageFilter::New(); m_ImageToIGTLMsgFilter->ConnectTo(this); // set the name of this filter to identify it easier m_ImageToIGTLMsgFilter->SetName(this->GetName()); // register this filter as micro service. The message provider looks for // provided IGTLMessageSources, once it found this microservice and someone // requested this data type then the provider will connect with this filter // automatically. m_ImageToIGTLMsgFilter->RegisterAsMicroservice(); } void mitk::USDevice::Deactivate() { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") << "Cannot deactivate a device which is not activae."; return; } if (!OnDeactivation()) { return; } DisableOIGTL(); m_DeviceState = State_Connected; this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE, false); this->UpdateServiceProperty( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, this->GetServicePropertyLabel()); } void mitk::USDevice::DisableOIGTL() { // TODO: This seems not to be enough cleanup to catch all cases. For example, if the device is disconnected // from the OIGTL GUI, this won't get cleaned up correctly. m_IGTLServer->CloseConnection(); m_IGTLMessageProvider->UnRegisterMicroservice(); m_ImageToIGTLMsgFilter->UnRegisterMicroservice(); } void mitk::USDevice::SetIsFreezed(bool freeze) { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice") << "Cannot freeze or unfreeze if device is not active."; return; } this->OnFreeze(freeze); if (freeze) { m_IsFreezed = true; } else { m_IsFreezed = false; // wake up the image acquisition thread m_FreezeBarrier->Signal(); } } bool mitk::USDevice::GetIsFreezed() { if (!this->GetIsActive()) { MITK_WARN("mitkUSDevice")("mitkUSTelemedDevice") << "Cannot get freeze state if the hardware interface is not ready. " "Returning false..."; return false; } return m_IsFreezed; } void mitk::USDevice::PushFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } imageSource->PushFilter(filter); } void mitk::USDevice::PushFilterIfNotPushedBefore( AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when pushing a filter."; } if (!imageSource->GetIsFilterInThePipeline(filter)) { imageSource->PushFilter(filter); } } bool mitk::USDevice::RemoveFilter(AbstractOpenCVImageFilter::Pointer filter) { mitk::USImageSource::Pointer imageSource = this->GetUSImageSource(); if (imageSource.IsNull()) { MITK_ERROR << "ImageSource must not be null when pushing a filter."; mitkThrow() << "ImageSource must not be null when removing a filter."; } return imageSource->RemoveFilter(filter); } void mitk::USDevice::UpdateServiceProperty(std::string key, std::string value) { m_ServiceProperties[key] = value; m_ServiceRegistration.SetProperties(m_ServiceProperties); // send event to notify listeners about the changed property m_PropertyChangedMessage(key, value); } void mitk::USDevice::UpdateServiceProperty(std::string key, double value) { std::stringstream stream; stream << value; this->UpdateServiceProperty(key, stream.str()); } void mitk::USDevice::UpdateServiceProperty(std::string key, bool value) { this->UpdateServiceProperty( key, value ? std::string("true") : std::string("false")); } /** mitk::Image* mitk::USDevice::GetOutput() { if (this->GetNumberOfOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::Image* mitk::USDevice::GetOutput(unsigned int idx) { if (this->GetNumberOfOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetOutput(idx)); } void mitk::USDevice::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::USDevice::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on USImage to copy member data output->Graft( graft ); } */ void mitk::USDevice::GrabImage() { mitk::Image::Pointer image = this->GetUSImageSource()->GetNextImage(); m_ImageMutex->Lock(); this->SetImage(image); m_ImageMutex->Unlock(); // if (image.IsNotNull() && (image->GetGeometry()!=NULL)){ // MITK_INFO << "Spacing: " << image->GetGeometry()->GetSpacing();} } //########### GETTER & SETTER ##################// bool mitk::USDevice::GetIsInitialized() { return m_DeviceState == State_Initialized; } bool mitk::USDevice::GetIsActive() { return m_DeviceState == State_Activated; } bool mitk::USDevice::GetIsConnected() { return m_DeviceState == State_Connected; } std::string mitk::USDevice::GetDeviceManufacturer() { return m_Manufacturer; } std::string mitk::USDevice::GetDeviceModel() { return m_Name; } std::string mitk::USDevice::GetDeviceComment() { return m_Comment; } void mitk::USDevice::GenerateData() { m_ImageMutex->Lock(); if (m_Image.IsNull() || !m_Image->IsInitialized()) { m_ImageMutex->Unlock(); return; } mitk::Image::Pointer output = this->GetOutput(); if (!output->IsInitialized() || output->GetDimension(0) != m_Image->GetDimension(0) || - output->GetDimension(1) != m_Image->GetDimension(1)) + output->GetDimension(1) != m_Image->GetDimension(1) || + output->GetDimension(2) != m_Image->GetDimension(2) || + output->GetPixelType() != m_Image->GetPixelType()) { output->Initialize(m_Image->GetPixelType(), m_Image->GetDimension(), m_Image->GetDimensions()); } - mitk::ImageReadAccessor inputReadAccessor(m_Image, - m_Image->GetSliceData(0, 0, 0)); - output->SetSlice(inputReadAccessor.GetData()); + // copy contents of the given image into the member variable, slice after slice + for (int sliceNumber = 0; sliceNumber < m_Image->GetDimension(2); ++sliceNumber) + { + if (m_Image->IsSliceSet(sliceNumber)) { + mitk::ImageReadAccessor inputReadAccessor(m_Image, m_Image->GetSliceData(sliceNumber, 0, 0)); + output->SetSlice(inputReadAccessor.GetData(), sliceNumber); + } + } + output->SetGeometry(m_Image->GetGeometry()); m_ImageMutex->Unlock(); }; std::string mitk::USDevice::GetServicePropertyLabel() { std::string isActive; if (this->GetIsActive()) { isActive = " (Active)"; } else { isActive = " (Inactive)"; } // e.g.: Zonare MyLab5 (Active) return m_Manufacturer + " " + m_Name + isActive; } ITK_THREAD_RETURN_TYPE mitk::USDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; while (device->GetIsActive()) { // lock this thread when ultrasound device is freezed if (device->m_IsFreezed) { itk::SimpleMutexLock* mutex = &(device->m_FreezeMutex); mutex->Lock(); if (device->m_FreezeBarrier.IsNotNull()) { device->m_FreezeBarrier->Wait(mutex); } } - device->GrabImage(); } return ITK_THREAD_RETURN_VALUE; } ITK_THREAD_RETURN_TYPE mitk::USDevice::ConnectThread(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct* pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USDevice* device = (mitk::USDevice*)pInfo->UserData; device->Connect(); return ITK_THREAD_RETURN_VALUE; } void mitk::USDevice::ProbeChanged(std::string probename) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED, probename); } void mitk::USDevice::DepthChanged(double depth) { this->UpdateServiceProperty(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH, depth); } diff --git a/Modules/US/files.cmake b/Modules/US/files.cmake index 7125e7cc77..93bf7bcfb2 100644 --- a/Modules/US/files.cmake +++ b/Modules/US/files.cmake @@ -1,33 +1,34 @@ SET(CPP_FILES ## Module Activator mitkUSActivator.cpp ## Model Classes USModel/mitkUSImage.cpp USModel/mitkUSImageMetadata.cpp USModel/mitkUSDevice.cpp USModel/mitkUSIGTLDevice.cpp USModel/mitkUSVideoDevice.cpp USModel/mitkUSVideoDeviceCustomControls.cpp USModel/mitkUSProbe.cpp USModel/mitkUSDevicePersistence.cpp ## Filters and Sources USFilters/mitkUSImageLoggingFilter.cpp USFilters/mitkUSImageSource.cpp USFilters/mitkUSImageVideoSource.cpp USFilters/mitkIGTLMessageToUSImageFilter.cpp ## Control Interfaces USControlInterfaces/mitkUSAbstractControlInterface.cpp USControlInterfaces/mitkUSControlInterfaceBMode.cpp USControlInterfaces/mitkUSControlInterfaceProbes.cpp USControlInterfaces/mitkUSControlInterfaceDoppler.cpp +USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp ) set(RESOURCE_FILES Interactions/USPointMarkInteractions.xml Interactions/USZoneInteractions.xml Interactions/USZoneInteractionsHold.xml ) diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp new file mode 100644 index 0000000000..de736b03e8 --- /dev/null +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp @@ -0,0 +1,419 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkUSControlsCustomDiPhASDeviceWidget.h" +#include "ui_QmitkUSControlsCustomDiPhASDeviceWidget.h" +#include + + +#include + +QmitkUSControlsCustomDiPhASDeviceWidget::QmitkUSControlsCustomDiPhASDeviceWidget(QWidget *parent) + : QmitkUSAbstractCustomWidget(parent), ui(new Ui::QmitkUSControlsCustomDiPhASDeviceWidget) +{ +} + +QmitkUSControlsCustomDiPhASDeviceWidget::~QmitkUSControlsCustomDiPhASDeviceWidget() +{ + m_ControlInterface = dynamic_cast + (this->GetDevice()->GetControlInterfaceCustom().GetPointer()); + + if (m_ControlInterface.IsNotNull()) + { + m_ControlInterface->passGUIOut([](QString str)->void {} ); + } + delete ui; +} + +std::string QmitkUSControlsCustomDiPhASDeviceWidget::GetDeviceClass() const +{ + return "org.mitk.modules.us.USDiPhASDevice"; +} + +QmitkUSAbstractCustomWidget* QmitkUSControlsCustomDiPhASDeviceWidget::Clone(QWidget* parent) const +{ + QmitkUSAbstractCustomWidget* clonedWidget = new QmitkUSControlsCustomDiPhASDeviceWidget(parent); + clonedWidget->SetDevice(this->GetDevice()); + return clonedWidget; +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnDeviceSet() +{ + m_ControlInterface = dynamic_cast + (this->GetDevice()->GetControlInterfaceCustom().GetPointer()); + + if ( m_ControlInterface.IsNotNull() ) + { + m_ControlInterface->passGUIOut([this](QString str)->void{ + if (this && this->ui) { + this->ui->CurrentState->setText(str); + } }); + } + else + { + MITK_WARN("QmitkUSAbstractCustomWidget")("QmitkUSControlsCustomDiPhASDeviceWidget") + << "Did not get a custom device control interface."; + } + + //now pass the default values + + m_OldReconstructionLines = 0; + + m_ControlInterface->SetSilentUpdate(true); // don't update the scanmode everytime + + OnTransmitPhaseLengthChanged(); + OnExcitationFrequencyChanged(); + OnTransmitEventsChanged(); + OnVoltageChanged(); + OnScanDepthChanged(); // HERE + OnAveragingCountChanged(); + OnTGCMinChanged(); + OnTGCMaxChanged(); + OnDataTypeChanged(); + OnPitchChanged(); + OnReconstructedSamplesChanged(); + OnReconstructedLinesChanged(); + OnSpeedOfSoundChanged(); + OnBandpassEnabledChanged(); + OnLowCutChanged(); + OnHighCutChanged(); + OnUseBModeFilterChanged(); // HERE + OnVerticalSpacingChanged(); + OnScatteringCoefficientChanged(); + OnCompensateScatteringChanged(); + OnChangedSavingSettings(); + OnCompensateEnergyChanged(); + + m_ControlInterface->SetSilentUpdate(false); // on the last update pass the scanmode and geometry! + + OnModeChanged(); // HERE +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::Initialize() +{ + ui->setupUi(this); + + connect(ui->CompensateEnergy, SIGNAL(stateChanged(int)), this, SLOT(OnCompensateEnergyChanged())); + connect(ui->UseBModeFilter, SIGNAL(stateChanged(int)), this, SLOT(OnUseBModeFilterChanged())); + connect(ui->StartStopRecord, SIGNAL(clicked()), this, SLOT(OnRecordChanged())); + connect(ui->ScatteringCoefficient, SIGNAL(valueChanged(int)), this, SLOT(OnScatteringCoefficientChanged())); + connect(ui->CompensateScattering, SIGNAL(stateChanged(int)), this, SLOT(OnCompensateScatteringChanged())); + connect(ui->VerticalSpacing, SIGNAL(valueChanged(double)), this, SLOT(OnVerticalSpacingChanged())); + connect(ui->SaveBeamformed, SIGNAL(stateChanged(int)), this, SLOT(OnChangedSavingSettings())); + connect(ui->SaveRaw, SIGNAL(stateChanged(int)), this, SLOT(OnChangedSavingSettings())); + //transmit + connect(ui->TransmitPhaseLength, SIGNAL(valueChanged(double)), this, SLOT(OnTransmitPhaseLengthChanged())); + connect(ui->ExcitationFrequency, SIGNAL(valueChanged(double)), this, SLOT(OnExcitationFrequencyChanged())); + connect(ui->TransmitEvents, SIGNAL(valueChanged(int)), this, SLOT(OnTransmitEventsChanged())); + connect(ui->Voltage, SIGNAL(valueChanged(int)), this, SLOT(OnVoltageChanged())); + connect(ui->Mode, SIGNAL(currentTextChanged(QString)), this, SLOT(OnModeChanged())); + + //Receive + connect(ui->ScanDepth, SIGNAL(valueChanged(double)), this, SLOT(OnScanDepthChanged())); + connect(ui->AveragingCount, SIGNAL(valueChanged(int)), this, SLOT(OnAveragingCountChanged())); + connect(ui->TimeGainCompensationMinSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTGCMinChanged())); + connect(ui->TimeGainCompensationMaxSlider, SIGNAL(valueChanged(int)), this, SLOT(OnTGCMaxChanged())); + connect(ui->DataType, SIGNAL(currentTextChanged(QString)), this, SLOT(OnDataTypeChanged())); + + //Beamforming + connect(ui->PitchOfTransducer, SIGNAL(valueChanged(double)), this, SLOT(OnPitchChanged())); + connect(ui->ReconstructedSamplesPerLine, SIGNAL(valueChanged(int)), this, SLOT(OnReconstructedSamplesChanged())); + connect(ui->ReconstructedLines, SIGNAL(valueChanged(int)), this, SLOT(OnReconstructedLinesChanged())); + connect(ui->SpeedOfSound, SIGNAL(valueChanged(int)), this, SLOT(OnSpeedOfSoundChanged())); + + //Bandpass + connect(ui->BandpassEnabled, SIGNAL(currentTextChanged(QString)), this, SLOT(OnBandpassEnabledChanged())); + connect(ui->LowCut, SIGNAL(valueChanged(double)), this, SLOT(OnLowCutChanged())); + connect(ui->HighCut, SIGNAL(valueChanged(double)), this, SLOT(OnHighCutChanged())); +} + +//slots + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnCompensateEnergyChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + bool CompensateEnergy = ui->CompensateEnergy->isChecked(); + m_ControlInterface->SetCompensateEnergy(CompensateEnergy); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnUseBModeFilterChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + bool UseBModeFilter = ui->UseBModeFilter->isChecked(); + m_ControlInterface->SetUseBModeFilter(UseBModeFilter); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnRecordChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + if (ui->StartStopRecord->text() == "Start Recording") + { + ui->StartStopRecord->setText("Stop Recording"); + + ui->UseBModeFilter->setEnabled(false); + ui->ScatteringCoefficient->setEnabled(false); + ui->CompensateScattering->setEnabled(false); + ui->VerticalSpacing->setEnabled(false); + ui->SaveBeamformed->setEnabled(false); + ui->SaveRaw->setEnabled(false); + ui->TransmitPhaseLength->setEnabled(false); + ui->ExcitationFrequency->setEnabled(false); + ui->TransmitEvents->setEnabled(false); + ui->Voltage->setEnabled(false); + ui->Mode->setEnabled(false); + ui->ScanDepth->setEnabled(false); + ui->AveragingCount->setEnabled(false); + ui->TimeGainCompensationMinSlider->setEnabled(false); + ui->TimeGainCompensationMaxSlider->setEnabled(false); + ui->DataType->setEnabled(false); + ui->PitchOfTransducer->setEnabled(false); + ui->ReconstructedSamplesPerLine->setEnabled(false); + ui->ReconstructedLines->setEnabled(false); + ui->SpeedOfSound->setEnabled(false); + ui->BandpassEnabled->setEnabled(false); + ui->LowCut->setEnabled(false); + ui->HighCut->setEnabled(false); + ui->CompensateEnergy->setEnabled(false); + + m_ControlInterface->SetRecord(true); + } + else + { + ui->StartStopRecord->setText("Start Recording"); + + ui->UseBModeFilter->setEnabled(true); + ui->CompensateScattering->setEnabled(true); + if(ui->CompensateScattering->isChecked()) + ui->ScatteringCoefficient->setEnabled(true); + ui->VerticalSpacing->setEnabled(true); + ui->SaveBeamformed->setEnabled(true); + ui->SaveRaw->setEnabled(true); + ui->TransmitPhaseLength->setEnabled(true); + ui->ExcitationFrequency->setEnabled(true); + ui->TransmitEvents->setEnabled(true); + ui->Voltage->setEnabled(true); + ui->Mode->setEnabled(true); + ui->ScanDepth->setEnabled(true); + ui->AveragingCount->setEnabled(true); + ui->TimeGainCompensationMinSlider->setEnabled(true); + ui->TimeGainCompensationMaxSlider->setEnabled(true); + ui->DataType->setEnabled(true); + ui->PitchOfTransducer->setEnabled(true); + ui->ReconstructedSamplesPerLine->setEnabled(true); + ui->ReconstructedLines->setEnabled(true); + ui->SpeedOfSound->setEnabled(true); + ui->BandpassEnabled->setEnabled(true); + ui->LowCut->setEnabled(true); + ui->HighCut->setEnabled(true); + ui->CompensateEnergy->setEnabled(true); + + m_ControlInterface->SetRecord(false); + } +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnVerticalSpacingChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetVerticalSpacing(ui->VerticalSpacing->value()); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnScatteringCoefficientChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetScatteringCoefficient(ui->ScatteringCoefficient->value()); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnCompensateScatteringChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + if (ui->CompensateScattering->isChecked()) + ui->ScatteringCoefficient->setEnabled(true); + else + ui->ScatteringCoefficient->setEnabled(false); + + m_ControlInterface->SetCompensateScattering(ui->CompensateScattering->isChecked()); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnChangedSavingSettings() +{ + if (m_ControlInterface.IsNull()) { return; } + + mitk::USDiPhASDeviceCustomControls::SavingSettings settings; + + settings.saveBeamformed = ui->SaveBeamformed->isChecked(); + settings.saveRaw = ui->SaveRaw->isChecked(); + + m_ControlInterface->SetSavingSettings(settings); +} + +//Transmit +void QmitkUSControlsCustomDiPhASDeviceWidget::OnTransmitPhaseLengthChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetTransmitPhaseLength(ui->TransmitPhaseLength->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnExcitationFrequencyChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetExcitationFrequency(ui->ExcitationFrequency->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnTransmitEventsChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + m_ControlInterface->SetTransmitEvents(ui->TransmitEvents->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnVoltageChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetVoltage(ui->Voltage->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnModeChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + QString Mode = ui->Mode->currentText(); + bool silent = m_ControlInterface->GetSilentUpdate(); + m_ControlInterface->SetSilentUpdate(true); + + if (Mode == "Ultrasound only") { + m_ControlInterface->SetMode(false); + ui->TransmitEvents->setValue(1); + } + else if (Mode == "Interleaved") { + m_ControlInterface->SetMode(true); + ui->TransmitEvents->setValue(1); + } + if (!silent) { m_ControlInterface->SetSilentUpdate(false); } + OnTransmitEventsChanged(); +} + +//Receive +void QmitkUSControlsCustomDiPhASDeviceWidget::OnScanDepthChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetScanDepth(ui->ScanDepth->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnAveragingCountChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetAveragingCount(ui->AveragingCount->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnTGCMinChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + int tgcMin = ui->TimeGainCompensationMinSlider->value(); + int tgcMax = ui->TimeGainCompensationMaxSlider->value(); + if (tgcMin > tgcMax) { + ui->TimeGainCompensationMinSlider->setValue(tgcMax); + MITK_INFO << "User tried to set tgcMin>tgcMax."; + } + + m_ControlInterface->SetTGCMin(ui->TimeGainCompensationMinSlider->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnTGCMaxChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + int tgcMin = ui->TimeGainCompensationMinSlider->value(); + int tgcMax = ui->TimeGainCompensationMaxSlider->value(); + if (tgcMin > tgcMax) { + ui->TimeGainCompensationMaxSlider->setValue(tgcMin); + MITK_INFO << "User tried to set tgcMin>tgcMax."; + } + + m_ControlInterface->SetTGCMax(ui->TimeGainCompensationMaxSlider->value()); +} + +void QmitkUSControlsCustomDiPhASDeviceWidget::OnDataTypeChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + QString DataType = ui->DataType->currentText(); + if (DataType == "Image Data") { + m_ControlInterface->SetDataType(mitk::USDiPhASDeviceCustomControls::DataType::Image_uChar); + } + else if (DataType == "Beamformed Data") { + m_ControlInterface->SetDataType(mitk::USDiPhASDeviceCustomControls::DataType::Beamformed_Short); + } +} + +//Beamforming +void QmitkUSControlsCustomDiPhASDeviceWidget::OnPitchChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetPitch(ui->PitchOfTransducer->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnReconstructedSamplesChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + m_ControlInterface->SetReconstructedSamples(ui->ReconstructedSamplesPerLine->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnReconstructedLinesChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + if (m_OldReconstructionLines == 0) + m_OldReconstructionLines = ui->ReconstructedLines->value(); + + m_ControlInterface->SetReconstructedLines(ui->ReconstructedLines->value()); + + ui->PitchOfTransducer->setValue(ui->PitchOfTransducer->value()*((double)m_OldReconstructionLines / (double)ui->ReconstructedLines->value())); + m_OldReconstructionLines = ui->ReconstructedLines->value(); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnSpeedOfSoundChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + m_ControlInterface->SetSpeedOfSound(ui->SpeedOfSound->value()); +} + +//Bandpass +void QmitkUSControlsCustomDiPhASDeviceWidget::OnBandpassEnabledChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + if (ui->BandpassEnabled->currentText() == "On") { + m_ControlInterface->SetBandpassEnabled(true); + } + else { + m_ControlInterface->SetBandpassEnabled(false); + } +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnLowCutChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + unsigned int Low = ui->LowCut->value(); + unsigned int High = ui->HighCut->value(); + if (Low > High) { + ui->LowCut->setValue(High); + MITK_INFO << "User tried to set LowCut>HighCut."; + } + + m_ControlInterface->SetLowCut(ui->LowCut->value()); +} +void QmitkUSControlsCustomDiPhASDeviceWidget::OnHighCutChanged() +{ + if (m_ControlInterface.IsNull()) { return; } + + unsigned int Low = ui->LowCut->value(); + unsigned int High = ui->HighCut->value(); + if (Low > High) { + ui->HighCut->setValue(Low); + MITK_INFO << "User tried to set LowCut>HighCut."; + } + + m_ControlInterface->SetHighCut(ui->HighCut->value()); +} diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h new file mode 100644 index 0000000000..d80fe50018 --- /dev/null +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h @@ -0,0 +1,116 @@ + +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkUSControlsCustomDiPhASDeviceWidget_H +#define QmitkUSControlsCustomDiPhASDeviceWidget_H + +#include "QmitkUSAbstractCustomWidget.h" +#include "mitkUSDiPhASDeviceCustomControls.h" + +#include "mitkUSDevice.h" + +#include + +namespace Ui { +class QmitkUSControlsCustomDiPhASDeviceWidget; +} + +/** \brief Widget for custom controls of mitk::USDiPhASDevice. + * This class handles the itk::USDiPhASDeviceCustomControls of video device + * objects. + */ +class QmitkUSControlsCustomDiPhASDeviceWidget : public QmitkUSAbstractCustomWidget +{ + Q_OBJECT + +private slots: + virtual void OnCompensateEnergyChanged(); + virtual void OnUseBModeFilterChanged(); + virtual void OnVerticalSpacingChanged(); + virtual void OnRecordChanged(); + virtual void OnScatteringCoefficientChanged(); + virtual void OnCompensateScatteringChanged(); + virtual void OnChangedSavingSettings(); + + //Transmit + virtual void OnTransmitPhaseLengthChanged(); + virtual void OnExcitationFrequencyChanged(); + virtual void OnTransmitEventsChanged(); + virtual void OnVoltageChanged(); + virtual void OnModeChanged(); + + //Receive + virtual void OnScanDepthChanged(); + virtual void OnAveragingCountChanged(); + virtual void OnTGCMinChanged(); + virtual void OnTGCMaxChanged(); + virtual void OnDataTypeChanged(); + + //Beamforming + virtual void OnPitchChanged(); + virtual void OnReconstructedSamplesChanged(); + virtual void OnReconstructedLinesChanged(); + virtual void OnSpeedOfSoundChanged(); + + //Bandpass + virtual void OnBandpassEnabledChanged(); + virtual void OnLowCutChanged(); + virtual void OnHighCutChanged(); + +public: + /** + * Constructs widget object. All gui control elements will be disabled until + * QmitkUSAbstractCustomWidget::SetDevice() was called. + */ + explicit QmitkUSControlsCustomDiPhASDeviceWidget(QWidget *parent = 0); + ~QmitkUSControlsCustomDiPhASDeviceWidget(); + + /** + * Getter for the device class of mitk:USDiPhASDevice. + */ + virtual std::string GetDeviceClass() const override; + + /** + * Creates new QmitkUSAbstractCustomWidget with the same mitk::USDiPhASDevice + * and the same mitk::USDiPhASDeviceCustomControls which were set on the + * original object. + * + * This method is just for being calles by the factory. Use + * QmitkUSAbstractCustomWidget::CloneForQt() instead, if you want a clone of + * an object. + */ + virtual QmitkUSAbstractCustomWidget* Clone(QWidget* parent = 0) const override; + + /** + * Gets control interface from the device which was currently set. Control + * elements are according to current crop area of the device. If custom + * control interface is null, the control elements stay disabled. + */ + virtual void OnDeviceSet() override; + + virtual void Initialize() override; + +protected: + void BlockSignalAndSetValue(QSpinBox* target, int value); + +private: + Ui::QmitkUSControlsCustomDiPhASDeviceWidget* ui; + mitk::USDiPhASDeviceCustomControls::Pointer m_ControlInterface; + int m_OldReconstructionLines; +}; + +#endif // QmitkUSControlsCustomDiPhASDeviceWidget_H \ No newline at end of file diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui new file mode 100644 index 0000000000..fffb5b2e76 --- /dev/null +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui @@ -0,0 +1,661 @@ + + + QmitkUSControlsCustomDiPhASDeviceWidget + + + + 0 + 0 + 311 + 903 + + + + Form + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + QFrame::WinPanel + + + QFrame::Raised + + + Started + + + Qt::AlignCenter + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Recording Settings</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Save Beamformed Images + + + + + + + Save Raw Images + + + + + + + + + + 100 + 25 + + + + Start Recording + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Receive Parameters</span></p></body></html> + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 200 + 200 + + + + 42 + + + Qt::Horizontal + + + + + + + 42 + + + Qt::Horizontal + + + 0 + + + + + + + Scan Depth [mm] + + + + + + + 1 + + + 100 + + + 1 + + + + + + + Averaging Count + + + + + + + false + + + + Beamformed Data + + + + + Image Data + + + + + + + + 2.000000000000000 + + + 1000.000000000000000 + + + 45.000000000000000 + + + + + + + DataType + + + + + + + TGC Min + + + + + + + TGC Max + + + + + + + + + + + Compensate Fluence For Scattering + + + + + + + + + false + + + 5 + + + 25 + + + 15 + + + + + + + false + + + Avg. μs' [1/cm] + + + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Beamforming Parameters</span></p></body></html> + + + + + + + + + 256 + + + 4096 + + + 256 + + + 2048 + + + + + + + 0.010000000000000 + + + 0.050000000000000 + + + 0.300000000000000 + + + + + + + Qt::PreventContextMenu + + + 128 + + + 1024 + + + 128 + + + 128 + + + + + + + Samples per Line + + + + + + + Reconstructed Lines + + + + + + + 1000 + + + 1000000 + + + 1540 + + + + + + + Speed of Sound [m/s] + + + + + + + Pitch of Transducer [mm] + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Display Parameters</span></p></body></html> + + + + + + + + + Envelope Filter + + + true + + + + + + + Compensate Energy Values + + + + + + + + + 0.010000000000000 + + + 1.200000000000000 + + + 0.050000000000000 + + + 0.300000000000000 + + + + + + + Vertical Spacing + + + + + + + + + + + <html><head/><body><p><span style=" font-weight:600;">Transmit Parameters</span></p></body></html> + + + + + + + + + 1.000000000000000 + + + 15.000000000000000 + + + 0.100000000000000 + + + 7.500000000000000 + + + + + + + 1 + + + 1 + + + + + + + Transmit Events + + + + + + + true + + + false + + + 1 + + + 1.000000000000000 + + + 10000.000000000000000 + + + 1.000000000000000 + + + + + + + Transmit Phase Length [us] + + + + + + + Excitation Frequency [MHz] + + + + + + + false + + + + Interleaved + + + + + Ultrasound only + + + + + + + + false + + + 5 + + + 75 + + + 75 + + + + + + + Voltage [V] + + + + + + + Mode + + + + + + + + + false + + + <html><head/><body><p><span style=" font-weight:600;">Bandpass Parameters</span></p></body></html> + + + + + + + + + false + + + High Cut [MHz] + + + + + + + false + + + Low Cut [MHz] + + + + + + + false + + + Bandpass Enabled + + + + + + + false + + + + + + + false + + + 5.000000000000000 + + + + + + + false + + + + Off + + + + + On + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/Modules/USUI/files.cmake b/Modules/USUI/files.cmake index d88a79270d..037da83963 100644 --- a/Modules/USUI/files.cmake +++ b/Modules/USUI/files.cmake @@ -1,36 +1,38 @@ set(CPP_FILES mitkUSUIActivator.cpp mitkUSUICustomWidgetFactory.cpp Qmitk/QmitkUSDeviceManagerWidget.cpp Qmitk/QmitkUSNewVideoDeviceWidget.cpp Qmitk/QmitkUSControlsBModeWidget.cpp Qmitk/QmitkUSControlsDopplerWidget.cpp Qmitk/QmitkUSControlsProbesWidget.cpp Qmitk/QmitkUSControlsCustomVideoDeviceWidget.cpp + Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp Qmitk/QmitkUSAbstractCustomWidget.cpp Qmitk/QmitkComboBoxStepThrough.cpp ) set(UI_FILES Qmitk/QmitkUSDeviceManagerWidgetControls.ui Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui Qmitk/QmitkUSControlsBModeWidget.ui Qmitk/QmitkUSControlsDopplerWidget.ui Qmitk/QmitkUSControlsProbesWidget.ui Qmitk/QmitkUSControlsCustomVideoDeviceWidget.ui + Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui ) - set(MOC_H_FILES Qmitk/QmitkUSDeviceManagerWidget.h Qmitk/QmitkUSNewVideoDeviceWidget.h Qmitk/QmitkUSControlsBModeWidget.h Qmitk/QmitkUSControlsDopplerWidget.h Qmitk/QmitkUSControlsProbesWidget.h Qmitk/QmitkUSControlsCustomVideoDeviceWidget.h + Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h Qmitk/QmitkUSAbstractCustomWidget.h Qmitk/QmitkComboBoxStepThrough.h ) set(QRC_FILES resources/USUI.qrc ) diff --git a/Modules/USUI/mitkUSUIActivator.cpp b/Modules/USUI/mitkUSUIActivator.cpp index ca510835fd..23317bf34d 100644 --- a/Modules/USUI/mitkUSUIActivator.cpp +++ b/Modules/USUI/mitkUSUIActivator.cpp @@ -1,64 +1,79 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUSUIActivator.h" #include "mitkUSUICustomWidgetFactory.h" #include "QmitkUSControlsCustomVideoDeviceWidget.h" +#include "QmitkUSControlsCustomDiPhASDeviceWidget.h" mitk::USUIActivator::USUIActivator() - : m_CustomWidgetFactory(0), m_CustomVideoDeviceWidget(0) + : m_CustomWidgetFactory(0), m_CustomVideoDeviceWidget(0), m_CustomDiPhASDeviceWidget(0) { } mitk::USUIActivator::~USUIActivator() { - delete m_CustomWidgetFactory; + for(auto i : m_CustomWidgetFactory) + delete i; delete m_CustomVideoDeviceWidget; if ( m_ServiceRegistration ) { m_ServiceRegistration.Unregister(); } } void mitk::USUIActivator::Load(us::ModuleContext* context) { // create a custom video device widget, which will be used as // a prototype for the custom widget factory - if ( ! m_CustomVideoDeviceWidget ) + + if (!m_CustomVideoDeviceWidget) { m_CustomVideoDeviceWidget = new QmitkUSControlsCustomVideoDeviceWidget(); } - // create a factory for custom widgets, using the video device - // widget as a prototype - if ( ! m_CustomWidgetFactory ) + // create a custom DiPhAS device widget, which will be used as + // a prototype for the custom widget factory + + if (!m_CustomDiPhASDeviceWidget) { - m_CustomWidgetFactory = new mitk::USUICustomWidgetFactory(m_CustomVideoDeviceWidget); + m_CustomDiPhASDeviceWidget = new QmitkUSControlsCustomDiPhASDeviceWidget(); } - // register the custom widget factory as a microservice - m_ServiceRegistration = m_CustomWidgetFactory->RegisterService(context); + // create a factory for custom widgets, using the video device + // widget as a prototype + m_CustomWidgetFactory.push_back(new mitk::USUICustomWidgetFactory(m_CustomVideoDeviceWidget)); + + // create a factory for custom widgets, using the DiPhAS device + // widget as a prototype + m_CustomWidgetFactory.push_back(new mitk::USUICustomWidgetFactory(m_CustomDiPhASDeviceWidget)); + + // register the custom widget factories as a microservice + for (auto i : m_CustomWidgetFactory) + m_ServiceRegistration = i->RegisterService(context); } void mitk::USUIActivator::Unload(us::ModuleContext* /*context*/) { m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; - delete m_CustomWidgetFactory; - m_CustomWidgetFactory = 0; + for (auto i : m_CustomWidgetFactory) + delete i; + + m_CustomWidgetFactory.clear(); delete m_CustomVideoDeviceWidget; m_CustomVideoDeviceWidget = 0; } diff --git a/Modules/USUI/mitkUSUIActivator.h b/Modules/USUI/mitkUSUIActivator.h index 663871d4b0..d99d46b974 100644 --- a/Modules/USUI/mitkUSUIActivator.h +++ b/Modules/USUI/mitkUSUIActivator.h @@ -1,65 +1,67 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkUSUIActivator_h #define __mitkUSUIActivator_h #include "QmitkUSAbstractCustomWidget.h" // Microservices #include #include class QmitkUSControlsCustomVideoDeviceWidget; +class QmitkUSControlsCustomDiPhASDeviceWidget; namespace mitk { class USUICustomWidgetFactory; /** * \brief Module activator for the USUI module. * Registers custom widget for mitk::USVideoDevice as microservice. */ class USUIActivator : public us::ModuleActivator { public: USUIActivator(); virtual ~USUIActivator(); /** * Custom video device widget is registered as a micro service on module * load. A plugin can get this widget then when using a * mitk::USVideoDevice. */ void Load(us::ModuleContext* context) override; /** * Custom video device widget is deregistered from micro service on module * unload. */ void Unload(us::ModuleContext* context) override; protected: us::ServiceRegistration m_ServiceRegistration; - USUICustomWidgetFactory* m_CustomWidgetFactory; + std::vector m_CustomWidgetFactory; QmitkUSControlsCustomVideoDeviceWidget* m_CustomVideoDeviceWidget; + QmitkUSControlsCustomDiPhASDeviceWidget* m_CustomDiPhASDeviceWidget; }; } // namespace mitk US_EXPORT_MODULE_ACTIVATOR(mitk::USUIActivator) #endif // __mitkUSUIActivator_h diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 4cdec681c8..f27a7559da 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,85 +1,87 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:OFF org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF + org.mitk.gui.qt.lasercontrol:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.multilabelsegmentation:ON org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF + org.mitk.gui.qt.photoacoustics.pausviewer:OFF ) diff --git a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorViewControls.ui b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorViewControls.ui index 65e4d0d94b..e318fbc528 100644 --- a/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorViewControls.ui +++ b/Plugins/org.mitk.gui.qt.imagenavigator/src/internal/QmitkImageNavigatorViewControls.ui @@ -1,223 +1,250 @@ QmitkImageNavigatorViewControls 0 0 - 399 + 296 440 0 0 QmitkTemplate - - - - Location (mm) + + + + + 0 + 0 + - - + + - + 0 0 - - false - - - 2 - - - -100000.000000000000000 - - - 100000.000000000000000 + + + 0 + 0 + - - + + - + 0 0 - - false - - - 2 - - - -100000.000000000000000 - - - 100000.000000000000000 - - - + + - + 0 0 - - false - - - 2 - - - -100000.000000000000000 - - - 100000.000000000000000 - 0 0 Axial - - + + - + 0 0 - - - 0 - 0 - + + Sagittal - - + + 0 0 - - Sagittal + + + 7 + + + + false + + + 2 + + + -100000.000000000000000 + + + 100000.000000000000000 - - + + + + Qt::Vertical + + + + 20 + 413 + + + + + + - + 0 0 + + Time + 0 0 Coronal - - + + - + 0 0 + + + 50 + 16777215 + + + + Loc. (mm) + - - + + 0 0 - - Time + + + 7 + + + + false + + + 2 + + + -100000.000000000000000 + + + 100000.000000000000000 - - + + - + 0 0 - - - - - - Qt::Vertical + + + 7 + - - - 20 - 413 - + + false - + + 2 + + + -100000.000000000000000 + + + 100000.000000000000000 + + QmitkSliderNavigatorWidget QWidget
QmitkSliderNavigatorWidget.h
1
QmitkDataStorageComboBox.h
diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt b/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt new file mode 100644 index 0000000000..b9d5a1cf05 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt @@ -0,0 +1,20 @@ +project(org_mitk_gui_qt_lasercontrol) + +IF(WIN32) + configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclib.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclibo.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclib.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclibo.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Debug/OphirPyroWrapper.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Release/OphirPyroWrapper.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Debug/OphirLMMeasurement.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Release/OphirLMMeasurement.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Debug/Interop.OphirLMMeasurementLib.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_OPHIR_API_PATH}/Release/Interop.OphirLMMeasurementLib.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) +ENDIF(WIN32) + +mitk_create_plugin( + EXPORT_DIRECTIVE LASERCONTROL_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkPhotoacousticsHardware +) diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..69fb486784 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/Manual.dox @@ -0,0 +1,17 @@ +/** +\page org_mitk_gui_qt_lasercontrol The Lasercontrol + +\imageMacro{icon.png,"Icon of Lasercontrol",2.00} + +\tableofcontents + +\section org_mitk_gui_qt_lasercontrolOverview Overview +Describe the features of your awesome plugin here +
    +
  • Increases productivity +
  • Creates beautiful images +
  • Generates PhD thesis +
  • Brings world peace +
+ +*/ diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..9057c20bc6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/UserManual/icon.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static const char * icon_xpm[] = { +"16 16 2 1", +" c #FF0000", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..1ecfa33fe9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_lasercontrol org.mitk.gui.qt.lasercontrol + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_lasercontrol_internal Internal + \ingroup org_mitk_gui_qt_lasercontrol + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.lasercontrol plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/files.cmake b/Plugins/org.mitk.gui.qt.lasercontrol/files.cmake new file mode 100644 index 0000000000..55ea3038dc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/files.cmake @@ -0,0 +1,37 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + mitkLaserControlPluginActivator.cpp + QmitkLaserControl.cpp + +) + +set(UI_FILES + src/internal/QmitkLaserControlControls.ui +) + +set(MOC_H_FILES + src/internal/mitkLaserControlPluginActivator.h + src/internal/QmitkLaserControl.h +) + +set(CACHED_RESOURCE_FILES + resources/iconLaser.xpm + plugin.xml +) + +set(QRC_FILES + +) + +set(CPP_FILES) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.lasercontrol/manifest_headers.cmake new file mode 100644 index 0000000000..a0b4a00020 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "MITK OPO Laser Control") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common.legacy) diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/plugin.xml b/Plugins/org.mitk.gui.qt.lasercontrol/plugin.xml new file mode 100644 index 0000000000..8bc554dbfe --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/resources/iconLaser.xpm b/Plugins/org.mitk.gui.qt.lasercontrol/resources/iconLaser.xpm new file mode 100644 index 0000000000..e2c5d7c620 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/resources/iconLaser.xpm @@ -0,0 +1,133 @@ +/* XPM */ +static char * iconLaser_xpm[] = { +"128 128 2 1", +" c None", +". c #000000", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .......... ", +" .. .......... ", +" .... .......... ", +" ....... .......... ", +" ........ .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" .......... .......... ", +" ......... .......... ", +" .......... .......... ", +" ......... .......... ", +" .......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .......... ", +" ......... .............. ", +" ......... .................. ", +" ...... .................... ", +" .... ...................... ", +" .. ........................ ", +" ........................ ", +" .......................... ", +" ............................ ", +" ............................ ", +" ............................ ", +" .............................. .................. ", +" .............................. ........................................ ", +" .............................. ........................................ ", +" .............................. ........................................ ", +" .............................. ......................................... ", +" .............................. ................................. ", +" .............................. ..... ", +" ............................ ", +" ............................ ", +" ............................ ", +" .......................... ", +" . ........................ ", +" ... ........................ ", +" ...... ...................... ", +" ........ .................... ", +" ........... .................. .. ", +" ........... .............. .... ", +" .......... .......... ....... ", +" ......... ........ ", +" ........ . ........ ", +" ..... ... ........ ", +" ... ...... ........ ", +" ... ..... ....... ", +" ..... ...... ....... ", +" ..... ..... ....... ", +" ..... ...... ....... ", +" ...... ..... ....... ", +" ..... ...... ....... ", +" ..... ..... ....... ", +" ..... ...... ....... ", +" ...... ..... ....... ", +" ..... ...... ........ ", +" ..... ..... ........ ", +" ..... ...... ........ ", +" ...... ..... ........ ", +" ..... ...... ....... ", +" ..... ..... ....... ", +" ..... ...... ....... ", +" ...... ..... ....... ", +" ..... ...... ....... ", +" ..... ..... ....... ", +" ..... ...... ....... ", +" ...... ..... ....... ", +" ..... ...... ....... ", +" ..... ..... ....... ", +" ..... ...... ........ ", +" ...... ..... ........ ", +" ..... ...... ........ ", +" ..... ...... ........ ", +" ..... ...... ........ ", +" ...... ...... ..... ", +" ..... ...... ... ", +" ..... ...... . ", +" ..... ...... ", +" ...... ..... ", +" ..... ... ", +" . ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.cpp b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.cpp new file mode 100644 index 0000000000..0100d6b356 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.cpp @@ -0,0 +1,368 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkLaserControl.h" + +// Qt +#include +#include + +const std::string OPOLaserControl::VIEW_ID = "org.mitk.views.lasercontrol"; + +void OPOLaserControl::SetFocus() +{ +} + +void OPOLaserControl::CreateQtPartControl(QWidget *parent) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi(parent); + connect(m_Controls.buttonInitLaser, SIGNAL(clicked()), this, SLOT(InitLaser())); + connect(m_Controls.buttonTune, SIGNAL(clicked()), this, SLOT(TuneWavelength())); + connect(m_Controls.buttonFastTuning, SIGNAL(clicked()), this, SLOT(StartFastTuning())); + connect(m_Controls.buttonFlashlamp, SIGNAL(clicked()), this, SLOT(ToggleFlashlamp())); + connect(m_Controls.buttonQSwitch, SIGNAL(clicked()), this, SLOT(ToggleQSwitch())); + connect(m_Controls.sliderWavelength, SIGNAL(valueChanged(int)), this, SLOT(SyncWavelengthSetBySlider())); + connect(m_Controls.spinBoxWavelength, SIGNAL(valueChanged(double)), this, SLOT(SyncWavelengthSetBySpinBox())); + connect(&m_ShutterWatcher, SIGNAL(finished()), this, SLOT(EnableLaser())); + + m_SyncFromSpinBox = true; + m_SyncFromSlider = true; + + m_PumpLaserConnected = false; + m_OPOConnected = false; + m_PyroConnected = false; +} + +void OPOLaserControl::EnableLaser() +{ + m_Controls.buttonQSwitch->setEnabled(true); + m_Controls.buttonQSwitch->setText("Start Laser"); + this->GetState(); +} + +void OPOLaserControl::SyncWavelengthSetBySlider() +{ + if (m_SyncFromSlider) + { + m_SyncFromSpinBox = false; + m_Controls.spinBoxWavelength->setValue(m_Controls.sliderWavelength->value() / 10); + } + else + m_SyncFromSlider = true; +} + +void OPOLaserControl::SyncWavelengthSetBySpinBox() +{ + if (m_SyncFromSpinBox) + { + m_SyncFromSlider = false; + m_Controls.sliderWavelength->setValue(m_Controls.spinBoxWavelength->value() * 10); + } + else + m_SyncFromSpinBox = true; +} + +void OPOLaserControl::InitLaser() +{ + m_Controls.buttonInitLaser->setEnabled(false); + m_Controls.buttonInitLaser->setText("working ..."); + + if (!m_PumpLaserConnected) + { + m_PumpLaserController = mitk::QuantelLaser::New(); + + if (m_PumpLaserController->OpenConnection("OpotekPhocusMobile")) + { + m_Controls.buttonFlashlamp->setEnabled(true); + m_Controls.buttonQSwitch->setEnabled(false); + m_Controls.buttonInitLaser->setText("Reset and Release Laser"); + + std::string answer(""); + std::string triggerCommand("TRIG "); + if (m_Controls.checkBoxTriggerExternally->isChecked()) + { + triggerCommand.append("EE"); // set both Triggers external + m_PumpLaserController->SendAndReceiveLine(&triggerCommand, &answer); + MITK_INFO << answer; + } + else + { + triggerCommand.append("II"); // set both Triggers internal + m_PumpLaserController->SendAndReceiveLine(&triggerCommand, &answer); + MITK_INFO << answer; + std::string energyCommand("QDLY 30"); + m_PumpLaserController->SendAndReceiveLine(&energyCommand, &answer); + MITK_INFO << answer; + } + + m_PumpLaserConnected = true; + this->GetState(); + } + else + { + QMessageBox::warning(NULL, "Laser Control", "Opotek Pump Laser Initialization Failed."); + m_Controls.buttonInitLaser->setText("Init Laser"); + m_Controls.buttonInitLaser->setEnabled(true); + return; + } + } + else + { + // destroy and free + if (m_PumpLaserController->CloseConnection()) + { + m_Controls.buttonFlashlamp->setEnabled(false); + m_Controls.buttonQSwitch->setEnabled(false); + m_Controls.buttonInitLaser->setText("Init Laser"); + m_PumpLaserConnected = false; + } + else + { + QMessageBox::warning(NULL, "Laser Control", "Opotek Pump Laser Release Failed."); + m_Controls.buttonInitLaser->setText("Reset and Release Laser"); + } + } + + if (!m_OPOConnected) + { + m_OPOMotor = mitk::GalilMotor::New(); + if (m_OPOMotor->OpenConnection("OpotekPhocusMobile")) + { + m_Controls.buttonTune->setEnabled(true); + m_Controls.buttonFastTuning->setEnabled(true); + m_Controls.sliderWavelength->setMinimum(m_OPOMotor->GetMinWavelength() * 10); + m_Controls.sliderWavelength->setMaximum(m_OPOMotor->GetMaxWavelength() * 10); + m_Controls.spinBoxWavelength->setMinimum(m_OPOMotor->GetMinWavelength()); + m_Controls.spinBoxWavelength->setMaximum(m_OPOMotor->GetMaxWavelength()); + m_Controls.sliderWavelength->setValue(m_OPOMotor->GetCurrentWavelength() * 10); + m_Controls.spinBoxWavelength->setValue(m_OPOMotor->GetCurrentWavelength()); + m_OPOConnected = true; // not always right FIXME + } + else + { + QMessageBox::warning(NULL, "Laser Control", "OPO Initialization Failed."); + m_Controls.buttonInitLaser->setText("Init Laser"); + } + } + else + { + // destroy and free + if (m_OPOMotor->CloseConnection()) + { + m_Controls.buttonTune->setEnabled(false); + m_Controls.buttonFastTuning->setEnabled(false); + m_Controls.buttonInitLaser->setText("Init Laser"); + m_OPOConnected = false; + } + else + { + QMessageBox::warning(NULL, "Laser Control", "OPO Release Failed."); + m_Controls.buttonInitLaser->setText("Reset and Release Laser"); + } + } + m_Controls.buttonInitLaser->setEnabled(true); + this->GetState(); + /* + try + { + if (!m_PyroConnected) + { + m_Pyro = mitk::OphirPyro::New(); + MITK_INFO << "[Pyro Debug] OpenConnection: " << m_Pyro->OpenConnection(); + MITK_INFO << "[Pyro Debug] StartDataAcquisition: " << m_Pyro->StartDataAcquisition(); + m_CurrentPulseEnergy = 0; + m_PyroConnected = true; + //QFuture future = QtConcurrent::run(this, &OPOLaserControl::ShowEnergy); + //m_EnergyWatcher.setFuture(future); + } + else + { + m_PyroConnected = false; + } + } catch (...) { + MITK_INFO << " While trying to connect to the Pyro an exception was caught (this almost always happens on the first try after reboot - try again!)"; + m_PyroConnected = false; + }*/ +} + +void OPOLaserControl::TuneWavelength() +{ + if (m_Controls.checkBoxCalibration->isChecked()) + { + m_OPOMotor->TuneToWavelength(m_Controls.spinBoxPosition->value(), true); + } + else + { + m_OPOMotor->TuneToWavelength(m_Controls.spinBoxWavelength->value(), false); + } + QString wavelengthText = QString::number(m_OPOMotor->GetCurrentWavelength()); + wavelengthText.append("nm"); + m_Controls.labelWavelength->setText(wavelengthText); +} + +void OPOLaserControl::StartFastTuning() +{ + std::vector listOfWavelengths; + double tmpWavelength = 0; + int currentRow = 0; + bool success = false; + + do + { + if (currentRow != 0) listOfWavelengths.push_back(tmpWavelength); + if (m_Controls.tableFastTuningWavelengths->item(0, currentRow)) + { + QString test = m_Controls.tableFastTuningWavelengths->item(0, currentRow)->text(); + tmpWavelength = test.toDouble(&success); + currentRow++; + } + else + tmpWavelength = 0; + + if (success == 0) + tmpWavelength = 0; + } while (tmpWavelength<950.1 && tmpWavelength>689.9); + + m_OPOMotor->FastTuneWavelengths(listOfWavelengths); +} + +void OPOLaserControl::ShutterCountDown() +{ + m_Controls.buttonFlashlamp->setText("Stop Lamp"); + m_Controls.buttonQSwitch->setEnabled(false); + m_Controls.buttonQSwitch->setText("10s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("9s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("8s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("7s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("6s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("5s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("4s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("3s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("2s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + m_Controls.buttonQSwitch->setText("1s ..."); + std::this_thread::sleep_for(std::chrono::seconds(1)); + return; +} + +void OPOLaserControl::ShowEnergy() +{ + /*forever + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + MITK_INFO << "[Pyro Debug] ShowEnergy()"; + if (!m_PyroConnected) + { + MITK_INFO << "[Pyro Debug] StopDataAcquisition: " << m_Pyro->StopDataAcquisition(); + MITK_INFO << "[Pyro Debug] CloseConnection: " << m_Pyro->CloseConnection(); + m_CurrentPulseEnergy = 0; + return; + } + // m_Pyro->GetDataFromSensor(); + m_CurrentPulseEnergy = 60000 * m_Pyro->LookupCurrentPulseEnergy(); + m_Controls.labelEnergy->setText(std::to_string(m_CurrentPulseEnergy).append(" mJ").c_str()); + }*/ +} + +void OPOLaserControl::ToggleFlashlamp() +{ + m_Controls.buttonFlashlamp->setText("..."); + if (!m_PumpLaserController->IsFlashing()) + { + if (m_PumpLaserController->StartFlashing()) + { + QFuture future = QtConcurrent::run(this, &OPOLaserControl::ShutterCountDown); + m_ShutterWatcher.setFuture(future); + } + else + m_Controls.buttonFlashlamp->setText("Start Lamp"); + } + else + { + if (m_PumpLaserController->StopFlashing()) + { + m_Controls.buttonFlashlamp->setText("Start Lamp"); + m_Controls.buttonQSwitch->setText("Start Laser"); + m_Controls.buttonQSwitch->setEnabled(false); + } + else + m_Controls.buttonFlashlamp->setText("Stop Lamp"); + } + this->GetState(); +} + +void OPOLaserControl::ToggleQSwitch() +{ + m_Controls.buttonQSwitch->setText("..."); + if (!m_PumpLaserController->IsEmitting()) + { + if (m_PumpLaserController->StartQswitching()) + m_Controls.buttonQSwitch->setText("Stop Laser"); + else + m_Controls.buttonQSwitch->setText("Start Laser"); + } + else + { + if (m_PumpLaserController->StopQswitching()) + m_Controls.buttonQSwitch->setText("Start Laser"); + else + m_Controls.buttonQSwitch->setText("Stop Laser"); + } + this->GetState(); +} + +void OPOLaserControl::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes) +{ +} + +void OPOLaserControl::GetState() +{ + mitk::QuantelLaser::LaserState pumpLaserState = m_PumpLaserController->GetState(); + + if (pumpLaserState == mitk::QuantelLaser::STATE0) + m_Controls.labelStatus->setText("PL0: Boot Fault."); + else if (pumpLaserState == mitk::QuantelLaser::STATE1) + m_Controls.labelStatus->setText("PL1: Warm Up."); + else if (pumpLaserState == mitk::QuantelLaser::STATE2) + m_Controls.labelStatus->setText("PL2: Laser Ready."); + else if (pumpLaserState == mitk::QuantelLaser::STATE3) + m_Controls.labelStatus->setText("PL3: Flashing. Pulse Disabled."); + else if (pumpLaserState == mitk::QuantelLaser::STATE4) + m_Controls.labelStatus->setText("PL4: Flashing. Shutter Closed."); + else if (pumpLaserState == mitk::QuantelLaser::STATE5) + m_Controls.labelStatus->setText("PL5: Flashing. Shutter Open."); + else if (pumpLaserState == mitk::QuantelLaser::STATE6) + m_Controls.labelStatus->setText("PL6: Flashing. Pulse Enabled."); + else if (pumpLaserState == mitk::QuantelLaser::STATE7) + m_Controls.labelStatus->setText("PL7: Undefined State."); + else if (pumpLaserState == mitk::QuantelLaser::UNCONNECTED) + m_Controls.labelStatus->setText("PL Not Connected."); +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.h b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.h new file mode 100644 index 0000000000..abf6c1f227 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControl.h @@ -0,0 +1,100 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef OPOLaserControl_h +#define OPOLaserControl_h + +#include + +#include + +#include "ui_QmitkLaserControlControls.h" + +#include +#include + +// Photoacoustics Hardware +#include +#include +//#include + +#include + +/** + \brief OPOLaserControl + + \warning This class is not yet documented. Use "git blame" and ask the author why he is a lazy fuck. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class OPOLaserControl : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + + static const std::string VIEW_ID; + + protected slots: + + /// \brief Called when the user clicks the GUI button + void GetState(); + + void InitLaser(); + void TuneWavelength(); + void StartFastTuning(); + + void ShutterCountDown(); + void EnableLaser(); + void ShowEnergy(); + + void ToggleFlashlamp(); + void ToggleQSwitch(); + void SyncWavelengthSetBySlider(); + void SyncWavelengthSetBySpinBox(); + + protected: + + virtual void CreateQtPartControl(QWidget *parent) override; + + virtual void SetFocus() override; + + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes ) override; + + Ui::OPOLaserControlControls m_Controls; + bool m_PumpLaserConnected; + bool m_OPOConnected; + bool m_PyroConnected; + bool m_SyncFromSpinBox; + bool m_SyncFromSlider; + double m_CurrentPulseEnergy; + + QFutureWatcher m_ShutterWatcher; + QFutureWatcher m_EnergyWatcher; + + mitk::QuantelLaser::Pointer m_PumpLaserController; + mitk::GalilMotor::Pointer m_OPOMotor; + //mitk::OphirPyro::Pointer m_Pyro; + +}; + +#endif // OPOLaserControl_h diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControlControls.ui b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControlControls.ui new file mode 100644 index 0000000000..903c570711 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/QmitkLaserControlControls.ui @@ -0,0 +1,726 @@ + + + OPOLaserControlControls + + + + 0 + 0 + 309 + 433 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + OPOTEK Phocus Control + + + + + 10 + 20 + 271 + 332 + + + + + + + true + + + Trigger Externally + + + true + + + + + + + Init Laser + + + + + + + + + false + + + Start Lamp + + + + + + + false + + + Start Laser + + + + + + + + + + 9 + 75 + true + + + + Laser Status + + + + + + + + + Current Wavelength + + + + + + + + 9 + 75 + true + PreferDefault + true + + + + 750.0 nm + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Pulse Energy + + + + + + + + 9 + 75 + true + PreferDefault + true + + + + 0 mJ + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + 6900 + + + 9500 + + + 5 + + + 100 + + + 7500 + + + Qt::Horizontal + + + QSlider::NoTicks + + + 10000 + + + + + + + + + 1 + + + 690.000000000000000 + + + 950.000000000000000 + + + 0.500000000000000 + + + 750.000000000000000 + + + + + + + nm + + + + + + + false + + + Tune + + + + + + + + + + 8 + 50 + false + + + + Fast Tuning Wavelengths + + + + + + + + 16777215 + 62 + + + + true + + + Qt::SolidLine + + + 42 + + + 50 + + + 20 + + + 20 + + + + λ/nm + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + 10 + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + 15 + + + + + 16 + + + + + 17 + + + + + 18 + + + + + 19 + + + + + 20 + + + + + 21 + + + + + 22 + + + + + 23 + + + + + 24 + + + + + 25 + + + + + 26 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 30 + + + + + 31 + + + + + 32 + + + + + 33 + + + + + 34 + + + + + 35 + + + + + 36 + + + + + 37 + + + + + 38 + + + + + 39 + + + + + 40 + + + + + 690 + + + + + 690 + + + + + 690 + + + + + 690 + + + + + 690 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + 800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + Start Fast Tuning + + + + + + + + + 10 + 350 + 191 + 31 + + + + + + + calibrate OPO + + + + + + + 50000 + + + 400 + + + 24400 + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.cpp b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.cpp new file mode 100644 index 0000000000..3b5a2c05f5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.cpp @@ -0,0 +1,33 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkLaserControlPluginActivator.h" +#include "QmitkLaserControl.h" + +namespace mitk { + +void org_mitk_gui_qt_lasercontrol_Activator::start(ctkPluginContext* context) +{ + BERRY_REGISTER_EXTENSION_CLASS(OPOLaserControl, context) +} + +void org_mitk_gui_qt_lasercontrol_Activator::stop(ctkPluginContext* context) +{ + Q_UNUSED(context) +} + +} diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.h b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.h new file mode 100644 index 0000000000..65875a7f75 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.lasercontrol/src/internal/mitkLaserControlPluginActivator.h @@ -0,0 +1,41 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef org_mitk_gui_qt_lasercontrol_Activator_h +#define org_mitk_gui_qt_lasercontrol_Activator_h + +#include + +namespace mitk { + +class org_mitk_gui_qt_lasercontrol_Activator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_lasercontrol") + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + +}; // org_mitk_gui_qt_lasercontrol_Activator + +} + +#endif // org_mitk_gui_qt_lasercontrol_Activator_h diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/CMakeLists.txt b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/CMakeLists.txt new file mode 100644 index 0000000000..37b3269ee4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/CMakeLists.txt @@ -0,0 +1,9 @@ +# The project name must correspond to the directory name of your plug-in +# and must not contain periods. +project(org_mitk_gui_qt_photoacoustics_pausviewer) + +mitk_create_plugin( + EXPORT_DIRECTIVE PHOTOACOUSTICS_PAUSVIEWER_EXPORTS + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgets +) diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/files.cmake b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/files.cmake new file mode 100644 index 0000000000..a9177ae3a3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/files.cmake @@ -0,0 +1,29 @@ +set(SRC_CPP_FILES + QmitkPAUSViewerView.cpp +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_photoacoustics_pausviewer_Activator.cpp +) + +set(UI_FILES + src/internal/QmitkPAUSViewerViewControls.ui +) + +set(MOC_H_FILES + src/QmitkPAUSViewerView.h + src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.h +) + +set(CACHED_RESOURCE_FILES + resources/PAUSViewer.png + plugin.xml +) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/manifest_headers.cmake new file mode 100644 index 0000000000..b0abe671c4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "PA US Viewer") +set(Plugin-Version "0.9") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/plugin.xml b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/plugin.xml new file mode 100644 index 0000000000..f2bda668ae --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/resources/PAUSViewer.png b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/resources/PAUSViewer.png new file mode 100644 index 0000000000..7846083408 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/resources/PAUSViewer.png differ diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp new file mode 100644 index 0000000000..5b5c64bc40 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp @@ -0,0 +1,130 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// Blueberry +#include +#include +#include "mitkScaleLegendOverlay.h" + +#include "QmitkPAUSViewerView.h" + +const std::string QmitkPAUSViewerView::VIEW_ID = "org.mitk.views.photoacoustics.pausviewer"; + +QmitkPAUSViewerView::QmitkPAUSViewerView() : m_PADataStorage(mitk::StandaloneDataStorage::New()), m_USDataStorage(mitk::StandaloneDataStorage::New()), m_UltrasoundReference(nullptr) +{ +} + +QmitkPAUSViewerView::~QmitkPAUSViewerView() +{ + if(m_UltrasoundReference != nullptr) + *m_UltrasoundReference = nullptr; +} + +void QmitkPAUSViewerView::InitWindows() +{ + AddOverlays(); +} + +void QmitkPAUSViewerView::SetFocus() +{ +} + +void QmitkPAUSViewerView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes) +{ +} + +void QmitkPAUSViewerView::CreateQtPartControl(QWidget *parent) +{ + m_Controls = new Ui::QmitkPAUSViewerViewControls; + m_Controls->setupUi(parent); + + m_Controls->m_PARenderWindow->GetRenderer()->SetDataStorage(m_PADataStorage); + m_Controls->m_USRenderWindow->GetRenderer()->SetDataStorage(m_USDataStorage); +} + +void QmitkPAUSViewerView::SetPADataStorage(mitk::StandaloneDataStorage::Pointer paStore) +{ + if (m_Controls == nullptr) + return; + + m_PADataStorage = paStore; + m_Controls->m_PARenderWindow->GetRenderer()->SetDataStorage(m_PADataStorage); + m_Controls->m_PALevelWindow->SetDataStorage(m_PADataStorage); +} + +void QmitkPAUSViewerView::SetUSDataStorage(mitk::StandaloneDataStorage::Pointer usStore) +{ + if (m_Controls == nullptr) + return; + + m_USDataStorage = usStore; + m_Controls->m_USRenderWindow->GetRenderer()->SetDataStorage(m_USDataStorage); + m_Controls->m_USLevelWindow->SetDataStorage(m_USDataStorage); +} + +vtkRenderWindow* QmitkPAUSViewerView::GetPARenderWindow() +{ + if (m_Controls == nullptr) + return nullptr; + + return m_Controls->m_PARenderWindow->GetRenderWindow(); +} + +vtkRenderWindow* QmitkPAUSViewerView::GetUSRenderWindow() +{ + if (m_Controls == nullptr) + return nullptr; + + return m_Controls->m_USRenderWindow->GetRenderWindow(); +} + + +void QmitkPAUSViewerView::AddOverlays() +{ + if (m_PARenderer == nullptr || m_PAOverlayManager == nullptr || m_USRenderer == nullptr || m_USOverlayManager == nullptr) + { + //setup an overlay manager + mitk::OverlayManager::Pointer OverlayManagerInstancePA = mitk::OverlayManager::New(); + m_PARenderer = mitk::BaseRenderer::GetInstance(GetPARenderWindow()); + m_PARenderer->SetOverlayManager(OverlayManagerInstancePA); + m_PAOverlayManager = m_PARenderer->GetOverlayManager(); + + mitk::OverlayManager::Pointer OverlayManagerInstanceUS = mitk::OverlayManager::New(); + m_USRenderer = mitk::BaseRenderer::GetInstance(GetUSRenderWindow()); + m_USRenderer->SetOverlayManager(OverlayManagerInstanceUS); + m_USOverlayManager = m_USRenderer->GetOverlayManager(); + } + + mitk::ScaleLegendOverlay::Pointer scaleOverlay = mitk::ScaleLegendOverlay::New(); + scaleOverlay->SetLeftAxisVisibility(true); + scaleOverlay->SetRightAxisVisibility(false); + scaleOverlay->SetRightAxisVisibility(false); + scaleOverlay->SetTopAxisVisibility(false); + scaleOverlay->SetCornerOffsetFactor(0); + m_PAOverlayManager->AddOverlay(scaleOverlay.GetPointer()); + m_USOverlayManager->AddOverlay(scaleOverlay.GetPointer()); +} + +void QmitkPAUSViewerView::RemoveOverlays() +{ + m_PAOverlayManager->RemoveAllOverlays(); +} + +void QmitkPAUSViewerView::SetUltrasoundReference(QmitkPAUSViewerView** ultrasoundReference) +{ + m_UltrasoundReference = ultrasoundReference; +} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.h b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.h new file mode 100644 index 0000000000..31c695c60b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.h @@ -0,0 +1,79 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKPAUSVIEWERVIEW_H_INCLUDED +#define QMITKPAUSVIEWERVIEW_H_INCLUDED + +#include +#include +#include +#include +#include "QmitkRenderWindow.h" +#include + +#include "ui_QmitkPAUSViewerViewControls.h" +#include "org_mitk_gui_qt_photoacoustics_pausviewer_Export.h" + +#include "mitkCommon.h" + +class PHOTOACOUSTICS_PAUSVIEWER_EXPORTS QmitkPAUSViewerView : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + + static const std::string VIEW_ID; + + QmitkPAUSViewerView(); + virtual ~QmitkPAUSViewerView(); + + virtual void CreateQtPartControl(QWidget *parent) override; + void InitWindows(); + + void SetPADataStorage(mitk::StandaloneDataStorage::Pointer paStore); + void SetUSDataStorage(mitk::StandaloneDataStorage::Pointer usStore); + + vtkRenderWindow* GetPARenderWindow(); + vtkRenderWindow* GetUSRenderWindow(); + + void SetUltrasoundReference(QmitkPAUSViewerView** ultrasoundReference); + +protected: + + void AddOverlays(); + void RemoveOverlays(); + + mitk::StandaloneDataStorage::Pointer m_PADataStorage; + mitk::StandaloneDataStorage::Pointer m_USDataStorage; + + mitk::OverlayManager::Pointer m_PAOverlayManager; + mitk::OverlayManager::Pointer m_USOverlayManager; + mitk::BaseRenderer::Pointer m_PARenderer; + mitk::BaseRenderer::Pointer m_USRenderer; + + virtual void SetFocus() override; + + virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, + const QList& nodes) override; + + Ui::QmitkPAUSViewerViewControls* m_Controls; + QmitkPAUSViewerView** m_UltrasoundReference; +}; + +#endif // QMITKPAUSVIEWERVIEW_H_INCLUDED + diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/QmitkPAUSViewerViewControls.ui b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/QmitkPAUSViewerViewControls.ui new file mode 100644 index 0000000000..8d192e8de4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/QmitkPAUSViewerViewControls.ui @@ -0,0 +1,129 @@ + + + QmitkPAUSViewerViewControls + + + + 0 + 0 + 1086 + 744 + + + + + 0 + 0 + + + + QmitkTemplate + + + false + + + + + + + + + 0 + 0 + + + + + + + + + 75 + true + + + + Ultrasound + + + + + + + + 0 + 0 + + + + + + + + + 75 + true + + + + Photoacoustics + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + + + + + QmitkRenderWindow + QListView +
QmitkRenderWindow.h
+
+ + QmitkLevelWindowWidget + QWidget +
QmitkLevelWindowWidget.h
+ 1 +
+
+ + QmitkDataStorageComboBox.h + + + +
diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.cpp b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.cpp new file mode 100644 index 0000000000..6c6193b374 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.cpp @@ -0,0 +1,33 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_gui_qt_photoacoustics_pausviewer_Activator.h" +#include "QmitkPAUSViewerView.h" + + +namespace mitk { + + void org_mitk_gui_qt_photoacoustics_pausviewer_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(QmitkPAUSViewerView, context) + } + + void org_mitk_gui_qt_photoacoustics_pausviewer_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context) + } + +} diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.h b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.h new file mode 100644 index 0000000000..e91e4d7f07 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/internal/org_mitk_gui_qt_photoacoustics_pausviewer_Activator.h @@ -0,0 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef _MITKPAUSVIEWERPLUGINACTIVATOR_H +#define _MITKPAUSVIEWERPLUGINACTIVATOR_H + +#include + +namespace mitk { + + class org_mitk_gui_qt_photoacoustics_pausviewer_Activator : + public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_photoacoustics_pausviewer") + Q_INTERFACES(ctkPluginActivator) + + public: + + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; + + }; + +} + +#endif // _MITKPAUSVIEWERPLUGINACTIVATOR_H diff --git a/Plugins/org.mitk.gui.qt.ultrasound/CMakeLists.txt b/Plugins/org.mitk.gui.qt.ultrasound/CMakeLists.txt index bd69a27e0c..b7b4f50565 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.ultrasound/CMakeLists.txt @@ -1,9 +1,25 @@ project(org_mitk_gui_qt_ultrasound) include_directories(${CTK_INCLUDE_DIRS}) +IF(WIN32) + IF(MITK_USE_US_DiPhAS_SDK) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Debug/Framework.IBMT.US.Core.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Debug/Framework.IBMT.US.CWrapper.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Debug/Framework.IBMT.US.OpenCL.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Debug/Framework.IBMT.US.PCIeInterface.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Debug/openclext.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) + + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Release/Framework.IBMT.US.Core.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Release/Framework.IBMT.US.CWrapper.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Release/Framework.IBMT.US.OpenCL.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Release/Framework.IBMT.US.PCIeInterface.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + configure_file( ${MITK_US_DiPhAS_SDK_PATH}/Release/openclext.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) + ENDIF(MITK_USE_US_DiPhAS_SDK) +ENDIF(WIN32) + mitk_create_plugin( EXPORT_DIRECTIVE ULTRASOUND_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt MitkUS MitkUSUI ) diff --git a/Plugins/org.mitk.gui.qt.ultrasound/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.ultrasound/manifest_headers.cmake index 182113f62b..ef169719cb 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/manifest_headers.cmake +++ b/Plugins/org.mitk.gui.qt.ultrasound/manifest_headers.cmake @@ -1,5 +1,5 @@ set(Plugin-Name "Ultrasound") set(Plugin-Version "0.1") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "") -set(Require-Plugin org.mitk.gui.qt.common) +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.photoacoustics.pausviewer) diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp index 25cbd1abec..fdd4707e25 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp @@ -1,500 +1,697 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include +#include //Mitk #include #include #include #include #include +#include +#include +#include +#include +#include +#include "QmitkRegisterClasses.h" +#include "QmitkRenderWindow.h" +#include +#include // Qmitk #include "UltrasoundSupport.h" - // Qt #include #include #include // Ultrasound #include "mitkUSDevice.h" #include "QmitkUSAbstractCustomWidget.h" #include #include #include "usServiceReference.h" #include "internal/org_mitk_gui_qt_ultrasound_Activator.h" +#include "mitkNodePredicateDataType.h" +#include const std::string UltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport"; void UltrasoundSupport::SetFocus() { } void UltrasoundSupport::CreateQtPartControl(QWidget *parent) { //initialize timers m_UpdateTimer = new QTimer(this); m_RenderingTimer2d = new QTimer(this); m_RenderingTimer3d = new QTimer(this); // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); //load persistence data before connecting slots (so no slots are called in this phase...) LoadUISettings(); //connect signals and slots... connect(m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this, SLOT(OnClickedAddNewDevice())); // Change Widget Visibilities connect(m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this->m_Controls.m_NewVideoDeviceWidget, SLOT(CreateNewDevice())); // Init NewDeviceWidget connect(m_Controls.m_ActiveVideoDevices, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnChangedActiveDevice())); connect(m_Controls.m_RunImageTimer, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice())); connect(m_Controls.m_ShowImageStream, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice())); connect(m_Controls.m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone())); // After NewDeviceWidget finished editing connect(m_Controls.m_FrameRatePipeline, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls.m_FrameRate2d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls.m_FrameRate3d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit())); connect(m_Controls.m_FreezeButton, SIGNAL(clicked()), this, SLOT(OnClickedFreezeButton())); connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateImage())); connect(m_RenderingTimer2d, SIGNAL(timeout()), this, SLOT(RenderImage2d())); connect(m_RenderingTimer3d, SIGNAL(timeout()), this, SLOT(RenderImage3d())); connect(m_Controls.m_Update2DView, SIGNAL(clicked()), this, SLOT(StartTimers())); connect(m_Controls.m_Update3DView, SIGNAL(clicked()), this, SLOT(StartTimers())); connect(m_Controls.m_DeviceManagerWidget, SIGNAL(EditDeviceButtonClicked(mitk::USDevice::Pointer)), this, SLOT(OnClickedEditDevice())); //Change Widget Visibilities connect(m_Controls.m_DeviceManagerWidget, SIGNAL(EditDeviceButtonClicked(mitk::USDevice::Pointer)), this->m_Controls.m_NewVideoDeviceWidget, SLOT(EditDevice(mitk::USDevice::Pointer))); // Initializations m_Controls.m_NewVideoDeviceWidget->setVisible(false); std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE + "=true))"; m_Controls.m_ActiveVideoDevices->Initialize( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, filter); m_Controls.m_ActiveVideoDevices->SetAutomaticallySelectFirstEntry(true); m_FrameCounterPipeline = 0; m_FrameCounter2d = 0; m_FrameCounter3d = 0; - // Create Node for US Stream - if (m_Node.IsNull()) + m_Controls.tabWidget->setTabEnabled(1, false); +} + +void UltrasoundSupport::CreateWindows() +{ + auto pausViewer = GetSite()->GetWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.photoacoustics.pausviewer"); + if (pausViewer != nullptr) { - m_Node = mitk::DataNode::New(); - m_Node->SetName("US Support Viewing Stream"); - //create a dummy image (gray values 0..255) for correct initialization of level window, etc. - mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255, 0); - m_Node->SetData(dummyImage); - m_OldGeometry = dynamic_cast(dummyImage->GetGeometry()); + m_PausViewerView = dynamic_cast(pausViewer.GetPointer()); + m_PausViewerView->SetPADataStorage(m_PADataStorage); + m_PausViewerView->SetUSDataStorage(m_USDataStorage); + + m_PausViewerView->InitWindows(); + m_PausViewerView->SetUltrasoundReference(&m_PausViewerView); + UpdateLevelWindows(); + + m_ForceRequestUpdateAll = true; } +} - m_Controls.tabWidget->setTabEnabled(1, false); +void UltrasoundSupport::InitNewNode() +{ + m_Node.push_back(nullptr); + auto& Node = m_Node.back(); + + Node = mitk::DataNode::New(); + Node->SetName("No Data received yet ..."); + //create a dummy image (gray values 0..255) for correct initialization of level window, etc. + mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255, 0); + Node->SetData(dummyImage); + m_OldGeometry = dynamic_cast(dummyImage->GetGeometry()); + + // Add to Control Datastorage + this->GetDataStorage()->Add(Node); + + // Add to Display Datastorage + if (m_Node.size() > 1) + m_USDataStorage->Add(Node); + else if (m_Node.size() == 1) + m_PADataStorage->Add(Node); +} + +void UltrasoundSupport::DestroyLastNode() +{ + auto& Node = m_Node.back(); + + // Remove from Control Datastorage + this->GetDataStorage()->Remove(Node); + + // Remove from Display Datastorage + if (m_Node.size() > 1) + m_USDataStorage->Remove(Node); + else if (m_Node.size() == 1) + m_PADataStorage->Remove(Node); + + // clean up + Node->ReleaseData(); + m_Node.pop_back(); +} + +void UltrasoundSupport::UpdateLevelWindows() +{ + mitk::LevelWindow levelWindow; + + if (m_Node.size() > 1) + { + for (int index = 0; index < m_AmountOfOutputs; ++index) + { + m_Node.at(index)->GetLevelWindow(levelWindow); + if (!m_curOutput.at(index)->IsEmpty()) + levelWindow.SetWindowBounds(0, 4 * (index+1)); + //levelWindow.SetAuto(m_curOutput.at(index), true, true); + m_Node.at(index)->SetLevelWindow(levelWindow); + } + } + else if (m_Node.size() == 1) + { + m_Node.back()->GetLevelWindow(levelWindow); + if (!m_curOutput.at(0)->IsEmpty()) + levelWindow.SetAuto(m_curOutput.at(0), true, true); + m_Node.back()->SetLevelWindow(levelWindow); + } +} + +void UltrasoundSupport::SetColormap(mitk::DataNode::Pointer node, mitk::LookupTable::LookupTableType type) +{ + // consider removing this, unused for now, and probably forever + + mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); + mitk::LookupTableProperty::Pointer lookupTableProperty = mitk::LookupTableProperty::New(); + lookupTable->SetType(type); + lookupTableProperty->SetLookupTable(lookupTable); + node->SetProperty("LookupTable", lookupTableProperty); + + mitk::RenderingModeProperty::Pointer renderingMode = + dynamic_cast(node->GetProperty("Image Rendering.Mode")); + renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); } void UltrasoundSupport::OnClickedAddNewDevice() { m_Controls.m_NewVideoDeviceWidget->setVisible(true); m_Controls.m_DeviceManagerWidget->setVisible(false); m_Controls.m_Headline->setText("Add New Video Device:"); m_Controls.m_WidgetActiveDevices->setVisible(false); } void UltrasoundSupport::OnClickedEditDevice() { m_Controls.m_NewVideoDeviceWidget->setVisible(true); m_Controls.m_DeviceManagerWidget->setVisible(false); m_Controls.m_WidgetActiveDevices->setVisible(false); m_Controls.m_Headline->setText("Edit Video Device:"); } -void UltrasoundSupport::UpdateImage() +void UltrasoundSupport::UpdateAmountOfOutputs() { - //Update device - m_Device->Modified(); - m_Device->Update(); + // Update the amount of Nodes; there should be one Node for every slide that is set. Note that we must check whether the slices are set, + // just using the m_Image->dimension(3) will produce nullpointers on slices of the image that were not set + bool isSet = true; + m_AmountOfOutputs = 0; + while (isSet) { + isSet = m_Image->IsSliceSet(m_AmountOfOutputs); + if (isSet) + ++m_AmountOfOutputs; + } + + // correct the amount of Nodes to display data + while (m_Node.size() < m_AmountOfOutputs) { + InitNewNode(); + } + while (m_Node.size() > m_AmountOfOutputs) { + DestroyLastNode(); + } + + // correct the amount of image outputs that we feed the nodes with + while (m_curOutput.size() < m_AmountOfOutputs) { + m_curOutput.push_back(mitk::Image::New()); - //Only update the view if the image is shown - if (m_Controls.m_ShowImageStream->isChecked()) + // initialize the slice images as 2d images with the size of m_Images + unsigned int* dimOld = m_Image->GetDimensions(); + unsigned int dim[2] = { dimOld[0], dimOld[1] }; + m_curOutput.back()->Initialize(m_Image->GetPixelType(), 2, dim); + } + while (m_curOutput.size() > m_AmountOfOutputs) { + m_curOutput.pop_back(); + } +} + +void UltrasoundSupport::UpdateImage() +{ + if(m_Controls.m_ShowImageStream->isChecked()) { - //Update data node - mitk::Image::Pointer curOutput = m_Device->GetOutput(); - if (curOutput->IsEmpty()) - { - m_Node->SetName("No Data received yet ..."); - //create a noise image for correct initialization of level window, etc. - mitk::Image::Pointer randomImage = mitk::ImageGenerator::GenerateRandomImage(32, 32, 1, 1, 1, 1, 1, 255, 0); - m_Node->SetData(randomImage); - curOutput->SetGeometry(randomImage->GetGeometry()); - } - else + m_Device->Modified(); + m_Device->Update(); + // Update device + + m_Image = m_Device->GetOutput(); + // get the Image data to display + UpdateAmountOfOutputs(); + // create as many Nodes and Outputs as there are slices in m_Image + + if (m_AmountOfOutputs == 0) + return; + // if there is no image to be displayed, skip the rest of this method + + for (int index = 0; index < m_AmountOfOutputs; ++index) { - m_Node->SetName("US Support Viewing Stream"); - m_Node->SetData(curOutput); + if (m_curOutput.at(index)->GetDimension(0) != m_Image->GetDimension(0) || + m_curOutput.at(index)->GetDimension(1) != m_Image->GetDimension(1) || + m_curOutput.at(index)->GetDimension(2) != m_Image->GetDimension(2) || + m_curOutput.at(index)->GetPixelType() != m_Image->GetPixelType()) + { + unsigned int* dimOld = m_Image->GetDimensions(); + unsigned int dim[2] = { dimOld[0], dimOld[1]}; + m_curOutput.at(index)->Initialize(m_Image->GetPixelType(), 2, dim); + // if we switched image resolution or type the outputs must be reinitialized! + } + + if (!m_Image->IsEmpty()) + { + mitk::ImageReadAccessor inputReadAccessor(m_Image, m_Image->GetSliceData(index,0,0,nullptr,mitk::Image::ReferenceMemory)); + // just reference the slices, to get a small performance gain + m_curOutput.at(index)->SetSlice(inputReadAccessor.GetData()); + m_curOutput.at(index)->GetGeometry()->SetIndexToWorldTransform(m_Image->GetSlicedGeometry()->GetIndexToWorldTransform()); + // Update the image Output with seperate slices + } + + if (m_curOutput.at(index)->IsEmpty()) + { + m_Node.at(index)->SetName("No Data received yet ..."); + // create a noise image for correct initialization of level window, etc. + mitk::Image::Pointer randomImage = mitk::ImageGenerator::GenerateRandomImage(32, 32, 1, 1, 1, 1, 1, 255, 0); + m_Node.at(index)->SetData(randomImage); + m_curOutput.at(index)->SetGeometry(randomImage->GetGeometry()); + } + else + { + char name[30]; + sprintf(name, "US Viewing Stream - Image %d", index); + m_Node.at(index)->SetName(name); + m_Node.at(index)->SetData(m_curOutput.at(index)); + // set the name of the Output + } } - // if the geometry changed: reinitialize the ultrasound image + + // if the geometry changed: reinitialize the ultrasound image. we use the m_curOutput.at(0) to readjust the geometry if ((m_OldGeometry.IsNotNull()) && - (curOutput->GetGeometry() != NULL) && - (!mitk::Equal(m_OldGeometry.GetPointer(), curOutput->GetGeometry(), 0.0001, false)) - ) + (m_curOutput.at(0)->GetGeometry() != NULL) && + (!mitk::Equal(m_OldGeometry.GetPointer(), m_curOutput.at(0)->GetGeometry(), 0.0001, false)) + || m_ForceRequestUpdateAll) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); - if ((renderWindow != NULL) && (curOutput->GetTimeGeometry()->IsValid()) && (m_Controls.m_ShowImageStream->isChecked())) + if ((renderWindow != NULL) && (m_curOutput.at(0)->GetTimeGeometry()->IsValid()) && (m_Controls.m_ShowImageStream->isChecked())) { renderWindow->GetRenderingManager()->InitializeViews( - curOutput->GetGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + m_curOutput.at(0)->GetGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); renderWindow->GetRenderingManager()->RequestUpdateAll(); } - m_CurrentImageWidth = curOutput->GetDimension(0); - m_CurrentImageHeight = curOutput->GetDimension(1); - m_OldGeometry = dynamic_cast(curOutput->GetGeometry()); + m_CurrentImageWidth = m_curOutput.at(0)->GetDimension(0); + m_CurrentImageHeight = m_curOutput.at(0)->GetDimension(1); + m_OldGeometry = dynamic_cast(m_curOutput.at(0)->GetGeometry()); + UpdateLevelWindows(); + m_ForceRequestUpdateAll = false; } } //Update frame counter m_FrameCounterPipeline++; if (m_FrameCounterPipeline >= 10) { - //compute framerate of pipeline update + // compute framerate of pipeline update int nMilliseconds = m_Clock.restart(); int fps = 10000.0f / (nMilliseconds); m_FPSPipeline = fps; m_FrameCounterPipeline = 0; - //display lowest framerate in UI + // display lowest framerate in UI int lowestFPS = m_FPSPipeline; if (m_Controls.m_Update2DView->isChecked() && (m_FPS2d < lowestFPS)) { lowestFPS = m_FPS2d; } if (m_Controls.m_Update3DView->isChecked() && (m_FPS3d < lowestFPS)) { lowestFPS = m_FPS3d; } m_Controls.m_FramerateLabel->setText("Current Framerate: " + QString::number(lowestFPS) + " FPS"); } } void UltrasoundSupport::RenderImage2d() { - this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); + if (!m_Controls.m_Update2DView->isChecked()) + return; + + if (m_PausViewerView != nullptr) + { + auto renderingManager = mitk::RenderingManager::GetInstance(); + renderingManager->RequestUpdate(m_PausViewerView->GetPARenderWindow()); + renderingManager->RequestUpdate(m_PausViewerView->GetUSRenderWindow()); + } + else + { + CreateWindows(); // try to check whether the PausViwer has been opened by now + } + + //mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); + //renderWindow->GetRenderingManager()->RequestUpdate(mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))->GetRenderWindow()); + // TODO: figure out how to proceed with the standard display + //this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); + m_FrameCounter2d++; if (m_FrameCounter2d >= 10) { - //compute framerate of 2d render window update + // compute framerate of 2d render window update int nMilliseconds = m_Clock2d.restart(); int fps = 10000.0f / (nMilliseconds); m_FPS2d = fps; m_FrameCounter2d = 0; } } void UltrasoundSupport::RenderImage3d() { + if (!m_Controls.m_Update3DView->isChecked()) + return; + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); m_FrameCounter3d++; if (m_FrameCounter3d >= 10) { - //compute framerate of 2d render window update + // compute framerate of 2d render window update int nMilliseconds = m_Clock3d.restart(); int fps = 10000.0f / (nMilliseconds); m_FPS3d = fps; m_FrameCounter3d = 0; } } void UltrasoundSupport::OnChangedFramerateLimit() { StopTimers(); int intervalPipeline = (1000 / m_Controls.m_FrameRatePipeline->value()); int interval2D = (1000 / m_Controls.m_FrameRate2d->value()); int interval3D = (1000 / m_Controls.m_FrameRate3d->value()); SetTimerIntervals(intervalPipeline, interval2D, interval3D); StartTimers(); } void UltrasoundSupport::OnClickedFreezeButton() { if (m_Device.IsNull()) { MITK_WARN("UltrasoundSupport") << "Freeze button clicked though no device is selected."; return; } if (m_Device->GetIsFreezed()) { m_Device->SetIsFreezed(false); m_Controls.m_FreezeButton->setText("Freeze"); } else { m_Device->SetIsFreezed(true); m_Controls.m_FreezeButton->setText("Start Viewing Again"); } } void UltrasoundSupport::OnChangedActiveDevice() { - //clean up and stop timer + //clean up, delete nodes and stop timer StopTimers(); this->RemoveControlWidgets(); - this->GetDataStorage()->Remove(m_Node); - m_Node->ReleaseData(); + for (auto& Node : m_Node) + { + this->GetDataStorage()->Remove(Node); + Node->ReleaseData(); + } + m_Node.clear(); + + // disconnect from the PausViewer + m_PausViewerView = nullptr; //get current device, abort if it is invalid m_Device = m_Controls.m_ActiveVideoDevices->GetSelectedService(); if (m_Device.IsNull()) { m_Controls.tabWidget->setTabEnabled(1, false); return; } //create the widgets for this device and enable the widget tab this->CreateControlWidgets(); m_Controls.tabWidget->setTabEnabled(1, true); - //show node if the option is enabled - if (m_Controls.m_ShowImageStream->isChecked()) - { - this->GetDataStorage()->Add(m_Node); - } - //start timer if (m_Controls.m_RunImageTimer->isChecked()) { int intervalPipeline = (1000 / m_Controls.m_FrameRatePipeline->value()); int interval2D = (1000 / m_Controls.m_FrameRate2d->value()); int interval3D = (1000 / m_Controls.m_FrameRate3d->value()); SetTimerIntervals(intervalPipeline, interval2D, interval3D); StartTimers(); m_Controls.m_TimerWidget->setEnabled(true); } else { m_Controls.m_TimerWidget->setEnabled(false); } + + // connect to PausViewer and Set it up + CreateWindows(); } void UltrasoundSupport::OnNewDeviceWidgetDone() { m_Controls.m_NewVideoDeviceWidget->setVisible(false); m_Controls.m_DeviceManagerWidget->setVisible(true); m_Controls.m_Headline->setText("Ultrasound Devices:"); m_Controls.m_WidgetActiveDevices->setVisible(true); } void UltrasoundSupport::CreateControlWidgets() { m_ControlProbesWidget = new QmitkUSControlsProbesWidget(m_Device->GetControlInterfaceProbes(), m_Controls.m_ToolBoxControlWidgets); m_Controls.probesWidgetContainer->addWidget(m_ControlProbesWidget); // create b mode widget for current device m_ControlBModeWidget = new QmitkUSControlsBModeWidget(m_Device->GetControlInterfaceBMode(), m_Controls.m_ToolBoxControlWidgets); - m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls"); - if (!m_Device->GetControlInterfaceBMode()) + + if (m_Device->GetControlInterfaceBMode()) { - m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count() - 1, false); + m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls"); + //m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count() - 1, false); } // create doppler widget for current device m_ControlDopplerWidget = new QmitkUSControlsDopplerWidget(m_Device->GetControlInterfaceDoppler(), m_Controls.m_ToolBoxControlWidgets); - m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls"); - if (!m_Device->GetControlInterfaceDoppler()) + + if (m_Device->GetControlInterfaceDoppler()) { - m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count() - 1, false); + m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls"); + //m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count() - 1, false); } ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { std::string filter = "(ork.mitk.services.UltrasoundCustomWidget.deviceClass=" + m_Device->GetDeviceClass() + ")"; QString interfaceName = QString::fromStdString(us_service_interface_iid()); m_CustomWidgetServiceReference = pluginContext->getServiceReferences(interfaceName, QString::fromStdString(filter)); if (m_CustomWidgetServiceReference.size() > 0) { m_ControlCustomWidget = pluginContext->getService (m_CustomWidgetServiceReference.at(0))->CloneForQt(m_Controls.tab2); m_ControlCustomWidget->SetDevice(m_Device); m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlCustomWidget, "Custom Controls"); } else { m_Controls.m_ToolBoxControlWidgets->addItem(new QWidget(m_Controls.m_ToolBoxControlWidgets), "Custom Controls"); m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count() - 1, false); } } // select first enabled control widget for (int n = 0; n < m_Controls.m_ToolBoxControlWidgets->count(); ++n) { if (m_Controls.m_ToolBoxControlWidgets->isItemEnabled(n)) { m_Controls.m_ToolBoxControlWidgets->setCurrentIndex(n); break; } } } void UltrasoundSupport::RemoveControlWidgets() { if (!m_ControlProbesWidget) { return; } //widgets do not exist... nothing to do // remove all control widgets from the tool box widget while (m_Controls.m_ToolBoxControlWidgets->count() > 0) { m_Controls.m_ToolBoxControlWidgets->removeItem(0); } // remove probes widget (which is not part of the tool box widget) m_Controls.probesWidgetContainer->removeWidget(m_ControlProbesWidget); delete m_ControlProbesWidget; m_ControlProbesWidget = 0; delete m_ControlBModeWidget; m_ControlBModeWidget = 0; delete m_ControlDopplerWidget; m_ControlDopplerWidget = 0; // delete custom widget if it is present if (m_ControlCustomWidget) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); delete m_ControlCustomWidget; m_ControlCustomWidget = 0; if (m_CustomWidgetServiceReference.size() > 0) { pluginContext->ungetService(m_CustomWidgetServiceReference.at(0)); } } } void UltrasoundSupport::OnDeciveServiceEvent(const ctkServiceEvent event) { if (m_Device.IsNull() || event.getType() != us::ServiceEvent::MODIFIED) { return; } ctkServiceReference service = event.getServiceReference(); if (m_Device->GetManufacturer() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER)).toString().toStdString() && m_Device->GetName() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME)).toString().toStdString()) { return; } if (!m_Device->GetIsActive() && m_UpdateTimer->isActive()) { StopTimers(); } if (m_CurrentDynamicRange != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble()) { m_CurrentDynamicRange = service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble(); // update level window for the current dynamic range mitk::LevelWindow levelWindow; - m_Node->GetLevelWindow(levelWindow); - levelWindow.SetAuto(m_Image, true, true); - m_Node->SetLevelWindow(levelWindow); + for (auto& Node : m_Node) + { + Node->GetLevelWindow(levelWindow); + levelWindow.SetAuto(m_Image, true, true); + levelWindow.SetWindowBounds(55, 125,true); + Node->SetLevelWindow(levelWindow); + } } } UltrasoundSupport::UltrasoundSupport() : m_ControlCustomWidget(0), m_ControlBModeWidget(0), m_ControlProbesWidget(0), m_ImageAlreadySetToNode(false), - m_CurrentImageWidth(0), m_CurrentImageHeight(0) + m_CurrentImageWidth(0), m_CurrentImageHeight(0), m_AmountOfOutputs(0), + m_PADataStorage(mitk::StandaloneDataStorage::New()), m_USDataStorage(mitk::StandaloneDataStorage::New()), m_ForceRequestUpdateAll(false) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { // to be notified about service event of an USDevice pluginContext->connectServiceListener(this, "OnDeciveServiceEvent", QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")")); } } UltrasoundSupport::~UltrasoundSupport() { try { StopTimers(); // Get all active devicesand deactivate them to prevent freeze std::vector devices = this->m_Controls.m_ActiveVideoDevices->GetAllServices(); for (int i = 0; i < devices.size(); i++) { mitk::USDevice::Pointer device = devices[i]; if (device.IsNotNull() && device->GetIsActive()) { device->Deactivate(); device->Disconnect(); } } StoreUISettings(); } catch (std::exception &e) { MITK_ERROR << "Exception during call of destructor! Message: " << e.what(); } } void UltrasoundSupport::StoreUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); settings.setValue("DisplayImage", QVariant(m_Controls.m_ShowImageStream->isChecked())); settings.setValue("RunImageTimer", QVariant(m_Controls.m_RunImageTimer->isChecked())); settings.setValue("Update2DView", QVariant(m_Controls.m_Update2DView->isChecked())); settings.setValue("Update3DView", QVariant(m_Controls.m_Update3DView->isChecked())); settings.setValue("UpdateRatePipeline", QVariant(m_Controls.m_FrameRatePipeline->value())); settings.setValue("UpdateRate2d", QVariant(m_Controls.m_FrameRate2d->value())); settings.setValue("UpdateRate3d", QVariant(m_Controls.m_FrameRate3d->value())); settings.endGroup(); } void UltrasoundSupport::LoadUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); m_Controls.m_ShowImageStream->setChecked(settings.value("DisplayImage", true).toBool()); m_Controls.m_RunImageTimer->setChecked(settings.value("RunImageTimer", true).toBool()); m_Controls.m_Update2DView->setChecked(settings.value("Update2DView", true).toBool()); m_Controls.m_Update3DView->setChecked(settings.value("Update3DView", true).toBool()); m_Controls.m_FrameRatePipeline->setValue(settings.value("UpdateRatePipeline", 50).toInt()); m_Controls.m_FrameRate2d->setValue(settings.value("UpdateRate2d", 20).toInt()); m_Controls.m_FrameRate3d->setValue(settings.value("UpdateRate3d", 5).toInt()); settings.endGroup(); } void UltrasoundSupport::StartTimers() { m_UpdateTimer->start(); if (m_Controls.m_Update2DView->isChecked()) { m_RenderingTimer2d->start(); } if (m_Controls.m_Update3DView->isChecked()) { m_RenderingTimer3d->start(); } } void UltrasoundSupport::StopTimers() { m_UpdateTimer->stop(); m_RenderingTimer2d->stop(); m_RenderingTimer3d->stop(); } void UltrasoundSupport::SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D) { m_UpdateTimer->setInterval(intervalPipeline); m_RenderingTimer2d->setInterval(interval2D); m_RenderingTimer3d->setInterval(interval3D); } diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h index 7275eb4796..1a46e29eee 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h @@ -1,150 +1,183 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef UltrasoundSupport_h #define UltrasoundSupport_h +#include +#include +#include + #include #include #include "ui_UltrasoundSupportControls.h" #include "QmitkUSAbstractCustomWidget.h" #include "QmitkUSControlsBModeWidget.h" #include "QmitkUSControlsDopplerWidget.h" #include "QmitkUSControlsProbesWidget.h" +#include +#include "QmitkRenderWindow.h" +#include +#include +#include +#include #include #include /*! \brief UltrasoundSupport This plugin provides functionality to manage Ultrasound devices, create video devices and to view device images. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class UltrasoundSupport : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: virtual void SetFocus() override; static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent) override; UltrasoundSupport(); virtual ~UltrasoundSupport(); public slots: /* * \brief This is called when the newDeviceWidget is closed */ void OnNewDeviceWidgetDone(); protected slots: void OnClickedAddNewDevice(); void OnChangedFramerateLimit(); void OnClickedEditDevice(); /* *\brief Called, when the selection in the list of the active devices changes. */ void OnChangedActiveDevice(); void OnClickedFreezeButton(); void OnDeciveServiceEvent(const ctkServiceEvent event); /* * \brief This is the main imaging loop that updates the image and is called regularily during the imaging process */ void UpdateImage(); void RenderImage2d(); void RenderImage3d(); void StartTimers(); void StopTimers(); protected: void CreateControlWidgets(); void RemoveControlWidgets(); + void CreateWindows(); + + QmitkPAUSViewerView* m_PausViewerView; + + mitk::StandaloneDataStorage::Pointer m_PADataStorage; + mitk::StandaloneDataStorage::Pointer m_USDataStorage; + /** The device that is currently used to aquire images */ mitk::USDevice::Pointer m_Device; void SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D); /** This timer triggers periodic updates to the pipeline */ QTimer* m_UpdateTimer; QTimer* m_RenderingTimer2d; QTimer* m_RenderingTimer3d; /** These clocks are used to compute the framerate in the methods DisplayImage(),RenderImage2d() and RenderImage3d(). */ QTime m_Clock; QTime m_Clock2d; QTime m_Clock3d; /** A counter to comute the framerate. */ int m_FrameCounterPipeline; int m_FrameCounter2d; int m_FrameCounter3d; int m_FPSPipeline, m_FPS2d, m_FPS3d; /** Stores the properties of some QWidgets (and the tool storage file name) to QSettings.*/ void StoreUISettings(); /** Loads the properties of some QWidgets (and the tool storage file name) from QSettings.*/ void LoadUISettings(); - /** The node that we feed images into.*/ - mitk::DataNode::Pointer m_Node; - - /** The image that is hold by the node above.*/ - mitk::Image::Pointer m_Image; + /** The nodes that we feed images into.*/ + std::vector m_Node; + /** Adds a new node to the m_Nodes vector*/ + void InitNewNode(); + /** Destroys the last node in the m_Nodes vector */ + void DestroyLastNode(); + /** Checks the amount of slices in the image from the USDevice and creates as many Nodes as there are slices */ + void UpdateAmountOfOutputs(); + + /** This function just checks how many nodes there are currently and sets the laser image to a jet transparent colormap. */ + void UpdateLevelWindows(); + bool m_ForceRequestUpdateAll; + + void SetColormap(mitk::DataNode::Pointer node, mitk::LookupTable::LookupTableType type); + + /** The image that holds all data given by the USDevice.*/ + mitk::Image::Pointer m_Image; + /** The seperated slices from m_Image */ + std::vector m_curOutput; + /** Keeps track of the amount of output Nodes*/ + int m_AmountOfOutputs; /** The old geometry of m_Image. It is needed to check if the geometry changed (e.g. because * the zoom factor was modified) and the image needs to be reinitialized. */ mitk::SlicedGeometry3D::Pointer m_OldGeometry; Ui::UltrasoundSupportControls m_Controls; QmitkUSAbstractCustomWidget* m_ControlCustomWidget; QmitkUSControlsBModeWidget* m_ControlBModeWidget; QmitkUSControlsDopplerWidget* m_ControlDopplerWidget; QmitkUSControlsProbesWidget* m_ControlProbesWidget; QList m_CustomWidgetServiceReference; bool m_ImageAlreadySetToNode; unsigned int m_CurrentImageWidth; unsigned int m_CurrentImageHeight; double m_CurrentDynamicRange; }; #endif // UltrasoundSupport_h diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui index 0043b03043..82f7fa1f3d 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui @@ -1,391 +1,412 @@ UltrasoundSupportControls 0 0 407 820 0 0 QmitkTemplate - + + 2 + + + 2 + + + 2 + + 2 - 0 + 1 true false false :/USUI/ultrasound01-probe-300ppi.png :/USUI/ultrasound01-probe-300ppi.png:/USUI/ultrasound01-probe-300ppi.png Device Management - + + 0 + + + 0 + + + 0 + + 0 10 75 true Ultrasound Devices: 10 75 true Active Devices: 0 0 Show US image in MITK true Qt::Vertical 20 40 false :/USUI/ultrasound02-scan-300ppi.png :/USUI/ultrasound02-scan-72ppi-deactivated.png :/USUI/ultrasound02-scan-300ppi.png:/USUI/ultrasound02-scan-300ppi.png US Imaging Qt::Vertical 20 40 Qt::Horizontal Update Image Data Automatically true Freeze :/USUI/system-lock-screen.png:/USUI/system-lock-screen.png <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Framrate Settings:</span></p></body></html> Current overall Framerate: 0 FPS Image Pipeline Framerate Limit [FPS]: Qt::Horizontal 40 20 1 500 50 Update 2D View - true + false + + + false Qt::Horizontal 40 20 Framerate Limit [FPS]: 1 100 20 Update 3D View - true + false Qt::Horizontal 18 20 Framerate Limit [FPS]: 1 100 5 QmitkUSDeviceManagerWidget QWidget
QmitkUSDeviceManagerWidget.h
1
QmitkUSNewVideoDeviceWidget QWidget
QmitkUSNewVideoDeviceWidget.h
1
QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1