diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp index b771d95c31..213c833329 100644 --- a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp @@ -1,479 +1,479 @@ /*=================================================================== 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 "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkImageReadAccessor.h" #include "mitkNavigationDataSmoothingFilter.h" #include "mitkNavigationDataDelayFilter.h" #include "mitkTrackingDeviceSource.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" //Microservices #include #include #include #include #include //TempIncludes #include //___ //Microservices -const std::string mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier = "org.mitk.modules.us.USCombinedModality"; +const std::string mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier = "org.mitk.modules.us.AbstractUltrasoundTrackerDevice"; const char* mitk::AbstractUltrasoundTrackerDevice::DefaultProbeIdentifier = "default"; const char* mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator = "_"; -const std::string mitk::AbstractUltrasoundTrackerDevice::US_INTERFACE_NAME = "org.mitk.services.USCombinedModality"; +const std::string mitk::AbstractUltrasoundTrackerDevice::US_INTERFACE_NAME = "org.mitk.services.AbstractUltrasoundTrackerDevice"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_CLASS = US_INTERFACE_NAME + ".class"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; //____ mitk::AbstractUltrasoundTrackerDevice::AbstractUltrasoundTrackerDevice( USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, bool trackedUltrasoundActive ) : m_UltrasoundDevice(usDevice), m_TrackingDeviceDataSource(trackingDevice), m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0)), m_NumberOfSmoothingValues(0), m_DelayCount(0), m_IsTrackedUltrasoundActive( trackedUltrasoundActive ) { this->RebuildFilterPipeline(); //create a new output (for the image data) mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); // Combined Modality should not spawn an own acquire thread, because // image acquiring is done by the included us device m_UltrasoundDevice->SetSpawnAcquireThread(false); } mitk::AbstractUltrasoundTrackerDevice::~AbstractUltrasoundTrackerDevice() { if (m_ServiceRegistration != nullptr) { m_ServiceRegistration.Unregister(); } m_ServiceRegistration = 0; } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration() { return this->GetCalibration( this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe() ); } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration(std::string depth) { return this->GetCalibration(depth, this->GetIdentifierForCurrentProbe()); } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration( std::string depth, std::string probe ) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + depth; // find calibration for combination of probe identifier and depth std::map::iterator calibrationIterator = m_Calibrations.find(calibrationKey); if (calibrationIterator == m_Calibrations.end()) { return 0; } return calibrationIterator->second; } void mitk::AbstractUltrasoundTrackerDevice::SetCalibration( mitk::AffineTransform3D::Pointer calibration ) { if( calibration.IsNull() ) { MITK_WARN << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call."; return; } std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if( calibrationKey.empty() ) { MITK_WARN << "Could not get a key for the calibration -> Calibration cannot be set."; return; } m_Calibrations[calibrationKey] = calibration; } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration() { return this->RemoveCalibration( this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe() ); } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration(std::string depth) { return this->RemoveCalibration( depth, this->GetIdentifierForCurrentProbe() ); } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration( std::string depth, std::string probe ) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + depth; return m_Calibrations.erase(calibrationKey) > 0; } std::string mitk::AbstractUltrasoundTrackerDevice::GetDeviceClass() { return DeviceClassIdentifier; } mitk::USImageSource::Pointer mitk::AbstractUltrasoundTrackerDevice::GetUSImageSource() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("AbstractUltrasoundTrackerDevice")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetUSImageSource(); } mitk::NavigationDataSource::Pointer mitk::AbstractUltrasoundTrackerDevice::GetNavigationDataSource() { return this->RebuildFilterPipeline(); } bool mitk::AbstractUltrasoundTrackerDevice::GetIsCalibratedForCurrentStatus() { return m_Calibrations.find(this->GetIdentifierForCurrentCalibration()) != m_Calibrations.end(); } bool mitk::AbstractUltrasoundTrackerDevice::GetContainsAtLeastOneCalibration() { return !m_Calibrations.empty(); } std::string mitk::AbstractUltrasoundTrackerDevice::SerializeCalibration() { std::stringstream result; result << "" << std::endl; // For each calibration in the set for( std::map::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); it++ ) { mitk::AffineTransform3D::MatrixType matrix = it->second->GetMatrix(); mitk::AffineTransform3D::TranslationType translation = it->second->GetTranslation(); TiXmlElement elem(it->first); // Serialize Matrix elem.SetDoubleAttribute("M00", matrix[0][0]); elem.SetDoubleAttribute("M01", matrix[0][1]); elem.SetDoubleAttribute("M02", matrix[0][2]); elem.SetDoubleAttribute("M10", matrix[1][0]); elem.SetDoubleAttribute("M11", matrix[1][1]); elem.SetDoubleAttribute("M12", matrix[1][2]); elem.SetDoubleAttribute("M20", matrix[2][0]); elem.SetDoubleAttribute("M21", matrix[2][1]); elem.SetDoubleAttribute("M22", matrix[2][2]); // Serialize Offset elem.SetDoubleAttribute("T0", translation[0]); elem.SetDoubleAttribute("T1", translation[1]); elem.SetDoubleAttribute("T2", translation[2]); result << elem << std::endl; } result << "" << std::endl; return result.str(); } void mitk::AbstractUltrasoundTrackerDevice::DeserializeCalibration( const std::string& xmlString, bool clearPreviousCalibrations ) { // Sanitize Input if (xmlString == "") { MITK_ERROR << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; mitkThrow() << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; return; } // Clear previous calibrations if necessary if (clearPreviousCalibrations) m_Calibrations.clear(); // Parse Input TiXmlDocument doc; if (!doc.Parse(xmlString.c_str())) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); mitkThrow() << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); return; } TiXmlElement* root = doc.FirstChildElement(); if (root == nullptr) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; mitkThrow() << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; return; } // Read Calibrations for (TiXmlElement* elem = root->FirstChildElement(); elem != nullptr; elem = elem->NextSiblingElement()) { mitk::AffineTransform3D::MatrixType matrix; mitk::AffineTransform3D::OffsetType translation; std::string calibName = elem->Value(); // Deserialize Matrix elem->QueryDoubleAttribute("M00", &matrix[0][0]); elem->QueryDoubleAttribute("M01", &matrix[0][1]); elem->QueryDoubleAttribute("M02", &matrix[0][2]); elem->QueryDoubleAttribute("M10", &matrix[1][0]); elem->QueryDoubleAttribute("M11", &matrix[1][1]); elem->QueryDoubleAttribute("M12", &matrix[1][2]); elem->QueryDoubleAttribute("M20", &matrix[2][0]); elem->QueryDoubleAttribute("M21", &matrix[2][1]); elem->QueryDoubleAttribute("M22", &matrix[2][2]); // Deserialize Offset elem->QueryDoubleAttribute("T0", &translation[0]); elem->QueryDoubleAttribute("T1", &translation[1]); elem->QueryDoubleAttribute("T2", &translation[2]); mitk::AffineTransform3D::Pointer calibration = mitk::AffineTransform3D::New(); calibration->SetMatrix(matrix); calibration->SetTranslation(translation); m_Calibrations[calibName] = calibration; } } void mitk::AbstractUltrasoundTrackerDevice::SetNumberOfSmoothingValues( unsigned int numberOfSmoothingValues ) { unsigned int oldNumber = m_NumberOfSmoothingValues; m_NumberOfSmoothingValues = numberOfSmoothingValues; // if filter should be activated or deactivated if ((oldNumber == 0 && numberOfSmoothingValues != 0) || (oldNumber != 0 && numberOfSmoothingValues == 0)) { this->RebuildFilterPipeline(); } m_SmoothingFilter->SetNumerOfValues(numberOfSmoothingValues); } void mitk::AbstractUltrasoundTrackerDevice::SetDelayCount( unsigned int delayCount ) { unsigned int oldCount = m_DelayCount; m_DelayCount = delayCount; // if filter should be activated or deactivated if ((oldCount == 0 && delayCount != 0) || (oldCount != 0 && delayCount == 0)) { this->RebuildFilterPipeline(); } m_DelayFilter->SetDelay(delayCount); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceCustom() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceBMode() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceProbes() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceDoppler() { return itk::SmartPointer(); } /*void mitk::AbstractUltrasoundTrackerDevice::UnregisterOnService() { if( m_UltrasoundDevice->GetDeviceState() == USDevice::State_Activated ) { m_UltrasoundDevice->Deactivate(); } if( m_UltrasoundDevice->GetDeviceState() == USDevice::State_Connected ) { m_UltrasoundDevice->Disconnect(); } if( m_ServiceRegistration != nullptr ) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } void mitk::AbstractUltrasoundTrackerDevice::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps //us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator("TEST", 16); m_ServiceProperties[US_PROPKEY_ID] = uidGen.GetUID(); m_ServiceProperties[US_PROPKEY_DEVICENAME] = m_UltrasoundDevice->GetName(); m_ServiceProperties[US_PROPKEY_CLASS] = mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier; m_ServiceRegistration = context->RegisterService(this, m_ServiceProperties); }*/ void mitk::AbstractUltrasoundTrackerDevice::GenerateData() { } std::string mitk::AbstractUltrasoundTrackerDevice::GetIdentifierForCurrentCalibration() { return this->GetIdentifierForCurrentProbe() + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + this->GetCurrentDepthValue(); } std::string mitk::AbstractUltrasoundTrackerDevice::GetIdentifierForCurrentProbe() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); us::ServiceProperties::const_iterator probeIt = usdeviceProperties.find( mitk::USDevice::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED); // get probe identifier from control interface for probes std::string probeName = mitk::AbstractUltrasoundTrackerDevice::DefaultProbeIdentifier; if (probeIt != usdeviceProperties.end()) { probeName = (probeIt->second).ToString(); } // make sure that there is no '/' which would cause problems for TinyXML std::replace(probeName.begin(), probeName.end(), '/', '-'); return probeName; } std::string mitk::AbstractUltrasoundTrackerDevice::GetCurrentDepthValue() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); // get string for depth value from the micro service properties std::string depth; us::ServiceProperties::iterator depthIterator = usdeviceProperties.find( mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH); if (depthIterator != usdeviceProperties.end()) { depth = depthIterator->second.ToString(); } else { depth = "0"; } return depth; } mitk::NavigationDataSource::Pointer mitk::AbstractUltrasoundTrackerDevice::RebuildFilterPipeline() { itk::SmartPointer filter = m_TrackingDeviceDataSource; if( m_NumberOfSmoothingValues > 0 ) { for (unsigned int i = 0; i < m_TrackingDeviceDataSource->GetNumberOfOutputs(); i++) { m_SmoothingFilter->SetInput(i, filter->GetOutput(i)); } filter = m_SmoothingFilter; } if( m_DelayCount > 0 ) { for( unsigned int i = 0; i < m_TrackingDeviceDataSource->GetNumberOfOutputs(); i++ ) { m_DelayFilter->SetInput(i, filter->GetOutput(i)); } filter = m_DelayFilter; } return filter.GetPointer(); } void mitk::AbstractUltrasoundTrackerDevice::UnregisterOnService() { if (m_UltrasoundDevice->GetDeviceState() == USDevice::State_Activated) { m_UltrasoundDevice->Deactivate(); } if (m_UltrasoundDevice->GetDeviceState() == USDevice::State_Connected) { m_UltrasoundDevice->Disconnect(); } if (m_ServiceRegistration != nullptr) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } void mitk::AbstractUltrasoundTrackerDevice::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps //us::ServiceProperties props; mitk::UIDGenerator uidGen = - mitk::UIDGenerator("org.mitk.services.USCombinedModality", 16); + mitk::UIDGenerator("org.mitk.services.AbstractUltrasoundTrackerDevice", 16); m_ServiceProperties[US_PROPKEY_ID] = uidGen.GetUID(); m_ServiceProperties[US_PROPKEY_DEVICENAME] = m_UltrasoundDevice->GetName(); m_ServiceProperties[US_PROPKEY_CLASS] = mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier; m_ServiceRegistration = context->RegisterService(this, m_ServiceProperties); } diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h index 584eacd1d3..e8bc035359 100644 --- a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h @@ -1,262 +1,261 @@ /*=================================================================== 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 __mitkAbstractUltrasoundTrackerDevice_h #define __mitkAbstractUltrasoundTrackerDevice_h #include #include "mitkUSDevice.h" #include "mitkImageSource.h" #include "mitkNavigationDataSource.h" // Microservices #include #include #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class NavigationDataSmoothingFilter; class NavigationDataDelayFilter; /** * \brief Abstract class for an easy handling of a combination of an USDevice and * a NavigationDataSource. * This class can be used as an ImageSource subclass. Additionally tracking data be * retrieved from the NavigationDataSource returned by GetTrackingDevice(). * * A calibration of the ultrasound image stream to the navigation datas can be set * for the currently active zoom level (of the ultrasound device) by SetCalibration() * The ultrasound images are transformed according to this calibration in the * GenerateData() method. */ class MITKUSNAVIGATION_EXPORT AbstractUltrasoundTrackerDevice : public mitk::ImageSource { public: static const std::string DeviceClassIdentifier; static const char* DefaultProbeIdentifier; static const char* ProbeAndDepthSeperator; static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_CLASS; static const std::string US_PROPKEY_ID; mitkClassMacro(AbstractUltrasoundTrackerDevice, mitk::ImageSource); mitkNewMacro3Param(AbstractUltrasoundTrackerDevice, USDevice::Pointer, itk::SmartPointer, bool); itkGetMacro(UltrasoundDevice, itk::SmartPointer); itkSetMacro(UltrasoundDevice, itk::SmartPointer); itkGetMacro(TrackingDeviceDataSource, itk::SmartPointer); itkSetMacro(TrackingDeviceDataSource, itk::SmartPointer); /** * \brief Getter for calibration data of the currently active depth and probe. * * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(); /** * \brief Getter for calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth); /** * \brief Getter for calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \param probe probe of the ultrasound device for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth, std::string probe); /** * \brief Sets a transformation as calibration data. * Calibration data is set for the currently activated probe and their current * zoom factor. It also marks the device as calibrated. */ void SetCalibration(AffineTransform3D::Pointer calibration); /** * \brief Removes the calibration data of the currently active depth and probe. * \return true on success, false if there was no calibration */ bool RemoveCalibration(); /** * \brief Removes the calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth); /** * \brief Removes the calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \param probe probe of the ultrasound device for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth, std::string probe); /** * \brief Returns the Class of the Device. */ std::string GetDeviceClass(); /** * \brief Wrapper for returning USImageSource of the UltrasoundDevice. */ USImageSource::Pointer GetUSImageSource(); itk::SmartPointer GetNavigationDataSource(); /** * \return true if the device is calibrated for the currently selected probe with the current zoom level */ bool GetIsCalibratedForCurrentStatus(); /** * \return true if a calibration was loaded for at least one probe and depth */ bool GetContainsAtLeastOneCalibration(); /** * \brief Serializes all contained calibrations into an xml fragment. * * The returned string contains one parent node named "calibrations" and several * subnodes, one for each calibration that is present. */ std::string SerializeCalibration(); /** * \brief Deserializes a string provided by a prior call to Serialize(). * If the bool flag is true, all prior calibrations will be deleted. * If the flag is set to false, prior calibrations will be retained, but overwritten * if one of equal name is present. * * \throws mitk::Exception if the given string could not be parsed correctly. */ void DeserializeCalibration(const std::string &xmlString, bool clearPreviousCalibrations = true); void SetNumberOfSmoothingValues(unsigned int numberOfSmoothingValues); void SetDelayCount(unsigned int delayCount); /** * \brief Remove this device from the micro service. * This method is public for mitk::USCombinedModality, because this devices * can be completly removed. This is not possible for API devices, which * should be available while their sub module is loaded. */ void UnregisterOnService(); virtual void RegisterAsMicroservice(); /** * \brief Wrapper for returning custom control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceCustom(); /** * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceBMode(); /** * \brief Wrapper for returning probes control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceProbes(); /** * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceDoppler(); /** *\brief These Constants are used in conjunction with Microservices */ /*static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_CLASS; static const std::string US_PROPKEY_ID;*/ protected: AbstractUltrasoundTrackerDevice( USDevice::Pointer usDevice, itk::SmartPointer trackingDevice, bool trackedUltrasoundActive ); virtual ~AbstractUltrasoundTrackerDevice(); itkGetMacro(IsTrackedUltrasoundActive, bool); /** * \brief Grabs the next frame from the input. * Must be implemented by the derived class. * This method is called internally, whenever Update() is invoked by an Output. */ virtual void GenerateData() override; std::string GetIdentifierForCurrentCalibration(); std::string GetIdentifierForCurrentProbe(); std::string GetCurrentDepthValue(); itk::SmartPointer RebuildFilterPipeline(); USDevice::Pointer m_UltrasoundDevice; itk::SmartPointer m_TrackingDeviceDataSource; std::map m_Calibrations; itk::SmartPointer m_SmoothingFilter; itk::SmartPointer m_DelayFilter; unsigned int m_NumberOfSmoothingValues; unsigned int m_DelayCount; /** * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. */ us::ServiceRegistration m_ServiceRegistration; /** * \brief Properties of the device's Microservice. */ us::ServiceProperties m_ServiceProperties; private: bool m_IsTrackedUltrasoundActive; }; } // namespace mitk -MITK_DECLARE_SERVICE_INTERFACE(mitk::AbstractUltrasoundTrackerDevice, "org.mitk.services.USCombinedModality") -//MITK_DECLARE_SERVICE_INTERFACE(mitk::AbstractUltrasoundTrackerDevice, "org.mitk.services.AbstractUltrasoundTrackerDevice") +MITK_DECLARE_SERVICE_INTERFACE(mitk::AbstractUltrasoundTrackerDevice, "org.mitk.services.AbstractUltrasoundTrackerDevice") #endif diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.cpp b/Modules/US/USNavigation/mitkUSCombinedModality.cpp index ff34903bb1..400a3a073d 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.cpp +++ b/Modules/US/USNavigation/mitkUSCombinedModality.cpp @@ -1,262 +1,262 @@ /*=================================================================== 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 "mitkUSCombinedModality.h" //#include "mitkNavigationDataSource.h" #include "mitkImageReadAccessor.h" #include #include #include "mitkTrackingDeviceSource.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" mitk::USCombinedModality::USCombinedModality( USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, bool trackedUltrasoundActive ) : AbstractUltrasoundTrackerDevice( usDevice, trackingDevice, trackedUltrasoundActive ) { } mitk::USCombinedModality::~USCombinedModality() { } - +/* void mitk::USCombinedModality::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps //us::ServiceProperties props; mitk::UIDGenerator uidGen = - mitk::UIDGenerator("org.mitk.services.USCombinedModality", 16); + mitk::UIDGenerator("org.mitk.services.AbstractUltrasoundTrackerDevice", 16); m_ServiceProperties[US_PROPKEY_ID] = uidGen.GetUID(); m_ServiceProperties[US_PROPKEY_DEVICENAME] = m_UltrasoundDevice->GetName(); m_ServiceProperties[US_PROPKEY_CLASS] = mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier; m_ServiceRegistration = context->RegisterService(this, m_ServiceProperties); -} +}*/ mitk::USAbstractControlInterface::Pointer mitk::USCombinedModality::GetControlInterfaceCustom() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceCustom(); } mitk::USControlInterfaceBMode::Pointer mitk::USCombinedModality::GetControlInterfaceBMode() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceBMode(); } mitk::USControlInterfaceProbes::Pointer mitk::USCombinedModality::GetControlInterfaceProbes() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceProbes(); } mitk::USControlInterfaceDoppler::Pointer mitk::USCombinedModality::GetControlInterfaceDoppler() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetControlInterfaceDoppler(); } void mitk::USCombinedModality::GenerateData() { if (m_UltrasoundDevice->GetIsFreezed()) { return; } //if the image is freezed: do nothing //get next image from ultrasound image source mitk::Image::Pointer image = m_UltrasoundDevice->GetUSImageSource()->GetNextImage(); if (image.IsNull() || !image->IsInitialized()) //check the image { MITK_WARN << "Invalid image in USCombinedModality, aborting!"; return; } //get output and initialize it if it wasn't initialized before mitk::Image::Pointer output = this->GetOutput(); if (!output->IsInitialized()) { output->Initialize(image); } //now update image data mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(0, 0, 0)); output->SetSlice(inputReadAccessor.GetData()); //copy image data output->GetGeometry()->SetSpacing(image->GetGeometry()->GetSpacing()); //copy spacing because this might also change //and update calibration (= transformation of the image) std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if (!calibrationKey.empty()) { std::map::iterator calibrationIterator = m_Calibrations.find(calibrationKey); if (calibrationIterator != m_Calibrations.end()) { // transform image according to callibration if one is set // for current configuration of probe and depth this->GetOutput()->GetGeometry()->SetIndexToWorldTransform(calibrationIterator->second); } } } //====================================================================================================================== /** bool mitk::USCombinedModality::OnInitialization() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } if (m_UltrasoundDevice->GetDeviceState() < mitk::USDevice::State_Initialized) { return m_UltrasoundDevice->Initialize(); } else { return true; } } bool mitk::USCombinedModality::OnConnection() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } // connect ultrasound device only if it is not already connected if (m_UltrasoundDevice->GetDeviceState() >= mitk::USDevice::State_Connected) { return true; } else { return m_UltrasoundDevice->Connect(); } } bool mitk::USCombinedModality::OnDisconnection() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->Disconnect(); } bool mitk::USCombinedModality::OnActivation() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot start tracking as TrackingDeviceSource is null."; } trackingDeviceSource->StartTracking(); // activate ultrasound device only if it is not already activated if (m_UltrasoundDevice->GetDeviceState() >= mitk::USDevice::State_Activated) { return true; } else { return m_UltrasoundDevice->Activate(); } } bool mitk::USCombinedModality::OnDeactivation() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot stop tracking as TrackingDeviceSource is null."; } trackingDeviceSource->StopTracking(); m_UltrasoundDevice->Deactivate(); return m_UltrasoundDevice->GetIsConnected(); } void mitk::USCombinedModality::OnFreeze(bool freeze) { mitk::TrackingDeviceSource::Pointer trackingDeviceSource = dynamic_cast(m_TrackingDevice.GetPointer()); if (trackingDeviceSource.IsNull()) { MITK_WARN("USCombinedModality")("USDevice") << "Cannot freeze tracking."; } else { if (freeze) { trackingDeviceSource->Freeze(); } else { trackingDeviceSource->UnFreeze(); } } if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } m_UltrasoundDevice->SetIsFreezed(freeze); } */ diff --git a/Modules/US/USNavigation/mitkUSCombinedModality.h b/Modules/US/USNavigation/mitkUSCombinedModality.h index 8d7949d1e5..cb146a6216 100644 --- a/Modules/US/USNavigation/mitkUSCombinedModality.h +++ b/Modules/US/USNavigation/mitkUSCombinedModality.h @@ -1,124 +1,124 @@ /*=================================================================== 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 MITKUSCombinedModality_H_HEADER_INCLUDED_ #define MITKUSCombinedModality_H_HEADER_INCLUDED_ #include #include "mitkUSDevice.h" #include "mitkImageSource.h" #include "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkNavigationDataSource.h" // Microservices #include #include namespace itk { template class SmartPointer; } namespace mitk { class USControlInterfaceBMode; class USControlInterfaceProbes; class USControlInterfaceDoppler; /** * \brief Combination of USDevice and NavigationDataSource. * This class can be used as an ImageSource subclass. Additionally tracking data be * retrieved from the NavigationDataSource returned by GetTrackingDevice(). * * A calibration of the ultrasound image stream to the navigation datas can be set * for the currently active zoom level (of the ultrasound device) by SetCalibration(). * The ultrasound images are transformed according to this calibration in the * GenerateData() method. */ class MITKUSNAVIGATION_EXPORT USCombinedModality : public mitk::AbstractUltrasoundTrackerDevice { public: mitkClassMacro(USCombinedModality, mitk::AbstractUltrasoundTrackerDevice); mitkNewMacro3Param(USCombinedModality, USDevice::Pointer, itk::SmartPointer, bool); /** * \brief Wrapper for returning custom control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceCustom() override; /** * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceBMode() override; /** * \brief Wrapper for returning probes control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceProbes() override; /** * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceDoppler() override; protected: USCombinedModality( USDevice::Pointer usDevice, itk::SmartPointer trackingDevice, bool trackedUltrasoundActive = false ); virtual ~USCombinedModality(); /** * \brief Initializes UltrasoundDevice. */ //___virtual bool OnInitialization(); /** * \brief Connects UltrasoundDevice. */ //___virtual bool OnConnection(); /** * \brief Disconnects UltrasoundDevice. */ //___virtual bool OnDisconnection(); /** * \brief Activates UltrasoundDevice. */ //___virtual bool OnActivation(); /** * \brief Deactivates UltrasoundDevice. */ //___ virtual bool OnDeactivation(); /** * \brief Freezes or unfreezes UltrasoundDevice. */ //___virtual void OnFreeze(bool); - void RegisterAsMicroservice() override; + // void RegisterAsMicroservice() override; /** * \brief Grabs the next frame from the input. * This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() override; }; } // namespace mitk #endif // MITKUSCombinedModality_H_HEADER_INCLUDED_ diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp index fc6f856adc..1914bda4bb 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.cpp @@ -1,208 +1,208 @@ /*=================================================================== 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 "QmitkUSAbstractNavigationStep.h" #include "ui_QmitkUSAbstractNavigationStep.h" #include "mitkNavigationDataToNavigationDataFilter.h" const char* QmitkUSAbstractNavigationStep::DATANAME_SETTINGS = "Settings"; const char* QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM = "US Image Stream"; const char* QmitkUSAbstractNavigationStep::DATANAME_BASENODE = QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM; QmitkUSAbstractNavigationStep::QmitkUSAbstractNavigationStep(QWidget *parent) : QWidget(parent), m_NavigationStepState(State_Stopped) { } QmitkUSAbstractNavigationStep::~QmitkUSAbstractNavigationStep() { } bool QmitkUSAbstractNavigationStep::OnRestartStep() { return this->OnStopStep() && this->OnStartStep(); } bool QmitkUSAbstractNavigationStep::GetIsRestartable() { return true; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSAbstractNavigationStep::GetFilter() { return FilterVector(); } void QmitkUSAbstractNavigationStep::SetDataStorage(itk::SmartPointer dataStorage) { m_DataStorage = dataStorage; } -void QmitkUSAbstractNavigationStep::SetCombinedModality(itk::SmartPointer combinedModality) +void QmitkUSAbstractNavigationStep::SetCombinedModality(itk::SmartPointer combinedModality) { m_CombinedModality = combinedModality; this->OnSetCombinedModality(); } bool QmitkUSAbstractNavigationStep::StartStep() { if ( this->GetNavigationStepState() == State_Stopped && this->OnStartStep() ) { m_NavigationStepState = State_Started; return true; } return false; } bool QmitkUSAbstractNavigationStep::StopStep() { if ( this->GetNavigationStepState() == State_Started || ( this->GetNavigationStepState() > State_Started && this->DeactivateStep() ) ) { if ( this->OnStopStep() ) { m_NavigationStepState = State_Stopped; return true; } } return false; } bool QmitkUSAbstractNavigationStep::RestartStep() { return this->OnRestartStep(); } bool QmitkUSAbstractNavigationStep::FinishStep() { if ( this->GetNavigationStepState() > State_Started && this->DeactivateStep() ) { if ( this->OnFinishStep() ) { m_NavigationStepState = State_Started; return true; } } return false; } bool QmitkUSAbstractNavigationStep::ActivateStep() { if ( this->GetNavigationStepState() == State_Started || ( this->GetNavigationStepState() < State_Started && this->StartStep() ) ) { if ( this->OnActivateStep() ) { m_NavigationStepState = State_Active; return true; } } return false; } bool QmitkUSAbstractNavigationStep::DeactivateStep() { if ( this->GetNavigationStepState() == State_Active ) { if ( this->OnDeactivateStep() ) { m_NavigationStepState = State_Started; return true; } } return false; } void QmitkUSAbstractNavigationStep::Update() { this->OnUpdate(); } QmitkUSAbstractNavigationStep::NavigationStepState QmitkUSAbstractNavigationStep::GetNavigationStepState() { return m_NavigationStepState; } itk::SmartPointer QmitkUSAbstractNavigationStep::GetDataStorage(bool throwNull) { if ( throwNull && m_DataStorage.IsNull() ) { MITK_ERROR << "Data storage must be set to step widget before."; mitkThrow() << "Data storage must be set to step widget before."; } return m_DataStorage; } itk::SmartPointer QmitkUSAbstractNavigationStep::GetCombinedModality(bool throwNull) { if ( throwNull && m_CombinedModality.IsNull() ) { MITK_ERROR << "Combined modality is not set yet for this widget."; mitkThrow() << "Combined modality is not set yet for this widget."; } return m_CombinedModality; } itk::SmartPointer QmitkUSAbstractNavigationStep::GetNamedDerivedNode(const char *name, const char *sourceName) { if ( m_DataStorage.IsNull() ) { MITK_ERROR << "Data storage must be set to step widget before."; mitkThrow() << "Data storage must be set to step widget before."; } mitk::DataNode::Pointer sourceNode = m_DataStorage->GetNamedNode(sourceName); if ( sourceNode.IsNull() ) { MITK_WARN << "Source node cannot be found in data storage. Returning null."; return nullptr; } return m_DataStorage->GetNamedDerivedNode(name, m_DataStorage->GetNamedNode(sourceName)); } itk::SmartPointer QmitkUSAbstractNavigationStep::GetNamedDerivedNodeAndCreate(const char* name, const char* sourceName) { if ( m_DataStorage.IsNull() ) { MITK_ERROR << "Data storage must be set to step widget before."; mitkThrow() << "Data storage must be set to step widget before."; } mitk::DataNode::Pointer sourceNode = m_DataStorage->GetNamedNode(sourceName); mitk::DataNode::Pointer dataNode = m_DataStorage->GetNamedDerivedNode(name, sourceNode); if ( dataNode.IsNull() ) { dataNode = mitk::DataNode::New(); dataNode->SetName(name); if ( sourceNode.IsNotNull() ) {this->GetDataStorage()->Add(dataNode, sourceNode);} else {this->GetDataStorage()->Add(dataNode);} } return dataNode; } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h index 17520876ca..166f1d57fd 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSAbstractNavigationStep.h @@ -1,311 +1,311 @@ /*=================================================================== 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 QMITKUSABSTRACTNAVIGATIONSTEP_H #define QMITKUSABSTRACTNAVIGATIONSTEP_H #include #include "mitkDataStorage.h" #include "mitkUSCombinedModality.h" namespace itk { template class SmartPointer; } namespace mitk { class NavigationDataToNavigationDataFilter; } /** * \brief Abstract base class for navigation step widgets. * * This class defines a life cycle for navigation steps. Steps can be activated * and deactivated. The first time a step is activated, it is started before * the activation. Steps can be stopped, finished and restarted, too. * * On every state change, the corresponding virtual On... method is called * (OnStartStep(), OnActivateStep(), OnFinishStep(), ...). These methods are * to implement by concrete navigation step widgets. While a step is in the * "active" state, its OnUpdate() method is called periodically. */ class QmitkUSAbstractNavigationStep : public QWidget { Q_OBJECT signals: /** * \brief Signals that all necessary actions where done. * The user can proceed with the next stept after this was signaled. */ void SignalReadyForNextStep(); /** * \brief Signals that it is no longer possible to proceed with following steps. * This signal is emmited when the result data of the step was removed or * changed, so that the old results are invalid for following steps. */ void SignalNoLongerReadyForNextStep(); /** * \brief Signals that the combined modality was changed by this step. * This signal is mainly for steps which creates the combined modality. The * new combined modality is given as a parameter. */ - void SignalCombinedModalityChanged(itk::SmartPointer); + void SignalCombinedModalityChanged(itk::SmartPointer); /** * \brief Signals that an intermediate result was produced. * The properties of the given data node must contain the results. This signal * can be used to log the intermediate results of an experiment, for example * by using the mitk::USNavigationExperimentLogging. */ void SignalIntermediateResult(const itk::SmartPointer); /** * \brief Signals that the settings node was changed. * This signal must not be emited in an OnSettingsChanged() method. */ void SignalSettingsNodeChanged(itk::SmartPointer); public: typedef std::vector< itk::SmartPointer > FilterVector; enum NavigationStepState { State_Stopped, State_Started, State_Active }; static const char* DATANAME_SETTINGS; static const char* DATANAME_IMAGESTREAM; static const char* DATANAME_BASENODE; explicit QmitkUSAbstractNavigationStep(QWidget *parent = 0); ~QmitkUSAbstractNavigationStep(); /** * \brief Getter for the title of the navigation step. * This title should be human readable and can be used to display the * available steps and the currently active step to the user. * The method has to be implemented by a concrete subclass. */ virtual QString GetTitle() = 0; /** * \brief Indicates if it makes sense to be able to restart the step. * This method must be implemented by concrete subclasses if it should not be * possible to restart them. * * \return true for the default implementation */ virtual bool GetIsRestartable(); /** * \brief Called every time the settings for the navigation process where changed. * This method may be implemented by a concrete subclass. The default * implementation does nothing. */ virtual void OnSettingsChanged(const itk::SmartPointer /*settingsNode*/) { } /** * \brief Getter for navigation data filters of the navigation step. * This method may be implemented by a concrete subclass. The default * implementation returns an empty vector. * * \return all navigation data filters that should be updated during the navigation process */ virtual FilterVector GetFilter(); /** * \brief Sets the data storage for the exchange of results between navigation steps. */ void SetDataStorage(itk::SmartPointer dataStorage); /** * \brief Sets the combined modality for the navigation step. * OnSetCombinedModality() is called internal. */ - void SetCombinedModality(itk::SmartPointer combinedModality); + void SetCombinedModality(itk::SmartPointer combinedModality); /** * \brief Should be called to start the navigation step. * \return true if the state was 'stopped' before and OnStartStep() returns true */ bool StartStep(); /** * \brief Should be called to stop the navigation step. * \return true if the state was 'started' (or 'active') and OnStopStep() (and OnDeactivateStep()) return true */ bool StopStep(); /** * \brief Should be called to restart the navigation step. * \return true if OnRestartStep() returns true */ bool RestartStep(); /** * \brief Should be called to finish the navigation step. * The state has to be 'active' before and is 'started' afterwards. * * \return true if the state was 'active' and DeactivateStep() and OnFinishStep() return true */ bool FinishStep(); /** * \brief Should be called to activate the navigation step. * The step gets started before if it was stopped. * * \return true if the state wasn't 'activated' and OnActivateStep() returns true */ bool ActivateStep(); /** * \brief Should be called to deactivate the navigation step. * \return true if the state was 'activated' and OnDeactivateStep() returns true */ bool DeactivateStep(); /** * \brief Should be called periodically while the navigation step is active. * Internal, the method OnUpdate() is called. */ void Update(); /** * \brief Get the current state of the navigation step. * \return State_Stopped, State_Started or State_Active */ NavigationStepState GetNavigationStepState(); protected: /** * \brief Called when the navigation step gets started. * This method has to be implemented by a concrete subclass to handle actions * necessary for starting the step (e.g. initializing that has only to be done * once). * * \return if the actions were done successfully */ virtual bool OnStartStep() = 0; /** * \brief Callen when the navigation step gets stopped. * This method may be implemented by a concrete subclass to handle actions * necessary for stopping the step (e.g. cleanup). The default implementation * does nothing. * * \return if the actions were done successfully; true on every call for the default implementation */ virtual bool OnStopStep() { return true; } /** * \brief Called when restarting a navigation step. * This method may be implemented by a concrete subclass to handle actions * necessary for restarting the navigation step. The default implementations * calls OnStopStep() followed by OnStartStep(). * * \return if the actions were done successfully */ virtual bool OnRestartStep(); /** * \brief Called when all necessary actions for the step where done. * This method has to be implemented by a concrete subclass to handle actions * necessary for finishing the navigation step. * * \return if the actions were done successfully */ virtual bool OnFinishStep() = 0; /** * \brief Called when the navigation step gets activated. * This method has to be implemented by a concrete subclass to handle actions * necessary on activating the navigation step. * * \return if the actions were done successfully */ virtual bool OnActivateStep() = 0; /** * \brief Called when the navigation step gets deactivated (-> state started). * This method may be implemented by a concrete subclass to handle actions * necessary on deactivating the navigation step, which means switching to * another step. * * \return if the actions were done successfully; true on every call for the default implementation */ virtual bool OnDeactivateStep() { return true; } /** * \brief Called periodically while a navigation step is active. * This method has to be implemented by a concrete subclass to handle all * periodic actions during the navigation step. */ virtual void OnUpdate() = 0; /** * \brief Called every time SetCombinedModality() was called. * This method may be implemented by a concrete subclass to handle this event. * The default implementation does nothing. */ virtual void OnSetCombinedModality() { } /** * \brief Returns the data storage set for the navigation step. * * \param throwNull if this method should throw an exception when the data storage is null (default: true) * \return the data storage set by SetDataStorage(); can only be null if the parameter throwNull is set to false * \throws mitk::Exception if the data storage is null and the parameter throwNull is set to true */ itk::SmartPointer GetDataStorage(bool throwNull = true); /** * \brief Returns the combined modality set for the navigation step. * * \param throwNull if this method should throw an exception when the combined modality is null (default: true) * \return the combined modality set by SetCombinedModality(); can only be null if the parameter throwNull is set to false * \throws mitk::Exception if the combined modality is null and the parameter throwNull is set to true */ itk::SmartPointer GetCombinedModality(bool throwNull = true); /** * \brief Returns node with the given name and the given source node (parent) from the data storage. * * \param name the name of the node which should be got from the data storage * \param sourceName name of the source node under which the node should be searched * \return node with the given name or null if no node with the given name and source node could be found * \throws mitk::Exception if the data storage (can be set by SetDataStorage()) is null */ itk::SmartPointer GetNamedDerivedNode(const char* name, const char* sourceName); /** * \brief Returns node with the given name and the given source node (parent) from the data storage. * The node is created if no matching node was found. * * \param name the name of the node which should be got from the data storage * \param sourceName name of the source node under which the node should be searched * \return node with the given name * \throws mitk::Exception if the data storage (can be set by SetDataStorage()) is null */ itk::SmartPointer GetNamedDerivedNodeAndCreate(const char* name, const char* sourceName); private: itk::SmartPointer m_DataStorage; itk::SmartPointer m_CombinedModality; NavigationStepState m_NavigationStepState; }; #endif // QMITKUSABSTRACTNAVIGATIONSTEP_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp index 1f29219b9c..586eead09a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp @@ -1,430 +1,430 @@ /*=================================================================== 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 "QmitkUSNavigationStepCombinedModality.h" #include "ui_QmitkUSNavigationStepCombinedModality.h" #include "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkUSCombinedModality.h" #include "../Widgets/QmitkUSCombinedModalityEditWidget.h" #include #include #include #include "mitkBaseRenderer.h" QmitkUSNavigationStepCombinedModality::QmitkUSNavigationStepCombinedModality(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_LastCalibrationFilename(""), m_CalibrationLoadedNecessary(true), m_ListenerDeviceChanged(this, &QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged), ui(new Ui::QmitkUSNavigationStepCombinedModality) { ui->setupUi(this); // combined modality create widget should only be visible after button press ui->combinedModalityCreateWidget->setVisible(false); ui->combinedModalityEditWidget->setVisible(false); connect(ui->combinedModalityListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityListWidget, SIGNAL(ServiceModified(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalCreated()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityEditExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalSaved()), this, SLOT(OnCombinedModalityEditExit())); - //std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.USCombinedModality)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + "))"; + std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.AbstractUltrasoundTrackerDevice)(" + mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_CLASS + "=" + mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier + "))"; //std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice))"; - ui->combinedModalityListWidget->Initialize(mitk::USCombinedModality::US_PROPKEY_DEVICENAME); + ui->combinedModalityListWidget->Initialize(filterOnlyCombinedModalities); ui->combinedModalityListWidget->SetAutomaticallySelectFirstEntry(true); //try to load UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); m_LastCalibrationFilename = settings.value("LastCalibrationFilename", QVariant("")).toString().toStdString(); MITK_DEBUG << "PERSISTENCE load: " << m_LastCalibrationFilename; settings.endGroup(); } QmitkUSNavigationStepCombinedModality::~QmitkUSNavigationStepCombinedModality() { ui->combinedModalityListWidget->blockSignals(true); //save UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); settings.setValue("LastCalibrationFilename", QVariant(m_LastCalibrationFilename.c_str())); settings.endGroup(); MITK_DEBUG << "PERSISTENCE save: " << m_LastCalibrationFilename; //delete UI delete ui; } void QmitkUSNavigationStepCombinedModality::OnDeviceSelectionChanged() { - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); bool combinedModalitySelected = combinedModality.IsNotNull(); ui->calibrationGroupBox->setEnabled(combinedModalitySelected); ui->combinedModalityDeleteButton->setEnabled(combinedModalitySelected); ui->combinedModalitEditButton->setEnabled(combinedModalitySelected); if (!combinedModalitySelected || m_CombinedModality != combinedModality) { emit SignalNoLongerReadyForNextStep(); if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } if (combinedModalitySelected && combinedModality->GetUltrasoundDevice().IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } } m_CombinedModality = combinedModality; if (combinedModalitySelected) { bool calibrated = this->UpdateCalibrationState(); if (!m_CalibrationLoadedNecessary) { emit SignalReadyForNextStep(); } else { if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } // enable disconnect button only if combined modality is connected or active ui->combinedModalityDistconnectButton->setEnabled(combinedModality->GetUltrasoundDevice()->GetDeviceState() >= mitk::USDevice::State_Connected); ui->combinedModalityActivateButton->setEnabled(combinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Activated); this->UpdateTrackingToolNames(); } else { ui->combinedModalityDistconnectButton->setEnabled(false); ui->combinedModalityActivateButton->setEnabled(false); } } void QmitkUSNavigationStepCombinedModality::OnLoadCalibration() { QString filename = QFileDialog::getOpenFileName(QApplication::activeWindow(), "Load Calibration", m_LastCalibrationFilename.c_str(), "Calibration files *.cal"); m_LastCalibrationFilename = filename.toStdString(); - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNull()) { ui->calibrationLoadStateLabel->setText("Selected device is no USCombinedModality."); emit SignalNoLongerReadyForNextStep(); return; } if (filename.isEmpty()) { bool calibrated = this->UpdateCalibrationState(); if (!calibrated) { emit SignalNoLongerReadyForNextStep(); } return; } QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for reading."; ui->calibrationLoadStateLabel->setText("Cannot open file '" + filename + "' for reading."); emit SignalNoLongerReadyForNextStep(); return; } QTextStream inStream(&file); m_LoadedCalibration = inStream.readAll().toStdString(); if (m_LoadedCalibration.empty()) { MITK_WARN << "Failed to load file. Unsupported format?"; ui->calibrationLoadStateLabel->setText("Failed to load file. Unsupported format?"); emit SignalNoLongerReadyForNextStep(); return; } try { combinedModality->DeserializeCalibration(m_LoadedCalibration); } catch (const mitk::Exception& /*exception*/) { MITK_WARN << "Failed to deserialize calibration. Unsuppoerted format?"; ui->calibrationLoadStateLabel->setText("Failed to deserialize calibration. Unsuppoerted format?"); emit SignalNoLongerReadyForNextStep(); return; } ui->calibrationLoadStateLabel->setText("Loaded calibration : " + filename); m_CombinedModality = combinedModality; emit SignalReadyForNextStep(); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreateNewButtonClicked() { this->SetCombinedModalityCreateWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreationExit() { this->SetCombinedModalityCreateWidgetEnabled(false); mitk::DataNode::Pointer usNode = mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage()//GetDataStorage ->GetNamedNode("US Viewing Stream - Image 0"); if (usNode.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews(//Reinit usNode->GetData()->GetTimeGeometry());//GetNode } else { mitkThrow()<< "No reinit possible"; } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditExit() { this->SetCombinedModalityEditWidgetEnabled(false); ui->combinedModalityEditWidget->SetCombinedModality(0); } void QmitkUSNavigationStepCombinedModality::OnDeleteButtonClicked() { - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->RemoveAllObservers(); combinedModality->UnregisterOnService(); } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditButtonClicked() { ui->combinedModalityEditWidget->SetCombinedModality(m_CombinedModality); this->SetCombinedModalityEditWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnActivateButtonClicked() { - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (!combinedModality->GetUltrasoundDevice()->GetIsConnected()) { combinedModality->GetUltrasoundDevice()->Connect(); } if (!combinedModality->GetUltrasoundDevice()->GetIsActive()) { combinedModality->GetUltrasoundDevice()->Activate(); } } } void QmitkUSNavigationStepCombinedModality::OnDisconnectButtonClicked() { - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (combinedModality->GetUltrasoundDevice()->GetIsActive()) { combinedModality->GetUltrasoundDevice()->Deactivate(); } if (combinedModality->GetUltrasoundDevice()->GetIsConnected()) { combinedModality->GetUltrasoundDevice()->Disconnect(); } } } bool QmitkUSNavigationStepCombinedModality::OnStartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnRestartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnFinishStep() { - mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { QApplication::setOverrideCursor(Qt::WaitCursor); // make sure that the combined modality is in connected state before using it if (combinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Connected) { combinedModality->GetUltrasoundDevice()->Connect(); } if (combinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Activated) { combinedModality->GetUltrasoundDevice()->Activate(); } QApplication::restoreOverrideCursor(); } emit SignalCombinedModalityChanged(combinedModality); this->CreateCombinedModalityResultAndSignalIt(); return true; } bool QmitkUSNavigationStepCombinedModality::OnActivateStep() { // make sure that device selection status is up-to-date this->OnDeviceSelectionChanged(); return true; } void QmitkUSNavigationStepCombinedModality::OnUpdate() { } QString QmitkUSNavigationStepCombinedModality::GetTitle() { return "Selection of Combined Modality"; } bool QmitkUSNavigationStepCombinedModality::GetIsRestartable() { return false; } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityCreateWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityCreateWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityEditWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityEditWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::CreateCombinedModalityResultAndSignalIt() { mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = this->GetCombinedModality(); mitk::USDevice::Pointer usDevice = combinedModality->GetUltrasoundDevice(); // save identifiers and calibration to a result object mitk::DataNode::Pointer combinedModalityResult = mitk::DataNode::New(); combinedModalityResult->SetName("CombinedModalityResult"); combinedModalityResult->SetStringProperty("USNavigation::CombinedModality", std::string(combinedModality->GetUltrasoundDevice()->GetManufacturer() + ": " + combinedModality->GetUltrasoundDevice()->GetName() + " (" + combinedModality->GetUltrasoundDevice()->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::UltrasoundDevice", std::string(usDevice->GetManufacturer() + ": " + usDevice->GetName() + " (" + usDevice->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::TrackingDevice", combinedModality->GetNavigationDataSource()->GetName().c_str()); combinedModalityResult->SetStringProperty("USNavigation::Calibration", combinedModality->SerializeCalibration().c_str()); emit SignalIntermediateResult(combinedModalityResult); } bool QmitkUSNavigationStepCombinedModality::UpdateCalibrationState() { if (m_CombinedModality.IsNull()) { return false; } bool calibrated = m_CombinedModality->GetContainsAtLeastOneCalibration(); if (calibrated) { ui->calibrationLoadStateLabel->setText("Selected device contains at least one calibration."); } else { ui->calibrationLoadStateLabel->setText("Selected device is not calibrated."); } return calibrated; } -mitk::USCombinedModality::Pointer QmitkUSNavigationStepCombinedModality::GetSelectedCombinedModality() +mitk::AbstractUltrasoundTrackerDevice::Pointer QmitkUSNavigationStepCombinedModality::GetSelectedCombinedModality() { // nothing more to do if no device is selected at the moment if (!ui->combinedModalityListWidget->GetIsServiceSelected()) { return 0; } - mitk::USCombinedModality::Pointer combinedModality = ui->combinedModalityListWidget->GetSelectedService(); + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality = ui->combinedModalityListWidget->GetSelectedService(); if (combinedModality.IsNull()) { MITK_WARN << "Selected device is no USCombinedModality."; } return combinedModality; } void QmitkUSNavigationStepCombinedModality::SetCalibrationLoadedNecessary(bool necessary) { m_CalibrationLoadedNecessary = necessary; } void QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged(const std::string& key, const std::string&) { // property changes only matter if the navigation step is currently active // (being sensitive to them in other states may even be dangerous) if (this->GetNavigationStepState() < QmitkUSAbstractNavigationStep::State_Active) { return; } // calibration state could have changed if the depth was changed if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { bool calibrated = this->UpdateCalibrationState(); if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } } void QmitkUSNavigationStepCombinedModality::UpdateTrackingToolNames() { //check if everything is initialized if (m_CombinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (GetDataStorage(false).IsNull()) { return; } // get the settings node mitk::DataNode::Pointer settingsNode = this->GetNamedDerivedNode(DATANAME_SETTINGS, DATANAME_BASENODE); std::string needleNames; itk::ProcessObject::DataObjectPointerArray outputs = navigationDataSource->GetOutputs(); for (itk::ProcessObject::DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { needleNames += std::string((static_cast(it->GetPointer()))->GetName()) + ";"; } // change the settings node only if the settings changed std::string oldProperty; if (!settingsNode->GetStringProperty("settings.needle-names", oldProperty) || oldProperty != needleNames || !settingsNode->GetStringProperty("settings.reference-names", oldProperty) || oldProperty != needleNames) { settingsNode->SetStringProperty("settings.needle-names", needleNames.c_str()); settingsNode->SetStringProperty("settings.reference-names", needleNames.c_str()); emit SignalSettingsNodeChanged(settingsNode); } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h index 4725191d28..2df8b2dd3a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h @@ -1,122 +1,122 @@ /*=================================================================== 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 QMITKUSNAVIGATIONSTEPCOMBINEDMODALITY_H #define QMITKUSNAVIGATIONSTEPCOMBINEDMODALITY_H #include "QmitkUSAbstractNavigationStep.h" namespace Ui { class QmitkUSNavigationStepCombinedModality; } /** * \brief Navigation step for creating and selecting a combined modality. * Already created combined modalities can be selected from a service list * widget and calibrations can be loaded for them. New combined modalities can * be created from two service list widgets of NavigationDataSources and * USDevices. */ class QmitkUSNavigationStepCombinedModality : public QmitkUSAbstractNavigationStep { Q_OBJECT protected slots: /** * \brief Triggered, when the selection in the service list widget has changed. */ void OnDeviceSelectionChanged(); /** * \brief Triggered, when the user has clicked "Load Calibration". * Opens a file open dialog and sets the selected calibration for the selected * combined modality. */ void OnLoadCalibration(); /** * \brief Triggered, when the button for creating a new combined modality was clicked. */ void OnCombinedModalityCreateNewButtonClicked(); /** * \brief Triggered, when the dialog for creating a new combined modality was closed. */ void OnCombinedModalityCreationExit(); void OnCombinedModalityEditExit(); /** * \brief Triggered, when the button for deleting a combined modality was clicked. * Unregisters the combined modality from the microservice and removes it. */ void OnDeleteButtonClicked(); void OnCombinedModalityEditButtonClicked(); void OnActivateButtonClicked(); /** * \brief Triggered, when the button for disconnecting a combined modality was clicked. * The state of the combined modality is changed to 'initialized'. */ void OnDisconnectButtonClicked(); public: explicit QmitkUSNavigationStepCombinedModality(QWidget *parent = 0); ~QmitkUSNavigationStepCombinedModality(); virtual bool OnStartStep(); virtual bool OnRestartStep(); virtual bool OnFinishStep(); virtual bool OnActivateStep(); virtual void OnUpdate(); virtual QString GetTitle(); virtual bool GetIsRestartable(); - mitk::USCombinedModality::Pointer GetSelectedCombinedModality(); + mitk::AbstractUltrasoundTrackerDevice::Pointer GetSelectedCombinedModality(); void SetCalibrationLoadedNecessary(bool); void OnDevicePropertyChanged(const std::string&, const std::string&); protected: void SetCombinedModalityCreateWidgetEnabled(bool enabled); void SetCombinedModalityEditWidgetEnabled(bool enabled); void CreateCombinedModalityResultAndSignalIt(); bool UpdateCalibrationState(); void UpdateTrackingToolNames(); /** * \brief The Combined Modality which was selected by the user. */ itk::SmartPointer m_CombinedModality; std::string m_LoadedCalibration; //<<< Temporary saving point for loaded calibration data. std::string m_LastCalibrationFilename; //<<< saves the filename last loaded calibration bool m_CalibrationLoadedNecessary; private: mitk::MessageDelegate2 m_ListenerDeviceChanged; Ui::QmitkUSNavigationStepCombinedModality *ui; }; #endif // QMITKUSNAVIGATIONSTEPCOMBINEDMODALITY_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp index 8ae43921ec..b1538387e1 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/QmitkUltrasoundCalibration.cpp @@ -1,1140 +1,1140 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkUltrasoundCalibration.h" #include // Qt #include #include #include #include // MITK #include //#include #include #include #include #include #include #include "mitkIRenderingManager.h" // us #include //VTK #include #include #include #include #include #include #include "internal/org_mbi_gui_qt_usnavigation_Activator.h" //sleep headers #include #include const std::string QmitkUltrasoundCalibration::VIEW_ID = "org.mitk.views.ultrasoundcalibration"; QmitkUltrasoundCalibration::QmitkUltrasoundCalibration() : m_USDeviceChanged(this, &QmitkUltrasoundCalibration::OnUSDepthChanged) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { // to be notified about service event of an USDevice pluginContext->connectServiceListener(this, "OnDeciveServiceEvent", QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")")); } } QmitkUltrasoundCalibration::~QmitkUltrasoundCalibration() { m_Controls.m_CombinedModalityManagerWidget->blockSignals(true); - mitk::USCombinedModality::Pointer combinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_USDeviceChanged); } m_Timer->stop(); // Sleep(500); //This might be problematic... seems like sometimes some ressources are still in use at calling time. this->OnStopCalibrationProcess(); this->OnStopPlusCalibration(); /*mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Calibration Points"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); node = this->GetDataStorage()->GetNamedNode("Image Calibration Points"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); node = this->GetDataStorage()->GetNamedNode("US Image Stream"); if (node.IsNotNull())this->GetDataStorage()->Remove(node);*/ mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path"); if (node.IsNotNull())this->GetDataStorage()->Remove(node); this->GetDataStorage()->Remove(m_VerificationReferencePointsDataNode); delete m_Timer; } void QmitkUltrasoundCalibration::SetFocus() { m_Controls.m_ToolBox->setFocus(); } void QmitkUltrasoundCalibration::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Controls.m_CombinedModalityManagerWidget->SetCalibrationLoadedNecessary(false); m_Timer = new QTimer(this); m_StreamingTimer = new QTimer(this); m_Controls.m_SpacingBtnFreeze->setEnabled(true); m_Controls.m_SpacingAddPoint->setEnabled(false); m_Controls.m_CalculateSpacing->setEnabled(false); m_SpacingPointsCount = 0; m_SpacingPoints = mitk::PointSet::New(); m_SpacingNode = mitk::DataNode::New(); m_SpacingNode->SetName("Spacing Points"); m_SpacingNode->SetData(this->m_SpacingPoints); this->GetDataStorage()->Add(m_SpacingNode); // Pointset for Calibration Points m_CalibPointsTool = mitk::PointSet::New(); // Pointset for Worldpoints m_CalibPointsImage = mitk::PointSet::New(); m_CalibPointsCount = 0; // Evaluation Pointsets (Non-Visualized) m_EvalPointsImage = mitk::PointSet::New(); m_EvalPointsTool = mitk::PointSet::New(); m_EvalPointsProjected = mitk::PointSet::New(); // Neelde Projection Filter m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New(); // Tracking Status Widgets m_Controls.m_CalibTrackingStatus->ShowStatusLabels(); m_Controls.m_EvalTrackingStatus->ShowStatusLabels(); m_OverrideSpacing = false; // General & Device Selection connect(m_Timer, SIGNAL(timeout()), this, SLOT(Update())); //connect(m_Controls.m_ToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabSwitch(int))); // Calibration connect(m_Controls.m_CalibBtnFreeze, SIGNAL(clicked()), this, SLOT(SwitchFreeze())); // Freeze connect(m_Controls.m_CalibBtnAddPoint, SIGNAL(clicked()), this, SLOT(OnAddCalibPoint())); // Tracking & Image Points (Calibration) connect(m_Controls.m_CalibBtnCalibrate, SIGNAL(clicked()), this, SLOT(OnCalibration())); // Perform Calibration // Evaluation connect(m_Controls.m_EvalBtnStep1, SIGNAL(clicked()), this, SLOT(OnAddEvalProjectedPoint())); // Needle Projection connect(m_Controls.m_EvalBtnStep2, SIGNAL(clicked()), this, SLOT(SwitchFreeze())); // Freeze connect(m_Controls.m_EvalBtnStep3, SIGNAL(clicked()), this, SLOT(OnAddEvalTargetPoint())); // Tracking & Image Points (Evaluation) connect(m_Controls.m_EvalBtnSave, SIGNAL(clicked()), this, SLOT(OnSaveEvaluation())); // Save Evaluation Results connect(m_Controls.m_CalibBtnSaveCalibration, SIGNAL(clicked()), this, SLOT(OnSaveCalibration())); // Save Evaluation Results connect(m_Controls.m_BtnReset, SIGNAL(clicked()), this, SLOT(OnReset())); // Reset Pointsets // PLUS Calibration connect(m_Controls.m_GetCalibrationFromPLUS, SIGNAL(clicked()), this, SLOT(OnGetPlusCalibration())); connect(m_Controls.m_StartStreaming, SIGNAL(clicked()), this, SLOT(OnStartStreaming())); connect(m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout())); connect(m_Controls.m_StopPlusCalibration, SIGNAL(clicked()), this, SLOT(OnStopPlusCalibration())); connect(m_Controls.m_SavePlusCalibration, SIGNAL(clicked()), this, SLOT(OnSaveCalibration())); connect(this, SIGNAL(NewConnectionSignal()), this, SLOT(OnNewConnection())); //Determine Spacing for Calibration of USVideoDevice connect(m_Controls.m_SpacingBtnFreeze, SIGNAL(clicked()), this, SLOT(OnFreezeClicked())); connect(m_Controls.m_SpacingAddPoint, SIGNAL(clicked()), this, SLOT(OnAddSpacingPoint())); connect(m_Controls.m_CalculateSpacing, SIGNAL(clicked()), this, SLOT(OnCalculateSpacing())); //connect( m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalCombinedModalitySelected(mitk::USCombinedModality::Pointer)), // this, SLOT(OnSelectDevice(mitk::USCombinedModality::Pointer)) ); connect(m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalReadyForNextStep()), this, SLOT(OnDeviceSelected())); connect(m_Controls.m_CombinedModalityManagerWidget, SIGNAL(SignalNoLongerReadyForNextStep()), this, SLOT(OnDeviceDeselected())); connect(m_Controls.m_StartCalibrationButton, SIGNAL(clicked()), this, SLOT(OnStartCalibrationProcess())); connect(m_Controls.m_StartPlusCalibrationButton, SIGNAL(clicked()), this, SLOT(OnStartPlusCalibration())); connect(m_Controls.m_CalibBtnRestartCalibration, SIGNAL(clicked()), this, SLOT(OnReset())); connect(m_Controls.m_CalibBtnStopCalibration, SIGNAL(clicked()), this, SLOT(OnStopCalibrationProcess())); connect(m_Controls.m_AddReferencePoints, SIGNAL(clicked()), this, SLOT(OnAddCurrentTipPositionToReferencePoints())); connect(m_Controls.m_AddCurrentPointerTipForVerification, SIGNAL(clicked()), this, SLOT(OnAddCurrentTipPositionForVerification())); connect(m_Controls.m_StartVerification, SIGNAL(clicked()), this, SLOT(OnStartVerification())); //initialize data storage combo box m_Controls.m_ReferencePointsComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ReferencePointsComboBox->SetAutoSelectNewItems(true); m_Controls.m_ReferencePointsComboBox->SetPredicate(mitk::NodePredicateDataType::New("PointSet")); //initialize point list widget if (m_VerificationReferencePoints.IsNull()) { m_VerificationReferencePoints = mitk::PointSet::New(); } if (m_VerificationReferencePointsDataNode.IsNull()) { m_VerificationReferencePointsDataNode = mitk::DataNode::New(); m_VerificationReferencePointsDataNode->SetName("US Verification Reference Points"); m_VerificationReferencePointsDataNode->SetData(m_VerificationReferencePoints); this->GetDataStorage()->Add(m_VerificationReferencePointsDataNode); } m_Controls.m_ReferencePointsPointListWidget->SetPointSetNode(m_VerificationReferencePointsDataNode); m_Controls.m_ToolBox->setCurrentIndex(0); } void QmitkUltrasoundCalibration::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& /*nodes*/) { } void QmitkUltrasoundCalibration::OnTabSwitch(int index) { switch (index) { case 0: if (m_Controls.m_ToolBox->isItemEnabled(1) || m_Controls.m_ToolBox->isItemEnabled(2)) { this->OnStopCalibrationProcess(); } break; default: ; } } //void QmitkUltrasoundCalibration::OnSelectDevice(mitk::USCombinedModality::Pointer combinedModality) void QmitkUltrasoundCalibration::OnDeviceSelected() { - mitk::USCombinedModality::Pointer combinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { //m_Tracker = m_CombinedModality->GetNavigationDataSource(); // Construct Pipeline //this->m_NeedleProjectionFilter->SetInput(0, m_Tracker->GetOutput(0)); combinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_USDeviceChanged); m_Controls.m_StartCalibrationButton->setEnabled(true); m_Controls.m_StartPlusCalibrationButton->setEnabled(true); m_Controls.m_ToolBox->setItemEnabled(1, true); m_Controls.m_ToolBox->setItemEnabled(2, true); } } void QmitkUltrasoundCalibration::OnDeviceDeselected() { - mitk::USCombinedModality::Pointer combinedModality; + mitk::AbstractUltrasoundTrackerDevice::Pointer combinedModality; combinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_USDeviceChanged); } m_Controls.m_StartCalibrationButton->setEnabled(false); m_Controls.m_StartPlusCalibrationButton->setEnabled(false); m_Controls.m_ToolBox->setCurrentIndex(0); m_Controls.m_ToolBox->setItemEnabled(1, false); m_Controls.m_ToolBox->setItemEnabled(2, false); } void QmitkUltrasoundCalibration::OnAddCurrentTipPositionToReferencePoints() { if (m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource().IsNull() || (m_Controls.m_VerificationPointerChoser->GetSelectedToolID() == -1)) { MITK_WARN << "No tool selected, aborting"; return; } mitk::NavigationData::Pointer currentPointerData = m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_VerificationPointerChoser->GetSelectedToolID()); mitk::Point3D currentTipPosition = currentPointerData->GetPosition(); m_VerificationReferencePoints->InsertPoint(m_VerificationReferencePoints->GetSize(), currentTipPosition); } void QmitkUltrasoundCalibration::OnStartVerification() { m_currentPoint = 0; mitk::PointSet::Pointer selectedPointSet = dynamic_cast(m_Controls.m_ReferencePointsComboBox->GetSelectedNode()->GetData()); m_Controls.m_CurrentPointLabel->setText("Point " + QString::number(m_currentPoint) + " of " + QString::number(selectedPointSet->GetSize())); m_allErrors = std::vector(); m_allReferencePoints = std::vector(); for (int i = 0; i < selectedPointSet->GetSize(); i++) { m_allReferencePoints.push_back(selectedPointSet->GetPoint(i)); } } void QmitkUltrasoundCalibration::OnAddCurrentTipPositionForVerification() { if (m_currentPoint == -1) { MITK_WARN << "Cannot add point"; return; } if (m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource().IsNull() || (m_Controls.m_VerificationPointerChoser->GetSelectedToolID() == -1)) { MITK_WARN << "No tool selected, aborting"; return; } mitk::NavigationData::Pointer currentPointerData = m_Controls.m_VerificationPointerChoser->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_VerificationPointerChoser->GetSelectedToolID()); mitk::Point3D currentTipPosition = currentPointerData->GetPosition(); double currentError = m_allReferencePoints.at(m_currentPoint).EuclideanDistanceTo(currentTipPosition); MITK_INFO << "Current Error: " << currentError << " mm"; m_allErrors.push_back(currentError); if (++m_currentPoint < static_cast(m_allReferencePoints.size())) { m_Controls.m_CurrentPointLabel->setText("Point " + QString::number(m_currentPoint) + " of " + QString::number(m_allReferencePoints.size())); } else { m_currentPoint = -1; double meanError = 0; for (std::size_t i = 0; i < m_allErrors.size(); ++i) { meanError += m_allErrors[i]; } meanError /= m_allErrors.size(); QString result = "Finished verification! \n Verification of " + QString::number(m_allErrors.size()) + " points, mean error: " + QString::number(meanError) + " mm"; m_Controls.m_ResultsTextEdit->setText(result); MITK_INFO << result.toStdString(); } } void QmitkUltrasoundCalibration::OnStartCalibrationProcess() { // US Image Stream m_Node = mitk::DataNode::New(); m_Node->SetName("US Calibration Viewing Stream"); //create a dummy image (gray values 0..255) for correct initialization of level window, etc. mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255, 0); m_Node->SetData(dummyImage); this->GetDataStorage()->Add(m_Node); // data node for calibration point set m_CalibNode = mitk::DataNode::New(); m_CalibNode->SetName("Tool Calibration Points"); m_CalibNode->SetData(this->m_CalibPointsImage); this->GetDataStorage()->Add(m_CalibNode); // data node for world point set m_WorldNode = mitk::DataNode::New(); m_WorldNode->SetName("Image Calibration Points"); m_WorldNode->SetData(this->m_CalibPointsTool); this->GetDataStorage()->Add(m_WorldNode); m_CombinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (m_CombinedModality.IsNull()) { return; } m_Tracker = m_CombinedModality->GetNavigationDataSource(); //QString curDepth = service.getProperty(QString::fromStdString(mitk::USDevice::US_PROPKEY_BMODE_DEPTH)).toString(); // Construct Pipeline this->m_NeedleProjectionFilter->SetInput(0, m_Tracker->GetOutput(0)); QApplication::setOverrideCursor(Qt::WaitCursor); // make sure that the combined modality is in connected state before using it if (m_CombinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Connected) { m_CombinedModality->GetUltrasoundDevice()->Connect(); } if (m_CombinedModality->GetUltrasoundDevice()->GetDeviceState() < mitk::USDevice::State_Activated) { m_CombinedModality->GetUltrasoundDevice()->Activate(); } QApplication::restoreOverrideCursor(); this->SwitchFreeze(); // Todo: Maybe display this elsewhere this->ShowNeedlePath(); // Switch active tab to Calibration page m_Controls.m_ToolBox->setItemEnabled(1, true); m_Controls.m_ToolBox->setCurrentIndex(1); } void QmitkUltrasoundCalibration::OnStartPlusCalibration() { if (m_CombinedModality.IsNull()){ m_CombinedModality = m_Controls.m_CombinedModalityManagerWidget->GetSelectedCombinedModality(); if (m_CombinedModality.IsNull()) { return; } //something went wrong, there is no combined modality } //setup server to send UltrasoundImages to PLUS mitk::IGTLServer::Pointer m_USServer = mitk::IGTLServer::New(true); m_USServer->SetName("EchoTrack Image Source"); m_USServer->SetHostname("127.0.0.1"); m_USServer->SetPortNumber(18944); m_USMessageProvider = mitk::IGTLMessageProvider::New(); m_USMessageProvider->SetIGTLDevice(m_USServer); m_USMessageProvider->SetFPS(5); m_USImageToIGTLMessageFilter = mitk::ImageToIGTLMessageFilter::New(); m_USImageToIGTLMessageFilter->ConnectTo(m_CombinedModality->GetUltrasoundDevice()); m_USImageToIGTLMessageFilter->SetName("USImage Filter"); //setup server to send TrackingData to PLUS m_TrackingServer = mitk::IGTLServer::New(true); m_TrackingServer->SetName("EchoTrack Tracking Source"); m_TrackingServer->SetHostname("127.0.0.1"); m_TrackingServer->SetPortNumber(18945); m_TrackingMessageProvider = mitk::IGTLMessageProvider::New(); m_TrackingMessageProvider->SetIGTLDevice(m_TrackingServer); m_TrackingMessageProvider->SetFPS(5); m_TrackingToIGTLMessageFilter = mitk::NavigationDataToIGTLMessageFilter::New(); m_TrackingToIGTLMessageFilter->ConnectTo(m_CombinedModality->GetTrackingDeviceDataSource()); m_TrackingToIGTLMessageFilter->SetName("Tracker Filter"); typedef itk::SimpleMemberCommand< QmitkUltrasoundCalibration > CurCommandType; CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkUltrasoundCalibration::OnPlusConnected); this->m_NewConnectionObserverTag = this->m_TrackingServer->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); //Open connections of both servers if (m_USServer->OpenConnection()) { MITK_INFO << "US Server opened its connection successfully"; m_USServer->StartCommunication(); } else { MITK_INFO << "US Server could not open its connection"; } if (m_TrackingServer->OpenConnection()) { MITK_INFO << "Tracking Server opened its connection successfully"; m_TrackingServer->StartCommunication(); } else { MITK_INFO << "Tracking Server could not open its connection"; } if (m_USMessageProvider->IsCommunicating() && m_TrackingMessageProvider->IsCommunicating()) { m_Controls.m_StartPlusCalibrationButton->setEnabled(false); m_Controls.m_GetCalibrationFromPLUS->setEnabled(true); m_Controls.m_StartStreaming->setEnabled(false); m_Controls.m_SavePlusCalibration->setEnabled(false); m_Controls.m_SetupStatus->setStyleSheet("QLabel { color : green; }"); m_Controls.m_SetupStatus->setText("Setup successfull you can now connect PLUS"); } else { m_Controls.m_SetupStatus->setStyleSheet("QLabel { color : red; }"); m_Controls.m_SetupStatus->setText("Something went wrong. Please try again"); } } void QmitkUltrasoundCalibration::OnStopPlusCalibration() { //closing all server and clients when PlusCalibration is finished if (m_USMessageProvider.IsNotNull()) { if (m_USMessageProvider->IsStreaming()) { m_USMessageProvider->StopStreamingOfSource(m_USImageToIGTLMessageFilter); } } if (m_TrackingMessageProvider.IsNotNull()) { if (m_TrackingMessageProvider->IsStreaming()) { m_TrackingMessageProvider->StopStreamingOfSource(m_TrackingToIGTLMessageFilter); } } if (m_USServer.IsNotNull()) { m_USServer->CloseConnection(); } if (m_TrackingServer.IsNotNull()) { m_TrackingServer->CloseConnection(); } if (m_TransformClient.IsNotNull()) { m_TransformClient->CloseConnection(); } m_Controls.m_GotCalibrationLabel->setText(""); m_Controls.m_ConnectionStatus->setText(""); m_Controls.m_SetupStatus->setText(""); m_Controls.m_StartPlusCalibrationButton->setEnabled(true); m_StreamingTimer->stop(); delete m_StreamingTimer; } void QmitkUltrasoundCalibration::OnPlusConnected() { emit NewConnectionSignal(); } void QmitkUltrasoundCalibration::OnNewConnection() { m_Controls.m_StartStreaming->setEnabled(true); m_Controls.m_ConnectionStatus->setStyleSheet("QLabel { color : green; }"); m_Controls.m_ConnectionStatus->setText("Connection successfull you can now start streaming"); } void QmitkUltrasoundCalibration::OnStreamingTimerTimeout() { m_USMessageProvider->Update(); m_TrackingMessageProvider->Update(); } void QmitkUltrasoundCalibration::OnStartStreaming() { m_USMessageProvider->StartStreamingOfSource(m_USImageToIGTLMessageFilter, 5); m_TrackingMessageProvider->StartStreamingOfSource(m_TrackingToIGTLMessageFilter, 5); m_Controls.m_StartStreaming->setEnabled(false); m_Controls.m_ConnectionStatus->setText(""); m_StreamingTimer->start((1.0 / 5.0 * 1000.0)); } void QmitkUltrasoundCalibration::OnGetPlusCalibration() { m_TransformClient = mitk::IGTLClient::New(true); m_TransformClient->SetHostname("127.0.0.1"); m_TransformClient->SetPortNumber(18946); m_TransformDeviceSource = mitk::IGTLDeviceSource::New(); m_TransformDeviceSource->SetIGTLDevice(m_TransformClient); m_TransformDeviceSource->Connect(); if (m_TransformDeviceSource->IsConnected()) { MITK_INFO << "successfully connected"; m_TransformDeviceSource->StartCommunication(); if (m_TransformDeviceSource->IsCommunicating()) { MITK_INFO << "communication started"; mitk::IGTLMessage::Pointer receivedMessage; bool condition = false; igtl::Matrix4x4 transformPLUS; while (!(receivedMessage.IsNotNull() && receivedMessage->IsDataValid())) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); m_TransformDeviceSource->Update(); receivedMessage = m_TransformDeviceSource->GetOutput(); igtl::TransformMessage::Pointer msg = dynamic_cast(m_TransformDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message could not be casted to TransformMessage. Skipping.."; continue; } else { if (std::strcmp(msg->GetDeviceName(), "ImageToTracker") != 0) { MITK_INFO << "Was not Image to Tracker Transform. Skipping..."; continue; } else { msg->GetMatrix(transformPLUS); condition = true; break; } } } if (condition) { this->ProcessPlusCalibration(transformPLUS); } else { m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } else { MITK_INFO << " no connection"; m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } else { m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : red; }"); m_Controls.m_GotCalibrationLabel->setText("Something went wrong. Please try again"); } } void QmitkUltrasoundCalibration::ProcessPlusCalibration(igtl::Matrix4x4& imageToTracker) { mitk::AffineTransform3D::Pointer imageToTrackerTransform = mitk::AffineTransform3D::New(); itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); rotationFloat[0][0] = imageToTracker[0][0]; rotationFloat[0][1] = imageToTracker[0][1]; rotationFloat[0][2] = imageToTracker[0][2]; rotationFloat[1][0] = imageToTracker[1][0]; rotationFloat[1][1] = imageToTracker[1][1]; rotationFloat[1][2] = imageToTracker[1][2]; rotationFloat[2][0] = imageToTracker[2][0]; rotationFloat[2][1] = imageToTracker[2][1]; rotationFloat[2][2] = imageToTracker[2][2]; translationFloat[0] = imageToTracker[0][3]; translationFloat[1] = imageToTracker[1][3]; translationFloat[2] = imageToTracker[2][3]; imageToTrackerTransform->SetTranslation(translationFloat); imageToTrackerTransform->SetMatrix(rotationFloat); m_CombinedModality->SetCalibration(imageToTrackerTransform); m_Controls.m_ToolBox->setItemEnabled(2, true); m_Controls.m_SavePlusCalibration->setEnabled(true); m_Controls.m_GotCalibrationLabel->setStyleSheet("QLabel { color : green; }"); m_Controls.m_GotCalibrationLabel->setText("Recieved Calibration from PLUS you can now save it"); } void QmitkUltrasoundCalibration::OnStopCalibrationProcess() { this->ClearTemporaryMembers(); m_Timer->stop(); this->GetDataStorage()->Remove(m_Node); m_Node = 0; this->GetDataStorage()->Remove(m_CalibNode); m_CalibNode = 0; this->GetDataStorage()->Remove(m_WorldNode); m_WorldNode = 0; m_Controls.m_ToolBox->setCurrentIndex(0); } void QmitkUltrasoundCalibration::OnDeciveServiceEvent(const ctkServiceEvent event) { if (m_CombinedModality.IsNull() || event.getType() != ctkServiceEvent::MODIFIED) { return; } ctkServiceReference service = event.getServiceReference(); QString curDepth = service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH)).toString(); if (m_CurrentDepth != curDepth) { m_CurrentDepth = curDepth; this->OnReset(); } } void QmitkUltrasoundCalibration::OnAddCalibPoint() { mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_CalibPointsImage->InsertPoint(m_CalibPointsCount, world); this->m_CalibPointsTool->InsertPoint(m_CalibPointsCount, this->m_FreezePoint); QString text = text.number(m_CalibPointsCount + 1); text = "Point " + text; this->m_Controls.m_CalibPointList->addItem(text); m_CalibPointsCount++; SwitchFreeze(); } void QmitkUltrasoundCalibration::OnCalibration() { // Compute transformation vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetSourceLandmarks(this->ConvertPointSetToVtkPolyData(m_CalibPointsImage)->GetPoints()); transform->SetTargetLandmarks(this->ConvertPointSetToVtkPolyData(m_CalibPointsTool)->GetPoints()); if (m_Controls.m_ScaleTransform->isChecked()) { transform->SetModeToSimilarity(); } //use affine transform else { transform->SetModeToRigidBody(); } //use similarity transform: scaling is not touched transform->Modified(); transform->Update(); // Convert from vtk to itk data types itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); vtkSmartPointer m = transform->GetMatrix(); rotationFloat[0][0] = m->GetElement(0, 0); rotationFloat[0][1] = m->GetElement(0, 1); rotationFloat[0][2] = m->GetElement(0, 2); rotationFloat[1][0] = m->GetElement(1, 0); rotationFloat[1][1] = m->GetElement(1, 1); rotationFloat[1][2] = m->GetElement(1, 2); rotationFloat[2][0] = m->GetElement(2, 0); rotationFloat[2][1] = m->GetElement(2, 1); rotationFloat[2][2] = m->GetElement(2, 2); translationFloat[0] = m->GetElement(0, 3); translationFloat[1] = m->GetElement(1, 3); translationFloat[2] = m->GetElement(2, 3); mitk::DataNode::Pointer CalibPointsImage = mitk::DataNode::New(); CalibPointsImage->SetName("Calibration Points Image"); CalibPointsImage->SetData(m_CalibPointsImage); this->GetDataStorage()->Add(CalibPointsImage); mitk::DataNode::Pointer CalibPointsTracking = mitk::DataNode::New(); CalibPointsTracking->SetName("Calibration Points Tracking"); CalibPointsTracking->SetData(m_CalibPointsTool); this->GetDataStorage()->Add(CalibPointsTracking); mitk::PointSet::Pointer ImagePointsTransformed = m_CalibPointsImage->Clone(); this->ApplyTransformToPointSet(ImagePointsTransformed, transform); mitk::DataNode::Pointer CalibPointsImageTransformed = mitk::DataNode::New(); CalibPointsImageTransformed->SetName("Calibration Points Image (Transformed)"); CalibPointsImageTransformed->SetData(ImagePointsTransformed); this->GetDataStorage()->Add(CalibPointsImageTransformed); // Set output variable mitk::AffineTransform3D::Pointer oldUSImageTransform = m_Image->GetGeometry()->GetIndexToWorldTransform(); //including spacing! MITK_INFO << "Old US Image transform: " << oldUSImageTransform; mitk::AffineTransform3D::Pointer calibTransform = mitk::AffineTransform3D::New(); calibTransform->SetTranslation(translationFloat); calibTransform->SetMatrix(rotationFloat); MITK_INFO << "Calibration transform: " << calibTransform; m_Transformation = mitk::AffineTransform3D::New(); if (!m_Controls.m_ScaleTransform->isChecked()) { m_Transformation->Compose(oldUSImageTransform); } m_Transformation->Compose(calibTransform); MITK_INFO << "New combined transform: " << m_Transformation; mitk::SlicedGeometry3D::Pointer sliced3d = dynamic_cast (m_Node->GetData()->GetGeometry()); mitk::PlaneGeometry::Pointer plane = const_cast (sliced3d->GetPlaneGeometry(0)); plane->SetIndexToWorldTransform(m_Transformation); // Save to US-Device m_CombinedModality->SetCalibration(m_Transformation); m_Controls.m_ToolBox->setItemEnabled(2, true); // Save to NeedleProjectionFilter m_NeedleProjectionFilter->SetTargetPlane(m_Transformation); // Update Calibration FRE m_CalibrationStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); mitk::PointSet::Pointer p1 = this->m_CalibPointsTool->Clone(); // We use clones to calculate statistics to avoid concurrency Problems // Create point set with transformed image calibration points for // calculating the difference of image calibration and tool // calibration points in one geometry space mitk::PointSet::Pointer p2 = mitk::PointSet::New(); int n = 0; for (mitk::PointSet::PointsConstIterator it = m_CalibPointsImage->Begin(); it != m_CalibPointsImage->End(); ++it, ++n) { p2->InsertPoint(n, m_Transformation->TransformPoint(it->Value())); } m_CalibrationStatistics->SetPointSets(p1, p2); //QString text = text.number(m_CalibrationStatistics->GetRMS()); QString text = QString::number(ComputeFRE(m_CalibPointsImage, m_CalibPointsTool, transform)); MITK_INFO << "Calibration FRE: " << text.toStdString().c_str(); m_Controls.m_EvalLblCalibrationFRE->setText(text); m_Node->SetStringProperty("Calibration FRE", text.toStdString().c_str()); // Enable Button to save Calibration m_Controls.m_CalibBtnSaveCalibration->setEnabled(true); } void QmitkUltrasoundCalibration::OnAddEvalTargetPoint() { mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_EvalPointsImage->InsertPoint(m_EvalPointsImage->GetSize(), world); this->m_EvalPointsTool->InsertPoint(m_EvalPointsTool->GetSize(), this->m_FreezePoint); QString text = text.number(this->m_EvalPointsTool->GetSize()); this->m_Controls.m_EvalLblNumTargetPoints->setText(text); // Update FREs // Update Evaluation FRE, but only if it contains more than one point (will crash otherwise) if ((m_EvalPointsProjected->GetSize() > 1) && (m_EvalPointsTool->GetSize() > 1)) { m_EvaluationStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); m_ProjectionStatistics = mitk::PointSetDifferenceStatisticsCalculator::New(); mitk::PointSet::Pointer p1 = this->m_EvalPointsTool->Clone(); // We use clones to calculate statistics to avoid concurrency Problems mitk::PointSet::Pointer p2 = this->m_EvalPointsImage->Clone(); mitk::PointSet::Pointer p3 = this->m_EvalPointsProjected->Clone(); m_EvaluationStatistics->SetPointSets(p1, p2); m_ProjectionStatistics->SetPointSets(p1, p3); QString evalText = evalText.number(m_EvaluationStatistics->GetRMS()); QString projText = projText.number(m_ProjectionStatistics->GetRMS()); m_Controls.m_EvalLblEvaluationFRE->setText(evalText); m_Controls.m_EvalLblProjectionFRE->setText(projText); } SwitchFreeze(); } void QmitkUltrasoundCalibration::OnAddEvalProjectedPoint() { MITK_WARN << "Projection Evaluation may currently be inaccurate."; // TODO: Verify correct Evaluation. Is the Point that is added really current? mitk::Point3D projection = this->m_NeedleProjectionFilter->GetProjection()->GetPoint(1); m_EvalPointsProjected->InsertPoint(m_EvalPointsProjected->GetSize(), projection); QString text = text.number(this->m_EvalPointsProjected->GetSize()); this->m_Controls.m_EvalLblNumProjectionPoints->setText(text); } void QmitkUltrasoundCalibration::OnSaveEvaluation() { //Filename without suffix QString filename = m_Controls.m_EvalFilePath->text() + "//" + m_Controls.m_EvalFilePrefix->text(); MITK_WARN << "CANNOT SAVE, ABORTING!"; /* not working any more TODO! mitk::PointSetWriter::Pointer psWriter = mitk::PointSetWriter::New(); psWriter->SetInput(0, m_CalibPointsImage); psWriter->SetInput(1, m_CalibPointsTool); psWriter->SetInput(2, m_EvalPointsImage); psWriter->SetInput(3, m_EvalPointsTool); psWriter->SetInput(4, m_EvalPointsProjected); psWriter->SetFileName(filename.toStdString() + ".xml"); psWriter->Write(); */ // TODO: New writer for transformations must be implemented. /* mitk::TransformationFileWriter::Pointer tWriter = mitk::TransformationFileWriter::New(); tWriter->SetInput(0, m_CalibPointsImage); tWriter->SetInput(1, m_CalibPointsTool); tWriter->SetInput(2, m_EvalPointsImage); tWriter->SetInput(3, m_EvalPointsTool); tWriter->SetInput(4, m_EvalPointsProjected); tWriter->SetOutputFilename(filename.toStdString() + ".txt"); tWriter->DoWrite(this->m_Transformation); */ } void QmitkUltrasoundCalibration::OnSaveCalibration() { m_Controls.m_GotCalibrationLabel->setText(""); QString filename = QFileDialog::getSaveFileName(QApplication::activeWindow(), "Save Calibration", "", "Calibration files *.cal"); QFile file(filename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for writing."; return; } std::string calibrationSerialization = m_CombinedModality->SerializeCalibration(); QTextStream outStream(&file); outStream << QString::fromStdString(calibrationSerialization); //save additional information if (m_Controls.m_saveAdditionalCalibrationLog->isChecked()) { mitk::SceneIO::Pointer mySceneIO = mitk::SceneIO::New(); QString filenameScene = filename + "_mitkScene.mitk"; mitk::NodePredicateNot::Pointer isNotHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); mySceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), filenameScene.toStdString().c_str()); } } void QmitkUltrasoundCalibration::OnReset() { this->ClearTemporaryMembers(); if (m_Transformation.IsNull()) { m_Transformation = mitk::AffineTransform3D::New(); } m_Transformation->SetIdentity(); if (m_Node.IsNotNull() && (m_Node->GetData() != nullptr) && (m_Node->GetData()->GetGeometry() != nullptr)) { mitk::SlicedGeometry3D::Pointer sliced3d = dynamic_cast (m_Node->GetData()->GetGeometry()); mitk::PlaneGeometry::Pointer plane = const_cast (sliced3d->GetPlaneGeometry(0)); plane->SetIndexToWorldTransform(m_Transformation); } QString text1 = text1.number(this->m_EvalPointsTool->GetSize()); this->m_Controls.m_EvalLblNumTargetPoints->setText(text1); QString text2 = text2.number(this->m_EvalPointsProjected->GetSize()); this->m_Controls.m_EvalLblNumProjectionPoints->setText(text2); } void QmitkUltrasoundCalibration::Update() { //QList nodes = this->GetDataManagerSelection(); // if (nodes.empty()) return; // Update Tracking Data std::vector* datas = new std::vector(); datas->push_back(m_Tracker->GetOutput()); m_Controls.m_CalibTrackingStatus->SetNavigationDatas(datas); m_Controls.m_CalibTrackingStatus->Refresh(); m_Controls.m_EvalTrackingStatus->SetNavigationDatas(datas); m_Controls.m_EvalTrackingStatus->Refresh(); // Update US Image m_CombinedModality->Modified(); m_CombinedModality->Update(); mitk::Image::Pointer m_Image = m_CombinedModality->GetOutput(); if (m_Image.IsNotNull() && m_Image->IsInitialized()) { if (m_OverrideSpacing) { m_Image->GetGeometry()->SetSpacing(m_Spacing); } if (m_Image.IsNotNull() && m_Image->IsInitialized()) { m_Node->SetData(m_Image); } } // Update Needle Projection m_NeedleProjectionFilter->Update(); //only update 2d window because it is faster //this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); } void QmitkUltrasoundCalibration::SwitchFreeze() { m_Controls.m_CalibBtnAddPoint->setEnabled(false); // generally deactivate // We use the activity state of the timer to determine whether we are currently viewing images if (!m_Timer->isActive()) // Activate Imaging { // if (m_Node) m_Node->ReleaseData(); if (m_CombinedModality.IsNull()){ m_Timer->stop(); return; } m_CombinedModality->Update(); m_Image = m_CombinedModality->GetOutput(); if (m_Image.IsNotNull() && m_Image->IsInitialized()) { m_Node->SetData(m_Image); } std::vector datas; datas.push_back(m_Tracker->GetOutput()); m_Controls.m_CalibTrackingStatus->SetNavigationDatas(&datas); m_Controls.m_CalibTrackingStatus->ShowStatusLabels(); m_Controls.m_CalibTrackingStatus->Refresh(); m_Controls.m_EvalTrackingStatus->SetNavigationDatas(&datas); m_Controls.m_EvalTrackingStatus->ShowStatusLabels(); m_Controls.m_EvalTrackingStatus->Refresh(); int interval = 40; m_Timer->setInterval(interval); m_Timer->start(); m_CombinedModality->GetUltrasoundDevice()->SetIsFreezed(false); } else if (this->m_Tracker->GetOutput(0)->IsDataValid()) { //deactivate Imaging m_Timer->stop(); // Remember last tracking coordinates m_FreezePoint = this->m_Tracker->GetOutput(0)->GetPosition(); m_Controls.m_CalibBtnAddPoint->setEnabled(true); // activate only, if valid point is set m_CombinedModality->GetUltrasoundDevice()->SetIsFreezed(true); } } void QmitkUltrasoundCalibration::ShowNeedlePath() { // Init Filter this->m_NeedleProjectionFilter->SelectInput(0); // Create Node for Pointset mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Needle Path"); if (node.IsNull()) { node = mitk::DataNode::New(); node->SetName("Needle Path"); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); this->GetDataStorage()->Add(node); } } void QmitkUltrasoundCalibration::ClearTemporaryMembers() { m_CalibPointsTool->Clear(); m_CalibPointsImage->Clear(); m_CalibPointsCount = 0; m_EvalPointsImage->Clear(); m_EvalPointsTool->Clear(); m_EvalPointsProjected->Clear(); this->m_Controls.m_CalibPointList->clear(); m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; } vtkSmartPointer QmitkUltrasoundCalibration::ConvertPointSetToVtkPolyData(mitk::PointSet::Pointer PointSet) { vtkSmartPointer returnValue = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); for (int i = 0; i < PointSet->GetSize(); i++) { double point[3] = { PointSet->GetPoint(i)[0], PointSet->GetPoint(i)[1], PointSet->GetPoint(i)[2] }; points->InsertNextPoint(point); } vtkSmartPointer temp = vtkSmartPointer::New(); temp->SetPoints(points); vtkSmartPointer vertexFilter = vtkSmartPointer::New(); vertexFilter->SetInputData(temp); vertexFilter->Update(); returnValue->ShallowCopy(vertexFilter->GetOutput()); return returnValue; } double QmitkUltrasoundCalibration::ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer transform) { if (imageFiducials->GetSize() != realWorldFiducials->GetSize()) return -1; double FRE = 0; for (int i = 0; i < imageFiducials->GetSize(); ++i) { itk::Point current_image_fiducial_point = imageFiducials->GetPoint(i); if (transform != nullptr) { current_image_fiducial_point = transform->TransformPoint(imageFiducials->GetPoint(i)[0], imageFiducials->GetPoint(i)[1], imageFiducials->GetPoint(i)[2]); } double cur_error_squared = current_image_fiducial_point.SquaredEuclideanDistanceTo(realWorldFiducials->GetPoint(i)); FRE += cur_error_squared; } FRE = sqrt(FRE / (double)imageFiducials->GetSize()); return FRE; } void QmitkUltrasoundCalibration::ApplyTransformToPointSet(mitk::PointSet::Pointer pointSet, vtkSmartPointer transform) { for (int i = 0; i < pointSet->GetSize(); ++i) { itk::Point current_point_transformed = itk::Point(); current_point_transformed = transform->TransformPoint(pointSet->GetPoint(i)[0], pointSet->GetPoint(i)[1], pointSet->GetPoint(i)[2]); pointSet->SetPoint(i, current_point_transformed); } } void QmitkUltrasoundCalibration::OnFreezeClicked() { if (m_CombinedModality->GetUltrasoundDevice()->GetIsFreezed()) { //device was already frozen so we need to delete all Spacing points because they need to be collected all at once // no need to check if all four points are already collected, because if thats the case you can no longer click the Freeze Button m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; m_Controls.m_SpacingAddPoint->setEnabled(false); m_CombinedModality->GetUltrasoundDevice()->SetIsFreezed(false); } else { m_CombinedModality->GetUltrasoundDevice()->SetIsFreezed(true); m_Controls.m_SpacingAddPoint->setEnabled(true); } //SwitchFreeze(); } void QmitkUltrasoundCalibration::OnAddSpacingPoint() { mitk::Point3D point = this->GetRenderWindowPart()->GetSelectedPosition(); this->m_SpacingPoints->InsertPoint(m_SpacingPointsCount, point); QString text = text.number(m_SpacingPointsCount + 1); text = "Point " + text; this->m_Controls.m_SpacingPointsList->addItem(text); m_SpacingPointsCount++; if (m_SpacingPointsCount == 4) //now we have all 4 points needed { m_Controls.m_SpacingAddPoint->setEnabled(false); m_Controls.m_CalculateSpacing->setEnabled(true); m_Controls.m_SpacingBtnFreeze->setEnabled(false); } } void QmitkUltrasoundCalibration::OnCalculateSpacing() { mitk::Point3D horizontalOne = m_SpacingPoints->GetPoint(0); mitk::Point3D horizontalTwo = m_SpacingPoints->GetPoint(1); mitk::Point3D verticalOne = m_SpacingPoints->GetPoint(2); mitk::Point3D verticalTwo = m_SpacingPoints->GetPoint(3); //Get the distances between the points in the image double xDistance = horizontalOne.EuclideanDistanceTo(horizontalTwo); double yDistance = verticalOne.EuclideanDistanceTo(verticalTwo); //Calculate the spacing of the image and fill a vector with it double xSpacing = 30 / xDistance; double ySpacing = 20 / yDistance; m_Spacing[0] = xSpacing; m_Spacing[1] = ySpacing; m_Spacing[2] = 1; MITK_INFO << m_Spacing; //Make sure the new spacing is applied to the USVideoDeviceImages m_OverrideSpacing = true; //Now that the spacing is set clear all stuff and return to Calibration m_SpacingPoints->Clear(); m_Controls.m_SpacingPointsList->clear(); m_SpacingPointsCount = 0; m_CombinedModality->GetUltrasoundDevice()->SetIsFreezed(false); } void QmitkUltrasoundCalibration::OnUSDepthChanged(const std::string& key, const std::string&) { //whenever depth of USImage is changed the spacing should no longer be overwritten if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { m_OverrideSpacing = false; } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp index b5e6c995e5..59c961e1ec 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp @@ -1,557 +1,557 @@ /*=================================================================== 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 "QmitkUSNavigationProcessWidget.h" #include "ui_QmitkUSNavigationProcessWidget.h" #include "../NavigationStepWidgets/QmitkUSAbstractNavigationStep.h" #include "../SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h" #include "mitkDataNode.h" #include "mitkNavigationDataToNavigationDataFilter.h" #include #include #include QmitkUSNavigationProcessWidget::QmitkUSNavigationProcessWidget(QWidget* parent) : QWidget(parent), m_SettingsWidget(0), m_BaseNode(mitk::DataNode::New()), m_CurrentTabIndex(0), m_CurrentMaxStep(0), m_ImageAlreadySetToNode(false), m_ReadySignalMapper(new QSignalMapper(this)), m_NoLongerReadySignalMapper(new QSignalMapper(this)), m_StdMultiWidget(0), m_UsePlanningStepWidget(false), ui(new Ui::QmitkUSNavigationProcessWidget) { m_Parent = parent; ui->setupUi(this); // remove the default page ui->stepsToolBox->setCurrentIndex(1);// ->removeItem(0); //set shortcuts QShortcut *nextShortcut = new QShortcut(QKeySequence("F10"), parent); QShortcut *prevShortcut = new QShortcut(QKeySequence("F11"), parent); connect(nextShortcut, SIGNAL(activated()), this, SLOT(OnNextButtonClicked())); connect(prevShortcut, SIGNAL(activated()), this, SLOT(OnPreviousButtonClicked())); //connect other slots connect( ui->restartStepButton, SIGNAL(clicked()), this, SLOT(OnRestartStepButtonClicked()) ); connect( ui->previousButton, SIGNAL(clicked()), this, SLOT(OnPreviousButtonClicked()) ); connect( ui->nextButton, SIGNAL(clicked()), this, SLOT(OnNextButtonClicked()) ); connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); connect (ui->settingsButton, SIGNAL(clicked()), this, SLOT(OnSettingsButtonClicked()) ); connect( m_ReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepReady(int)) ); connect( m_NoLongerReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepNoLongerReady(int)) ); ui->settingsFrameWidget->setHidden(true); } QmitkUSNavigationProcessWidget::~QmitkUSNavigationProcessWidget() { ui->stepsToolBox->blockSignals(true); for ( NavigationStepVector::iterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it ) { if ( (*it)->GetNavigationStepState() > QmitkUSAbstractNavigationStep::State_Stopped ) { (*it)->StopStep(); } delete *it; } m_NavigationSteps.clear(); if ( m_SettingsNode.IsNotNull() && m_DataStorage.IsNotNull() ) { m_DataStorage->Remove(m_SettingsNode); } delete ui; } void QmitkUSNavigationProcessWidget::EnableInteraction(bool enable) { if (enable) { ui->restartStepButton->setEnabled(true); ui->previousButton->setEnabled(true); ui->nextButton->setEnabled(true); ui->stepsToolBox->setEnabled(true); } else { ui->restartStepButton->setEnabled(false); ui->previousButton->setEnabled(false); ui->nextButton->setEnabled(false); ui->stepsToolBox->setEnabled(false); } } void QmitkUSNavigationProcessWidget::SetDataStorage(itk::SmartPointer dataStorage) { m_DataStorage = dataStorage; if ( dataStorage.IsNull() ) { mitkThrow() << "Data Storage must not be null for QmitkUSNavigationProcessWidget."; } // test if base node is already in the data storage and add it if not m_BaseNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( m_BaseNode.IsNull() ) { m_BaseNode = mitk::DataNode::New(); m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); dataStorage->Add(m_BaseNode); } // base node and image stream node may be the same node if ( strcmp(QmitkUSAbstractNavigationStep::DATANAME_BASENODE, QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM) != 0) { m_ImageStreamNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); if (m_ImageStreamNode.IsNull()) { // Create Node for US Stream m_ImageStreamNode = mitk::DataNode::New(); m_ImageStreamNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); dataStorage->Add(m_ImageStreamNode); } } else { m_ImageStreamNode = m_BaseNode; } m_SettingsNode = dataStorage->GetNamedDerivedNode(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS, m_BaseNode); if ( m_SettingsNode.IsNull() ) { m_SettingsNode = mitk::DataNode::New(); m_SettingsNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS); dataStorage->Add(m_SettingsNode, m_BaseNode); } if (m_SettingsWidget) { m_SettingsWidget->SetSettingsNode(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::SetSettingsWidget(QmitkUSNavigationAbstractSettingsWidget* settingsWidget) { // disconnect slots to settings widget if there was a widget before if ( m_SettingsWidget ) { disconnect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); disconnect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); disconnect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); ui->settingsWidget->removeWidget(m_SettingsWidget); } m_SettingsWidget = settingsWidget; if ( m_SettingsWidget ) { m_SettingsWidget->LoadSettings(); connect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); connect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); connect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); if ( m_SettingsNode.IsNotNull() ) { m_SettingsWidget->SetSettingsNode(m_SettingsNode, true); } ui->settingsWidget->addWidget(m_SettingsWidget); } ui->settingsButton->setEnabled(m_SettingsWidget != 0); } void QmitkUSNavigationProcessWidget::SetNavigationSteps(NavigationStepVector navigationSteps) { disconnect( this, SLOT(OnTabChanged(int)) ); for ( int n = ui->stepsToolBox->count()-1; n >= 0; --n ) { //ui->stepsToolBox->removeItem(n); } connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_NavigationSteps.clear(); m_NavigationSteps = navigationSteps; this->InitializeNavigationStepWidgets(); // notify all navigation step widgets about the current settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::ResetNavigationProcess() { MITK_INFO("QmitkUSNavigationProcessWidget") << "Resetting navigation process."; ui->stepsToolBox->blockSignals(true); for ( int n = 0; n <= m_CurrentMaxStep; ++n ) { m_NavigationSteps.at(n)->StopStep(); //if ( n > 0 ) { ui->stepsToolBox->setItemEnabled(n, false); } } ui->stepsToolBox->blockSignals(false); m_CurrentMaxStep = 0; ui->stepsToolBox->setCurrentIndex(0); if ( m_NavigationSteps.size() > 0 ) { m_NavigationSteps.at(0)->ActivateStep(); } this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::UpdateNavigationProgress() { if ( m_CombinedModality.IsNotNull() && !m_CombinedModality->GetUltrasoundDevice()->GetIsFreezed() ) { m_CombinedModality->Modified(); m_CombinedModality->Update(); if ( m_LastNavigationDataFilter.IsNotNull() ) { m_LastNavigationDataFilter->Update(); } mitk::Image::Pointer image = m_CombinedModality->GetOutput(); // make sure that always the current image is set to the data node if ( image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized() ) { m_ImageStreamNode->SetData(image); m_ImageAlreadySetToNode = true; } } if ( m_CurrentTabIndex > 0 && static_cast(m_CurrentTabIndex) < m_NavigationSteps.size() ) { m_NavigationSteps.at(m_CurrentTabIndex)->Update(); } } void QmitkUSNavigationProcessWidget::OnNextButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice()->GetIsFreezed()) {return;} //no moving through steps when the modality is nullptr or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex >= m_CurrentMaxStep) { MITK_WARN << "Next button clicked though no next tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(++currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnPreviousButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice()->GetIsFreezed()) {return;} //no moving through steps when the modality is nullptr or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex <= 0) { MITK_WARN << "Previous button clicked though no previous tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(--currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnRestartStepButtonClicked() { MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Restarting step " << m_CurrentTabIndex << " (" << m_NavigationSteps.at(m_CurrentTabIndex)->GetTitle().toStdString() << ")."; m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->RestartStep(); m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->ActivateStep(); } void QmitkUSNavigationProcessWidget::OnTabChanged(int index) { emit SignalActiveNavigationStepChangeRequested(index); if ( index < 0 || index >= static_cast(m_NavigationSteps.size()) ) { return; } else if ( m_CurrentTabIndex == index ) { // just activate the step if it is the same step againg m_NavigationSteps.at(index)->ActivateStep(); return; } MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Activating navigation step " << index << " (" << m_NavigationSteps.at(index)->GetTitle().toStdString() <<")."; if (index > m_CurrentTabIndex) { this->UpdateFilterPipeline(); // finish all previous steps to make sure that all data is valid for (int n = m_CurrentTabIndex; n < index; ++n) { m_NavigationSteps.at(n)->FinishStep(); } } // deactivate the previously active step if ( m_CurrentTabIndex > 0 && m_NavigationSteps.size() > static_cast(m_CurrentTabIndex) ) { m_NavigationSteps.at(m_CurrentTabIndex)->DeactivateStep(); } // start step of the current tab if it wasn't started before if ( m_NavigationSteps.at(index)->GetNavigationStepState() == QmitkUSAbstractNavigationStep::State_Stopped ) { m_NavigationSteps.at(index)->StartStep(); } m_NavigationSteps.at(index)->ActivateStep(); if (static_cast(index) < m_NavigationSteps.size()) ui->restartStepButton->setEnabled(m_NavigationSteps.at(index)->GetIsRestartable()); this->UpdatePrevNextButtons(); m_CurrentTabIndex = index; emit SignalActiveNavigationStepChanged(index); } void QmitkUSNavigationProcessWidget::OnSettingsButtonClicked() { this->SetSettingsWidgetVisible(true); } void QmitkUSNavigationProcessWidget::OnSettingsWidgetReturned() { this->SetSettingsWidgetVisible(false); } void QmitkUSNavigationProcessWidget::OnSettingsNodeChanged(itk::SmartPointer dataNode) { if ( m_SettingsWidget ) m_SettingsWidget->SetSettingsNode(dataNode); } void QmitkUSNavigationProcessWidget::OnStepReady(int index) { if (m_CurrentMaxStep <= index) { m_CurrentMaxStep = index + 1; this->UpdatePrevNextButtons(); for (int n = 0; n <= m_CurrentMaxStep; ++n) { //ui->stepsToolBox->setItemEnabled(n, true); } } emit SignalNavigationStepFinished(index, true); } void QmitkUSNavigationProcessWidget::OnStepNoLongerReady(int index) { if (m_CurrentMaxStep > index) { m_CurrentMaxStep = index; this->UpdatePrevNextButtons(); this->UpdateFilterPipeline(); for (int n = m_CurrentMaxStep+1; n < ui->stepsToolBox->count(); ++n) { //ui->stepsToolBox->setItemEnabled(n, false); m_NavigationSteps.at(n)->StopStep(); } } emit SignalNavigationStepFinished(index, false); } -void QmitkUSNavigationProcessWidget::OnCombinedModalityChanged(itk::SmartPointer combinedModality) +void QmitkUSNavigationProcessWidget::OnCombinedModalityChanged(itk::SmartPointer combinedModality) { m_CombinedModality = combinedModality; m_ImageAlreadySetToNode = false; if ( combinedModality.IsNotNull() ) { if ( combinedModality->GetNavigationDataSource().IsNull() ) { MITK_WARN << "There is no navigation data source set for the given combined modality."; return; } this->UpdateFilterPipeline(); } for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->SetCombinedModality(combinedModality); } emit SignalCombinedModalityChanged(combinedModality); } void QmitkUSNavigationProcessWidget::OnSettingsChanged(const mitk::DataNode::Pointer dataNode) { static bool methodEntered = false; if ( methodEntered ) { MITK_WARN("QmitkUSNavigationProcessWidget") << "Ignoring recursive call to 'OnSettingsChanged()'. " << "Make sure to no emit 'SignalSettingsNodeChanged' in an 'OnSettingsChanged()' method."; return; } methodEntered = true; std::string application; if ( dataNode->GetStringProperty("settings.application", application) ) { QString applicationQString = QString::fromStdString(application); if ( applicationQString != ui->titleLabel->text() ) { ui->titleLabel->setText(applicationQString); } } // notify all navigation step widgets about the changed settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(dataNode); } emit SignalSettingsChanged(dataNode); methodEntered = false; } void QmitkUSNavigationProcessWidget::InitializeNavigationStepWidgets() { // do not listen for steps tool box signal during insertion of items into tool box disconnect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_CurrentMaxStep = 0; mitk::DataStorage::Pointer dataStorage = m_DataStorage; for (unsigned int n = 0; n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(n); curNavigationStep->SetDataStorage(dataStorage); connect( curNavigationStep, SIGNAL(SignalReadyForNextStep()), m_ReadySignalMapper, SLOT(map())); connect( curNavigationStep, SIGNAL(SignalNoLongerReadyForNextStep()), m_NoLongerReadySignalMapper, SLOT(map()) ); connect( curNavigationStep, SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), this, SLOT(OnCombinedModalityChanged(itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), this, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalSettingsNodeChanged(itk::SmartPointer)), this, SLOT(OnSettingsNodeChanged(itk::SmartPointer)) ); m_ReadySignalMapper->setMapping(curNavigationStep, n); m_NoLongerReadySignalMapper->setMapping(curNavigationStep, n); ui->stepsToolBox->insertWidget(n, curNavigationStep); //if ( n > 0 ) { ui->stepsToolBox->get(n, false); } } ui->restartStepButton->setEnabled(m_NavigationSteps.at(0)->GetIsRestartable()); ui->stepsToolBox->setCurrentIndex(0); // activate the first navigation step widgets if ( ! m_NavigationSteps.empty() ) { m_NavigationSteps.at(0)->ActivateStep(); } // after filling the steps tool box the signal is interesting again connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); this->UpdateFilterPipeline(); } void QmitkUSNavigationProcessWidget::UpdatePrevNextButtons() { int currentIndex = ui->stepsToolBox->currentIndex(); ui->previousButton->setEnabled(currentIndex > 0); ui->nextButton->setEnabled(currentIndex < m_CurrentMaxStep); } void QmitkUSNavigationProcessWidget::UpdateFilterPipeline() { if ( m_CombinedModality.IsNull() ) { return; } std::vector filterList; mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); for (unsigned int n = 0; n <= static_cast(m_CurrentMaxStep) && n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep::FilterVector filter = m_NavigationSteps.at(n)->GetFilter(); if ( ! filter.empty() ) { filterList.insert(filterList.end(), filter.begin(), filter.end()); } } if ( ! filterList.empty() ) { for (unsigned int n = 0; n < navigationDataSource->GetNumberOfOutputs(); ++n) { filterList.at(0)->SetInput(n, navigationDataSource->GetOutput(n)); } for (std::vector::iterator it = filterList.begin()+1; it != filterList.end(); ++it) { std::vector::iterator prevIt = it-1; for (unsigned int n = 0; n < (*prevIt)->GetNumberOfOutputs(); ++n) { (*it)->SetInput(n, (*prevIt)->GetOutput(n)); } } m_LastNavigationDataFilter = filterList.at(filterList.size()-1); } else { m_LastNavigationDataFilter = navigationDataSource.GetPointer(); } } void QmitkUSNavigationProcessWidget::SetSettingsWidgetVisible(bool visible) { ui->settingsFrameWidget->setVisible(visible); ui->stepsToolBox->setHidden(visible); ui->settingsButton->setHidden(visible); ui->restartStepButton->setHidden(visible); ui->previousButton->setHidden(visible); ui->nextButton->setHidden(visible); } void QmitkUSNavigationProcessWidget::FinishCurrentNavigationStep() { int currentIndex = ui->stepsToolBox->currentIndex(); QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(currentIndex); curNavigationStep->FinishStep(); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h index 9b5d9975ca..38fdb208c4 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h @@ -1,179 +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 USNAVIGATIONPROCESSWIDGET_H #define USNAVIGATIONPROCESSWIDGET_H #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class NodeDisplacementFilter; } namespace Ui { class QmitkUSNavigationProcessWidget; } class QmitkUSAbstractNavigationStep; class QmitkUSNavigationAbstractSettingsWidget; class QmitkUSNavigationStepCombinedModality; class QmitkStdMultiWidget; class QTimer; class QSignalMapper; /** * \brief Widget for handling navigation steps. * The navigation steps (subclasses of QmitkUSAbstractNavigationStep) can be set * in a vector. The coordination of this steps is done by this widget then. */ class QmitkUSNavigationProcessWidget : public QWidget { Q_OBJECT signals: /** * \brief Signals a replacement of the combined modality by one of the navigation steps. */ - void SignalCombinedModalityChanged(itk::SmartPointer); + void SignalCombinedModalityChanged(itk::SmartPointer); /** * \brief Signals a change of the navigation settings. */ void SignalSettingsChanged(itk::SmartPointer); /** * \brief Signals if a change of the currently active navigation step is requested. Gives the index of the new step. */ void SignalActiveNavigationStepChangeRequested(int); /** * \brief Signals a change of the currently active navigation step after the step was changed. */ void SignalActiveNavigationStepChanged(int); /** * \brief Signals that the navigation step with the given id was finished. */ void SignalNavigationStepFinished(int, bool); /** * \brief Signals the creation of an intermediate result. * The result data is given as properties of the data node. */ void SignalIntermediateResult(const itk::SmartPointer); protected slots: void OnNextButtonClicked(); void OnPreviousButtonClicked(); void OnRestartStepButtonClicked(); void OnTabChanged(int index); void OnSettingsButtonClicked(); void OnSettingsWidgetReturned(); void OnSettingsNodeChanged(itk::SmartPointer); void OnStepReady(int); void OnStepNoLongerReady(int); - void OnCombinedModalityChanged(itk::SmartPointer); + void OnCombinedModalityChanged(itk::SmartPointer); void OnSettingsChanged(const itk::SmartPointer); public: typedef std::vector NavigationStepVector; typedef NavigationStepVector::iterator NavigationStepIterator; explicit QmitkUSNavigationProcessWidget(QWidget* parent = 0); ~QmitkUSNavigationProcessWidget(); /** * \brief Setter for the data storage used for storing the navigation progress. */ void SetDataStorage(itk::SmartPointer dataStorage); void SetSettingsWidget(QmitkUSNavigationAbstractSettingsWidget*); /** * \brief Setter for a vector of navigation step widgets. * These widgets are used for the navigation process in the order of their * appearance in this vector. */ void SetNavigationSteps(NavigationStepVector navigationSteps); /** * \brief Forget the current progress of the navigation process. * The process will then start again at the beginning. */ void ResetNavigationProcess(); /** Enables/disables the (navigation step) interaction with this widget. * The settings button is not affected by this flag. */ void EnableInteraction(bool enable); /** Finishes the current navigation step. */ void FinishCurrentNavigationStep(); /** Updates the navigation process widget, which includes updating the * navigation pipeline. Has to be called from outside this class with * a given update rate. So no additional internal timer is needed. */ void UpdateNavigationProgress(); protected: void InitializeNavigationStepWidgets(); void UpdatePrevNextButtons(); void UpdateFilterPipeline(); void SetSettingsWidgetVisible(bool visible); itk::SmartPointer m_DataStorage; NavigationStepVector m_NavigationSteps; QmitkUSNavigationAbstractSettingsWidget* m_SettingsWidget; itk::SmartPointer m_BaseNode; itk::SmartPointer m_SettingsNode; int m_CurrentTabIndex; int m_CurrentMaxStep; itk::SmartPointer m_ImageStreamNode; bool m_ImageAlreadySetToNode; itk::SmartPointer m_CombinedModality; itk::SmartPointer m_LastNavigationDataFilter; QWidget* m_Parent; QSignalMapper* m_ReadySignalMapper; QSignalMapper* m_NoLongerReadySignalMapper; QmitkStdMultiWidget* m_StdMultiWidget; bool m_UsePlanningStepWidget; private: Ui::QmitkUSNavigationProcessWidget *ui; }; #endif // USNAVIGATIONPROCESSWIDGET_H