diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp index f66263f8df..43a9b83613 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASCustomControls.cpp @@ -1,196 +1,196 @@ /*=================================================================== 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->SetUseBModeFilter(isSet); + imageSource->ModifyUseBModeFilter(isSet); } void mitk::USDiPhASCustomControls::OnSetRecord(bool record) { mitk::USDiPhASImageSource* imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); imageSource->SetRecordingStatus(record); } //Transmit void mitk::USDiPhASCustomControls::OnSetTransmitPhaseLength(double us) { m_device->GetScanMode().transmitPhaseLengthSeconds = us*1000*1000; 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(int type) { auto& scanMode = m_device->GetScanMode(); auto imageSource = dynamic_cast(m_device->GetUSImageSource().GetPointer()); switch (type) { case 0: { scanMode.transferBeamformedData = false; scanMode.transferImageData = true; m_device->UpdateScanmode(); - imageSource->SetDataType(0); + imageSource->ModifyDataType(0); break; } case 1: { scanMode.transferBeamformedData = true; scanMode.transferImageData = false; m_device->UpdateScanmode(); - imageSource->SetDataType(1); + imageSource->ModifyDataType(1); 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/mitkUSDiPhASDevice.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp index 19a68f5e90..b2c3d5f250 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASDevice.cpp @@ -1,308 +1,308 @@ /*=================================================================== 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, channelDatalinesPerDataset, 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 fits the current scanmode // 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() { - if (m_IsRunning) - m_IsRunning = toggleFreeze(); + OnFreeze(true); /*m_ScanMode.imageHeight = m_ScanMode.reconstructionSamplesPerLine; m_ScanMode.imageWidth = m_ScanMode.reconstructionLines;*/ m_ScanMode.imageHeight = 512; m_ScanMode.imageWidth = 512; // a higher resolution is useless, this also ensures correct spacing using any data types UpdateTransmitEvents(); if (!(dynamic_cast(this->m_ControlInterfaceCustom.GetPointer())->GetSilentUpdate())) { setupScan(this->m_ScanMode); } - if (!m_IsRunning) - m_IsRunning = toggleFreeze(); + 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 = false; // configure reconstruction processing: m_ScanMode.averageSpeedOfSound = 1540; m_ScanMode.computeBeamforming = true; // setup beamforming parameters: SetInterleaved(true); m_ScanMode.reconstructedLinePitchMmOrAngleDegree = 0.15f; m_ScanMode.reconstructionLines = 256; 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 = 70; 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 = true; // 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 = 1; + 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/mitkUSDiPhASImageSource.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp index 737070892c..06fa643034 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp @@ -1,427 +1,497 @@ /*=================================================================== 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 // mitk dependencies #include "mitkUSDiPhASImageSource.h" #include "mitkUSDiPhASDevice.h" #include #include "mitkUSDiPhASBModeImageFilter.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" mitk::USDiPhASImageSource::USDiPhASImageSource(mitk::USDiPhASDevice* device) : m_Image(mitk::Image::New()), m_device(device), startTime(((float)std::clock()) / CLOCKS_PER_SEC), useGUIOutPut(false), m_DataType(0), m_GUIOutput(nullptr), useBModeFilter(false), - currentlyRecording(false) + currentlyRecording(false), + m_DataTypeModified(true), + m_DataTypeNext(0), + m_UseBModeFilterModified(true), + m_UseBModeFilterNext(true) { } mitk::USDiPhASImageSource::~USDiPhASImageSource( ) { } 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 //static itk::FastMutexLock::Pointer nextImageMutex = itk::FastMutexLock::New(); //nextImageMutex->Lock(); if (m_Image->IsInitialized()) { //initialize the image the first time if (image.IsNull()) { image = mitk::Image::New(); image->Initialize(m_Image->GetPixelType(), m_Image->GetDimension(), m_Image->GetDimensions()); } // write the data of m_Image to image if it changed if (image->GetPixelType() != m_Image->GetPixelType() || image->GetDimensions() != m_Image->GetDimensions()) { image = mitk::Image::New(); image->Initialize(m_Image->GetPixelType(), m_Image->GetDimension(), m_Image->GetDimensions()); } // if DataType == 0 : if imageData is given just bypass the filter here, as imageData is already enveloped. if (!useBModeFilter || m_DataType == 0) { // copy contents of the given image into the member variable mitk::ImageReadAccessor inputReadAccessor(m_Image, m_Image->GetVolumeData()); image->SetVolume(inputReadAccessor.GetData()); } else { // feed the m_image to the BMode filter and grab it back; if (m_DataType ==1) image = ApplyBmodeFilter(m_Image); } // always copy the geometry from the m_Image image->SetGeometry(m_Image->GetGeometry()); } if (!useGUIOutPut && m_GUIOutput) { // Need to do this because the program initializes the GUI twice // this is probably a bug in UltrasoundSupport, if it's fixed the timing becomes unneccesary float timePassed = ((float)std::clock()) / CLOCKS_PER_SEC - startTime; if (timePassed > 10) { useGUIOutPut = true; } } if (useGUIOutPut) { // pass some beamformer state infos to the GUI getSystemInfo(&BeamformerInfos); std::ostringstream s; s << "state info: PRF:" << BeamformerInfos.systemPRF << "Hz, datarate: " << BeamformerInfos.dataTransferRateMBit << "MBit/s"; m_GUIOutput(QString::fromStdString(s.str())); } //nextImageMutex->Unlock(); } mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyBmodeFilter2d(mitk::Image::Pointer inputImage) { // we use this seperate ApplyBmodeFilter Method for processing of images that are to be saved later on (see SetRecordingStatus(bool)). // 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, 2 > itkInputImageType; typedef itk::Image< short, 2 > itkOutputImageType; typedef itk::PhotoacousticBModeImageFilter < itkInputImageType, itkOutputImageType > PhotoacousticBModeImageFilter; PhotoacousticBModeImageFilter::Pointer photoacousticBModeFilter = PhotoacousticBModeImageFilter::New(); itkInputImageType::Pointer itkImage; mitk::CastToItkImage(inputImage, itkImage); photoacousticBModeFilter->SetInput(itkImage); photoacousticBModeFilter->SetDirection(0); return mitk::GrabItkImageMemory(photoacousticBModeFilter->GetOutput()); } mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyBmodeFilter(mitk::Image::Pointer inputImage) { // 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 > itkInputImageType; typedef itk::Image< short, 3 > itkOutputImageType; typedef itk::PhotoacousticBModeImageFilter < itkInputImageType, itkOutputImageType > PhotoacousticBModeImageFilter; PhotoacousticBModeImageFilter::Pointer photoacousticBModeFilter = PhotoacousticBModeImageFilter::New(); itkInputImageType::Pointer itkImage; mitk::CastToItkImage(inputImage, itkImage); photoacousticBModeFilter->SetInput(itkImage); photoacousticBModeFilter->SetDirection(0); return mitk::GrabItkImageMemory(photoacousticBModeFilter->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) { bool writeImage = ((m_DataType == 0) && (imageData != nullptr)) || ((m_DataType == 1) && (rfDataArrayBeamformed != nullptr)) && !m_Image.IsNull(); if (writeImage) { - - // initialize mitk::Image with given image size on the first time - if ( !m_Image->IsInitialized() ) + + if (m_DataTypeModified) + { + SetDataType(m_DataTypeNext); + m_DataTypeModified = false; + } + + if (m_UseBModeFilterModified) { - UpdateImageDataType(imageHeight, imageWidth); // update data type and image pixel dimensions + SetUseBModeFilter(m_UseBModeFilterNext); + m_UseBModeFilterModified = false; } + + // lock the image for writing an copy the given buffer into the image then switch (m_DataType) { case 0: { + // initialize mitk::Image with given image size on the first time + if (!m_Image->IsInitialized()) + { + UpdateImageDataType(imageHeight, imageWidth); // update data type and image pixel dimensions + } for (int i = 0; i < imageSetsTotal; i++) { m_Image->SetSlice(&imageData[i*imageHeight*imageWidth], i); } break; } case 1: { short* flipme = new short[beamformedLines*beamformedSamples*beamformedTotalDatasets]; int pixelsPerImage = beamformedLines*beamformedSamples; + MITK_INFO << "Debug Garbage:"; + MITK_INFO << "Datasets: " << beamformedTotalDatasets; + MITK_INFO << "Beamformed Lines: " << beamformedLines; + MITK_INFO << "Beamformed Samples: " << beamformedSamples; + // initialize mitk::Image with given image size on the first time + if (!m_Image->IsInitialized()) + { + UpdateImageDataType(beamformedSamples, beamformedLines); // update data type and image pixel dimensions + } + for (char currentSet = 0; currentSet < beamformedTotalDatasets; currentSet++) { for (unsigned int sample = 0; sample < beamformedSamples; sample++) { for (short line = 0; line < beamformedLines; line++) { if (currentSet == 0) { flipme[sample*beamformedLines + line + pixelsPerImage*currentSet] = rfDataArrayBeamformed[line*beamformedSamples + sample + pixelsPerImage*currentSet]; } else { flipme[sample*beamformedLines + line + pixelsPerImage*currentSet] = rfDataArrayBeamformed[sample*beamformedLines + line + pixelsPerImage*currentSet]; } } } // the beamformed laser image is flipped by 90 degrees; we need to flip it manually } for (int i = 0; i < beamformedTotalDatasets; i++) { m_Image->SetSlice(&flipme[i*beamformedLines*beamformedSamples], i); // set every image to a different slice } delete[] flipme; break; } }/* for (int i = 0; i < channelDataTotalDatasets; i++) { m_Image->SetSlice(&rfDataChannelData[i*channelDataChannelsPerDataset*channelDataSamplesPerChannel], i); // set every image to a different slice }*/ } // if the user decides to start recording, we feed the vector the generated images if (currentlyRecording) { for (int index = 0; index < m_Image->GetDimension(2); ++index) { if (m_Image->IsSliceSet(index)) { m_recordedImages.push_back(Image::New()); m_recordedImages.back()->Initialize(m_Image->GetPixelType(), 2, m_Image->GetDimensions()); m_recordedImages.back()->SetGeometry(m_Image->GetGeometry()); mitk::ImageReadAccessor inputReadAccessor(m_Image, m_Image->GetSliceData(index)); m_recordedImages.back()->SetSlice(inputReadAccessor.GetData()); } } } } void mitk::USDiPhASImageSource::UpdateImageDataType(int imageHeight, int imageWidth) { int addEvents = 0; if (m_device->IsInterleaved()) addEvents = 1; unsigned int dim[] = { imageWidth, imageHeight, m_device->GetScanMode().transmitEventsCount + addEvents }; // image dimensions; every image needs a seperate slice! m_Image = mitk::Image::New(); + MITK_INFO << "Initializing image..."; switch (m_DataType) { case 0: { m_Image->Initialize(mitk::MakeScalarPixelType(), 3, dim); break; } case 1: { m_Image->Initialize(mitk::MakeScalarPixelType(), 3, dim); break; } } // 0:imageData 1:beamformed + MITK_INFO << "Initializing image...[DOINE]"; + MITK_INFO << "Updating geometry..."; UpdateImageGeometry(); // update the image geometry + MITK_INFO << "Updating geometry...[DOINE]"; startTime = ((float)std::clock()) / CLOCKS_PER_SEC; //wait till the callback is available again useGUIOutPut = false; } void mitk::USDiPhASImageSource::UpdateImageGeometry() { mitk::Vector3D spacing; MITK_INFO << "Retreaving Image Geometry Information for Spacing..."; float& recordTime = m_device->GetScanMode().receivePhaseLengthSeconds; int& speedOfSound = m_device->GetScanMode().averageSpeedOfSound; - int& imageWidth = m_device->GetScanMode().imageWidth; - int& imageHeight = m_device->GetScanMode().imageHeight; float& pitch = m_device->GetScanMode().reconstructedLinePitchMmOrAngleDegree; int& reconstructionLines = m_device->GetScanMode().reconstructionLines; - MITK_INFO << "Retreaving Image Geometry Information for Spacing...[DONE]"; - spacing[0] = (pitch*reconstructionLines) / imageWidth; - spacing[1] = ((recordTime*speedOfSound / 2) * 1000) / imageHeight; - spacing[2] = 1; + switch (m_DataType) + { + case 0: { + int& imageWidth = m_device->GetScanMode().imageWidth; + int& imageHeight = m_device->GetScanMode().imageHeight; + spacing[0] = pitch * reconstructionLines / imageWidth; + spacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; + break; + } + case 1: { + int& imageWidth = reconstructionLines; + int& imageHeight = m_device->GetScanMode().reconstructionSamplesPerLine; + spacing[0] = pitch; + spacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; + break; + } + } // 0:imageData 1:beamformed + + MITK_INFO << "Retreaving Image Geometry Information for Spacing " << spacing[0] << " ... " << spacing[1] << " ... " << spacing[2] << " ...[DONE]"; + + spacing[2] = 0.6; //recalculate correct spacing if (m_Image.IsNotNull() && (m_Image->GetGeometry() != NULL)) { m_Image->GetGeometry()->SetSpacing(spacing); m_Image->GetGeometry()->Modified(); } else { MITK_WARN << "image or geometry was NULL, can't adapt geometry"; } } +void mitk::USDiPhASImageSource::ModifyDataType(int DataT) +{ + m_DataTypeModified = true; + m_DataTypeNext = DataT; +} + +void mitk::USDiPhASImageSource::ModifyUseBModeFilter(bool isSet) +{ + m_UseBModeFilterModified = true; + m_UseBModeFilterNext = isSet; +} + void mitk::USDiPhASImageSource::SetDataType(int DataT) { if (DataT != m_DataType) { m_DataType = DataT; - UpdateImageDataType(m_device->GetScanMode().imageHeight, m_device->GetScanMode().imageWidth); + MITK_INFO << "Setting new DataType..." << DataT; + switch (m_DataType) + { + case 0: + MITK_INFO << "height: " << m_device->GetScanMode().imageHeight << " width: " << m_device->GetScanMode().imageWidth; + UpdateImageDataType(m_device->GetScanMode().imageHeight, m_device->GetScanMode().imageWidth); + break; + case 1: + MITK_INFO << "samples: " << m_device->GetScanMode().reconstructionSamplesPerLine << " lines: " << m_device->GetScanMode().reconstructionLines; + UpdateImageDataType(m_device->GetScanMode().reconstructionSamplesPerLine, m_device->GetScanMode().reconstructionLines); + break; + } // 0:imageData 1:beamformed + MITK_INFO << "Setting new DataType...[DOINE]"; } } void mitk::USDiPhASImageSource::SetGUIOutput(std::function out) { USDiPhASImageSource::m_GUIOutput = out; } void mitk::USDiPhASImageSource::SetUseBModeFilter(bool isSet) { useBModeFilter = isSet; } // 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) { currentlyRecording = true; m_recordedImages.clear(); // we make sure there are no leftovers } // save images, end recording, and clean up else { 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()); // if checked, we add the bmode filter here for (int index = 0; index < m_recordedImages.size(); ++index) { if (m_DataType == 1 && useBModeFilter) m_recordedImages.at(index) = ApplyBmodeFilter2d(m_recordedImages.at(index)); } Image::Pointer LaserImage = Image::New(); Image::Pointer SoundImage = Image::New(); std::string pathLaser = "c:\\DiPhASImageData\\" + currentDate + "\\" + "LaserImages" + ".nrrd"; std::string pathSound = "c:\\DiPhASImageData\\" + currentDate + "\\" + "USImages" + ".nrrd"; // order the images and save them if (m_device->GetScanMode().beamformingAlgorithm == (int)Beamforming::Interleaved_OA_US) // save a LaserImage if we used interleaved mode { OrderImagesInterleaved(LaserImage, SoundImage); mitk::IOUtil::Save(SoundImage, pathSound); mitk::IOUtil::Save(LaserImage, pathLaser); } else if (m_device->GetScanMode().beamformingAlgorithm == (int)Beamforming::PlaneWaveCompound) // save no LaserImage if we used US only mode { OrderImagesUltrasound(SoundImage); mitk::IOUtil::Save(SoundImage, pathSound); } m_recordedImages.clear(); // clean up the images } } void mitk::USDiPhASImageSource::OrderImagesInterleaved(Image::Pointer LaserImage, Image::Pointer SoundImage) { unsigned int width = m_device->GetScanMode().imageWidth; unsigned int height = m_device->GetScanMode().imageHeight; unsigned int events = m_device->GetScanMode().transmitEventsCount + 1; // the laser event is not included in the transmitEvents, so we add 1 here unsigned int dimLaser[] = { width, height, m_recordedImages.size() / events}; unsigned int dimSound[] = { width, height, m_recordedImages.size() / events * (events-1)}; LaserImage->Initialize(m_Image->GetPixelType(), 3, dimLaser); LaserImage->SetGeometry(m_Image->GetGeometry()); SoundImage->Initialize(m_Image->GetPixelType(), 3, dimSound); SoundImage->SetGeometry(m_Image->GetGeometry()); for (int index = 0; index < m_recordedImages.size(); ++index) { mitk::ImageReadAccessor inputReadAccessor(m_recordedImages.at(index)); if (index % events == 0) { LaserImage->SetSlice(inputReadAccessor.GetData(), index / events); } else { SoundImage->SetSlice(inputReadAccessor.GetData(), ((index - (index % events)) / events) + (index % events)-1); } } } void mitk::USDiPhASImageSource::OrderImagesUltrasound(Image::Pointer SoundImage) { unsigned int width = m_device->GetScanMode().imageWidth; unsigned int height = m_device->GetScanMode().imageHeight; unsigned int events = m_device->GetScanMode().transmitEventsCount; unsigned int dimSound[] = { width, height, m_recordedImages.size()}; SoundImage->Initialize(m_Image->GetPixelType(), 3, dimSound); SoundImage->SetGeometry(m_Image->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 9065c9012b..4cd3570c86 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h @@ -1,128 +1,136 @@ /*=================================================================== 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 "Framework.IBMT.US.CWrapper.h" #include "mitkImageReadAccessor.h" #include "itkFastMutexLock.h" #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); /** * 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); - void SetDataType(int DataT); - void SetUseBModeFilter(bool isSet); /** This starts or ends the recording session*/ void SetRecordingStatus(bool record); + void ModifyDataType(int DataT); + void ModifyUseBModeFilter(bool isSet); + protected: + void SetDataType(int 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; mitk::Image::Pointer ApplyBmodeFilter(mitk::Image::Pointer inputImage); mitk::Image::Pointer ApplyBmodeFilter2d(mitk::Image::Pointer inputImage); void OrderImagesInterleaved(Image::Pointer LaserImage, Image::Pointer SoundImage); void OrderImagesUltrasound(Image::Pointer SoundImage); /** Reinitializes the image according to the DataType set. */ void UpdateImageDataType(int imageHeight, int imageWidth); /** * Sets the spacing used in the image based on the informations of the ScanMode in USDiPhAS Device */ void UpdateImageGeometry(); /** This image holds the image to be displayed right now*/ mitk::Image::Pointer m_Image; 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 startTime; bool useGUIOutPut; BeamformerStateInfoNative BeamformerInfos; int m_DataType; // 0: Use image data; 1: Use beamformed data bool useBModeFilter; bool currentlyRecording; + bool m_DataTypeModified; + int m_DataTypeNext; + bool m_UseBModeFilterModified; + bool m_UseBModeFilterNext; }; } // namespace mitk #endif // MITKUSDiPhASImageSource_H diff --git a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp index 99fb99c0a4..db65aa59a8 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.cpp @@ -1,303 +1,303 @@ /*=================================================================== 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(); + OnScanDepthChanged(); // HERE OnAveragingCountChanged(); OnTGCMinChanged(); OnTGCMaxChanged(); OnDataTypeChanged(); OnPitchChanged(); OnReconstructedSamplesChanged(); OnReconstructedLinesChanged(); OnSpeedOfSoundChanged(); OnBandpassEnabledChanged(); OnLowCutChanged(); OnHighCutChanged(); - OnUseBModeFilterChanged(); + OnUseBModeFilterChanged(); // HERE m_ControlInterface->SetSilentUpdate(false); // on the last update pass the scanmode and geometry! - OnModeChanged(); + 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())); //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->TimeGainCompensationMin, SIGNAL(valueChanged(int)), this, SLOT(OnTGCMinChanged())); connect(ui->TimeGainCompensationMax, 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 (ui->StartStopRecord->text() == "Start Recording") { ui->StartStopRecord->setText("Stop Recording"); m_ControlInterface->SetRecord(true); } else { ui->StartStopRecord->setText("Start Recording"); m_ControlInterface->SetRecord(false); } } //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->TimeGainCompensationMin->value(); int tgcMax = ui->TimeGainCompensationMax->value(); if (tgcMin > tgcMax) { ui->TimeGainCompensationMin->setValue(tgcMax); MITK_INFO << "User tried to set tgcMin>tgcMax."; } m_ControlInterface->SetTGCMin(ui->TimeGainCompensationMin->value()); } void QmitkUSControlsCustomDiPhASDeviceWidget::OnTGCMaxChanged() { if (m_ControlInterface.IsNull()) { return; } int tgcMin = ui->TimeGainCompensationMin->value(); int tgcMax = ui->TimeGainCompensationMax->value(); if (tgcMin > tgcMax) { ui->TimeGainCompensationMax->setValue(tgcMin); MITK_INFO << "User tried to set tgcMin>tgcMax."; } m_ControlInterface->SetTGCMax(ui->TimeGainCompensationMax->value()); } void QmitkUSControlsCustomDiPhASDeviceWidget::OnDataTypeChanged() { if (m_ControlInterface.IsNull()) { return; } QString DataType = ui->DataType->currentText(); if (DataType == "Image Data") { m_ControlInterface->SetDataType(0); } else if (DataType == "Beamformed Data") { m_ControlInterface->SetDataType(1); } } // 0= image; 1= beamformed; //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.ui b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui index 5c047705a8..2392a28d0f 100644 --- a/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui +++ b/Modules/USUI/Qmitk/QmitkUSControlsCustomDiPhASDeviceWidget.ui @@ -1,498 +1,513 @@ QmitkUSControlsCustomDiPhASDeviceWidget 0 0 579 903 Form 0 50 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 Use BMode Envelope Filter false Qt::Horizontal 40 20 100 50 Start Recording Qt::Horizontal 40 20 <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 - 0.100000000000000 + 1.000000000000000 10000.000000000000000 1.000000000000000 Transmit Phase Length [us] Excitation Frequency [MHz] + + false + Interleaved Ultrasound only + + false + 5 75 70 Voltage [V] Mode <html><head/><body><p><span style=" font-weight:600;">Receive Parameters</span></p></body></html> Scan Depth [mm] 1 - 10000 + 100 1 Averaging Count 42 0 TimeGainCompensationMin 42 0 TimeGainCompensationMax false - Image Data + Beamformed Data - Beamformed Data + Image Data DataType 1000.000000000000000 50.000000000000000 <html><head/><body><p><span style=" font-weight:600;">Beamforming Parameters</span></p></body></html> 256 4096 256 2048 Pitch of Transducer [mm] - 256 + 128 1024 - 256 + 128 256 Reconstructed Samples per Line 0.050000000000000 0.150000000000000 Speed of Sound [m/s] 1000000 1540 Reconstructed Lines <html><head/><body><p><span style=" font-weight:600;">Bandpass Parameters</span></p></body></html> High Cut [MHz] Low Cut [MHz] Bandpass Enabled 5.000000000000000 Off On Qt::Vertical 20 40