diff --git a/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp index 32fd950518..4903694259 100644 --- a/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp +++ b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.cpp @@ -1,181 +1,192 @@ /*=================================================================== 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::SetUseBModeFilter(bool isSet) { this->OnSetUseBModeFilter(isSet); } void mitk::USDiPhASDeviceCustomControls::SetRecord(bool record) { this->OnSetRecord(record); } void mitk::USDiPhASDeviceCustomControls::SetVerticalSpacing(float mm) { - this->SetVerticalSpacing(mm); + this->OnSetVerticalSpacing(mm); +} + +void mitk::USDiPhASDeviceCustomControls::SetScatteringCoefficient(float coeff) +{ + this->OnSetScatteringCoefficient(coeff); +} +void mitk::USDiPhASDeviceCustomControls::SetCompensateScattering(bool compensate) +{ + this->OnSetCompensateScattering(compensate); } //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::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) {} //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 index 069fe6ed54..94d703fa54 100644 --- a/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.h +++ b/Modules/US/USControlInterfaces/mitkUSDiPhASDeviceCustomControls.h @@ -1,132 +1,135 @@ /*=================================================================== 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 }; /** * \return if this custom controls are currently activated */ virtual bool GetIsActive( ) override; virtual void SetUseBModeFilter(bool isSet); virtual void SetVerticalSpacing(float mm); - virtual void SetRecord(bool record); + virtual void SetRecord(bool record); + virtual void SetScatteringCoefficient(float coeff); + virtual void SetCompensateScattering(bool compensate); //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 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/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/mitkUSDiPhASCustomControls.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp index 4de14c7ebb..c33248296d 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp @@ -1,201 +1,213 @@ /*=================================================================== 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::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); } //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 index 892228c059..2d6d64e9a5 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.h +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.h @@ -1,102 +1,104 @@ /*=================================================================== 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; /** * 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 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; //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/mitkUSDiPhASImageSource.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp index fc47965acf..22f356c4e8 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp @@ -1,565 +1,700 @@ /*=================================================================== 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 // 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_UseBModeFilterModified(false), - m_UseBModeFilterNext(false), m_CurrentImageTimestamp(0), m_PyroConnected(false), m_ImageTimestampBuffer(), - m_VerticalSpacing(0) + 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_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; + for (int i = 5; i <= 25; ++i) + { + name = "Fluence" + i; + name += ".nrrd"; + + name = "FranzTissue.nrrd"; + + resourceFile = us::GetModuleContext()->GetModule()->GetResource(name); + + //m_FluenceCompensationImagesOriginal.push_back(mitk::IOUtil::LoadImage(resourceFile.GetResourcePath())); + m_FluenceCompOriginal.push_back(mitk::IOUtil::LoadImage("d:\\FranzTissue.nrrd")); // TODO: make it actually load the images we want, not some test image.... + } + + m_FluenceCompResized.insert(m_FluenceCompResized.begin(), 21, Image::New()); + m_FluenceCompRaw.insert(m_FluenceCompRaw.begin(), 21, nullptr); } 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) { // we get this image pointer from the USDevice and write into it the data we got from the DiPhAS API + // resize the fluence reference images, if needed + + // modify all settings if (m_DataTypeModified) { SetDataType(m_DataTypeNext); m_DataTypeModified = false; } 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; + } // 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()) { + // first, we compensate using our ImageEnergyValue // dooooooooit - // now apply BmodeFilter to the image, if the option has been selected. - if (m_UseBModeFilter && m_DataType == DataType::Beamformed_Short) + // now apply BmodeFilter and/or scattering compensation to the image, if the option has been selected. + if ((m_CompensateForScattering || m_UseBModeFilter) && m_DataType == DataType::Beamformed_Short) { - if (image->GetDimension(2) == 1) + if (image->GetDimension(2) == 1 && m_UseBModeFilter) { - image = ApplyBmodeFilter(image, true, 0.15); + image = ApplyBmodeFilter(image, true, m_VerticalSpacing); } // this is for ultrasound only mode else { Image::Pointer imageCopy = Image::New(); unsigned int dim[] = { image->GetDimension(0),image->GetDimension(1),1}; imageCopy->Initialize(image->GetPixelType(), 3, dim); imageCopy->SetGeometry(image->GetGeometry()); mitk::ImageReadAccessor inputReadAccessorCopy(image, image->GetSliceData(0)); imageCopy->SetSlice(inputReadAccessorCopy.GetData(), 0); - - image = ApplyBmodeFilter(image ,true , 0); - imageCopy = ApplyBmodeFilter(imageCopy, false, 0); + if (m_UseBModeFilter) + { + image = ApplyBmodeFilter(image, true, m_VerticalSpacing); + imageCopy = ApplyBmodeFilter(imageCopy, false, m_VerticalSpacing); + } + if (m_CompensateForScattering) + { + // update the fluence reference images! + bool doResampling = image->GetDimension(0) != m_FluenceCompResized.at(m_ScatteringCoefficient)->GetDimension(0) || image->GetDimension(1) != m_FluenceCompResized.at(m_ScatteringCoefficient)->GetDimension(1); + if (doResampling) + { + m_FluenceCompResized.at(m_ScatteringCoefficient) = ApplyResampling(m_FluenceCompOriginal.at(m_ScatteringCoefficient), image->GetGeometry()->GetSpacing(), image->GetDimensions()); + m_FluenceCompRaw.at(m_ScatteringCoefficient) = (double*)m_FluenceCompResized.at(m_ScatteringCoefficient)->GetData(); + } + + imageCopy = ApplyScatteringCompensation(imageCopy, m_ScatteringCoefficient); + } mitk::ImageReadAccessor inputReadAccessor(imageCopy, imageCopy->GetSliceData(0)); image->SetSlice(inputReadAccessor.GetData(), 0); } } } } -mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyBmodeFilter(mitk::Image::Pointer inputImage, bool UseLogFilter, int resampleSpacing) +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] = 256; 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) +{ + Image::Pointer image = Image::New(); + image->Initialize(inputImage); + image->SetGeometry(inputImage->GetGeometry()); + + mitk::Vector3D imageSpacing = inputImage->GetGeometry()->GetSpacing(); + mitk::Vector3D refSpacing = m_FluenceCompOriginal[0]->GetGeometry()->GetSpacing(); + + unsigned int* imageDimensions = inputImage->GetDimensions(); + unsigned int* refDimensions = m_FluenceCompOriginal[0]->GetDimensions(); + + itk::Index<3> curPixel; + itk::Index<3> refPixel; + + for (curPixel = { 0,0,0 }; curPixel[2] < imageDimensions[2]; ++curPixel[2]) + { + refPixel[2] = 0; + for (curPixel; curPixel[1] < imageDimensions[1]; ++curPixel[1]) + { + + refPixel[1] = 0; + for (curPixel; curPixel[0] < imageDimensions[0]; ++curPixel[0]) + { + + } + } + } + + image = inputImage; + return image; +} + +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; + + outputSpacingItk[0] = outputSpacing[0]; + outputSpacingItk[1] = outputSpacing[1]; + outputSpacingItk[2] = outputSpacing[2]; + + outputSizeItk[0] = outputSize[0]; + outputSizeItk[1] = outputSize[1]; + outputSizeItk[2] = 1; + + typedef itk::IdentityTransform TransformType; + resampleImageFilter->SetInput(itkImage); + resampleImageFilter->SetSize(outputSizeItk); + resampleImageFilter->SetOutputSpacing(outputSpacingItk); + resampleImageFilter->SetTransform(TransformType::New()); + + resampleImageFilter->UpdateLargestPossibleRegion(); + return mitk::GrabItkImageMemory(resampleImageFilter->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_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 (int 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 (int currentSet = 0; currentSet < beamformedTotalDatasets; currentSet++) { for (int sample = 0; sample < beamformedSamples; sample++) { for (int 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 (int i = 0; i < beamformedTotalDatasets; i++) { image->SetSlice(&flipme[i*beamformedLines*beamformedSamples], i); // set every image to a different slice } delete[] flipme; break; } } itk::Index<3> pixel = { { (image->GetDimension(0) / 2), 84, 0 } }; //22/532*2048 TODO: make this more general to any Spacing/Sampling, Depth, etc if (!m_Pyro->IsSyncDelaySet() &&(image->GetPixelValueByIndex(pixel) < -30)) // #MagicNumber { MITK_INFO << "Setting SyncDelay"; 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 (int 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::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_VerticalSpacing = mm; - cout << m_VerticalSpacing; + m_VerticalSpacingNext = mm; + m_VerticalSpacingModified = true; } // 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(); // we make sure there are no leftovers m_ImageTimestampRecord.clear(); // also for the timestamps m_PixelValues.clear(); // aaaand for the pixel values // tell the callback to start recording images m_CurrentlyRecording = true; } // save images, end recording, and clean up else { m_CurrentlyRecording = false; // 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"; 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 OrderImagesInterleaved(PAImage, USImage); mitk::IOUtil::Save(USImage, pathUS); mitk::IOUtil::Save(PAImage, pathPA); // read the pixelvalues of the enveloped images at this position itk::Index<3> pixel = { { m_RecordedImages.at(1)->GetDimension(0) / 2, 84, 0 } }; //22/532*2048 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); mitk::IOUtil::Save(USImage, pathUS); } m_PixelValues.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) { 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 (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, m_RecordedImages.size() / events}; unsigned int dimSound[] = { width, height, m_RecordedImages.size() / events * (events-1)}; PAImage->Initialize(m_RecordedImages.back()->GetPixelType(), 3, dimLaser); PAImage->SetGeometry(m_RecordedImages.back()->GetGeometry()); USImage->Initialize(m_RecordedImages.back()->GetPixelType(), 3, dimSound); USImage->SetGeometry(m_RecordedImages.back()->GetGeometry()); for (int index = 0; index < m_RecordedImages.size(); ++index) { mitk::ImageReadAccessor inputReadAccessor(m_RecordedImages.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 SoundImage) { 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, m_RecordedImages.size()}; SoundImage->Initialize(m_RecordedImages.back()->GetPixelType(), 3, dimSound); SoundImage->SetGeometry(m_RecordedImages.back()->GetGeometry()); for (int index = 0; index < m_RecordedImages.size(); ++index) { mitk::ImageReadAccessor inputReadAccessor(m_RecordedImages.at(index)); SoundImage->SetSlice(inputReadAccessor.GetData(), index); } } \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h index 086c2040dd..ed291fbd22 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h @@ -1,161 +1,179 @@ /*=================================================================== 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; /** * 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 SetVerticalSpacing(float mm); void ModifyDataType(DataType DataT); void ModifyUseBModeFilter(bool isSet); + void ModifyScatteringCoefficient(int coeff); + void ModifyCompensateForScattering(bool useIt); /** * 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_ImageTimestampRecord; std::vector m_ImageTimestampBuffer; long long m_CurrentImageTimestamp; bool m_CurrentlyRecording; mitk::OphirPyro::Pointer m_Pyro; bool m_PyroConnected; - float m_VerticalSpacing; + std::vector m_FluenceCompOriginal; + std::vector m_FluenceCompResized; + std::vector m_FluenceCompRaw; 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, int resampleSpacing = 0.15); + 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]); void OrderImagesInterleaved(Image::Pointer LaserImage, Image::Pointer SoundImage); void OrderImagesUltrasound(Image::Pointer SoundImage); 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. */ 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; + DataType m_DataType; }; } // namespace mitk #endif // MITKUSDiPhASImageSource_H diff --git a/Modules/US/USHardwareDiPhAS/resources/FranzTissue.nrrd b/Modules/US/USHardwareDiPhAS/resources/FranzTissue.nrrd new file mode 100644 index 0000000000..224a89f7ff Binary files /dev/null and b/Modules/US/USHardwareDiPhAS/resources/FranzTissue.nrrd differ diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp index 15614bb645..bf871e715a 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp @@ -1,310 +1,330 @@ /*=================================================================== 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_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(); m_ControlInterface->SetSilentUpdate(false); // on the last update pass the scanmode and geometry! OnModeChanged(); // HERE } void QmitkUSControlsCustomDiPhASDeviceWidget::Initialize() { ui->setupUi(this); 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())); //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::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"); m_ControlInterface->SetRecord(true); } else { ui->StartStopRecord->setText("Start Recording"); 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; } + m_ControlInterface->SetCompensateScattering(ui->CompensateScattering->isChecked()); +} + + //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; } m_ControlInterface->SetReconstructedLines(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 index 21e109bcb2..de4c13f864 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.h @@ -1,110 +1,112 @@ /*=================================================================== 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 OnUseBModeFilterChanged(); virtual void OnVerticalSpacingChanged(); virtual void OnRecordChanged(); + virtual void OnScatteringCoefficientChanged(); + virtual void OnCompensateScatteringChanged(); //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; }; #endif // QmitkUSControlsCustomDiPhASDeviceWidget_H \ No newline at end of file diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui index 8e798f8ba7..4b3fff08d5 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui @@ -1,567 +1,614 @@ QmitkUSControlsCustomDiPhASDeviceWidget 0 0 259 903 Form 0 25 16777215 25 QFrame::WinPanel QFrame::Raised Started Qt::AlignCenter <html><head/><body><p><span style=" font-weight:600;">General Settings</span></p></body></html> Qt::Horizontal 40 20 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 1000.000000000000000 40.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.050000000000000 0.150000000000000 Qt::PreventContextMenu 128 1024 128 256 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 - 5.000000000000000 + 1.000000000000000 + + + 0.050000000000000 + + + 0.150000000000000 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] true Interleaved Ultrasound only false 5 75 70 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